WP Statistics - Version 12.2

Version Description

  • The new version proves itself more than twice as faster because we had a lot of changes in the plugin.
  • Improvement: Many functions converted to classes.
  • Improvement: Export data on the optimization page.
  • Improvement: Constants, Include files.
  • Improvement: Setting/Optimization page stylesheet and removed jQuery UI to generate tabs.
  • Added: Top Search Words in the plugin.
  • Fixed: Some notices error.
  • Removed: Some unused variables.
  • Removed: Force English option feature in the plugin.
  • Thanks Farhad Sakhaei To help us with these changes.
Download this release

Release Info

Developer mostafa.s1990
Plugin Icon 128x128 WP Statistics
Version 12.2
Comparing to
See all releases

Code changes from version 12.1.3 to 12.2

Files changed (61) hide show
  1. README.md +4 -1
  2. ajax.php +0 -335
  3. assets/css/admin.css +50 -50
  4. assets/css/jquery-ui-1.10.4.custom.min.css +0 -5
  5. assets/css/log.css +6 -1
  6. assets/js/Chart.bundle.min.js +9 -9
  7. assets/js/Chart.min.js +9 -9
  8. assets/js/admin.js +44 -0
  9. composer.json +9 -4
  10. composer.lock +111 -16
  11. dashboard.php +0 -233
  12. editor.php +0 -152
  13. includes/classes/class-wp-statistics-ajax.php +398 -0
  14. includes/classes/class-wp-statistics-bootstrap.php +1482 -0
  15. includes/classes/class-wp-statistics-dashboard.php +359 -0
  16. includes/classes/class-wp-statistics-editor.php +187 -0
  17. includes/classes/{hits.geoip.class.php → class-wp-statistics-geo-ip-hits.php} +13 -8
  18. includes/classes/{hits.class.php → class-wp-statistics-hits.php} +159 -104
  19. includes/classes/class-wp-statistics-install.php +453 -0
  20. includes/classes/{pagination.class.php → class-wp-statistics-pagination.php} +153 -82
  21. includes/classes/class-wp-statistics-schedule.php +312 -0
  22. includes/classes/class-wp-statistics-shortcode.php +222 -0
  23. includes/classes/class-wp-statistics-uninstall.php +57 -0
  24. includes/classes/class-wp-statistics-updates.php +573 -0
  25. includes/classes/class-wp-statistics-widget.php +437 -0
  26. includes/classes/class-wp-statistics.php +1166 -0
  27. includes/classes/important.txt +2 -0
  28. includes/classes/statistics.class.php +0 -822
  29. includes/functions/country-codes.php +1 -2
  30. includes/functions/country-coordinates.php +0 -1
  31. includes/functions/export.php +38 -30
  32. includes/functions/functions.php +489 -255
  33. includes/functions/geoip-populate.php +0 -53
  34. includes/functions/purge-hits.php +31 -15
  35. includes/functions/purge.php +128 -45
  36. includes/{classes → github/elidickinson/php-export-data}/php-export-data.class.php +91 -101
  37. includes/log/all-browsers.php +221 -203
  38. includes/log/authors.php +189 -162
  39. includes/log/categories.php +185 -160
  40. includes/log/exclusions.php +160 -138
  41. includes/log/hit-statistics.php +141 -127
  42. includes/log/last-search.php +120 -67
  43. includes/log/last-visitor.php +124 -65
  44. includes/log/log.php +138 -92
  45. includes/log/online.php +89 -50
  46. includes/log/page-statistics.php +44 -32
  47. includes/log/search-statistics.php +100 -92
  48. includes/log/searched-phrases.php +191 -0
  49. includes/log/tags.php +177 -159
  50. includes/log/top-countries.php +62 -43
  51. includes/log/top-pages.php +143 -101
  52. includes/log/top-referring.php +177 -87
  53. includes/log/top-visitors.php +51 -32
  54. includes/log/widgets/about.php +29 -17
  55. includes/log/widgets/browsers.php +45 -45
  56. includes/log/widgets/countries.php +22 -15
  57. includes/log/widgets/hits.php +59 -59
  58. includes/log/widgets/jqv.map.php +31 -29
  59. includes/log/widgets/page.php +69 -58
  60. includes/log/widgets/pages.php +16 -4
  61. includes/log/widgets/quickstats.php +179 -120
README.md CHANGED
@@ -9,6 +9,10 @@ On screen statistics presented as graphs are easily viewed through the WordPress
9
 
10
  This product includes GeoLite2 data created by MaxMind, available from https://www.maxmind.com.
11
 
 
 
 
 
12
  # Features
13
 
14
  * Online users, visits, visitors and page statistics
@@ -50,4 +54,3 @@ WP Statistics supports shortcodes in WordPress, these can be used in either a po
50
  Thank you [jetbrains](https://www.jetbrains.com) for giving us Intellij IDEA Ultimate licenses for develop this project.
51
  * [Wordpress plugin page](http://wordpress.org/plugins/wp-statistics/)
52
  * [Plugin website](https://wp-statistics.com)
53
- * [Donate](https://wp-statistics.com/donate/)
9
 
10
  This product includes GeoLite2 data created by MaxMind, available from https://www.maxmind.com.
11
 
12
+ **Do you like this project? Support it by donating**
13
+ - ![Paypal](https://raw.githubusercontent.com/reek/anti-adblock-killer/gh-pages/images/paypal.png) Paypal: [Donate](https://wp-statistics.com/donate/)
14
+ - ![btc](https://camo.githubusercontent.com/4bc31b03fc4026aa2f14e09c25c09b81e06d5e71/687474703a2f2f7777772e6d6f6e747265616c626974636f696e2e636f6d2f696d672f66617669636f6e2e69636f) Bitcoin: 1vKe5vWbr18KitxFeFnBfjBWcFGBxTd2N
15
+
16
  # Features
17
 
18
  * Online users, visits, visitors and page statistics
54
  Thank you [jetbrains](https://www.jetbrains.com) for giving us Intellij IDEA Ultimate licenses for develop this project.
55
  * [Wordpress plugin page](http://wordpress.org/plugins/wp-statistics/)
56
  * [Plugin website](https://wp-statistics.com)
 
ajax.php DELETED
@@ -1,335 +0,0 @@
1
- <?php
2
-
3
- // Setup an AJAX action to close the donation nag banner on the overview page.
4
- function wp_statistics_close_donation_nag_action_callback() {
5
- GLOBAL $WP_Statistics, $wpdb; // this is how you get access to the database
6
-
7
- $manage_cap = wp_statistics_validate_capability( $WP_Statistics->get_option( 'manage_capability', 'manage_options' ) );
8
-
9
- if ( current_user_can( $manage_cap ) ) {
10
- $WP_Statistics->update_option( 'disable_donation_nag', true );
11
- }
12
-
13
- wp_die(); // this is required to terminate immediately and return a proper response
14
- }
15
-
16
- add_action( 'wp_ajax_wp_statistics_close_donation_nag', 'wp_statistics_close_donation_nag_action_callback' );
17
-
18
- // Setup an AJAX action to delete an agent in the optimization page.
19
- function wp_statistics_delete_agents_action_callback() {
20
- GLOBAL $WP_Statistics, $wpdb; // this is how you get access to the database
21
-
22
- $manage_cap = wp_statistics_validate_capability( $WP_Statistics->get_option( 'manage_capability', 'manage_options' ) );
23
-
24
- if ( current_user_can( $manage_cap ) ) {
25
- $agent = $_POST['agent-name'];
26
-
27
- if ( $agent ) {
28
-
29
- $result = $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}statistics_visitor WHERE `agent` = %s", $agent ) );
30
-
31
- if ( $result ) {
32
- echo sprintf( __( '%s agent data deleted successfully.', 'wp-statistics' ), '<code>' . $agent . '</code>' );
33
- } else {
34
- _e( 'No agent data found to remove!', 'wp-statistics' );
35
- }
36
-
37
- } else {
38
- _e( 'Please select the desired items.', 'wp-statistics' );
39
- }
40
- } else {
41
- _e( 'Access denied!', 'wp-statistics' );
42
- }
43
-
44
- wp_die(); // this is required to terminate immediately and return a proper response
45
- }
46
-
47
- add_action( 'wp_ajax_wp_statistics_delete_agents', 'wp_statistics_delete_agents_action_callback' );
48
-
49
- // Setup an AJAX action to delete a platform in the optimization page.
50
- function wp_statistics_delete_platforms_action_callback() {
51
- GLOBAL $WP_Statistics, $wpdb; // this is how you get access to the database
52
-
53
- $manage_cap = wp_statistics_validate_capability( $WP_Statistics->get_option( 'manage_capability', 'manage_options' ) );
54
-
55
- if ( current_user_can( $manage_cap ) ) {
56
- $platform = $_POST['platform-name'];
57
-
58
- if ( $platform ) {
59
-
60
- $result = $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}statistics_visitor WHERE `platform` = %s", $platform ) );
61
-
62
- if ( $result ) {
63
- echo sprintf( __( '%s platform data deleted successfully.', 'wp-statistics' ), '<code>' . htmlentities( $platform, ENT_QUOTES ) . '</code>' );
64
- } else {
65
- _e( 'No platform data found to remove!', 'wp-statistics' );
66
- }
67
- } else {
68
- _e( 'Please select the desired items.', 'wp-statistics' );
69
- }
70
- } else {
71
- _e( 'Access denied!', 'wp-statistics' );
72
- }
73
-
74
- wp_die(); // this is required to terminate immediately and return a proper response
75
- }
76
-
77
- add_action( 'wp_ajax_wp_statistics_delete_platforms', 'wp_statistics_delete_platforms_action_callback' );
78
-
79
- // Setup an AJAX action to empty a table in the optimization page.
80
- function wp_statistics_empty_table_action_callback() {
81
- GLOBAL $WP_Statistics, $wpdb; // this is how you get access to the database
82
-
83
- $manage_cap = wp_statistics_validate_capability( $WP_Statistics->get_option( 'manage_capability', 'manage_options' ) );
84
-
85
- if ( current_user_can( $manage_cap ) ) {
86
- $table_name = $_POST['table-name'];
87
-
88
- if ( $table_name ) {
89
-
90
- switch ( $table_name ) {
91
- case 'useronline':
92
- echo wp_statitiscs_empty_table( $wpdb->prefix . 'statistics_useronline' );
93
- break;
94
- case 'visit':
95
- echo wp_statitiscs_empty_table( $wpdb->prefix . 'statistics_visit' );
96
- break;
97
- case 'visitors':
98
- echo wp_statitiscs_empty_table( $wpdb->prefix . 'statistics_visitor' );
99
- break;
100
- case 'exclusions':
101
- echo wp_statitiscs_empty_table( $wpdb->prefix . 'statistics_exclusions' );
102
- break;
103
- case 'pages':
104
- echo wp_statitiscs_empty_table( $wpdb->prefix . 'statistics_pages' );
105
- break;
106
- case 'search':
107
- echo wp_statitiscs_empty_table( $wpdb->prefix . 'statistics_search' );
108
- break;
109
- case 'all':
110
- $result_string = wp_statitiscs_empty_table( $wpdb->prefix . 'statistics_useronline' );
111
- $result_string .= '<br>' . wp_statitiscs_empty_table( $wpdb->prefix . 'statistics_visit' );
112
- $result_string .= '<br>' . wp_statitiscs_empty_table( $wpdb->prefix . 'statistics_visitor' );
113
- $result_string .= '<br>' . wp_statitiscs_empty_table( $wpdb->prefix . 'statistics_exclusions' );
114
- $result_string .= '<br>' . wp_statitiscs_empty_table( $wpdb->prefix . 'statistics_pages' );
115
- $result_string .= '<br>' . wp_statitiscs_empty_table( $wpdb->prefix . 'statistics_search' );
116
-
117
- echo $result_string;
118
-
119
- break;
120
- default:
121
- _e( 'Please select the desired items.', 'wp-statistics' );
122
- }
123
-
124
- $WP_Statistics->Primary_Values();
125
-
126
- } else {
127
- _e( 'Please select the desired items.', 'wp-statistics' );
128
- }
129
- } else {
130
- _e( 'Access denied!', 'wp-statistics' );
131
- }
132
-
133
- wp_die(); // this is required to terminate immediately and return a proper response
134
- }
135
-
136
- add_action( 'wp_ajax_wp_statistics_empty_table', 'wp_statistics_empty_table_action_callback' );
137
-
138
- // Setup an AJAX action to purge old data in the optimization page.
139
- function wp_statistics_purge_data_action_callback() {
140
- GLOBAL $WP_Statistics, $wpdb; // this is how you get access to the database
141
-
142
- require( $WP_Statistics->plugin_dir . '/includes/functions/purge.php' );
143
-
144
- $manage_cap = wp_statistics_validate_capability( $WP_Statistics->get_option( 'manage_capability', 'manage_options' ) );
145
-
146
- if ( current_user_can( $manage_cap ) ) {
147
- $purge_days = 0;
148
-
149
- if ( array_key_exists( 'purge-days', $_POST ) ) {
150
- // Get the number of days to purge data before.
151
- $purge_days = intval( $_POST['purge-days'] );
152
- }
153
-
154
- echo wp_statistics_purge_data( $purge_days );
155
- } else {
156
- _e( 'Access denied!', 'wp-statistics' );
157
- }
158
-
159
- wp_die(); // this is required to terminate immediately and return a proper response
160
- }
161
-
162
- add_action( 'wp_ajax_wp_statistics_purge_data', 'wp_statistics_purge_data_action_callback' );
163
-
164
- // Setup an AJAX action to purge visitors with more than a defined number of hits.
165
- function wp_statistics_purge_visitor_hits_action_callback() {
166
- GLOBAL $WP_Statistics, $wpdb; // this is how you get access to the database
167
-
168
- require( $WP_Statistics->plugin_dir . '/includes/functions/purge-hits.php' );
169
-
170
- $manage_cap = wp_statistics_validate_capability( $WP_Statistics->get_option( 'manage_capability', 'manage_options' ) );
171
-
172
- if ( current_user_can( $manage_cap ) ) {
173
- $purge_hits = 10;
174
-
175
- if ( array_key_exists( 'purge-hits', $_POST ) ) {
176
- // Get the number of days to purge data before.
177
- $purge_hits = intval( $_POST['purge-hits'] );
178
- }
179
-
180
- if ( $purge_hits < 10 ) {
181
- _e( 'Number of hits must be greater than or equal to 10!', 'wp-statistics' );
182
- } else {
183
- echo wp_statistics_purge_visitor_hits( $purge_hits );
184
- }
185
- } else {
186
- _e( 'Access denied!', 'wp-statistics' );
187
- }
188
-
189
- wp_die(); // this is required to terminate immediately and return a proper response
190
- }
191
-
192
- add_action( 'wp_ajax_wp_statistics_purge_visitor_hits', 'wp_statistics_purge_visitor_hits_action_callback' );
193
-
194
- // Setup an AJAX action to purge visitors with more than a defined number of hits.
195
- function wp_statistics_get_widget_contents_callback() {
196
- GLOBAL $WP_Statistics, $wpdb; // this is how you get access to the database
197
-
198
- $widgets = array(
199
- 'about',
200
- 'browsers',
201
- 'map',
202
- 'countries',
203
- 'hits',
204
- 'hitsmap',
205
- 'page',
206
- 'pages',
207
- 'quickstats',
208
- 'recent',
209
- 'referring',
210
- 'search',
211
- 'summary',
212
- 'top.visitors',
213
- 'words'
214
- );
215
-
216
- if ( array_key_exists( 'format', $_POST ) and $_POST['format'] == 'dashboard' ) {
217
- $size = 220;
218
- $days = 10;
219
- } else {
220
- $size = 110;
221
- $days = 20;
222
- }
223
-
224
- $view_cap = wp_statistics_validate_capability( $WP_Statistics->get_option( 'read_capability', 'manage_options' ) );
225
-
226
- if ( current_user_can( $view_cap ) ) {
227
- $widget = '';
228
-
229
- if ( array_key_exists( 'widget', $_POST ) ) {
230
- // Get the widget we're going to display.
231
-
232
- if ( in_array( $_POST['widget'], $widgets ) ) {
233
- $widget = $_POST['widget'];
234
- }
235
- }
236
-
237
- if ( 'map' == $widget || 'hitsmap' == $widget ) {
238
- $widget = 'jqv.map';
239
- }
240
-
241
- if ( '' == $widget ) {
242
- _e( 'No matching widget found!', 'wp-statistics' );
243
- wp_die();
244
- }
245
-
246
- $ISOCountryCode = $WP_Statistics->get_country_codes();
247
- $search_engines = wp_statistics_searchengine_list();
248
-
249
- require( $WP_Statistics->plugin_dir . '/includes/log/widgets/' . $widget . '.php' );
250
-
251
- switch ( $widget ) {
252
- case 'summary':
253
- wp_statistics_generate_summary_postbox_content( $search_engines );
254
-
255
- break;
256
- case 'quickstats':
257
- wp_statistics_generate_quickstats_postbox_content( $search_engines );
258
-
259
- break;
260
-
261
- case 'browsers':
262
- wp_statistics_generate_browsers_postbox_content();
263
-
264
- break;
265
- case 'referring':
266
- wp_statistics_generate_referring_postbox_content();
267
-
268
- break;
269
- case 'countries':
270
- wp_statistics_generate_countries_postbox_content( $ISOCountryCode );
271
-
272
- break;
273
- case 'jqv.map':
274
- wp_statistics_generate_map_postbox_content( $ISOCountryCode );
275
-
276
- break;
277
- case 'hits':
278
- wp_statistics_generate_hits_postbox_content( $size, $days );
279
-
280
- break;
281
- case 'search':
282
- wp_statistics_generate_search_postbox_content( $search_engines, $size, $days );
283
-
284
- break;
285
- case 'words':
286
- wp_statistics_generate_words_postbox_content( $ISOCountryCode );
287
-
288
- break;
289
- case 'page':
290
- _e( 'This feature temporarily disabled.', 'wp-statistics' );
291
-
292
- if ( array_key_exists( 'page-id', $_POST ) ) {
293
- $pageid = (int) $_POST['page-id'];
294
- echo '&nbsp;';
295
- echo sprintf( __( '<a href="admin.php?page=wps_pages_page&page-id=%s">Click here</a> to see page stats.', 'wp-statistics' ), $pageid );
296
-
297
- // This feature temporarily disabled because there is conflicts.
298
- //wp_statistics_generate_page_postbox_content( null, $pageid );
299
- }
300
-
301
- break;
302
- case 'pages':
303
- list( $total, $uris ) = wp_statistics_get_top_pages();
304
- wp_statistics_generate_pages_postbox_content( $total, $uris );
305
-
306
- break;
307
- case 'recent':
308
- wp_statistics_generate_recent_postbox_content( $ISOCountryCode );
309
-
310
- break;
311
- case 'top.visitors':
312
- $format = null;
313
-
314
- if ( array_key_exists( 'format', $_POST ) ) {
315
- $format = 'compact';
316
- }
317
-
318
- wp_statistics_generate_top_visitors_postbox_content( $ISOCountryCode, 'today', 10, $format );
319
-
320
- break;
321
- case 'about':
322
- wp_statistics_generate_about_postbox_content( $ISOCountryCode );
323
-
324
- break;
325
- default:
326
- _e( 'ERROR: Widget not found!', 'wp-statistics' );
327
- }
328
- } else {
329
- _e( 'Access denied!', 'wp-statistics' );
330
- }
331
-
332
- wp_die(); // this is required to terminate immediately and return a proper response
333
- }
334
-
335
- add_action( 'wp_ajax_wp_statistics_get_widget_contents', 'wp_statistics_get_widget_contents_callback' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
assets/css/admin.css CHANGED
@@ -1,16 +1,4 @@
1
- .wps-center {
2
- text-align: center;
3
- }
4
-
5
- #wps_about_postbox #about_postbox img {
6
- max-width: 170px;
7
- margin: 0 0 9px 0;
8
- }
9
-
10
- .column-wp-statistics {
11
- width: 52px;
12
- }
13
-
14
  .wp-statistics-plugins .widefat > * {
15
  float: left;
16
  }
@@ -52,62 +40,61 @@
52
  margin-top: 51px;
53
  }
54
 
55
- .wp-statistics-settings #tabs {
56
- margin-top: 18px;
57
  }
58
 
59
- .wp-statistics-settings .ui-tabs .ui-tabs-nav .ui-tabs-anchor {
60
- padding-right: 8px;
61
- padding-left: 8px;
 
62
  }
63
 
64
- .wp-statistics-settings #tabs .ui-widget-content {
65
- background-color: white;
66
- border-left: 1px solid #dadada;
67
- border-right: 1px solid #dadada;
68
- border-bottom: 1px solid #dadada;
 
 
 
69
  }
70
 
71
- .wp-statistics-settings .ui-tabs .ui-tabs-nav {
72
- padding: 0;
 
 
 
 
 
 
73
  }
74
 
75
- .wp-statistics-settings .ui-tabs .ui-tabs-nav li {
76
- border-color: #dadada;
 
 
 
 
 
 
77
  }
78
 
79
- .wp-statistics-settings .ui-widget-header {
80
- border-bottom-color: #dadada;
81
  }
82
 
83
  .rtl .wp-statistics-settings .widefat {
84
  float: right;
85
  }
86
 
87
- .wp-statistics-settings .ui-widget-content .ui-tabs-panel a {
88
- color: #0073aa;
89
- }
90
-
91
- @media only screen and (max-width: 1482px) {
92
- .wp-statistics-settings .ui-tabs .ui-tabs-nav .ui-tabs-anchor {
93
- padding-right: 6px;
94
- padding-left: 6px;
95
- font-size: 12px;
96
- }
97
-
98
- .wp-statistics-settings .ui-tabs .ui-tabs-nav li.ui-tabs-active {
99
- margin-right: 5px;
100
- }
101
-
102
- .wp-statistics-settings .ui-tabs .ui-tabs-nav li {
103
- margin-right: 5px;
104
- }
105
-
106
- .wp-statistics-settings .postbox-container {
107
- margin-top: 11px;
108
  }
109
  }
110
 
 
111
  .note {
112
  color: #FF0000;
113
  font-size: 11px !important;
@@ -122,4 +109,17 @@
122
 
123
  .data code {
124
  border-radius: 2px 2px 2px 2px;
 
 
 
 
 
 
 
 
 
 
 
 
 
125
  }
1
+ /** Add-Ons page **/
 
 
 
 
 
 
 
 
 
 
 
 
2
  .wp-statistics-plugins .widefat > * {
3
  float: left;
4
  }
40
  margin-top: 51px;
41
  }
42
 
43
+ .wp-statistics-container {
44
+ margin: 0 auto;
45
  }
46
 
47
+ .wp-statistics-settings ul.tabs {
48
+ margin: 0px;
49
+ padding: 0px;
50
+ list-style: none;
51
  }
52
 
53
+ .wp-statistics-settings ul.tabs li {
54
+ background: none;
55
+ color: #222;
56
+ display: inline-block;
57
+ padding: 10px 10px;
58
+ cursor: pointer;
59
+ border: 1px solid #f1f1f1;
60
+ margin: 0;
61
  }
62
 
63
+ .wp-statistics-settings ul.tabs li.current {
64
+ background: #ffffff;
65
+ color: #222;
66
+ border-right-color: #e5e5e5;
67
+ border-left-color: #e5e5e5;
68
+ border-bottom-color: #ffffff;
69
+ border-top-color: #e5e5e5;
70
+ padding-bottom: 11px;
71
  }
72
 
73
+ .wp-statistics-settings .tab-content {
74
+ display: none;
75
+ background: #ffffff;
76
+ padding: 15px;
77
+ -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
78
+ border: 1px solid #e5e5e5;
79
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
80
+ margin: -1px 0 0 0;
81
  }
82
 
83
+ .wp-statistics-settings .tab-content.current {
84
+ display: inherit;
85
  }
86
 
87
  .rtl .wp-statistics-settings .widefat {
88
  float: right;
89
  }
90
 
91
+ @media only screen and (max-width: 1327px) {
92
+ .wp-statistics-settings ul.tabs li {
93
+ padding: 10px 5px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  }
95
  }
96
 
97
+ /** Other CSS **/
98
  .note {
99
  color: #FF0000;
100
  font-size: 11px !important;
109
 
110
  .data code {
111
  border-radius: 2px 2px 2px 2px;
112
+ }
113
+
114
+ .wps-center {
115
+ text-align: center;
116
+ }
117
+
118
+ #wps_about_postbox #about_postbox img {
119
+ max-width: 170px;
120
+ margin: 0 0 9px 0;
121
+ }
122
+
123
+ .column-wp-statistics {
124
+ width: 52px;
125
  }
assets/css/jquery-ui-1.10.4.custom.min.css DELETED
@@ -1,5 +0,0 @@
1
- /*! jQuery UI - v1.10.4 - 2014-03-06
2
- * http://jqueryui.com
3
- * Includes: jquery.ui.core.css, jquery.ui.progressbar.css, jquery.ui.tabs.css, jquery.ui.theme.css
4
- * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=0px&bgColorHeader=%2300ffff&bgTextureHeader=highlight_soft&bgImgOpacityHeader=100&borderColorHeader=%23aaaaaa&fcHeader=%23222222&iconColorHeader=%23222222&bgColorContent=%23ffffff&bgTextureContent=flat&bgImgOpacityContent=75&borderColorContent=%23aaaaaa&fcContent=%23222222&iconColorContent=%23222222&bgColorDefault=%23e6e6e6&bgTextureDefault=glass&bgImgOpacityDefault=75&borderColorDefault=%23d3d3d3&fcDefault=%23555555&iconColorDefault=%23888888&bgColorHover=%23dadada&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=%23999999&fcHover=%23212121&iconColorHover=%23454545&bgColorActive=%23ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=%23aaaaaa&fcActive=%23212121&iconColorActive=%23454545&bgColorHighlight=%23fbf9ee&bgTextureHighlight=glass&bgImgOpacityHighlight=55&borderColorHighlight=%23fcefa1&fcHighlight=%23363636&iconColorHighlight=%232e83ff&bgColorError=%23fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=%23cd0a0a&fcError=%23cd0a0a&iconColorError=%23cd0a0a&bgColorOverlay=%23aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=%23aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
5
- * Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default !important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-progressbar .ui-progressbar-overlay{background:url("images/animated-overlay.gif");height:100%;filter:alpha(opacity=25);opacity:.25}.ui-progressbar-indeterminate .ui-progressbar-value{background-image:none}#tabs{border:0;padding:0;margin:0}.ui-tabs{position:relative;padding:.2em}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;margin-right:10px;border-bottom-width:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav .ui-tabs-anchor{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px;margin-right:10px}.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor{cursor:text}.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:0}.ui-widget{font-family:Verdana,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Verdana,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #aaa;background:transparent;color:#222}.ui-widget-content a{color:#222}.ui-widget-header{border-left:0;border-top:0;border-right:0;border-bottom:1px solid #aaa;background:transparent;color:#222;font-weight:bold}.ui-widget-header a{color:#222}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #d3d3d3;background:#e6e6e6;font-weight:normal;color:#555}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#555;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #999;background:#dadada;font-weight:normal;color:#212121}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited{color:#212121;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #aaa;background:#fff;font-weight:normal;color:#212121}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#212121;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fcefa1;background:#fbf9ee;color:#363636}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#fef1ec;color:#cd0a0a}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#cd0a0a}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#cd0a0a}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:0}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:0}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:0}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:0}.ui-widget-overlay{background:#aaa;opacity:.3;filter:Alpha(Opacity=30)}.ui-widget-shadow{margin:-8px 0 0 -8px;padding:8px;background:#aaa;opacity:.3;filter:Alpha(Opacity=30);border-radius:8px}
 
 
 
 
 
assets/css/log.css CHANGED
@@ -318,7 +318,12 @@
318
 
319
  #donate-button {
320
  float: right;
321
- margin: 12px 0 0;
 
 
 
 
 
322
  }
323
 
324
  .jqvmap-label {
318
 
319
  #donate-button {
320
  float: right;
321
+ margin: -2px 0 0 0;
322
+ }
323
+
324
+ #donate-button a {
325
+ height: 23px;
326
+ line-height: 22px;
327
  }
328
 
329
  .jqvmap-label {
assets/js/Chart.bundle.min.js CHANGED
@@ -1,10 +1,10 @@
1
- /*!
2
- * Chart.js
3
- * http://chartjs.org/
4
- * Version: 2.7.0
5
- *
6
- * Copyright 2017 Nick Downie
7
- * Released under the MIT license
8
- * https://github.com/chartjs/Chart.js/blob/master/LICENSE.md
9
- */
10
  !function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).Chart=t()}}(function(){return function t(e,n,i){function a(o,s){if(!n[o]){if(!e[o]){var l="function"==typeof require&&require;if(!s&&l)return l(o,!0);if(r)return r(o,!0);var u=new Error("Cannot find module '"+o+"'");throw u.code="MODULE_NOT_FOUND",u}var d=n[o]={exports:{}};e[o][0].call(d.exports,function(t){var n=e[o][1][t];return a(n||t)},d,d.exports,t,e,n,i)}return n[o].exports}for(var r="function"==typeof require&&require,o=0;o<i.length;o++)a(i[o]);return a}({1:[function(t,e,n){function i(t){if(t){var e=/^#([a-fA-F0-9]{3})$/i,n=/^#([a-fA-F0-9]{6})$/i,i=/^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i,a=/^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i,r=/(\w+)/,o=[0,0,0],s=1,l=t.match(e);if(l){l=l[1];for(d=0;d<o.length;d++)o[d]=parseInt(l[d]+l[d],16)}else if(l=t.match(n)){l=l[1];for(d=0;d<o.length;d++)o[d]=parseInt(l.slice(2*d,2*d+2),16)}else if(l=t.match(i)){for(d=0;d<o.length;d++)o[d]=parseInt(l[d+1]);s=parseFloat(l[4])}else if(l=t.match(a)){for(d=0;d<o.length;d++)o[d]=Math.round(2.55*parseFloat(l[d+1]));s=parseFloat(l[4])}else if(l=t.match(r)){if("transparent"==l[1])return[0,0,0,0];if(!(o=c[l[1]]))return}for(var d=0;d<o.length;d++)o[d]=u(o[d],0,255);return s=s||0==s?u(s,0,1):1,o[3]=s,o}}function a(t){if(t){var e=/^hsla?\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/,n=t.match(e);if(n){var i=parseFloat(n[4]);return[u(parseInt(n[1]),0,360),u(parseFloat(n[2]),0,100),u(parseFloat(n[3]),0,100),u(isNaN(i)?1:i,0,1)]}}}function r(t){if(t){var e=/^hwb\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/,n=t.match(e);if(n){var i=parseFloat(n[4]);return[u(parseInt(n[1]),0,360),u(parseFloat(n[2]),0,100),u(parseFloat(n[3]),0,100),u(isNaN(i)?1:i,0,1)]}}}function o(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"rgba("+t[0]+", "+t[1]+", "+t[2]+", "+e+")"}function s(t,e){return"rgba("+Math.round(t[0]/255*100)+"%, "+Math.round(t[1]/255*100)+"%, "+Math.round(t[2]/255*100)+"%, "+(e||t[3]||1)+")"}function l(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"hsla("+t[0]+", "+t[1]+"%, "+t[2]+"%, "+e+")"}function u(t,e,n){return Math.min(Math.max(e,t),n)}function d(t){var e=t.toString(16).toUpperCase();return e.length<2?"0"+e:e}var c=t(5);e.exports={getRgba:i,getHsla:a,getRgb:function(t){var e=i(t);return e&&e.slice(0,3)},getHsl:function(t){var e=a(t);return e&&e.slice(0,3)},getHwb:r,getAlpha:function(t){var e=i(t);return e?e[3]:(e=a(t))?e[3]:(e=r(t))?e[3]:void 0},hexString:function(t){return"#"+d(t[0])+d(t[1])+d(t[2])},rgbString:function(t,e){return e<1||t[3]&&t[3]<1?o(t,e):"rgb("+t[0]+", "+t[1]+", "+t[2]+")"},rgbaString:o,percentString:function(t,e){return e<1||t[3]&&t[3]<1?s(t,e):"rgb("+Math.round(t[0]/255*100)+"%, "+Math.round(t[1]/255*100)+"%, "+Math.round(t[2]/255*100)+"%)"},percentaString:s,hslString:function(t,e){return e<1||t[3]&&t[3]<1?l(t,e):"hsl("+t[0]+", "+t[1]+"%, "+t[2]+"%)"},hslaString:l,hwbString:function(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"hwb("+t[0]+", "+t[1]+"%, "+t[2]+"%"+(void 0!==e&&1!==e?", "+e:"")+")"},keyword:function(t){return h[t.slice(0,3)]}};var h={};for(var f in c)h[c[f]]=f},{5:5}],2:[function(t,e,n){var i=t(4),a=t(1),r=function(t){if(t instanceof r)return t;if(!(this instanceof r))return new r(t);this.valid=!1,this.values={rgb:[0,0,0],hsl:[0,0,0],hsv:[0,0,0],hwb:[0,0,0],cmyk:[0,0,0,0],alpha:1};var e;"string"==typeof t?(e=a.getRgba(t))?this.setValues("rgb",e):(e=a.getHsla(t))?this.setValues("hsl",e):(e=a.getHwb(t))&&this.setValues("hwb",e):"object"==typeof t&&(void 0!==(e=t).r||void 0!==e.red?this.setValues("rgb",e):void 0!==e.l||void 0!==e.lightness?this.setValues("hsl",e):void 0!==e.v||void 0!==e.value?this.setValues("hsv",e):void 0!==e.w||void 0!==e.whiteness?this.setValues("hwb",e):void 0===e.c&&void 0===e.cyan||this.setValues("cmyk",e))};r.prototype={isValid:function(){return this.valid},rgb:function(){return this.setSpace("rgb",arguments)},hsl:function(){return this.setSpace("hsl",arguments)},hsv:function(){return this.setSpace("hsv",arguments)},hwb:function(){return this.setSpace("hwb",arguments)},cmyk:function(){return this.setSpace("cmyk",arguments)},rgbArray:function(){return this.values.rgb},hslArray:function(){return this.values.hsl},hsvArray:function(){return this.values.hsv},hwbArray:function(){var t=this.values;return 1!==t.alpha?t.hwb.concat([t.alpha]):t.hwb},cmykArray:function(){return this.values.cmyk},rgbaArray:function(){var t=this.values;return t.rgb.concat([t.alpha])},hslaArray:function(){var t=this.values;return t.hsl.concat([t.alpha])},alpha:function(t){return void 0===t?this.values.alpha:(this.setValues("alpha",t),this)},red:function(t){return this.setChannel("rgb",0,t)},green:function(t){return this.setChannel("rgb",1,t)},blue:function(t){return this.setChannel("rgb",2,t)},hue:function(t){return t&&(t=(t%=360)<0?360+t:t),this.setChannel("hsl",0,t)},saturation:function(t){return this.setChannel("hsl",1,t)},lightness:function(t){return this.setChannel("hsl",2,t)},saturationv:function(t){return this.setChannel("hsv",1,t)},whiteness:function(t){return this.setChannel("hwb",1,t)},blackness:function(t){return this.setChannel("hwb",2,t)},value:function(t){return this.setChannel("hsv",2,t)},cyan:function(t){return this.setChannel("cmyk",0,t)},magenta:function(t){return this.setChannel("cmyk",1,t)},yellow:function(t){return this.setChannel("cmyk",2,t)},black:function(t){return this.setChannel("cmyk",3,t)},hexString:function(){return a.hexString(this.values.rgb)},rgbString:function(){return a.rgbString(this.values.rgb,this.values.alpha)},rgbaString:function(){return a.rgbaString(this.values.rgb,this.values.alpha)},percentString:function(){return a.percentString(this.values.rgb,this.values.alpha)},hslString:function(){return a.hslString(this.values.hsl,this.values.alpha)},hslaString:function(){return a.hslaString(this.values.hsl,this.values.alpha)},hwbString:function(){return a.hwbString(this.values.hwb,this.values.alpha)},keyword:function(){return a.keyword(this.values.rgb,this.values.alpha)},rgbNumber:function(){var t=this.values.rgb;return t[0]<<16|t[1]<<8|t[2]},luminosity:function(){for(var t=this.values.rgb,e=[],n=0;n<t.length;n++){var i=t[n]/255;e[n]=i<=.03928?i/12.92:Math.pow((i+.055)/1.055,2.4)}return.2126*e[0]+.7152*e[1]+.0722*e[2]},contrast:function(t){var e=this.luminosity(),n=t.luminosity();return e>n?(e+.05)/(n+.05):(n+.05)/(e+.05)},level:function(t){var e=this.contrast(t);return e>=7.1?"AAA":e>=4.5?"AA":""},dark:function(){var t=this.values.rgb;return(299*t[0]+587*t[1]+114*t[2])/1e3<128},light:function(){return!this.dark()},negate:function(){for(var t=[],e=0;e<3;e++)t[e]=255-this.values.rgb[e];return this.setValues("rgb",t),this},lighten:function(t){var e=this.values.hsl;return e[2]+=e[2]*t,this.setValues("hsl",e),this},darken:function(t){var e=this.values.hsl;return e[2]-=e[2]*t,this.setValues("hsl",e),this},saturate:function(t){var e=this.values.hsl;return e[1]+=e[1]*t,this.setValues("hsl",e),this},desaturate:function(t){var e=this.values.hsl;return e[1]-=e[1]*t,this.setValues("hsl",e),this},whiten:function(t){var e=this.values.hwb;return e[1]+=e[1]*t,this.setValues("hwb",e),this},blacken:function(t){var e=this.values.hwb;return e[2]+=e[2]*t,this.setValues("hwb",e),this},greyscale:function(){var t=this.values.rgb,e=.3*t[0]+.59*t[1]+.11*t[2];return this.setValues("rgb",[e,e,e]),this},clearer:function(t){var e=this.values.alpha;return this.setValues("alpha",e-e*t),this},opaquer:function(t){var e=this.values.alpha;return this.setValues("alpha",e+e*t),this},rotate:function(t){var e=this.values.hsl,n=(e[0]+t)%360;return e[0]=n<0?360+n:n,this.setValues("hsl",e),this},mix:function(t,e){var n=this,i=t,a=void 0===e?.5:e,r=2*a-1,o=n.alpha()-i.alpha(),s=((r*o==-1?r:(r+o)/(1+r*o))+1)/2,l=1-s;return this.rgb(s*n.red()+l*i.red(),s*n.green()+l*i.green(),s*n.blue()+l*i.blue()).alpha(n.alpha()*a+i.alpha()*(1-a))},toJSON:function(){return this.rgb()},clone:function(){var t,e,n=new r,i=this.values,a=n.values;for(var o in i)i.hasOwnProperty(o)&&(t=i[o],"[object Array]"===(e={}.toString.call(t))?a[o]=t.slice(0):"[object Number]"===e?a[o]=t:console.error("unexpected color value:",t));return n}},r.prototype.spaces={rgb:["red","green","blue"],hsl:["hue","saturation","lightness"],hsv:["hue","saturation","value"],hwb:["hue","whiteness","blackness"],cmyk:["cyan","magenta","yellow","black"]},r.prototype.maxes={rgb:[255,255,255],hsl:[360,100,100],hsv:[360,100,100],hwb:[360,100,100],cmyk:[100,100,100,100]},r.prototype.getValues=function(t){for(var e=this.values,n={},i=0;i<t.length;i++)n[t.charAt(i)]=e[t][i];return 1!==e.alpha&&(n.a=e.alpha),n},r.prototype.setValues=function(t,e){var n,a=this.values,r=this.spaces,o=this.maxes,s=1;if(this.valid=!0,"alpha"===t)s=e;else if(e.length)a[t]=e.slice(0,t.length),s=e[t.length];else if(void 0!==e[t.charAt(0)]){for(n=0;n<t.length;n++)a[t][n]=e[t.charAt(n)];s=e.a}else if(void 0!==e[r[t][0]]){var l=r[t];for(n=0;n<t.length;n++)a[t][n]=e[l[n]];s=e.alpha}if(a.alpha=Math.max(0,Math.min(1,void 0===s?a.alpha:s)),"alpha"===t)return!1;var u;for(n=0;n<t.length;n++)u=Math.max(0,Math.min(o[t][n],a[t][n])),a[t][n]=Math.round(u);for(var d in r)d!==t&&(a[d]=i[t][d](a[t]));return!0},r.prototype.setSpace=function(t,e){var n=e[0];return void 0===n?this.getValues(t):("number"==typeof n&&(n=Array.prototype.slice.call(e)),this.setValues(t,n),this)},r.prototype.setChannel=function(t,e,n){var i=this.values[t];return void 0===n?i[e]:n===i[e]?this:(i[e]=n,this.setValues(t,i),this)},"undefined"!=typeof window&&(window.Color=r),e.exports=r},{1:1,4:4}],3:[function(t,e,n){function i(t){var e,n,i,a=t[0]/255,r=t[1]/255,o=t[2]/255,s=Math.min(a,r,o),l=Math.max(a,r,o),u=l-s;return l==s?e=0:a==l?e=(r-o)/u:r==l?e=2+(o-a)/u:o==l&&(e=4+(a-r)/u),(e=Math.min(60*e,360))<0&&(e+=360),i=(s+l)/2,n=l==s?0:i<=.5?u/(l+s):u/(2-l-s),[e,100*n,100*i]}function a(t){var e,n,i,a=t[0],r=t[1],o=t[2],s=Math.min(a,r,o),l=Math.max(a,r,o),u=l-s;return n=0==l?0:u/l*1e3/10,l==s?e=0:a==l?e=(r-o)/u:r==l?e=2+(o-a)/u:o==l&&(e=4+(a-r)/u),(e=Math.min(60*e,360))<0&&(e+=360),i=l/255*1e3/10,[e,n,i]}function o(t){var e=t[0],n=t[1],a=t[2];return[i(t)[0],100*(1/255*Math.min(e,Math.min(n,a))),100*(a=1-1/255*Math.max(e,Math.max(n,a)))]}function s(t){var e,n,i,a,r=t[0]/255,o=t[1]/255,s=t[2]/255;return a=Math.min(1-r,1-o,1-s),e=(1-r-a)/(1-a)||0,n=(1-o-a)/(1-a)||0,i=(1-s-a)/(1-a)||0,[100*e,100*n,100*i,100*a]}function l(t){return S[JSON.stringify(t)]}function u(t){var e=t[0]/255,n=t[1]/255,i=t[2]/255;return[100*(.4124*(e=e>.04045?Math.pow((e+.055)/1.055,2.4):e/12.92)+.3576*(n=n>.04045?Math.pow((n+.055)/1.055,2.4):n/12.92)+.1805*(i=i>.04045?Math.pow((i+.055)/1.055,2.4):i/12.92)),100*(.2126*e+.7152*n+.0722*i),100*(.0193*e+.1192*n+.9505*i)]}function d(t){var e,n,i,a=u(t),r=a[0],o=a[1],s=a[2];return r/=95.047,o/=100,s/=108.883,r=r>.008856?Math.pow(r,1/3):7.787*r+16/116,o=o>.008856?Math.pow(o,1/3):7.787*o+16/116,s=s>.008856?Math.pow(s,1/3):7.787*s+16/116,e=116*o-16,n=500*(r-o),i=200*(o-s),[e,n,i]}function c(t){var e,n,i,a,r,o=t[0]/360,s=t[1]/100,l=t[2]/100;if(0==s)return r=255*l,[r,r,r];e=2*l-(n=l<.5?l*(1+s):l+s-l*s),a=[0,0,0];for(var u=0;u<3;u++)(i=o+1/3*-(u-1))<0&&i++,i>1&&i--,r=6*i<1?e+6*(n-e)*i:2*i<1?n:3*i<2?e+(n-e)*(2/3-i)*6:e,a[u]=255*r;return a}function h(t){var e=t[0]/60,n=t[1]/100,i=t[2]/100,a=Math.floor(e)%6,r=e-Math.floor(e),o=255*i*(1-n),s=255*i*(1-n*r),l=255*i*(1-n*(1-r)),i=255*i;switch(a){case 0:return[i,l,o];case 1:return[s,i,o];case 2:return[o,i,l];case 3:return[o,s,i];case 4:return[l,o,i];case 5:return[i,o,s]}}function f(t){var e,n,i,a,o=t[0]/360,s=t[1]/100,l=t[2]/100,u=s+l;switch(u>1&&(s/=u,l/=u),e=Math.floor(6*o),n=1-l,i=6*o-e,0!=(1&e)&&(i=1-i),a=s+i*(n-s),e){default:case 6:case 0:r=n,g=a,b=s;break;case 1:r=a,g=n,b=s;break;case 2:r=s,g=n,b=a;break;case 3:r=s,g=a,b=n;break;case 4:r=a,g=s,b=n;break;case 5:r=n,g=s,b=a}return[255*r,255*g,255*b]}function m(t){var e,n,i,a=t[0]/100,r=t[1]/100,o=t[2]/100,s=t[3]/100;return e=1-Math.min(1,a*(1-s)+s),n=1-Math.min(1,r*(1-s)+s),i=1-Math.min(1,o*(1-s)+s),[255*e,255*n,255*i]}function p(t){var e,n,i,a=t[0]/100,r=t[1]/100,o=t[2]/100;return e=3.2406*a+-1.5372*r+-.4986*o,n=-.9689*a+1.8758*r+.0415*o,i=.0557*a+-.204*r+1.057*o,e=e>.0031308?1.055*Math.pow(e,1/2.4)-.055:e*=12.92,n=n>.0031308?1.055*Math.pow(n,1/2.4)-.055:n*=12.92,i=i>.0031308?1.055*Math.pow(i,1/2.4)-.055:i*=12.92,e=Math.min(Math.max(0,e),1),n=Math.min(Math.max(0,n),1),i=Math.min(Math.max(0,i),1),[255*e,255*n,255*i]}function v(t){var e,n,i,a=t[0],r=t[1],o=t[2];return a/=95.047,r/=100,o/=108.883,a=a>.008856?Math.pow(a,1/3):7.787*a+16/116,r=r>.008856?Math.pow(r,1/3):7.787*r+16/116,o=o>.008856?Math.pow(o,1/3):7.787*o+16/116,e=116*r-16,n=500*(a-r),i=200*(r-o),[e,n,i]}function y(t){var e,n,i,a,r=t[0],o=t[1],s=t[2];return r<=8?a=(n=100*r/903.3)/100*7.787+16/116:(n=100*Math.pow((r+16)/116,3),a=Math.pow(n/100,1/3)),e=e/95.047<=.008856?e=95.047*(o/500+a-16/116)/7.787:95.047*Math.pow(o/500+a,3),i=i/108.883<=.008859?i=108.883*(a-s/200-16/116)/7.787:108.883*Math.pow(a-s/200,3),[e,n,i]}function x(t){var e,n,i,a=t[0],r=t[1],o=t[2];return e=Math.atan2(o,r),(n=360*e/2/Math.PI)<0&&(n+=360),i=Math.sqrt(r*r+o*o),[a,i,n]}function _(t){return p(y(t))}function k(t){var e,n,i,a=t[0],r=t[1];return i=t[2]/360*2*Math.PI,e=r*Math.cos(i),n=r*Math.sin(i),[a,e,n]}function w(t){return M[t]}e.exports={rgb2hsl:i,rgb2hsv:a,rgb2hwb:o,rgb2cmyk:s,rgb2keyword:l,rgb2xyz:u,rgb2lab:d,rgb2lch:function(t){return x(d(t))},hsl2rgb:c,hsl2hsv:function(t){var e,n,i=t[0],a=t[1]/100,r=t[2]/100;return 0===r?[0,0,0]:(r*=2,a*=r<=1?r:2-r,n=(r+a)/2,e=2*a/(r+a),[i,100*e,100*n])},hsl2hwb:function(t){return o(c(t))},hsl2cmyk:function(t){return s(c(t))},hsl2keyword:function(t){return l(c(t))},hsv2rgb:h,hsv2hsl:function(t){var e,n,i=t[0],a=t[1]/100,r=t[2]/100;return n=(2-a)*r,e=a*r,e/=n<=1?n:2-n,e=e||0,n/=2,[i,100*e,100*n]},hsv2hwb:function(t){return o(h(t))},hsv2cmyk:function(t){return s(h(t))},hsv2keyword:function(t){return l(h(t))},hwb2rgb:f,hwb2hsl:function(t){return i(f(t))},hwb2hsv:function(t){return a(f(t))},hwb2cmyk:function(t){return s(f(t))},hwb2keyword:function(t){return l(f(t))},cmyk2rgb:m,cmyk2hsl:function(t){return i(m(t))},cmyk2hsv:function(t){return a(m(t))},cmyk2hwb:function(t){return o(m(t))},cmyk2keyword:function(t){return l(m(t))},keyword2rgb:w,keyword2hsl:function(t){return i(w(t))},keyword2hsv:function(t){return a(w(t))},keyword2hwb:function(t){return o(w(t))},keyword2cmyk:function(t){return s(w(t))},keyword2lab:function(t){return d(w(t))},keyword2xyz:function(t){return u(w(t))},xyz2rgb:p,xyz2lab:v,xyz2lch:function(t){return x(v(t))},lab2xyz:y,lab2rgb:_,lab2lch:x,lch2lab:k,lch2xyz:function(t){return y(k(t))},lch2rgb:function(t){return _(k(t))}};var M={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]},S={};for(var D in M)S[JSON.stringify(M[D])]=D},{}],4:[function(t,e,n){var i=t(3),a=function(){return new u};for(var r in i){a[r+"Raw"]=function(t){return function(e){return"number"==typeof e&&(e=Array.prototype.slice.call(arguments)),i[t](e)}}(r);var o=/(\w+)2(\w+)/.exec(r),s=o[1],l=o[2];(a[s]=a[s]||{})[l]=a[r]=function(t){return function(e){"number"==typeof e&&(e=Array.prototype.slice.call(arguments));var n=i[t](e);if("string"==typeof n||void 0===n)return n;for(var a=0;a<n.length;a++)n[a]=Math.round(n[a]);return n}}(r)}var u=function(){this.convs={}};u.prototype.routeSpace=function(t,e){var n=e[0];return void 0===n?this.getValues(t):("number"==typeof n&&(n=Array.prototype.slice.call(e)),this.setValues(t,n))},u.prototype.setValues=function(t,e){return this.space=t,this.convs={},this.convs[t]=e,this},u.prototype.getValues=function(t){var e=this.convs[t];if(!e){var n=this.space,i=this.convs[n];e=a[n][t](i),this.convs[t]=e}return e},["rgb","hsl","hsv","cmyk","keyword"].forEach(function(t){u.prototype[t]=function(e){return this.routeSpace(t,arguments)}}),e.exports=a},{3:3}],5:[function(t,e,n){"use strict";e.exports={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]}},{}],6:[function(t,e,n){!function(t,i){"object"==typeof n&&void 0!==e?e.exports=i():t.moment=i()}(this,function(){"use strict";function n(){return xe.apply(null,arguments)}function i(t){return t instanceof Array||"[object Array]"===Object.prototype.toString.call(t)}function a(t){return null!=t&&"[object Object]"===Object.prototype.toString.call(t)}function r(t){var e;for(e in t)return!1;return!0}function o(t){return void 0===t}function s(t){return"number"==typeof t||"[object Number]"===Object.prototype.toString.call(t)}function l(t){return t instanceof Date||"[object Date]"===Object.prototype.toString.call(t)}function u(t,e){var n,i=[];for(n=0;n<t.length;++n)i.push(e(t[n],n));return i}function d(t,e){return Object.prototype.hasOwnProperty.call(t,e)}function c(t,e){for(var n in e)d(e,n)&&(t[n]=e[n]);return d(e,"toString")&&(t.toString=e.toString),d(e,"valueOf")&&(t.valueOf=e.valueOf),t}function h(t,e,n,i){return Yt(t,e,n,i,!0).utc()}function f(){return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1,parsedDateParts:[],meridiem:null,rfc2822:!1,weekdayMismatch:!1}}function g(t){return null==t._pf&&(t._pf=f()),t._pf}function m(t){if(null==t._isValid){var e=g(t),n=ke.call(e.parsedDateParts,function(t){return null!=t}),i=!isNaN(t._d.getTime())&&e.overflow<0&&!e.empty&&!e.invalidMonth&&!e.invalidWeekday&&!e.nullInput&&!e.invalidFormat&&!e.userInvalidated&&(!e.meridiem||e.meridiem&&n);if(t._strict&&(i=i&&0===e.charsLeftOver&&0===e.unusedTokens.length&&void 0===e.bigHour),null!=Object.isFrozen&&Object.isFrozen(t))return i;t._isValid=i}return t._isValid}function p(t){var e=h(NaN);return null!=t?c(g(e),t):g(e).userInvalidated=!0,e}function v(t,e){var n,i,a;if(o(e._isAMomentObject)||(t._isAMomentObject=e._isAMomentObject),o(e._i)||(t._i=e._i),o(e._f)||(t._f=e._f),o(e._l)||(t._l=e._l),o(e._strict)||(t._strict=e._strict),o(e._tzm)||(t._tzm=e._tzm),o(e._isUTC)||(t._isUTC=e._isUTC),o(e._offset)||(t._offset=e._offset),o(e._pf)||(t._pf=g(e)),o(e._locale)||(t._locale=e._locale),we.length>0)for(n=0;n<we.length;n++)o(a=e[i=we[n]])||(t[i]=a);return t}function y(t){v(this,t),this._d=new Date(null!=t._d?t._d.getTime():NaN),this.isValid()||(this._d=new Date(NaN)),!1===Me&&(Me=!0,n.updateOffset(this),Me=!1)}function b(t){return t instanceof y||null!=t&&null!=t._isAMomentObject}function x(t){return t<0?Math.ceil(t)||0:Math.floor(t)}function _(t){var e=+t,n=0;return 0!==e&&isFinite(e)&&(n=x(e)),n}function k(t,e,n){var i,a=Math.min(t.length,e.length),r=Math.abs(t.length-e.length),o=0;for(i=0;i<a;i++)(n&&t[i]!==e[i]||!n&&_(t[i])!==_(e[i]))&&o++;return o+r}function w(t){!1===n.suppressDeprecationWarnings&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+t)}function M(t,e){var i=!0;return c(function(){if(null!=n.deprecationHandler&&n.deprecationHandler(null,t),i){for(var a,r=[],o=0;o<arguments.length;o++){if(a="","object"==typeof arguments[o]){a+="\n["+o+"] ";for(var s in arguments[0])a+=s+": "+arguments[0][s]+", ";a=a.slice(0,-2)}else a=arguments[o];r.push(a)}w(t+"\nArguments: "+Array.prototype.slice.call(r).join("")+"\n"+(new Error).stack),i=!1}return e.apply(this,arguments)},e)}function S(t,e){null!=n.deprecationHandler&&n.deprecationHandler(t,e),Se[t]||(w(e),Se[t]=!0)}function D(t){return t instanceof Function||"[object Function]"===Object.prototype.toString.call(t)}function C(t,e){var n,i=c({},t);for(n in e)d(e,n)&&(a(t[n])&&a(e[n])?(i[n]={},c(i[n],t[n]),c(i[n],e[n])):null!=e[n]?i[n]=e[n]:delete i[n]);for(n in t)d(t,n)&&!d(e,n)&&a(t[n])&&(i[n]=c({},i[n]));return i}function P(t){null!=t&&this.set(t)}function T(t,e){var n=t.toLowerCase();Fe[n]=Fe[n+"s"]=Fe[e]=t}function I(t){return"string"==typeof t?Fe[t]||Fe[t.toLowerCase()]:void 0}function A(t){var e,n,i={};for(n in t)d(t,n)&&(e=I(n))&&(i[e]=t[n]);return i}function O(t,e){Re[t]=e}function F(t){var e=[];for(var n in t)e.push({unit:n,priority:Re[n]});return e.sort(function(t,e){return t.priority-e.priority}),e}function R(t,e){return function(i){return null!=i?(W(this,t,i),n.updateOffset(this,e),this):L(this,t)}}function L(t,e){return t.isValid()?t._d["get"+(t._isUTC?"UTC":"")+e]():NaN}function W(t,e,n){t.isValid()&&t._d["set"+(t._isUTC?"UTC":"")+e](n)}function Y(t,e,n){var i=""+Math.abs(t),a=e-i.length;return(t>=0?n?"+":"":"-")+Math.pow(10,Math.max(0,a)).toString().substr(1)+i}function N(t,e,n,i){var a=i;"string"==typeof i&&(a=function(){return this[i]()}),t&&(Ne[t]=a),e&&(Ne[e[0]]=function(){return Y(a.apply(this,arguments),e[1],e[2])}),n&&(Ne[n]=function(){return this.localeData().ordinal(a.apply(this,arguments),t)})}function z(t){return t.match(/\[[\s\S]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"")}function B(t){var e,n,i=t.match(Le);for(e=0,n=i.length;e<n;e++)Ne[i[e]]?i[e]=Ne[i[e]]:i[e]=z(i[e]);return function(e){var a,r="";for(a=0;a<n;a++)r+=D(i[a])?i[a].call(e,t):i[a];return r}}function V(t,e){return t.isValid()?(e=H(e,t.localeData()),Ye[e]=Ye[e]||B(e),Ye[e](t)):t.localeData().invalidDate()}function H(t,e){var n=5;for(We.lastIndex=0;n>=0&&We.test(t);)t=t.replace(We,function(t){return e.longDateFormat(t)||t}),We.lastIndex=0,n-=1;return t}function E(t,e,n){nn[t]=D(e)?e:function(t,i){return t&&n?n:e}}function j(t,e){return d(nn,t)?nn[t](e._strict,e._locale):new RegExp(U(t))}function U(t){return q(t.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(t,e,n,i,a){return e||n||i||a}))}function q(t){return t.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function G(t,e){var n,i=e;for("string"==typeof t&&(t=[t]),s(e)&&(i=function(t,n){n[e]=_(t)}),n=0;n<t.length;n++)an[t[n]]=i}function Z(t,e){G(t,function(t,n,i,a){i._w=i._w||{},e(t,i._w,i,a)})}function X(t,e,n){null!=e&&d(an,t)&&an[t](e,n._a,n,t)}function J(t,e){return new Date(Date.UTC(t,e+1,0)).getUTCDate()}function K(t,e,n){var i,a,r,o=t.toLocaleLowerCase();if(!this._monthsParse)for(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[],i=0;i<12;++i)r=h([2e3,i]),this._shortMonthsParse[i]=this.monthsShort(r,"").toLocaleLowerCase(),this._longMonthsParse[i]=this.months(r,"").toLocaleLowerCase();return n?"MMM"===e?-1!==(a=gn.call(this._shortMonthsParse,o))?a:null:-1!==(a=gn.call(this._longMonthsParse,o))?a:null:"MMM"===e?-1!==(a=gn.call(this._shortMonthsParse,o))?a:-1!==(a=gn.call(this._longMonthsParse,o))?a:null:-1!==(a=gn.call(this._longMonthsParse,o))?a:-1!==(a=gn.call(this._shortMonthsParse,o))?a:null}function Q(t,e){var n;if(!t.isValid())return t;if("string"==typeof e)if(/^\d+$/.test(e))e=_(e);else if(e=t.localeData().monthsParse(e),!s(e))return t;return n=Math.min(t.date(),J(t.year(),e)),t._d["set"+(t._isUTC?"UTC":"")+"Month"](e,n),t}function $(t){return null!=t?(Q(this,t),n.updateOffset(this,!0),this):L(this,"Month")}function tt(){function t(t,e){return e.length-t.length}var e,n,i=[],a=[],r=[];for(e=0;e<12;e++)n=h([2e3,e]),i.push(this.monthsShort(n,"")),a.push(this.months(n,"")),r.push(this.months(n,"")),r.push(this.monthsShort(n,""));for(i.sort(t),a.sort(t),r.sort(t),e=0;e<12;e++)i[e]=q(i[e]),a[e]=q(a[e]);for(e=0;e<24;e++)r[e]=q(r[e]);this._monthsRegex=new RegExp("^("+r.join("|")+")","i"),this._monthsShortRegex=this._monthsRegex,this._monthsStrictRegex=new RegExp("^("+a.join("|")+")","i"),this._monthsShortStrictRegex=new RegExp("^("+i.join("|")+")","i")}function et(t){return nt(t)?366:365}function nt(t){return t%4==0&&t%100!=0||t%400==0}function it(t,e,n,i,a,r,o){var s=new Date(t,e,n,i,a,r,o);return t<100&&t>=0&&isFinite(s.getFullYear())&&s.setFullYear(t),s}function at(t){var e=new Date(Date.UTC.apply(null,arguments));return t<100&&t>=0&&isFinite(e.getUTCFullYear())&&e.setUTCFullYear(t),e}function rt(t,e,n){var i=7+e-n;return-((7+at(t,0,i).getUTCDay()-e)%7)+i-1}function ot(t,e,n,i,a){var r,o,s=1+7*(e-1)+(7+n-i)%7+rt(t,i,a);return s<=0?o=et(r=t-1)+s:s>et(t)?(r=t+1,o=s-et(t)):(r=t,o=s),{year:r,dayOfYear:o}}function st(t,e,n){var i,a,r=rt(t.year(),e,n),o=Math.floor((t.dayOfYear()-r-1)/7)+1;return o<1?i=o+lt(a=t.year()-1,e,n):o>lt(t.year(),e,n)?(i=o-lt(t.year(),e,n),a=t.year()+1):(a=t.year(),i=o),{week:i,year:a}}function lt(t,e,n){var i=rt(t,e,n),a=rt(t+1,e,n);return(et(t)-i+a)/7}function ut(t,e){return"string"!=typeof t?t:isNaN(t)?"number"==typeof(t=e.weekdaysParse(t))?t:null:parseInt(t,10)}function dt(t,e){return"string"==typeof t?e.weekdaysParse(t)%7||7:isNaN(t)?null:t}function ct(t,e,n){var i,a,r,o=t.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],i=0;i<7;++i)r=h([2e3,1]).day(i),this._minWeekdaysParse[i]=this.weekdaysMin(r,"").toLocaleLowerCase(),this._shortWeekdaysParse[i]=this.weekdaysShort(r,"").toLocaleLowerCase(),this._weekdaysParse[i]=this.weekdays(r,"").toLocaleLowerCase();return n?"dddd"===e?-1!==(a=gn.call(this._weekdaysParse,o))?a:null:"ddd"===e?-1!==(a=gn.call(this._shortWeekdaysParse,o))?a:null:-1!==(a=gn.call(this._minWeekdaysParse,o))?a:null:"dddd"===e?-1!==(a=gn.call(this._weekdaysParse,o))?a:-1!==(a=gn.call(this._shortWeekdaysParse,o))?a:-1!==(a=gn.call(this._minWeekdaysParse,o))?a:null:"ddd"===e?-1!==(a=gn.call(this._shortWeekdaysParse,o))?a:-1!==(a=gn.call(this._weekdaysParse,o))?a:-1!==(a=gn.call(this._minWeekdaysParse,o))?a:null:-1!==(a=gn.call(this._minWeekdaysParse,o))?a:-1!==(a=gn.call(this._weekdaysParse,o))?a:-1!==(a=gn.call(this._shortWeekdaysParse,o))?a:null}function ht(){function t(t,e){return e.length-t.length}var e,n,i,a,r,o=[],s=[],l=[],u=[];for(e=0;e<7;e++)n=h([2e3,1]).day(e),i=this.weekdaysMin(n,""),a=this.weekdaysShort(n,""),r=this.weekdays(n,""),o.push(i),s.push(a),l.push(r),u.push(i),u.push(a),u.push(r);for(o.sort(t),s.sort(t),l.sort(t),u.sort(t),e=0;e<7;e++)s[e]=q(s[e]),l[e]=q(l[e]),u[e]=q(u[e]);this._weekdaysRegex=new RegExp("^("+u.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+l.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+s.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+o.join("|")+")","i")}function ft(){return this.hours()%12||12}function gt(t,e){N(t,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),e)})}function mt(t,e){return e._meridiemParse}function pt(t){return t?t.toLowerCase().replace("_","-"):t}function vt(t){for(var e,n,i,a,r=0;r<t.length;){for(e=(a=pt(t[r]).split("-")).length,n=(n=pt(t[r+1]))?n.split("-"):null;e>0;){if(i=yt(a.slice(0,e).join("-")))return i;if(n&&n.length>=e&&k(a,n,!0)>=e-1)break;e--}r++}return null}function yt(n){var i=null;if(!On[n]&&void 0!==e&&e&&e.exports)try{i=Pn._abbr,t("./locale/"+n),bt(i)}catch(t){}return On[n]}function bt(t,e){var n;return t&&(n=o(e)?_t(t):xt(t,e))&&(Pn=n),Pn._abbr}function xt(t,e){if(null!==e){var n=An;if(e.abbr=t,null!=On[t])S("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),n=On[t]._config;else if(null!=e.parentLocale){if(null==On[e.parentLocale])return Fn[e.parentLocale]||(Fn[e.parentLocale]=[]),Fn[e.parentLocale].push({name:t,config:e}),null;n=On[e.parentLocale]._config}return On[t]=new P(C(n,e)),Fn[t]&&Fn[t].forEach(function(t){xt(t.name,t.config)}),bt(t),On[t]}return delete On[t],null}function _t(t){var e;if(t&&t._locale&&t._locale._abbr&&(t=t._locale._abbr),!t)return Pn;if(!i(t)){if(e=yt(t))return e;t=[t]}return vt(t)}function kt(t){var e,n=t._a;return n&&-2===g(t).overflow&&(e=n[on]<0||n[on]>11?on:n[sn]<1||n[sn]>J(n[rn],n[on])?sn:n[ln]<0||n[ln]>24||24===n[ln]&&(0!==n[un]||0!==n[dn]||0!==n[cn])?ln:n[un]<0||n[un]>59?un:n[dn]<0||n[dn]>59?dn:n[cn]<0||n[cn]>999?cn:-1,g(t)._overflowDayOfYear&&(e<rn||e>sn)&&(e=sn),g(t)._overflowWeeks&&-1===e&&(e=hn),g(t)._overflowWeekday&&-1===e&&(e=fn),g(t).overflow=e),t}function wt(t){var e,n,i,a,r,o,s=t._i,l=Rn.exec(s)||Ln.exec(s);if(l){for(g(t).iso=!0,e=0,n=Yn.length;e<n;e++)if(Yn[e][1].exec(l[1])){a=Yn[e][0],i=!1!==Yn[e][2];break}if(null==a)return void(t._isValid=!1);if(l[3]){for(e=0,n=Nn.length;e<n;e++)if(Nn[e][1].exec(l[3])){r=(l[2]||" ")+Nn[e][0];break}if(null==r)return void(t._isValid=!1)}if(!i&&null!=r)return void(t._isValid=!1);if(l[4]){if(!Wn.exec(l[4]))return void(t._isValid=!1);o="Z"}t._f=a+(r||"")+(o||""),It(t)}else t._isValid=!1}function Mt(t){var e,n,i,a,r,o,s,l,u={" GMT":" +0000"," EDT":" -0400"," EST":" -0500"," CDT":" -0500"," CST":" -0600"," MDT":" -0600"," MST":" -0700"," PDT":" -0700"," PST":" -0800"};if(e=t._i.replace(/\([^\)]*\)|[\n\t]/g," ").replace(/(\s\s+)/g," ").replace(/^\s|\s$/g,""),n=Bn.exec(e)){if(i=n[1]?"ddd"+(5===n[1].length?", ":" "):"",a="D MMM "+(n[2].length>10?"YYYY ":"YY "),r="HH:mm"+(n[4]?":ss":""),n[1]){var d=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"][new Date(n[2]).getDay()];if(n[1].substr(0,3)!==d)return g(t).weekdayMismatch=!0,void(t._isValid=!1)}switch(n[5].length){case 2:s=0===l?" +0000":((l="YXWVUTSRQPONZABCDEFGHIKLM".indexOf(n[5][1].toUpperCase())-12)<0?" -":" +")+(""+l).replace(/^-?/,"0").match(/..$/)[0]+"00";break;case 4:s=u[n[5]];break;default:s=u[" GMT"]}n[5]=s,t._i=n.splice(1).join(""),o=" ZZ",t._f=i+a+r+o,It(t),g(t).rfc2822=!0}else t._isValid=!1}function St(t){var e=zn.exec(t._i);null===e?(wt(t),!1===t._isValid&&(delete t._isValid,Mt(t),!1===t._isValid&&(delete t._isValid,n.createFromInputFallback(t)))):t._d=new Date(+e[1])}function Dt(t,e,n){return null!=t?t:null!=e?e:n}function Ct(t){var e=new Date(n.now());return t._useUTC?[e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()]:[e.getFullYear(),e.getMonth(),e.getDate()]}function Pt(t){var e,n,i,a,r=[];if(!t._d){for(i=Ct(t),t._w&&null==t._a[sn]&&null==t._a[on]&&Tt(t),null!=t._dayOfYear&&(a=Dt(t._a[rn],i[rn]),(t._dayOfYear>et(a)||0===t._dayOfYear)&&(g(t)._overflowDayOfYear=!0),n=at(a,0,t._dayOfYear),t._a[on]=n.getUTCMonth(),t._a[sn]=n.getUTCDate()),e=0;e<3&&null==t._a[e];++e)t._a[e]=r[e]=i[e];for(;e<7;e++)t._a[e]=r[e]=null==t._a[e]?2===e?1:0:t._a[e];24===t._a[ln]&&0===t._a[un]&&0===t._a[dn]&&0===t._a[cn]&&(t._nextDay=!0,t._a[ln]=0),t._d=(t._useUTC?at:it).apply(null,r),null!=t._tzm&&t._d.setUTCMinutes(t._d.getUTCMinutes()-t._tzm),t._nextDay&&(t._a[ln]=24)}}function Tt(t){var e,n,i,a,r,o,s,l;if(null!=(e=t._w).GG||null!=e.W||null!=e.E)r=1,o=4,n=Dt(e.GG,t._a[rn],st(Nt(),1,4).year),i=Dt(e.W,1),((a=Dt(e.E,1))<1||a>7)&&(l=!0);else{r=t._locale._week.dow,o=t._locale._week.doy;var u=st(Nt(),r,o);n=Dt(e.gg,t._a[rn],u.year),i=Dt(e.w,u.week),null!=e.d?((a=e.d)<0||a>6)&&(l=!0):null!=e.e?(a=e.e+r,(e.e<0||e.e>6)&&(l=!0)):a=r}i<1||i>lt(n,r,o)?g(t)._overflowWeeks=!0:null!=l?g(t)._overflowWeekday=!0:(s=ot(n,i,a,r,o),t._a[rn]=s.year,t._dayOfYear=s.dayOfYear)}function It(t){if(t._f!==n.ISO_8601)if(t._f!==n.RFC_2822){t._a=[],g(t).empty=!0;var e,i,a,r,o,s=""+t._i,l=s.length,u=0;for(a=H(t._f,t._locale).match(Le)||[],e=0;e<a.length;e++)r=a[e],(i=(s.match(j(r,t))||[])[0])&&((o=s.substr(0,s.indexOf(i))).length>0&&g(t).unusedInput.push(o),s=s.slice(s.indexOf(i)+i.length),u+=i.length),Ne[r]?(i?g(t).empty=!1:g(t).unusedTokens.push(r),X(r,i,t)):t._strict&&!i&&g(t).unusedTokens.push(r);g(t).charsLeftOver=l-u,s.length>0&&g(t).unusedInput.push(s),t._a[ln]<=12&&!0===g(t).bigHour&&t._a[ln]>0&&(g(t).bigHour=void 0),g(t).parsedDateParts=t._a.slice(0),g(t).meridiem=t._meridiem,t._a[ln]=At(t._locale,t._a[ln],t._meridiem),Pt(t),kt(t)}else Mt(t);else wt(t)}function At(t,e,n){var i;return null==n?e:null!=t.meridiemHour?t.meridiemHour(e,n):null!=t.isPM?((i=t.isPM(n))&&e<12&&(e+=12),i||12!==e||(e=0),e):e}function Ot(t){var e,n,i,a,r;if(0===t._f.length)return g(t).invalidFormat=!0,void(t._d=new Date(NaN));for(a=0;a<t._f.length;a++)r=0,e=v({},t),null!=t._useUTC&&(e._useUTC=t._useUTC),e._f=t._f[a],It(e),m(e)&&(r+=g(e).charsLeftOver,r+=10*g(e).unusedTokens.length,g(e).score=r,(null==i||r<i)&&(i=r,n=e));c(t,n||e)}function Ft(t){if(!t._d){var e=A(t._i);t._a=u([e.year,e.month,e.day||e.date,e.hour,e.minute,e.second,e.millisecond],function(t){return t&&parseInt(t,10)}),Pt(t)}}function Rt(t){var e=new y(kt(Lt(t)));return e._nextDay&&(e.add(1,"d"),e._nextDay=void 0),e}function Lt(t){var e=t._i,n=t._f;return t._locale=t._locale||_t(t._l),null===e||void 0===n&&""===e?p({nullInput:!0}):("string"==typeof e&&(t._i=e=t._locale.preparse(e)),b(e)?new y(kt(e)):(l(e)?t._d=e:i(n)?Ot(t):n?It(t):Wt(t),m(t)||(t._d=null),t))}function Wt(t){var e=t._i;o(e)?t._d=new Date(n.now()):l(e)?t._d=new Date(e.valueOf()):"string"==typeof e?St(t):i(e)?(t._a=u(e.slice(0),function(t){return parseInt(t,10)}),Pt(t)):a(e)?Ft(t):s(e)?t._d=new Date(e):n.createFromInputFallback(t)}function Yt(t,e,n,o,s){var l={};return!0!==n&&!1!==n||(o=n,n=void 0),(a(t)&&r(t)||i(t)&&0===t.length)&&(t=void 0),l._isAMomentObject=!0,l._useUTC=l._isUTC=s,l._l=n,l._i=t,l._f=e,l._strict=o,Rt(l)}function Nt(t,e,n,i){return Yt(t,e,n,i,!1)}function zt(t,e){var n,a;if(1===e.length&&i(e[0])&&(e=e[0]),!e.length)return Nt();for(n=e[0],a=1;a<e.length;++a)e[a].isValid()&&!e[a][t](n)||(n=e[a]);return n}function Bt(t){for(var e in t)if(-1===En.indexOf(e)||null!=t[e]&&isNaN(t[e]))return!1;for(var n=!1,i=0;i<En.length;++i)if(t[En[i]]){if(n)return!1;parseFloat(t[En[i]])!==_(t[En[i]])&&(n=!0)}return!0}function Vt(t){var e=A(t),n=e.year||0,i=e.quarter||0,a=e.month||0,r=e.week||0,o=e.day||0,s=e.hour||0,l=e.minute||0,u=e.second||0,d=e.millisecond||0;this._isValid=Bt(e),this._milliseconds=+d+1e3*u+6e4*l+1e3*s*60*60,this._days=+o+7*r,this._months=+a+3*i+12*n,this._data={},this._locale=_t(),this._bubble()}function Ht(t){return t instanceof Vt}function Et(t){return t<0?-1*Math.round(-1*t):Math.round(t)}function jt(t,e){N(t,0,0,function(){var t=this.utcOffset(),n="+";return t<0&&(t=-t,n="-"),n+Y(~~(t/60),2)+e+Y(~~t%60,2)})}function Ut(t,e){var n=(e||"").match(t);if(null===n)return null;var i=((n[n.length-1]||[])+"").match(jn)||["-",0,0],a=60*i[1]+_(i[2]);return 0===a?0:"+"===i[0]?a:-a}function qt(t,e){var i,a;return e._isUTC?(i=e.clone(),a=(b(t)||l(t)?t.valueOf():Nt(t).valueOf())-i.valueOf(),i._d.setTime(i._d.valueOf()+a),n.updateOffset(i,!1),i):Nt(t).local()}function Gt(t){return 15*-Math.round(t._d.getTimezoneOffset()/15)}function Zt(){return!!this.isValid()&&(this._isUTC&&0===this._offset)}function Xt(t,e){var n,i,a,r=t,o=null;return Ht(t)?r={ms:t._milliseconds,d:t._days,M:t._months}:s(t)?(r={},e?r[e]=t:r.milliseconds=t):(o=Un.exec(t))?(n="-"===o[1]?-1:1,r={y:0,d:_(o[sn])*n,h:_(o[ln])*n,m:_(o[un])*n,s:_(o[dn])*n,ms:_(Et(1e3*o[cn]))*n}):(o=qn.exec(t))?(n="-"===o[1]?-1:1,r={y:Jt(o[2],n),M:Jt(o[3],n),w:Jt(o[4],n),d:Jt(o[5],n),h:Jt(o[6],n),m:Jt(o[7],n),s:Jt(o[8],n)}):null==r?r={}:"object"==typeof r&&("from"in r||"to"in r)&&(a=Qt(Nt(r.from),Nt(r.to)),(r={}).ms=a.milliseconds,r.M=a.months),i=new Vt(r),Ht(t)&&d(t,"_locale")&&(i._locale=t._locale),i}function Jt(t,e){var n=t&&parseFloat(t.replace(",","."));return(isNaN(n)?0:n)*e}function Kt(t,e){var n={milliseconds:0,months:0};return n.months=e.month()-t.month()+12*(e.year()-t.year()),t.clone().add(n.months,"M").isAfter(e)&&--n.months,n.milliseconds=+e-+t.clone().add(n.months,"M"),n}function Qt(t,e){var n;return t.isValid()&&e.isValid()?(e=qt(e,t),t.isBefore(e)?n=Kt(t,e):((n=Kt(e,t)).milliseconds=-n.milliseconds,n.months=-n.months),n):{milliseconds:0,months:0}}function $t(t,e){return function(n,i){var a,r;return null===i||isNaN(+i)||(S(e,"moment()."+e+"(period, number) is deprecated. Please use moment()."+e+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),r=n,n=i,i=r),n="string"==typeof n?+n:n,a=Xt(n,i),te(this,a,t),this}}function te(t,e,i,a){var r=e._milliseconds,o=Et(e._days),s=Et(e._months);t.isValid()&&(a=null==a||a,r&&t._d.setTime(t._d.valueOf()+r*i),o&&W(t,"Date",L(t,"Date")+o*i),s&&Q(t,L(t,"Month")+s*i),a&&n.updateOffset(t,o||s))}function ee(t,e){var n,i=12*(e.year()-t.year())+(e.month()-t.month()),a=t.clone().add(i,"months");return n=e-a<0?(e-a)/(a-t.clone().add(i-1,"months")):(e-a)/(t.clone().add(i+1,"months")-a),-(i+n)||0}function ne(t){var e;return void 0===t?this._locale._abbr:(null!=(e=_t(t))&&(this._locale=e),this)}function ie(){return this._locale}function ae(t,e){N(0,[t,t.length],0,e)}function re(t,e,n,i,a){var r;return null==t?st(this,i,a).year:(r=lt(t,i,a),e>r&&(e=r),oe.call(this,t,e,n,i,a))}function oe(t,e,n,i,a){var r=ot(t,e,n,i,a),o=at(r.year,0,r.dayOfYear);return this.year(o.getUTCFullYear()),this.month(o.getUTCMonth()),this.date(o.getUTCDate()),this}function se(t){return t}function le(t,e,n,i){var a=_t(),r=h().set(i,e);return a[n](r,t)}function ue(t,e,n){if(s(t)&&(e=t,t=void 0),t=t||"",null!=e)return le(t,e,n,"month");var i,a=[];for(i=0;i<12;i++)a[i]=le(t,i,n,"month");return a}function de(t,e,n,i){"boolean"==typeof t?(s(e)&&(n=e,e=void 0),e=e||""):(n=e=t,t=!1,s(e)&&(n=e,e=void 0),e=e||"");var a=_t(),r=t?a._week.dow:0;if(null!=n)return le(e,(n+r)%7,i,"day");var o,l=[];for(o=0;o<7;o++)l[o]=le(e,(o+r)%7,i,"day");return l}function ce(t,e,n,i){var a=Xt(e,n);return t._milliseconds+=i*a._milliseconds,t._days+=i*a._days,t._months+=i*a._months,t._bubble()}function he(t){return t<0?Math.floor(t):Math.ceil(t)}function fe(t){return 4800*t/146097}function ge(t){return 146097*t/4800}function me(t){return function(){return this.as(t)}}function pe(t){return function(){return this.isValid()?this._data[t]:NaN}}function ve(t,e,n,i,a){return a.relativeTime(e||1,!!n,t,i)}function ye(t,e,n){var i=Xt(t).abs(),a=bi(i.as("s")),r=bi(i.as("m")),o=bi(i.as("h")),s=bi(i.as("d")),l=bi(i.as("M")),u=bi(i.as("y")),d=a<=xi.ss&&["s",a]||a<xi.s&&["ss",a]||r<=1&&["m"]||r<xi.m&&["mm",r]||o<=1&&["h"]||o<xi.h&&["hh",o]||s<=1&&["d"]||s<xi.d&&["dd",s]||l<=1&&["M"]||l<xi.M&&["MM",l]||u<=1&&["y"]||["yy",u];return d[2]=e,d[3]=+t>0,d[4]=n,ve.apply(null,d)}function be(){if(!this.isValid())return this.localeData().invalidDate();var t,e,n,i=_i(this._milliseconds)/1e3,a=_i(this._days),r=_i(this._months);e=x((t=x(i/60))/60),i%=60,t%=60;var o=n=x(r/12),s=r%=12,l=a,u=e,d=t,c=i,h=this.asSeconds();return h?(h<0?"-":"")+"P"+(o?o+"Y":"")+(s?s+"M":"")+(l?l+"D":"")+(u||d||c?"T":"")+(u?u+"H":"")+(d?d+"M":"")+(c?c+"S":""):"P0D"}var xe,_e,ke=_e=Array.prototype.some?Array.prototype.some:function(t){for(var e=Object(this),n=e.length>>>0,i=0;i<n;i++)if(i in e&&t.call(this,e[i],i,e))return!0;return!1},we=n.momentProperties=[],Me=!1,Se={};n.suppressDeprecationWarnings=!1,n.deprecationHandler=null;var De,Ce,Pe=De=Object.keys?Object.keys:function(t){var e,n=[];for(e in t)d(t,e)&&n.push(e);return n},Te={sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},Ie={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},Ae=/\d{1,2}/,Oe={future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},Fe={},Re={},Le=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,We=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,Ye={},Ne={},ze=/\d/,Be=/\d\d/,Ve=/\d{3}/,He=/\d{4}/,Ee=/[+-]?\d{6}/,je=/\d\d?/,Ue=/\d\d\d\d?/,qe=/\d\d\d\d\d\d?/,Ge=/\d{1,3}/,Ze=/\d{1,4}/,Xe=/[+-]?\d{1,6}/,Je=/\d+/,Ke=/[+-]?\d+/,Qe=/Z|[+-]\d\d:?\d\d/gi,$e=/Z|[+-]\d\d(?::?\d\d)?/gi,tn=/[+-]?\d+(\.\d{1,3})?/,en=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,nn={},an={},rn=0,on=1,sn=2,ln=3,un=4,dn=5,cn=6,hn=7,fn=8,gn=Ce=Array.prototype.indexOf?Array.prototype.indexOf:function(t){var e;for(e=0;e<this.length;++e)if(this[e]===t)return e;return-1};N("M",["MM",2],"Mo",function(){return this.month()+1}),N("MMM",0,0,function(t){return this.localeData().monthsShort(this,t)}),N("MMMM",0,0,function(t){return this.localeData().months(this,t)}),T("month","M"),O("month",8),E("M",je),E("MM",je,Be),E("MMM",function(t,e){return e.monthsShortRegex(t)}),E("MMMM",function(t,e){return e.monthsRegex(t)}),G(["M","MM"],function(t,e){e[on]=_(t)-1}),G(["MMM","MMMM"],function(t,e,n,i){var a=n._locale.monthsParse(t,i,n._strict);null!=a?e[on]=a:g(n).invalidMonth=t});var mn=/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/,pn="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),vn="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),yn=en,bn=en;N("Y",0,0,function(){var t=this.year();return t<=9999?""+t:"+"+t}),N(0,["YY",2],0,function(){return this.year()%100}),N(0,["YYYY",4],0,"year"),N(0,["YYYYY",5],0,"year"),N(0,["YYYYYY",6,!0],0,"year"),T("year","y"),O("year",1),E("Y",Ke),E("YY",je,Be),E("YYYY",Ze,He),E("YYYYY",Xe,Ee),E("YYYYYY",Xe,Ee),G(["YYYYY","YYYYYY"],rn),G("YYYY",function(t,e){e[rn]=2===t.length?n.parseTwoDigitYear(t):_(t)}),G("YY",function(t,e){e[rn]=n.parseTwoDigitYear(t)}),G("Y",function(t,e){e[rn]=parseInt(t,10)}),n.parseTwoDigitYear=function(t){return _(t)+(_(t)>68?1900:2e3)};var xn=R("FullYear",!0);N("w",["ww",2],"wo","week"),N("W",["WW",2],"Wo","isoWeek"),T("week","w"),T("isoWeek","W"),O("week",5),O("isoWeek",5),E("w",je),E("ww",je,Be),E("W",je),E("WW",je,Be),Z(["w","ww","W","WW"],function(t,e,n,i){e[i.substr(0,1)]=_(t)});var _n={dow:0,doy:6};N("d",0,"do","day"),N("dd",0,0,function(t){return this.localeData().weekdaysMin(this,t)}),N("ddd",0,0,function(t){return this.localeData().weekdaysShort(this,t)}),N("dddd",0,0,function(t){return this.localeData().weekdays(this,t)}),N("e",0,0,"weekday"),N("E",0,0,"isoWeekday"),T("day","d"),T("weekday","e"),T("isoWeekday","E"),O("day",11),O("weekday",11),O("isoWeekday",11),E("d",je),E("e",je),E("E",je),E("dd",function(t,e){return e.weekdaysMinRegex(t)}),E("ddd",function(t,e){return e.weekdaysShortRegex(t)}),E("dddd",function(t,e){return e.weekdaysRegex(t)}),Z(["dd","ddd","dddd"],function(t,e,n,i){var a=n._locale.weekdaysParse(t,i,n._strict);null!=a?e.d=a:g(n).invalidWeekday=t}),Z(["d","e","E"],function(t,e,n,i){e[i]=_(t)});var kn="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),wn="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),Mn="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),Sn=en,Dn=en,Cn=en;N("H",["HH",2],0,"hour"),N("h",["hh",2],0,ft),N("k",["kk",2],0,function(){return this.hours()||24}),N("hmm",0,0,function(){return""+ft.apply(this)+Y(this.minutes(),2)}),N("hmmss",0,0,function(){return""+ft.apply(this)+Y(this.minutes(),2)+Y(this.seconds(),2)}),N("Hmm",0,0,function(){return""+this.hours()+Y(this.minutes(),2)}),N("Hmmss",0,0,function(){return""+this.hours()+Y(this.minutes(),2)+Y(this.seconds(),2)}),gt("a",!0),gt("A",!1),T("hour","h"),O("hour",13),E("a",mt),E("A",mt),E("H",je),E("h",je),E("k",je),E("HH",je,Be),E("hh",je,Be),E("kk",je,Be),E("hmm",Ue),E("hmmss",qe),E("Hmm",Ue),E("Hmmss",qe),G(["H","HH"],ln),G(["k","kk"],function(t,e,n){var i=_(t);e[ln]=24===i?0:i}),G(["a","A"],function(t,e,n){n._isPm=n._locale.isPM(t),n._meridiem=t}),G(["h","hh"],function(t,e,n){e[ln]=_(t),g(n).bigHour=!0}),G("hmm",function(t,e,n){var i=t.length-2;e[ln]=_(t.substr(0,i)),e[un]=_(t.substr(i)),g(n).bigHour=!0}),G("hmmss",function(t,e,n){var i=t.length-4,a=t.length-2;e[ln]=_(t.substr(0,i)),e[un]=_(t.substr(i,2)),e[dn]=_(t.substr(a)),g(n).bigHour=!0}),G("Hmm",function(t,e,n){var i=t.length-2;e[ln]=_(t.substr(0,i)),e[un]=_(t.substr(i))}),G("Hmmss",function(t,e,n){var i=t.length-4,a=t.length-2;e[ln]=_(t.substr(0,i)),e[un]=_(t.substr(i,2)),e[dn]=_(t.substr(a))});var Pn,Tn=/[ap]\.?m?\.?/i,In=R("Hours",!0),An={calendar:Te,longDateFormat:Ie,invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:Ae,relativeTime:Oe,months:pn,monthsShort:vn,week:_n,weekdays:kn,weekdaysMin:Mn,weekdaysShort:wn,meridiemParse:Tn},On={},Fn={},Rn=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,Ln=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,Wn=/Z|[+-]\d\d(?::?\d\d)?/,Yn=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],Nn=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],zn=/^\/?Date\((\-?\d+)/i,Bn=/^((?:Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d?\d\s(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(?:\d\d)?\d\d\s)(\d\d:\d\d)(\:\d\d)?(\s(?:UT|GMT|[ECMP][SD]T|[A-IK-Za-ik-z]|[+-]\d{4}))$/;n.createFromInputFallback=M("value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.",function(t){t._d=new Date(t._i+(t._useUTC?" UTC":""))}),n.ISO_8601=function(){},n.RFC_2822=function(){};var Vn=M("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var t=Nt.apply(null,arguments);return this.isValid()&&t.isValid()?t<this?this:t:p()}),Hn=M("moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var t=Nt.apply(null,arguments);return this.isValid()&&t.isValid()?t>this?this:t:p()}),En=["year","quarter","month","week","day","hour","minute","second","millisecond"];jt("Z",":"),jt("ZZ",""),E("Z",$e),E("ZZ",$e),G(["Z","ZZ"],function(t,e,n){n._useUTC=!0,n._tzm=Ut($e,t)});var jn=/([\+\-]|\d\d)/gi;n.updateOffset=function(){};var Un=/^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/,qn=/^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/;Xt.fn=Vt.prototype,Xt.invalid=function(){return Xt(NaN)};var Gn=$t(1,"add"),Zn=$t(-1,"subtract");n.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",n.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var Xn=M("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(t){return void 0===t?this.localeData():this.locale(t)});N(0,["gg",2],0,function(){return this.weekYear()%100}),N(0,["GG",2],0,function(){return this.isoWeekYear()%100}),ae("gggg","weekYear"),ae("ggggg","weekYear"),ae("GGGG","isoWeekYear"),ae("GGGGG","isoWeekYear"),T("weekYear","gg"),T("isoWeekYear","GG"),O("weekYear",1),O("isoWeekYear",1),E("G",Ke),E("g",Ke),E("GG",je,Be),E("gg",je,Be),E("GGGG",Ze,He),E("gggg",Ze,He),E("GGGGG",Xe,Ee),E("ggggg",Xe,Ee),Z(["gggg","ggggg","GGGG","GGGGG"],function(t,e,n,i){e[i.substr(0,2)]=_(t)}),Z(["gg","GG"],function(t,e,i,a){e[a]=n.parseTwoDigitYear(t)}),N("Q",0,"Qo","quarter"),T("quarter","Q"),O("quarter",7),E("Q",ze),G("Q",function(t,e){e[on]=3*(_(t)-1)}),N("D",["DD",2],"Do","date"),T("date","D"),O("date",9),E("D",je),E("DD",je,Be),E("Do",function(t,e){return t?e._dayOfMonthOrdinalParse||e._ordinalParse:e._dayOfMonthOrdinalParseLenient}),G(["D","DD"],sn),G("Do",function(t,e){e[sn]=_(t.match(je)[0],10)});var Jn=R("Date",!0);N("DDD",["DDDD",3],"DDDo","dayOfYear"),T("dayOfYear","DDD"),O("dayOfYear",4),E("DDD",Ge),E("DDDD",Ve),G(["DDD","DDDD"],function(t,e,n){n._dayOfYear=_(t)}),N("m",["mm",2],0,"minute"),T("minute","m"),O("minute",14),E("m",je),E("mm",je,Be),G(["m","mm"],un);var Kn=R("Minutes",!1);N("s",["ss",2],0,"second"),T("second","s"),O("second",15),E("s",je),E("ss",je,Be),G(["s","ss"],dn);var Qn=R("Seconds",!1);N("S",0,0,function(){return~~(this.millisecond()/100)}),N(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),N(0,["SSS",3],0,"millisecond"),N(0,["SSSS",4],0,function(){return 10*this.millisecond()}),N(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),N(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),N(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),N(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),N(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),T("millisecond","ms"),O("millisecond",16),E("S",Ge,ze),E("SS",Ge,Be),E("SSS",Ge,Ve);var $n;for($n="SSSS";$n.length<=9;$n+="S")E($n,Je);for($n="S";$n.length<=9;$n+="S")G($n,function(t,e){e[cn]=_(1e3*("0."+t))});var ti=R("Milliseconds",!1);N("z",0,0,"zoneAbbr"),N("zz",0,0,"zoneName");var ei=y.prototype;ei.add=Gn,ei.calendar=function(t,e){var i=t||Nt(),a=qt(i,this).startOf("day"),r=n.calendarFormat(this,a)||"sameElse",o=e&&(D(e[r])?e[r].call(this,i):e[r]);return this.format(o||this.localeData().calendar(r,this,Nt(i)))},ei.clone=function(){return new y(this)},ei.diff=function(t,e,n){var i,a,r,o;return this.isValid()&&(i=qt(t,this)).isValid()?(a=6e4*(i.utcOffset()-this.utcOffset()),"year"===(e=I(e))||"month"===e||"quarter"===e?(o=ee(this,i),"quarter"===e?o/=3:"year"===e&&(o/=12)):(r=this-i,o="second"===e?r/1e3:"minute"===e?r/6e4:"hour"===e?r/36e5:"day"===e?(r-a)/864e5:"week"===e?(r-a)/6048e5:r),n?o:x(o)):NaN},ei.endOf=function(t){return void 0===(t=I(t))||"millisecond"===t?this:("date"===t&&(t="day"),this.startOf(t).add(1,"isoWeek"===t?"week":t).subtract(1,"ms"))},ei.format=function(t){t||(t=this.isUtc()?n.defaultFormatUtc:n.defaultFormat);var e=V(this,t);return this.localeData().postformat(e)},ei.from=function(t,e){return this.isValid()&&(b(t)&&t.isValid()||Nt(t).isValid())?Xt({to:this,from:t}).locale(this.locale()).humanize(!e):this.localeData().invalidDate()},ei.fromNow=function(t){return this.from(Nt(),t)},ei.to=function(t,e){return this.isValid()&&(b(t)&&t.isValid()||Nt(t).isValid())?Xt({from:this,to:t}).locale(this.locale()).humanize(!e):this.localeData().invalidDate()},ei.toNow=function(t){return this.to(Nt(),t)},ei.get=function(t){return t=I(t),D(this[t])?this[t]():this},ei.invalidAt=function(){return g(this).overflow},ei.isAfter=function(t,e){var n=b(t)?t:Nt(t);return!(!this.isValid()||!n.isValid())&&("millisecond"===(e=I(o(e)?"millisecond":e))?this.valueOf()>n.valueOf():n.valueOf()<this.clone().startOf(e).valueOf())},ei.isBefore=function(t,e){var n=b(t)?t:Nt(t);return!(!this.isValid()||!n.isValid())&&("millisecond"===(e=I(o(e)?"millisecond":e))?this.valueOf()<n.valueOf():this.clone().endOf(e).valueOf()<n.valueOf())},ei.isBetween=function(t,e,n,i){return("("===(i=i||"()")[0]?this.isAfter(t,n):!this.isBefore(t,n))&&(")"===i[1]?this.isBefore(e,n):!this.isAfter(e,n))},ei.isSame=function(t,e){var n,i=b(t)?t:Nt(t);return!(!this.isValid()||!i.isValid())&&("millisecond"===(e=I(e||"millisecond"))?this.valueOf()===i.valueOf():(n=i.valueOf(),this.clone().startOf(e).valueOf()<=n&&n<=this.clone().endOf(e).valueOf()))},ei.isSameOrAfter=function(t,e){return this.isSame(t,e)||this.isAfter(t,e)},ei.isSameOrBefore=function(t,e){return this.isSame(t,e)||this.isBefore(t,e)},ei.isValid=function(){return m(this)},ei.lang=Xn,ei.locale=ne,ei.localeData=ie,ei.max=Hn,ei.min=Vn,ei.parsingFlags=function(){return c({},g(this))},ei.set=function(t,e){if("object"==typeof t)for(var n=F(t=A(t)),i=0;i<n.length;i++)this[n[i].unit](t[n[i].unit]);else if(t=I(t),D(this[t]))return this[t](e);return this},ei.startOf=function(t){switch(t=I(t)){case"year":this.month(0);case"quarter":case"month":this.date(1);case"week":case"isoWeek":case"day":case"date":this.hours(0);case"hour":this.minutes(0);case"minute":this.seconds(0);case"second":this.milliseconds(0)}return"week"===t&&this.weekday(0),"isoWeek"===t&&this.isoWeekday(1),"quarter"===t&&this.month(3*Math.floor(this.month()/3)),this},ei.subtract=Zn,ei.toArray=function(){var t=this;return[t.year(),t.month(),t.date(),t.hour(),t.minute(),t.second(),t.millisecond()]},ei.toObject=function(){var t=this;return{years:t.year(),months:t.month(),date:t.date(),hours:t.hours(),minutes:t.minutes(),seconds:t.seconds(),milliseconds:t.milliseconds()}},ei.toDate=function(){return new Date(this.valueOf())},ei.toISOString=function(){if(!this.isValid())return null;var t=this.clone().utc();return t.year()<0||t.year()>9999?V(t,"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]"):D(Date.prototype.toISOString)?this.toDate().toISOString():V(t,"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]")},ei.inspect=function(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var t="moment",e="";this.isLocal()||(t=0===this.utcOffset()?"moment.utc":"moment.parseZone",e="Z");var n="["+t+'("]',i=0<=this.year()&&this.year()<=9999?"YYYY":"YYYYYY",a=e+'[")]';return this.format(n+i+"-MM-DD[T]HH:mm:ss.SSS"+a)},ei.toJSON=function(){return this.isValid()?this.toISOString():null},ei.toString=function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},ei.unix=function(){return Math.floor(this.valueOf()/1e3)},ei.valueOf=function(){return this._d.valueOf()-6e4*(this._offset||0)},ei.creationData=function(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}},ei.year=xn,ei.isLeapYear=function(){return nt(this.year())},ei.weekYear=function(t){return re.call(this,t,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)},ei.isoWeekYear=function(t){return re.call(this,t,this.isoWeek(),this.isoWeekday(),1,4)},ei.quarter=ei.quarters=function(t){return null==t?Math.ceil((this.month()+1)/3):this.month(3*(t-1)+this.month()%3)},ei.month=$,ei.daysInMonth=function(){return J(this.year(),this.month())},ei.week=ei.weeks=function(t){var e=this.localeData().week(this);return null==t?e:this.add(7*(t-e),"d")},ei.isoWeek=ei.isoWeeks=function(t){var e=st(this,1,4).week;return null==t?e:this.add(7*(t-e),"d")},ei.weeksInYear=function(){var t=this.localeData()._week;return lt(this.year(),t.dow,t.doy)},ei.isoWeeksInYear=function(){return lt(this.year(),1,4)},ei.date=Jn,ei.day=ei.days=function(t){if(!this.isValid())return null!=t?this:NaN;var e=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=t?(t=ut(t,this.localeData()),this.add(t-e,"d")):e},ei.weekday=function(t){if(!this.isValid())return null!=t?this:NaN;var e=(this.day()+7-this.localeData()._week.dow)%7;return null==t?e:this.add(t-e,"d")},ei.isoWeekday=function(t){if(!this.isValid())return null!=t?this:NaN;if(null!=t){var e=dt(t,this.localeData());return this.day(this.day()%7?e:e-7)}return this.day()||7},ei.dayOfYear=function(t){var e=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==t?e:this.add(t-e,"d")},ei.hour=ei.hours=In,ei.minute=ei.minutes=Kn,ei.second=ei.seconds=Qn,ei.millisecond=ei.milliseconds=ti,ei.utcOffset=function(t,e,i){var a,r=this._offset||0;if(!this.isValid())return null!=t?this:NaN;if(null!=t){if("string"==typeof t){if(null===(t=Ut($e,t)))return this}else Math.abs(t)<16&&!i&&(t*=60);return!this._isUTC&&e&&(a=Gt(this)),this._offset=t,this._isUTC=!0,null!=a&&this.add(a,"m"),r!==t&&(!e||this._changeInProgress?te(this,Xt(t-r,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,n.updateOffset(this,!0),this._changeInProgress=null)),this}return this._isUTC?r:Gt(this)},ei.utc=function(t){return this.utcOffset(0,t)},ei.local=function(t){return this._isUTC&&(this.utcOffset(0,t),this._isUTC=!1,t&&this.subtract(Gt(this),"m")),this},ei.parseZone=function(){if(null!=this._tzm)this.utcOffset(this._tzm,!1,!0);else if("string"==typeof this._i){var t=Ut(Qe,this._i);null!=t?this.utcOffset(t):this.utcOffset(0,!0)}return this},ei.hasAlignedHourOffset=function(t){return!!this.isValid()&&(t=t?Nt(t).utcOffset():0,(this.utcOffset()-t)%60==0)},ei.isDST=function(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},ei.isLocal=function(){return!!this.isValid()&&!this._isUTC},ei.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},ei.isUtc=Zt,ei.isUTC=Zt,ei.zoneAbbr=function(){return this._isUTC?"UTC":""},ei.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},ei.dates=M("dates accessor is deprecated. Use date instead.",Jn),ei.months=M("months accessor is deprecated. Use month instead",$),ei.years=M("years accessor is deprecated. Use year instead",xn),ei.zone=M("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",function(t,e){return null!=t?("string"!=typeof t&&(t=-t),this.utcOffset(t,e),this):-this.utcOffset()}),ei.isDSTShifted=M("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",function(){if(!o(this._isDSTShifted))return this._isDSTShifted;var t={};if(v(t,this),(t=Lt(t))._a){var e=t._isUTC?h(t._a):Nt(t._a);this._isDSTShifted=this.isValid()&&k(t._a,e.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted});var ni=P.prototype;ni.calendar=function(t,e,n){var i=this._calendar[t]||this._calendar.sameElse;return D(i)?i.call(e,n):i},ni.longDateFormat=function(t){var e=this._longDateFormat[t],n=this._longDateFormat[t.toUpperCase()];return e||!n?e:(this._longDateFormat[t]=n.replace(/MMMM|MM|DD|dddd/g,function(t){return t.slice(1)}),this._longDateFormat[t])},ni.invalidDate=function(){return this._invalidDate},ni.ordinal=function(t){return this._ordinal.replace("%d",t)},ni.preparse=se,ni.postformat=se,ni.relativeTime=function(t,e,n,i){var a=this._relativeTime[n];return D(a)?a(t,e,n,i):a.replace(/%d/i,t)},ni.pastFuture=function(t,e){var n=this._relativeTime[t>0?"future":"past"];return D(n)?n(e):n.replace(/%s/i,e)},ni.set=function(t){var e,n;for(n in t)D(e=t[n])?this[n]=e:this["_"+n]=e;this._config=t,this._dayOfMonthOrdinalParseLenient=new RegExp((this._dayOfMonthOrdinalParse.source||this._ordinalParse.source)+"|"+/\d{1,2}/.source)},ni.months=function(t,e){return t?i(this._months)?this._months[t.month()]:this._months[(this._months.isFormat||mn).test(e)?"format":"standalone"][t.month()]:i(this._months)?this._months:this._months.standalone},ni.monthsShort=function(t,e){return t?i(this._monthsShort)?this._monthsShort[t.month()]:this._monthsShort[mn.test(e)?"format":"standalone"][t.month()]:i(this._monthsShort)?this._monthsShort:this._monthsShort.standalone},ni.monthsParse=function(t,e,n){var i,a,r;if(this._monthsParseExact)return K.call(this,t,e,n);for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),i=0;i<12;i++){if(a=h([2e3,i]),n&&!this._longMonthsParse[i]&&(this._longMonthsParse[i]=new RegExp("^"+this.months(a,"").replace(".","")+"$","i"),this._shortMonthsParse[i]=new RegExp("^"+this.monthsShort(a,"").replace(".","")+"$","i")),n||this._monthsParse[i]||(r="^"+this.months(a,"")+"|^"+this.monthsShort(a,""),this._monthsParse[i]=new RegExp(r.replace(".",""),"i")),n&&"MMMM"===e&&this._longMonthsParse[i].test(t))return i;if(n&&"MMM"===e&&this._shortMonthsParse[i].test(t))return i;if(!n&&this._monthsParse[i].test(t))return i}},ni.monthsRegex=function(t){return this._monthsParseExact?(d(this,"_monthsRegex")||tt.call(this),t?this._monthsStrictRegex:this._monthsRegex):(d(this,"_monthsRegex")||(this._monthsRegex=bn),this._monthsStrictRegex&&t?this._monthsStrictRegex:this._monthsRegex)},ni.monthsShortRegex=function(t){return this._monthsParseExact?(d(this,"_monthsRegex")||tt.call(this),t?this._monthsShortStrictRegex:this._monthsShortRegex):(d(this,"_monthsShortRegex")||(this._monthsShortRegex=yn),this._monthsShortStrictRegex&&t?this._monthsShortStrictRegex:this._monthsShortRegex)},ni.week=function(t){return st(t,this._week.dow,this._week.doy).week},ni.firstDayOfYear=function(){return this._week.doy},ni.firstDayOfWeek=function(){return this._week.dow},ni.weekdays=function(t,e){return t?i(this._weekdays)?this._weekdays[t.day()]:this._weekdays[this._weekdays.isFormat.test(e)?"format":"standalone"][t.day()]:i(this._weekdays)?this._weekdays:this._weekdays.standalone},ni.weekdaysMin=function(t){return t?this._weekdaysMin[t.day()]:this._weekdaysMin},ni.weekdaysShort=function(t){return t?this._weekdaysShort[t.day()]:this._weekdaysShort},ni.weekdaysParse=function(t,e,n){var i,a,r;if(this._weekdaysParseExact)return ct.call(this,t,e,n);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),i=0;i<7;i++){if(a=h([2e3,1]).day(i),n&&!this._fullWeekdaysParse[i]&&(this._fullWeekdaysParse[i]=new RegExp("^"+this.weekdays(a,"").replace(".",".?")+"$","i"),this._shortWeekdaysParse[i]=new RegExp("^"+this.weekdaysShort(a,"").replace(".",".?")+"$","i"),this._minWeekdaysParse[i]=new RegExp("^"+this.weekdaysMin(a,"").replace(".",".?")+"$","i")),this._weekdaysParse[i]||(r="^"+this.weekdays(a,"")+"|^"+this.weekdaysShort(a,"")+"|^"+this.weekdaysMin(a,""),this._weekdaysParse[i]=new RegExp(r.replace(".",""),"i")),n&&"dddd"===e&&this._fullWeekdaysParse[i].test(t))return i;if(n&&"ddd"===e&&this._shortWeekdaysParse[i].test(t))return i;if(n&&"dd"===e&&this._minWeekdaysParse[i].test(t))return i;if(!n&&this._weekdaysParse[i].test(t))return i}},ni.weekdaysRegex=function(t){return this._weekdaysParseExact?(d(this,"_weekdaysRegex")||ht.call(this),t?this._weekdaysStrictRegex:this._weekdaysRegex):(d(this,"_weekdaysRegex")||(this._weekdaysRegex=Sn),this._weekdaysStrictRegex&&t?this._weekdaysStrictRegex:this._weekdaysRegex)},ni.weekdaysShortRegex=function(t){return this._weekdaysParseExact?(d(this,"_weekdaysRegex")||ht.call(this),t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(d(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=Dn),this._weekdaysShortStrictRegex&&t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)},ni.weekdaysMinRegex=function(t){return this._weekdaysParseExact?(d(this,"_weekdaysRegex")||ht.call(this),t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(d(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=Cn),this._weekdaysMinStrictRegex&&t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)},ni.isPM=function(t){return"p"===(t+"").toLowerCase().charAt(0)},ni.meridiem=function(t,e,n){return t>11?n?"pm":"PM":n?"am":"AM"},bt("en",{dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(t){var e=t%10;return t+(1===_(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th")}}),n.lang=M("moment.lang is deprecated. Use moment.locale instead.",bt),n.langData=M("moment.langData is deprecated. Use moment.localeData instead.",_t);var ii=Math.abs,ai=me("ms"),ri=me("s"),oi=me("m"),si=me("h"),li=me("d"),ui=me("w"),di=me("M"),ci=me("y"),hi=pe("milliseconds"),fi=pe("seconds"),gi=pe("minutes"),mi=pe("hours"),pi=pe("days"),vi=pe("months"),yi=pe("years"),bi=Math.round,xi={ss:44,s:45,m:45,h:22,d:26,M:11},_i=Math.abs,ki=Vt.prototype;return ki.isValid=function(){return this._isValid},ki.abs=function(){var t=this._data;return this._milliseconds=ii(this._milliseconds),this._days=ii(this._days),this._months=ii(this._months),t.milliseconds=ii(t.milliseconds),t.seconds=ii(t.seconds),t.minutes=ii(t.minutes),t.hours=ii(t.hours),t.months=ii(t.months),t.years=ii(t.years),this},ki.add=function(t,e){return ce(this,t,e,1)},ki.subtract=function(t,e){return ce(this,t,e,-1)},ki.as=function(t){if(!this.isValid())return NaN;var e,n,i=this._milliseconds;if("month"===(t=I(t))||"year"===t)return e=this._days+i/864e5,n=this._months+fe(e),"month"===t?n:n/12;switch(e=this._days+Math.round(ge(this._months)),t){case"week":return e/7+i/6048e5;case"day":return e+i/864e5;case"hour":return 24*e+i/36e5;case"minute":return 1440*e+i/6e4;case"second":return 86400*e+i/1e3;case"millisecond":return Math.floor(864e5*e)+i;default:throw new Error("Unknown unit "+t)}},ki.asMilliseconds=ai,ki.asSeconds=ri,ki.asMinutes=oi,ki.asHours=si,ki.asDays=li,ki.asWeeks=ui,ki.asMonths=di,ki.asYears=ci,ki.valueOf=function(){return this.isValid()?this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*_(this._months/12):NaN},ki._bubble=function(){var t,e,n,i,a,r=this._milliseconds,o=this._days,s=this._months,l=this._data;return r>=0&&o>=0&&s>=0||r<=0&&o<=0&&s<=0||(r+=864e5*he(ge(s)+o),o=0,s=0),l.milliseconds=r%1e3,t=x(r/1e3),l.seconds=t%60,e=x(t/60),l.minutes=e%60,n=x(e/60),l.hours=n%24,o+=x(n/24),a=x(fe(o)),s+=a,o-=he(ge(a)),i=x(s/12),s%=12,l.days=o,l.months=s,l.years=i,this},ki.get=function(t){return t=I(t),this.isValid()?this[t+"s"]():NaN},ki.milliseconds=hi,ki.seconds=fi,ki.minutes=gi,ki.hours=mi,ki.days=pi,ki.weeks=function(){return x(this.days()/7)},ki.months=vi,ki.years=yi,ki.humanize=function(t){if(!this.isValid())return this.localeData().invalidDate();var e=this.localeData(),n=ye(this,!t,e);return t&&(n=e.pastFuture(+this,n)),e.postformat(n)},ki.toISOString=be,ki.toString=be,ki.toJSON=be,ki.locale=ne,ki.localeData=ie,ki.toIsoString=M("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",be),ki.lang=Xn,N("X",0,0,"unix"),N("x",0,0,"valueOf"),E("x",Ke),E("X",tn),G("X",function(t,e,n){n._d=new Date(1e3*parseFloat(t,10))}),G("x",function(t,e,n){n._d=new Date(_(t))}),n.version="2.18.1",function(t){xe=t}(Nt),n.fn=ei,n.min=function(){return zt("isBefore",[].slice.call(arguments,0))},n.max=function(){return zt("isAfter",[].slice.call(arguments,0))},n.now=function(){return Date.now?Date.now():+new Date},n.utc=h,n.unix=function(t){return Nt(1e3*t)},n.months=function(t,e){return ue(t,e,"months")},n.isDate=l,n.locale=bt,n.invalid=p,n.duration=Xt,n.isMoment=b,n.weekdays=function(t,e,n){return de(t,e,n,"weekdays")},n.parseZone=function(){return Nt.apply(null,arguments).parseZone()},n.localeData=_t,n.isDuration=Ht,n.monthsShort=function(t,e){return ue(t,e,"monthsShort")},n.weekdaysMin=function(t,e,n){return de(t,e,n,"weekdaysMin")},n.defineLocale=xt,n.updateLocale=function(t,e){if(null!=e){var n,i=An;null!=On[t]&&(i=On[t]._config),(n=new P(e=C(i,e))).parentLocale=On[t],On[t]=n,bt(t)}else null!=On[t]&&(null!=On[t].parentLocale?On[t]=On[t].parentLocale:null!=On[t]&&delete On[t]);return On[t]},n.locales=function(){return Pe(On)},n.weekdaysShort=function(t,e,n){return de(t,e,n,"weekdaysShort")},n.normalizeUnits=I,n.relativeTimeRounding=function(t){return void 0===t?bi:"function"==typeof t&&(bi=t,!0)},n.relativeTimeThreshold=function(t,e){return void 0!==xi[t]&&(void 0===e?xi[t]:(xi[t]=e,"s"===t&&(xi.ss=e-1),!0))},n.calendarFormat=function(t,e){var n=t.diff(e,"days",!0);return n<-6?"sameElse":n<-1?"lastWeek":n<0?"lastDay":n<1?"sameDay":n<2?"nextDay":n<7?"nextWeek":"sameElse"},n.prototype=ei,n})},{}],7:[function(t,e,n){var i=t(29)();i.helpers=t(45),t(27)(i),i.defaults=t(25),i.Element=t(26),i.elements=t(40),i.Interaction=t(28),i.platform=t(48),t(31)(i),t(22)(i),t(23)(i),t(24)(i),t(30)(i),t(33)(i),t(32)(i),t(35)(i),t(54)(i),t(52)(i),t(53)(i),t(55)(i),t(56)(i),t(57)(i),t(15)(i),t(16)(i),t(17)(i),t(18)(i),t(19)(i),t(20)(i),t(21)(i),t(8)(i),t(9)(i),t(10)(i),t(11)(i),t(12)(i),t(13)(i),t(14)(i);var a=[];a.push(t(49)(i),t(50)(i),t(51)(i)),i.plugins.register(a),i.platform.initialize(),e.exports=i,"undefined"!=typeof window&&(window.Chart=i),i.canvasHelpers=i.helpers.canvas},{10:10,11:11,12:12,13:13,14:14,15:15,16:16,17:17,18:18,19:19,20:20,21:21,22:22,23:23,24:24,25:25,26:26,27:27,28:28,29:29,30:30,31:31,32:32,33:33,35:35,40:40,45:45,48:48,49:49,50:50,51:51,52:52,53:53,54:54,55:55,56:56,57:57,8:8,9:9}],8:[function(t,e,n){"use strict";e.exports=function(t){t.Bar=function(e,n){return n.type="bar",new t(e,n)}}},{}],9:[function(t,e,n){"use strict";e.exports=function(t){t.Bubble=function(e,n){return n.type="bubble",new t(e,n)}}},{}],10:[function(t,e,n){"use strict";e.exports=function(t){t.Doughnut=function(e,n){return n.type="doughnut",new t(e,n)}}},{}],11:[function(t,e,n){"use strict";e.exports=function(t){t.Line=function(e,n){return n.type="line",new t(e,n)}}},{}],12:[function(t,e,n){"use strict";e.exports=function(t){t.PolarArea=function(e,n){return n.type="polarArea",new t(e,n)}}},{}],13:[function(t,e,n){"use strict";e.exports=function(t){t.Radar=function(e,n){return n.type="radar",new t(e,n)}}},{}],14:[function(t,e,n){"use strict";e.exports=function(t){t.Scatter=function(e,n){return n.type="scatter",new t(e,n)}}},{}],15:[function(t,e,n){"use strict";var i=t(25),a=t(40),r=t(45);i._set("bar",{hover:{mode:"label"},scales:{xAxes:[{type:"category",categoryPercentage:.8,barPercentage:.9,offset:!0,gridLines:{offsetGridLines:!0}}],yAxes:[{type:"linear"}]}}),i._set("horizontalBar",{hover:{mode:"index",axis:"y"},scales:{xAxes:[{type:"linear",position:"bottom"}],yAxes:[{position:"left",type:"category",categoryPercentage:.8,barPercentage:.9,offset:!0,gridLines:{offsetGridLines:!0}}]},elements:{rectangle:{borderSkipped:"left"}},tooltips:{callbacks:{title:function(t,e){var n="";return t.length>0&&(t[0].yLabel?n=t[0].yLabel:e.labels.length>0&&t[0].index<e.labels.length&&(n=e.labels[t[0].index])),n},label:function(t,e){return(e.datasets[t.datasetIndex].label||"")+": "+t.xLabel}},mode:"index",axis:"y"}}),e.exports=function(t){t.controllers.bar=t.DatasetController.extend({dataElementType:a.Rectangle,initialize:function(){var e,n=this;t.DatasetController.prototype.initialize.apply(n,arguments),(e=n.getMeta()).stack=n.getDataset().stack,e.bar=!0},update:function(t){var e,n,i=this,a=i.getMeta().data;for(i._ruler=i.getRuler(),e=0,n=a.length;e<n;++e)i.updateElement(a[e],e,t)},updateElement:function(t,e,n){var i=this,a=i.chart,o=i.getMeta(),s=i.getDataset(),l=t.custom||{},u=a.options.elements.rectangle;t._xScale=i.getScaleForId(o.xAxisID),t._yScale=i.getScaleForId(o.yAxisID),t._datasetIndex=i.index,t._index=e,t._model={datasetLabel:s.label,label:a.data.labels[e],borderSkipped:l.borderSkipped?l.borderSkipped:u.borderSkipped,backgroundColor:l.backgroundColor?l.backgroundColor:r.valueAtIndexOrDefault(s.backgroundColor,e,u.backgroundColor),borderColor:l.borderColor?l.borderColor:r.valueAtIndexOrDefault(s.borderColor,e,u.borderColor),borderWidth:l.borderWidth?l.borderWidth:r.valueAtIndexOrDefault(s.borderWidth,e,u.borderWidth)},i.updateElementGeometry(t,e,n),t.pivot()},updateElementGeometry:function(t,e,n){var i=this,a=t._model,r=i.getValueScale(),o=r.getBasePixel(),s=r.isHorizontal(),l=i._ruler||i.getRuler(),u=i.calculateBarValuePixels(i.index,e),d=i.calculateBarIndexPixels(i.index,e,l);a.horizontal=s,a.base=n?o:u.base,a.x=s?n?o:u.head:d.center,a.y=s?d.center:n?o:u.head,a.height=s?d.size:void 0,a.width=s?void 0:d.size},getValueScaleId:function(){return this.getMeta().yAxisID},getIndexScaleId:function(){return this.getMeta().xAxisID},getValueScale:function(){return this.getScaleForId(this.getValueScaleId())},getIndexScale:function(){return this.getScaleForId(this.getIndexScaleId())},getStackCount:function(t){var e,n,i=this,a=i.chart,r=i.getIndexScale().options.stacked,o=void 0===t?a.data.datasets.length:t+1,s=[];for(e=0;e<o;++e)(n=a.getDatasetMeta(e)).bar&&a.isDatasetVisible(e)&&(!1===r||!0===r&&-1===s.indexOf(n.stack)||void 0===r&&(void 0===n.stack||-1===s.indexOf(n.stack)))&&s.push(n.stack);return s.length},getStackIndex:function(t){return this.getStackCount(t)-1},getRuler:function(){var t,e,n=this,i=n.getIndexScale(),a=n.getStackCount(),r=n.index,o=[],s=i.isHorizontal(),l=s?i.left:i.top,u=l+(s?i.width:i.height);for(t=0,e=n.getMeta().data.length;t<e;++t)o.push(i.getPixelForValue(null,t,r));return{pixels:o,start:l,end:u,stackCount:a,scale:i}},calculateBarValuePixels:function(t,e){var n,i,a,r,o,s,l=this,u=l.chart,d=l.getMeta(),c=l.getValueScale(),h=u.data.datasets,f=c.getRightValue(h[t].data[e]),g=c.options.stacked,m=d.stack,p=0;if(g||void 0===g&&void 0!==m)for(n=0;n<t;++n)(i=u.getDatasetMeta(n)).bar&&i.stack===m&&i.controller.getValueScaleId()===c.id&&u.isDatasetVisible(n)&&(a=c.getRightValue(h[n].data[e]),(f<0&&a<0||f>=0&&a>0)&&(p+=a));return r=c.getPixelForValue(p),o=c.getPixelForValue(p+f),s=(o-r)/2,{size:s,base:r,head:o,center:o+s/2}},calculateBarIndexPixels:function(t,e,n){var i,a,o,s,l,u,d=this,c=n.scale.options,h=d.getStackIndex(t),f=n.pixels,g=f[e],m=f.length,p=n.start,v=n.end;return 1===m?(i=g>p?g-p:v-g,a=g<v?v-g:g-p):(e>0&&(i=(g-f[e-1])/2,e===m-1&&(a=i)),e<m-1&&(a=(f[e+1]-g)/2,0===e&&(i=a))),o=i*c.categoryPercentage,s=a*c.categoryPercentage,l=(o+s)/n.stackCount,u=l*c.barPercentage,u=Math.min(r.valueOrDefault(c.barThickness,u),r.valueOrDefault(c.maxBarThickness,1/0)),g-=o,g+=l*h,g+=(l-u)/2,{size:u,base:g,head:g+u,center:g+u/2}},draw:function(){var t=this,e=t.chart,n=t.getValueScale(),i=t.getMeta().data,a=t.getDataset(),o=i.length,s=0;for(r.canvas.clipArea(e.ctx,e.chartArea);s<o;++s)isNaN(n.getRightValue(a.data[s]))||i[s].draw();r.canvas.unclipArea(e.ctx)},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t._index,i=t.custom||{},a=t._model;a.backgroundColor=i.hoverBackgroundColor?i.hoverBackgroundColor:r.valueAtIndexOrDefault(e.hoverBackgroundColor,n,r.getHoverColor(a.backgroundColor)),a.borderColor=i.hoverBorderColor?i.hoverBorderColor:r.valueAtIndexOrDefault(e.hoverBorderColor,n,r.getHoverColor(a.borderColor)),a.borderWidth=i.hoverBorderWidth?i.hoverBorderWidth:r.valueAtIndexOrDefault(e.hoverBorderWidth,n,a.borderWidth)},removeHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t._index,i=t.custom||{},a=t._model,o=this.chart.options.elements.rectangle;a.backgroundColor=i.backgroundColor?i.backgroundColor:r.valueAtIndexOrDefault(e.backgroundColor,n,o.backgroundColor),a.borderColor=i.borderColor?i.borderColor:r.valueAtIndexOrDefault(e.borderColor,n,o.borderColor),a.borderWidth=i.borderWidth?i.borderWidth:r.valueAtIndexOrDefault(e.borderWidth,n,o.borderWidth)}}),t.controllers.horizontalBar=t.controllers.bar.extend({getValueScaleId:function(){return this.getMeta().xAxisID},getIndexScaleId:function(){return this.getMeta().yAxisID}})}},{25:25,40:40,45:45}],16:[function(t,e,n){"use strict";var i=t(25),a=t(40),r=t(45);i._set("bubble",{hover:{mode:"single"},scales:{xAxes:[{type:"linear",position:"bottom",id:"x-axis-0"}],yAxes:[{type:"linear",position:"left",id:"y-axis-0"}]},tooltips:{callbacks:{title:function(){return""},label:function(t,e){var n=e.datasets[t.datasetIndex].label||"",i=e.datasets[t.datasetIndex].data[t.index];return n+": ("+t.xLabel+", "+t.yLabel+", "+i.r+")"}}}}),e.exports=function(t){t.controllers.bubble=t.DatasetController.extend({dataElementType:a.Point,update:function(t){var e=this,n=e.getMeta().data;r.each(n,function(n,i){e.updateElement(n,i,t)})},updateElement:function(t,e,n){var i=this,a=i.getMeta(),r=t.custom||{},o=i.getScaleForId(a.xAxisID),s=i.getScaleForId(a.yAxisID),l=i._resolveElementOptions(t,e),u=i.getDataset().data[e],d=i.index,c=n?o.getPixelForDecimal(.5):o.getPixelForValue("object"==typeof u?u:NaN,e,d),h=n?s.getBasePixel():s.getPixelForValue(u,e,d);t._xScale=o,t._yScale=s,t._options=l,t._datasetIndex=d,t._index=e,t._model={backgroundColor:l.backgroundColor,borderColor:l.borderColor,borderWidth:l.borderWidth,hitRadius:l.hitRadius,pointStyle:l.pointStyle,radius:n?0:l.radius,skip:r.skip||isNaN(c)||isNaN(h),x:c,y:h},t.pivot()},setHoverStyle:function(t){var e=t._model,n=t._options;e.backgroundColor=r.valueOrDefault(n.hoverBackgroundColor,r.getHoverColor(n.backgroundColor)),e.borderColor=r.valueOrDefault(n.hoverBorderColor,r.getHoverColor(n.borderColor)),e.borderWidth=r.valueOrDefault(n.hoverBorderWidth,n.borderWidth),e.radius=n.radius+n.hoverRadius},removeHoverStyle:function(t){var e=t._model,n=t._options;e.backgroundColor=n.backgroundColor,e.borderColor=n.borderColor,e.borderWidth=n.borderWidth,e.radius=n.radius},_resolveElementOptions:function(t,e){var n,i,a,o=this,s=o.chart,l=s.data.datasets[o.index],u=t.custom||{},d=s.options.elements.point,c=r.options.resolve,h=l.data[e],f={},g={chart:s,dataIndex:e,dataset:l,datasetIndex:o.index},m=["backgroundColor","borderColor","borderWidth","hoverBackgroundColor","hoverBorderColor","hoverBorderWidth","hoverRadius","hitRadius","pointStyle"];for(n=0,i=m.length;n<i;++n)f[a=m[n]]=c([u[a],l[a],d[a]],g,e);return f.radius=c([u.radius,h?h.r:void 0,l.radius,d.radius],g,e),f}})}},{25:25,40:40,45:45}],17:[function(t,e,n){"use strict";var i=t(25),a=t(40),r=t(45);i._set("doughnut",{animation:{animateRotate:!0,animateScale:!1},hover:{mode:"single"},legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');var n=t.data,i=n.datasets,a=n.labels;if(i.length)for(var r=0;r<i[0].data.length;++r)e.push('<li><span style="background-color:'+i[0].backgroundColor[r]+'"></span>'),a[r]&&e.push(a[r]),e.push("</li>");return e.push("</ul>"),e.join("")},legend:{labels:{generateLabels:function(t){var e=t.data;return e.labels.length&&e.datasets.length?e.labels.map(function(n,i){var a=t.getDatasetMeta(0),o=e.datasets[0],s=a.data[i],l=s&&s.custom||{},u=r.valueAtIndexOrDefault,d=t.options.elements.arc;return{text:n,fillStyle:l.backgroundColor?l.backgroundColor:u(o.backgroundColor,i,d.backgroundColor),strokeStyle:l.borderColor?l.borderColor:u(o.borderColor,i,d.borderColor),lineWidth:l.borderWidth?l.borderWidth:u(o.borderWidth,i,d.borderWidth),hidden:isNaN(o.data[i])||a.data[i].hidden,index:i}}):[]}},onClick:function(t,e){var n,i,a,r=e.index,o=this.chart;for(n=0,i=(o.data.datasets||[]).length;n<i;++n)(a=o.getDatasetMeta(n)).data[r]&&(a.data[r].hidden=!a.data[r].hidden);o.update()}},cutoutPercentage:50,rotation:-.5*Math.PI,circumference:2*Math.PI,tooltips:{callbacks:{title:function(){return""},label:function(t,e){var n=e.labels[t.index],i=": "+e.datasets[t.datasetIndex].data[t.index];return r.isArray(n)?(n=n.slice())[0]+=i:n+=i,n}}}}),i._set("pie",r.clone(i.doughnut)),i._set("pie",{cutoutPercentage:0}),e.exports=function(t){t.controllers.doughnut=t.controllers.pie=t.DatasetController.extend({dataElementType:a.Arc,linkScales:r.noop,getRingIndex:function(t){for(var e=0,n=0;n<t;++n)this.chart.isDatasetVisible(n)&&++e;return e},update:function(t){var e=this,n=e.chart,i=n.chartArea,a=n.options,o=a.elements.arc,s=i.right-i.left-o.borderWidth,l=i.bottom-i.top-o.borderWidth,u=Math.min(s,l),d={x:0,y:0},c=e.getMeta(),h=a.cutoutPercentage,f=a.circumference;if(f<2*Math.PI){var g=a.rotation%(2*Math.PI),m=(g+=2*Math.PI*(g>=Math.PI?-1:g<-Math.PI?1:0))+f,p={x:Math.cos(g),y:Math.sin(g)},v={x:Math.cos(m),y:Math.sin(m)},y=g<=0&&m>=0||g<=2*Math.PI&&2*Math.PI<=m,b=g<=.5*Math.PI&&.5*Math.PI<=m||g<=2.5*Math.PI&&2.5*Math.PI<=m,x=g<=-Math.PI&&-Math.PI<=m||g<=Math.PI&&Math.PI<=m,_=g<=.5*-Math.PI&&.5*-Math.PI<=m||g<=1.5*Math.PI&&1.5*Math.PI<=m,k=h/100,w={x:x?-1:Math.min(p.x*(p.x<0?1:k),v.x*(v.x<0?1:k)),y:_?-1:Math.min(p.y*(p.y<0?1:k),v.y*(v.y<0?1:k))},M={x:y?1:Math.max(p.x*(p.x>0?1:k),v.x*(v.x>0?1:k)),y:b?1:Math.max(p.y*(p.y>0?1:k),v.y*(v.y>0?1:k))},S={width:.5*(M.x-w.x),height:.5*(M.y-w.y)};u=Math.min(s/S.width,l/S.height),d={x:-.5*(M.x+w.x),y:-.5*(M.y+w.y)}}n.borderWidth=e.getMaxBorderWidth(c.data),n.outerRadius=Math.max((u-n.borderWidth)/2,0),n.innerRadius=Math.max(h?n.outerRadius/100*h:0,0),n.radiusLength=(n.outerRadius-n.innerRadius)/n.getVisibleDatasetCount(),n.offsetX=d.x*n.outerRadius,n.offsetY=d.y*n.outerRadius,c.total=e.calculateTotal(),e.outerRadius=n.outerRadius-n.radiusLength*e.getRingIndex(e.index),e.innerRadius=Math.max(e.outerRadius-n.radiusLength,0),r.each(c.data,function(n,i){e.updateElement(n,i,t)})},updateElement:function(t,e,n){var i=this,a=i.chart,o=a.chartArea,s=a.options,l=s.animation,u=(o.left+o.right)/2,d=(o.top+o.bottom)/2,c=s.rotation,h=s.rotation,f=i.getDataset(),g=n&&l.animateRotate?0:t.hidden?0:i.calculateCircumference(f.data[e])*(s.circumference/(2*Math.PI)),m=n&&l.animateScale?0:i.innerRadius,p=n&&l.animateScale?0:i.outerRadius,v=r.valueAtIndexOrDefault;r.extend(t,{_datasetIndex:i.index,_index:e,_model:{x:u+a.offsetX,y:d+a.offsetY,startAngle:c,endAngle:h,circumference:g,outerRadius:p,innerRadius:m,label:v(f.label,e,a.data.labels[e])}});var y=t._model;this.removeHoverStyle(t),n&&l.animateRotate||(y.startAngle=0===e?s.rotation:i.getMeta().data[e-1]._model.endAngle,y.endAngle=y.startAngle+y.circumference),t.pivot()},removeHoverStyle:function(e){t.DatasetController.prototype.removeHoverStyle.call(this,e,this.chart.options.elements.arc)},calculateTotal:function(){var t,e=this.getDataset(),n=this.getMeta(),i=0;return r.each(n.data,function(n,a){t=e.data[a],isNaN(t)||n.hidden||(i+=Math.abs(t))}),i},calculateCircumference:function(t){var e=this.getMeta().total;return e>0&&!isNaN(t)?2*Math.PI*(t/e):0},getMaxBorderWidth:function(t){for(var e,n,i=0,a=this.index,r=t.length,o=0;o<r;o++)e=t[o]._model?t[o]._model.borderWidth:0,i=(n=t[o]._chart?t[o]._chart.config.data.datasets[a].hoverBorderWidth:0)>(i=e>i?e:i)?n:i;return i}})}},{25:25,40:40,45:45}],18:[function(t,e,n){"use strict";var i=t(25),a=t(40),r=t(45);i._set("line",{showLines:!0,spanGaps:!1,hover:{mode:"label"},scales:{xAxes:[{type:"category",id:"x-axis-0"}],yAxes:[{type:"linear",id:"y-axis-0"}]}}),e.exports=function(t){function e(t,e){return r.valueOrDefault(t.showLine,e.showLines)}t.controllers.line=t.DatasetController.extend({datasetElementType:a.Line,dataElementType:a.Point,update:function(t){var n,i,a,o=this,s=o.getMeta(),l=s.dataset,u=s.data||[],d=o.chart.options,c=d.elements.line,h=o.getScaleForId(s.yAxisID),f=o.getDataset(),g=e(f,d);for(g&&(a=l.custom||{},void 0!==f.tension&&void 0===f.lineTension&&(f.lineTension=f.tension),l._scale=h,l._datasetIndex=o.index,l._children=u,l._model={spanGaps:f.spanGaps?f.spanGaps:d.spanGaps,tension:a.tension?a.tension:r.valueOrDefault(f.lineTension,c.tension),backgroundColor:a.backgroundColor?a.backgroundColor:f.backgroundColor||c.backgroundColor,borderWidth:a.borderWidth?a.borderWidth:f.borderWidth||c.borderWidth,borderColor:a.borderColor?a.borderColor:f.borderColor||c.borderColor,borderCapStyle:a.borderCapStyle?a.borderCapStyle:f.borderCapStyle||c.borderCapStyle,borderDash:a.borderDash?a.borderDash:f.borderDash||c.borderDash,borderDashOffset:a.borderDashOffset?a.borderDashOffset:f.borderDashOffset||c.borderDashOffset,borderJoinStyle:a.borderJoinStyle?a.borderJoinStyle:f.borderJoinStyle||c.borderJoinStyle,fill:a.fill?a.fill:void 0!==f.fill?f.fill:c.fill,steppedLine:a.steppedLine?a.steppedLine:r.valueOrDefault(f.steppedLine,c.stepped),cubicInterpolationMode:a.cubicInterpolationMode?a.cubicInterpolationMode:r.valueOrDefault(f.cubicInterpolationMode,c.cubicInterpolationMode)},l.pivot()),n=0,i=u.length;n<i;++n)o.updateElement(u[n],n,t);for(g&&0!==l._model.tension&&o.updateBezierControlPoints(),n=0,i=u.length;n<i;++n)u[n].pivot()},getPointBackgroundColor:function(t,e){var n=this.chart.options.elements.point.backgroundColor,i=this.getDataset(),a=t.custom||{};return a.backgroundColor?n=a.backgroundColor:i.pointBackgroundColor?n=r.valueAtIndexOrDefault(i.pointBackgroundColor,e,n):i.backgroundColor&&(n=i.backgroundColor),n},getPointBorderColor:function(t,e){var n=this.chart.options.elements.point.borderColor,i=this.getDataset(),a=t.custom||{};return a.borderColor?n=a.borderColor:i.pointBorderColor?n=r.valueAtIndexOrDefault(i.pointBorderColor,e,n):i.borderColor&&(n=i.borderColor),n},getPointBorderWidth:function(t,e){var n=this.chart.options.elements.point.borderWidth,i=this.getDataset(),a=t.custom||{};return isNaN(a.borderWidth)?!isNaN(i.pointBorderWidth)||r.isArray(i.pointBorderWidth)?n=r.valueAtIndexOrDefault(i.pointBorderWidth,e,n):isNaN(i.borderWidth)||(n=i.borderWidth):n=a.borderWidth,n},updateElement:function(t,e,n){var i,a,o=this,s=o.getMeta(),l=t.custom||{},u=o.getDataset(),d=o.index,c=u.data[e],h=o.getScaleForId(s.yAxisID),f=o.getScaleForId(s.xAxisID),g=o.chart.options.elements.point;void 0!==u.radius&&void 0===u.pointRadius&&(u.pointRadius=u.radius),void 0!==u.hitRadius&&void 0===u.pointHitRadius&&(u.pointHitRadius=u.hitRadius),i=f.getPixelForValue("object"==typeof c?c:NaN,e,d),a=n?h.getBasePixel():o.calculatePointY(c,e,d),t._xScale=f,t._yScale=h,t._datasetIndex=d,t._index=e,t._model={x:i,y:a,skip:l.skip||isNaN(i)||isNaN(a),radius:l.radius||r.valueAtIndexOrDefault(u.pointRadius,e,g.radius),pointStyle:l.pointStyle||r.valueAtIndexOrDefault(u.pointStyle,e,g.pointStyle),backgroundColor:o.getPointBackgroundColor(t,e),borderColor:o.getPointBorderColor(t,e),borderWidth:o.getPointBorderWidth(t,e),tension:s.dataset._model?s.dataset._model.tension:0,steppedLine:!!s.dataset._model&&s.dataset._model.steppedLine,hitRadius:l.hitRadius||r.valueAtIndexOrDefault(u.pointHitRadius,e,g.hitRadius)}},calculatePointY:function(t,e,n){var i,a,r,o=this,s=o.chart,l=o.getMeta(),u=o.getScaleForId(l.yAxisID),d=0,c=0;if(u.options.stacked){for(i=0;i<n;i++)if(a=s.data.datasets[i],"line"===(r=s.getDatasetMeta(i)).type&&r.yAxisID===u.id&&s.isDatasetVisible(i)){var h=Number(u.getRightValue(a.data[e]));h<0?c+=h||0:d+=h||0}var f=Number(u.getRightValue(t));return f<0?u.getPixelForValue(c+f):u.getPixelForValue(d+f)}return u.getPixelForValue(t)},updateBezierControlPoints:function(){function t(t,e,n){return Math.max(Math.min(t,n),e)}var e,n,i,a,o=this,s=o.getMeta(),l=o.chart.chartArea,u=s.data||[];if(s.dataset._model.spanGaps&&(u=u.filter(function(t){return!t._model.skip})),"monotone"===s.dataset._model.cubicInterpolationMode)r.splineCurveMonotone(u);else for(e=0,n=u.length;e<n;++e)i=u[e]._model,a=r.splineCurve(r.previousItem(u,e)._model,i,r.nextItem(u,e)._model,s.dataset._model.tension),i.controlPointPreviousX=a.previous.x,i.controlPointPreviousY=a.previous.y,i.controlPointNextX=a.next.x,i.controlPointNextY=a.next.y;if(o.chart.options.elements.line.capBezierPoints)for(e=0,n=u.length;e<n;++e)(i=u[e]._model).controlPointPreviousX=t(i.controlPointPreviousX,l.left,l.right),i.controlPointPreviousY=t(i.controlPointPreviousY,l.top,l.bottom),i.controlPointNextX=t(i.controlPointNextX,l.left,l.right),i.controlPointNextY=t(i.controlPointNextY,l.top,l.bottom)},draw:function(){var t=this,n=t.chart,i=t.getMeta(),a=i.data||[],o=n.chartArea,s=a.length,l=0;for(r.canvas.clipArea(n.ctx,o),e(t.getDataset(),n.options)&&i.dataset.draw(),r.canvas.unclipArea(n.ctx);l<s;++l)a[l].draw(o)},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t._index,i=t.custom||{},a=t._model;a.radius=i.hoverRadius||r.valueAtIndexOrDefault(e.pointHoverRadius,n,this.chart.options.elements.point.hoverRadius),a.backgroundColor=i.hoverBackgroundColor||r.valueAtIndexOrDefault(e.pointHoverBackgroundColor,n,r.getHoverColor(a.backgroundColor)),a.borderColor=i.hoverBorderColor||r.valueAtIndexOrDefault(e.pointHoverBorderColor,n,r.getHoverColor(a.borderColor)),a.borderWidth=i.hoverBorderWidth||r.valueAtIndexOrDefault(e.pointHoverBorderWidth,n,a.borderWidth)},removeHoverStyle:function(t){var e=this,n=e.chart.data.datasets[t._datasetIndex],i=t._index,a=t.custom||{},o=t._model;void 0!==n.radius&&void 0===n.pointRadius&&(n.pointRadius=n.radius),o.radius=a.radius||r.valueAtIndexOrDefault(n.pointRadius,i,e.chart.options.elements.point.radius),o.backgroundColor=e.getPointBackgroundColor(t,i),o.borderColor=e.getPointBorderColor(t,i),o.borderWidth=e.getPointBorderWidth(t,i)}})}},{25:25,40:40,45:45}],19:[function(t,e,n){"use strict";var i=t(25),a=t(40),r=t(45);i._set("polarArea",{scale:{type:"radialLinear",angleLines:{display:!1},gridLines:{circular:!0},pointLabels:{display:!1},ticks:{beginAtZero:!0}},animation:{animateRotate:!0,animateScale:!0},startAngle:-.5*Math.PI,legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');var n=t.data,i=n.datasets,a=n.labels;if(i.length)for(var r=0;r<i[0].data.length;++r)e.push('<li><span style="background-color:'+i[0].backgroundColor[r]+'"></span>'),a[r]&&e.push(a[r]),e.push("</li>");return e.push("</ul>"),e.join("")},legend:{labels:{generateLabels:function(t){var e=t.data;return e.labels.length&&e.datasets.length?e.labels.map(function(n,i){var a=t.getDatasetMeta(0),o=e.datasets[0],s=a.data[i].custom||{},l=r.valueAtIndexOrDefault,u=t.options.elements.arc;return{text:n,fillStyle:s.backgroundColor?s.backgroundColor:l(o.backgroundColor,i,u.backgroundColor),strokeStyle:s.borderColor?s.borderColor:l(o.borderColor,i,u.borderColor),lineWidth:s.borderWidth?s.borderWidth:l(o.borderWidth,i,u.borderWidth),hidden:isNaN(o.data[i])||a.data[i].hidden,index:i}}):[]}},onClick:function(t,e){var n,i,a,r=e.index,o=this.chart;for(n=0,i=(o.data.datasets||[]).length;n<i;++n)(a=o.getDatasetMeta(n)).data[r].hidden=!a.data[r].hidden;o.update()}},tooltips:{callbacks:{title:function(){return""},label:function(t,e){return e.labels[t.index]+": "+t.yLabel}}}}),e.exports=function(t){t.controllers.polarArea=t.DatasetController.extend({dataElementType:a.Arc,linkScales:r.noop,update:function(t){var e=this,n=e.chart,i=n.chartArea,a=e.getMeta(),o=n.options,s=o.elements.arc,l=Math.min(i.right-i.left,i.bottom-i.top);n.outerRadius=Math.max((l-s.borderWidth/2)/2,0),n.innerRadius=Math.max(o.cutoutPercentage?n.outerRadius/100*o.cutoutPercentage:1,0),n.radiusLength=(n.outerRadius-n.innerRadius)/n.getVisibleDatasetCount(),e.outerRadius=n.outerRadius-n.radiusLength*e.index,e.innerRadius=e.outerRadius-n.radiusLength,a.count=e.countVisibleElements(),r.each(a.data,function(n,i){e.updateElement(n,i,t)})},updateElement:function(t,e,n){for(var i=this,a=i.chart,o=i.getDataset(),s=a.options,l=s.animation,u=a.scale,d=a.data.labels,c=i.calculateCircumference(o.data[e]),h=u.xCenter,f=u.yCenter,g=0,m=i.getMeta(),p=0;p<e;++p)isNaN(o.data[p])||m.data[p].hidden||++g;var v=s.startAngle,y=t.hidden?0:u.getDistanceFromCenterForValue(o.data[e]),b=v+c*g,x=b+(t.hidden?0:c),_=l.animateScale?0:u.getDistanceFromCenterForValue(o.data[e]);r.extend(t,{_datasetIndex:i.index,_index:e,_scale:u,_model:{x:h,y:f,innerRadius:0,outerRadius:n?_:y,startAngle:n&&l.animateRotate?v:b,endAngle:n&&l.animateRotate?v:x,label:r.valueAtIndexOrDefault(d,e,d[e])}}),i.removeHoverStyle(t),t.pivot()},removeHoverStyle:function(e){t.DatasetController.prototype.removeHoverStyle.call(this,e,this.chart.options.elements.arc)},countVisibleElements:function(){var t=this.getDataset(),e=this.getMeta(),n=0;return r.each(e.data,function(e,i){isNaN(t.data[i])||e.hidden||n++}),n},calculateCircumference:function(t){var e=this.getMeta().count;return e>0&&!isNaN(t)?2*Math.PI/e:0}})}},{25:25,40:40,45:45}],20:[function(t,e,n){"use strict";var i=t(25),a=t(40),r=t(45);i._set("radar",{scale:{type:"radialLinear"},elements:{line:{tension:0}}}),e.exports=function(t){t.controllers.radar=t.DatasetController.extend({datasetElementType:a.Line,dataElementType:a.Point,linkScales:r.noop,update:function(t){var e=this,n=e.getMeta(),i=n.dataset,a=n.data,o=i.custom||{},s=e.getDataset(),l=e.chart.options.elements.line,u=e.chart.scale;void 0!==s.tension&&void 0===s.lineTension&&(s.lineTension=s.tension),r.extend(n.dataset,{_datasetIndex:e.index,_scale:u,_children:a,_loop:!0,_model:{tension:o.tension?o.tension:r.valueOrDefault(s.lineTension,l.tension),backgroundColor:o.backgroundColor?o.backgroundColor:s.backgroundColor||l.backgroundColor,borderWidth:o.borderWidth?o.borderWidth:s.borderWidth||l.borderWidth,borderColor:o.borderColor?o.borderColor:s.borderColor||l.borderColor,fill:o.fill?o.fill:void 0!==s.fill?s.fill:l.fill,borderCapStyle:o.borderCapStyle?o.borderCapStyle:s.borderCapStyle||l.borderCapStyle,borderDash:o.borderDash?o.borderDash:s.borderDash||l.borderDash,borderDashOffset:o.borderDashOffset?o.borderDashOffset:s.borderDashOffset||l.borderDashOffset,borderJoinStyle:o.borderJoinStyle?o.borderJoinStyle:s.borderJoinStyle||l.borderJoinStyle}}),n.dataset.pivot(),r.each(a,function(n,i){e.updateElement(n,i,t)},e),e.updateBezierControlPoints()},updateElement:function(t,e,n){var i=this,a=t.custom||{},o=i.getDataset(),s=i.chart.scale,l=i.chart.options.elements.point,u=s.getPointPositionForValue(e,o.data[e]);void 0!==o.radius&&void 0===o.pointRadius&&(o.pointRadius=o.radius),void 0!==o.hitRadius&&void 0===o.pointHitRadius&&(o.pointHitRadius=o.hitRadius),r.extend(t,{_datasetIndex:i.index,_index:e,_scale:s,_model:{x:n?s.xCenter:u.x,y:n?s.yCenter:u.y,tension:a.tension?a.tension:r.valueOrDefault(o.lineTension,i.chart.options.elements.line.tension),radius:a.radius?a.radius:r.valueAtIndexOrDefault(o.pointRadius,e,l.radius),backgroundColor:a.backgroundColor?a.backgroundColor:r.valueAtIndexOrDefault(o.pointBackgroundColor,e,l.backgroundColor),borderColor:a.borderColor?a.borderColor:r.valueAtIndexOrDefault(o.pointBorderColor,e,l.borderColor),borderWidth:a.borderWidth?a.borderWidth:r.valueAtIndexOrDefault(o.pointBorderWidth,e,l.borderWidth),pointStyle:a.pointStyle?a.pointStyle:r.valueAtIndexOrDefault(o.pointStyle,e,l.pointStyle),hitRadius:a.hitRadius?a.hitRadius:r.valueAtIndexOrDefault(o.pointHitRadius,e,l.hitRadius)}}),t._model.skip=a.skip?a.skip:isNaN(t._model.x)||isNaN(t._model.y)},updateBezierControlPoints:function(){var t=this.chart.chartArea,e=this.getMeta();r.each(e.data,function(n,i){var a=n._model,o=r.splineCurve(r.previousItem(e.data,i,!0)._model,a,r.nextItem(e.data,i,!0)._model,a.tension);a.controlPointPreviousX=Math.max(Math.min(o.previous.x,t.right),t.left),a.controlPointPreviousY=Math.max(Math.min(o.previous.y,t.bottom),t.top),a.controlPointNextX=Math.max(Math.min(o.next.x,t.right),t.left),a.controlPointNextY=Math.max(Math.min(o.next.y,t.bottom),t.top),n.pivot()})},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t.custom||{},i=t._index,a=t._model;a.radius=n.hoverRadius?n.hoverRadius:r.valueAtIndexOrDefault(e.pointHoverRadius,i,this.chart.options.elements.point.hoverRadius),a.backgroundColor=n.hoverBackgroundColor?n.hoverBackgroundColor:r.valueAtIndexOrDefault(e.pointHoverBackgroundColor,i,r.getHoverColor(a.backgroundColor)),a.borderColor=n.hoverBorderColor?n.hoverBorderColor:r.valueAtIndexOrDefault(e.pointHoverBorderColor,i,r.getHoverColor(a.borderColor)),a.borderWidth=n.hoverBorderWidth?n.hoverBorderWidth:r.valueAtIndexOrDefault(e.pointHoverBorderWidth,i,a.borderWidth)},removeHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t.custom||{},i=t._index,a=t._model,o=this.chart.options.elements.point;a.radius=n.radius?n.radius:r.valueAtIndexOrDefault(e.pointRadius,i,o.radius),a.backgroundColor=n.backgroundColor?n.backgroundColor:r.valueAtIndexOrDefault(e.pointBackgroundColor,i,o.backgroundColor),a.borderColor=n.borderColor?n.borderColor:r.valueAtIndexOrDefault(e.pointBorderColor,i,o.borderColor),a.borderWidth=n.borderWidth?n.borderWidth:r.valueAtIndexOrDefault(e.pointBorderWidth,i,o.borderWidth)}})}},{25:25,40:40,45:45}],21:[function(t,e,n){"use strict";t(25)._set("scatter",{hover:{mode:"single"},scales:{xAxes:[{id:"x-axis-1",type:"linear",position:"bottom"}],yAxes:[{id:"y-axis-1",type:"linear",position:"left"}]},showLines:!1,tooltips:{callbacks:{title:function(){return""},label:function(t){return"("+t.xLabel+", "+t.yLabel+")"}}}}),e.exports=function(t){t.controllers.scatter=t.controllers.line}},{25:25}],22:[function(t,e,n){"use strict";var i=t(25),a=t(26),r=t(45);i._set("global",{animation:{duration:1e3,easing:"easeOutQuart",onProgress:r.noop,onComplete:r.noop}}),e.exports=function(t){t.Animation=a.extend({chart:null,currentStep:0,numSteps:60,easing:"",render:null,onAnimationProgress:null,onAnimationComplete:null}),t.animationService={frameDuration:17,animations:[],dropFrames:0,request:null,addAnimation:function(t,e,n,i){var a,r,o=this.animations;for(e.chart=t,i||(t.animating=!0),a=0,r=o.length;a<r;++a)if(o[a].chart===t)return void(o[a]=e);o.push(e),1===o.length&&this.requestAnimationFrame()},cancelAnimation:function(t){var e=r.findIndex(this.animations,function(e){return e.chart===t});-1!==e&&(this.animations.splice(e,1),t.animating=!1)},requestAnimationFrame:function(){var t=this;null===t.request&&(t.request=r.requestAnimFrame.call(window,function(){t.request=null,t.startDigest()}))},startDigest:function(){var t=this,e=Date.now(),n=0;t.dropFrames>1&&(n=Math.floor(t.dropFrames),t.dropFrames=t.dropFrames%1),t.advance(1+n);var i=Date.now();t.dropFrames+=(i-e)/t.frameDuration,t.animations.length>0&&t.requestAnimationFrame()},advance:function(t){for(var e,n,i=this.animations,a=0;a<i.length;)n=(e=i[a]).chart,e.currentStep=(e.currentStep||0)+t,e.currentStep=Math.min(e.currentStep,e.numSteps),r.callback(e.render,[n,e],n),r.callback(e.onAnimationProgress,[e],n),e.currentStep>=e.numSteps?(r.callback(e.onAnimationComplete,[e],n),n.animating=!1,i.splice(a,1)):++a}},Object.defineProperty(t.Animation.prototype,"animationObject",{get:function(){return this}}),Object.defineProperty(t.Animation.prototype,"chartInstance",{get:function(){return this.chart},set:function(t){this.chart=t}})}},{25:25,26:26,45:45}],23:[function(t,e,n){"use strict";var i=t(25),a=t(45),r=t(28),o=t(48);e.exports=function(t){function e(t){var e=(t=t||{}).data=t.data||{};return e.datasets=e.datasets||[],e.labels=e.labels||[],t.options=a.configMerge(i.global,i[t.type],t.options||{}),t}function n(t){var e=t.options;e.scale?t.scale.options=e.scale:e.scales&&e.scales.xAxes.concat(e.scales.yAxes).forEach(function(e){t.scales[e.id].options=e}),t.tooltip._options=e.tooltips}function s(t){return"top"===t||"bottom"===t}var l=t.plugins;t.types={},t.instances={},t.controllers={},a.extend(t.prototype,{construct:function(n,i){var r=this;i=e(i);var s=o.acquireContext(n,i),l=s&&s.canvas,u=l&&l.height,d=l&&l.width;r.id=a.uid(),r.ctx=s,r.canvas=l,r.config=i,r.width=d,r.height=u,r.aspectRatio=u?d/u:null,r.options=i.options,r._bufferedRender=!1,r.chart=r,r.controller=r,t.instances[r.id]=r,Object.defineProperty(r,"data",{get:function(){return r.config.data},set:function(t){r.config.data=t}}),s&&l?(r.initialize(),r.update()):console.error("Failed to create chart: can't acquire context from the given item")},initialize:function(){var t=this;return l.notify(t,"beforeInit"),a.retinaScale(t,t.options.devicePixelRatio),t.bindEvents(),t.options.responsive&&t.resize(!0),t.ensureScalesHaveIDs(),t.buildScales(),t.initToolTip(),l.notify(t,"afterInit"),t},clear:function(){return a.canvas.clear(this),this},stop:function(){return t.animationService.cancelAnimation(this),this},resize:function(t){var e=this,n=e.options,i=e.canvas,r=n.maintainAspectRatio&&e.aspectRatio||null,o=Math.max(0,Math.floor(a.getMaximumWidth(i))),s=Math.max(0,Math.floor(r?o/r:a.getMaximumHeight(i)));if((e.width!==o||e.height!==s)&&(i.width=e.width=o,i.height=e.height=s,i.style.width=o+"px",i.style.height=s+"px",a.retinaScale(e,n.devicePixelRatio),!t)){var u={width:o,height:s};l.notify(e,"resize",[u]),e.options.onResize&&e.options.onResize(e,u),e.stop(),e.update(e.options.responsiveAnimationDuration)}},ensureScalesHaveIDs:function(){var t=this.options,e=t.scales||{},n=t.scale;a.each(e.xAxes,function(t,e){t.id=t.id||"x-axis-"+e}),a.each(e.yAxes,function(t,e){t.id=t.id||"y-axis-"+e}),n&&(n.id=n.id||"scale")},buildScales:function(){var e=this,n=e.options,i=e.scales={},r=[];n.scales&&(r=r.concat((n.scales.xAxes||[]).map(function(t){return{options:t,dtype:"category",dposition:"bottom"}}),(n.scales.yAxes||[]).map(function(t){return{options:t,dtype:"linear",dposition:"left"}}))),n.scale&&r.push({options:n.scale,dtype:"radialLinear",isDefault:!0,dposition:"chartArea"}),a.each(r,function(n){var r=n.options,o=a.valueOrDefault(r.type,n.dtype),l=t.scaleService.getScaleConstructor(o);if(l){s(r.position)!==s(n.dposition)&&(r.position=n.dposition);var u=new l({id:r.id,options:r,ctx:e.ctx,chart:e});i[u.id]=u,u.mergeTicksOptions(),n.isDefault&&(e.scale=u)}}),t.scaleService.addScalesToLayout(this)},buildOrUpdateControllers:function(){var e=this,n=[],i=[];return a.each(e.data.datasets,function(a,r){var o=e.getDatasetMeta(r),s=a.type||e.config.type;if(o.type&&o.type!==s&&(e.destroyDatasetMeta(r),o=e.getDatasetMeta(r)),o.type=s,n.push(o.type),o.controller)o.controller.updateIndex(r);else{var l=t.controllers[o.type];if(void 0===l)throw new Error('"'+o.type+'" is not a chart type.');o.controller=new l(e,r),i.push(o.controller)}},e),i},resetElements:function(){var t=this;a.each(t.data.datasets,function(e,n){t.getDatasetMeta(n).controller.reset()},t)},reset:function(){this.resetElements(),this.tooltip.initialize()},update:function(t){var e=this;if(t&&"object"==typeof t||(t={duration:t,lazy:arguments[1]}),n(e),!1!==l.notify(e,"beforeUpdate")){e.tooltip._data=e.data;var i=e.buildOrUpdateControllers();a.each(e.data.datasets,function(t,n){e.getDatasetMeta(n).controller.buildOrUpdateElements()},e),e.updateLayout(),a.each(i,function(t){t.reset()}),e.updateDatasets(),l.notify(e,"afterUpdate"),e._bufferedRender?e._bufferedRequest={duration:t.duration,easing:t.easing,lazy:t.lazy}:e.render(t)}},updateLayout:function(){var e=this;!1!==l.notify(e,"beforeLayout")&&(t.layoutService.update(this,this.width,this.height),l.notify(e,"afterScaleUpdate"),l.notify(e,"afterLayout"))},updateDatasets:function(){var t=this;if(!1!==l.notify(t,"beforeDatasetsUpdate")){for(var e=0,n=t.data.datasets.length;e<n;++e)t.updateDataset(e);l.notify(t,"afterDatasetsUpdate")}},updateDataset:function(t){var e=this,n=e.getDatasetMeta(t),i={meta:n,index:t};!1!==l.notify(e,"beforeDatasetUpdate",[i])&&(n.controller.update(),l.notify(e,"afterDatasetUpdate",[i]))},render:function(e){var n=this;e&&"object"==typeof e||(e={duration:e,lazy:arguments[1]});var i=e.duration,r=e.lazy;if(!1!==l.notify(n,"beforeRender")){var o=n.options.animation,s=function(t){l.notify(n,"afterRender"),a.callback(o&&o.onComplete,[t],n)};if(o&&(void 0!==i&&0!==i||void 0===i&&0!==o.duration)){var u=new t.Animation({numSteps:(i||o.duration)/16.66,easing:e.easing||o.easing,render:function(t,e){var n=a.easing.effects[e.easing],i=e.currentStep,r=i/e.numSteps;t.draw(n(r),r,i)},onAnimationProgress:o.onProgress,onAnimationComplete:s});t.animationService.addAnimation(n,u,i,r)}else n.draw(),s(new t.Animation({numSteps:0,chart:n}));return n}},draw:function(t){var e=this;e.clear(),a.isNullOrUndef(t)&&(t=1),e.transition(t),!1!==l.notify(e,"beforeDraw",[t])&&(a.each(e.boxes,function(t){t.draw(e.chartArea)},e),e.scale&&e.scale.draw(),e.drawDatasets(t),e.tooltip.draw(),l.notify(e,"afterDraw",[t]))},transition:function(t){for(var e=this,n=0,i=(e.data.datasets||[]).length;n<i;++n)e.isDatasetVisible(n)&&e.getDatasetMeta(n).controller.transition(t);e.tooltip.transition(t)},drawDatasets:function(t){var e=this;if(!1!==l.notify(e,"beforeDatasetsDraw",[t])){for(var n=(e.data.datasets||[]).length-1;n>=0;--n)e.isDatasetVisible(n)&&e.drawDataset(n,t);l.notify(e,"afterDatasetsDraw",[t])}},drawDataset:function(t,e){var n=this,i=n.getDatasetMeta(t),a={meta:i,index:t,easingValue:e};!1!==l.notify(n,"beforeDatasetDraw",[a])&&(i.controller.draw(e),l.notify(n,"afterDatasetDraw",[a]))},getElementAtEvent:function(t){return r.modes.single(this,t)},getElementsAtEvent:function(t){return r.modes.label(this,t,{intersect:!0})},getElementsAtXAxis:function(t){return r.modes["x-axis"](this,t,{intersect:!0})},getElementsAtEventForMode:function(t,e,n){var i=r.modes[e];return"function"==typeof i?i(this,t,n):[]},getDatasetAtEvent:function(t){return r.modes.dataset(this,t,{intersect:!0})},getDatasetMeta:function(t){var e=this,n=e.data.datasets[t];n._meta||(n._meta={});var i=n._meta[e.id];return i||(i=n._meta[e.id]={type:null,data:[],dataset:null,controller:null,hidden:null,xAxisID:null,yAxisID:null}),i},getVisibleDatasetCount:function(){for(var t=0,e=0,n=this.data.datasets.length;e<n;++e)this.isDatasetVisible(e)&&t++;return t},isDatasetVisible:function(t){var e=this.getDatasetMeta(t);return"boolean"==typeof e.hidden?!e.hidden:!this.data.datasets[t].hidden},generateLegend:function(){return this.options.legendCallback(this)},destroyDatasetMeta:function(t){var e=this.id,n=this.data.datasets[t],i=n._meta&&n._meta[e];i&&(i.controller.destroy(),delete n._meta[e])},destroy:function(){var e,n,i=this,r=i.canvas;for(i.stop(),e=0,n=i.data.datasets.length;e<n;++e)i.destroyDatasetMeta(e);r&&(i.unbindEvents(),a.canvas.clear(i),o.releaseContext(i.ctx),i.canvas=null,i.ctx=null),l.notify(i,"destroy"),delete t.instances[i.id]},toBase64Image:function(){return this.canvas.toDataURL.apply(this.canvas,arguments)},initToolTip:function(){var e=this;e.tooltip=new t.Tooltip({_chart:e,_chartInstance:e,_data:e.data,_options:e.options.tooltips},e)},bindEvents:function(){var t=this,e=t._listeners={},n=function(){t.eventHandler.apply(t,arguments)};a.each(t.options.events,function(i){o.addEventListener(t,i,n),e[i]=n}),t.options.responsive&&(n=function(){t.resize()},o.addEventListener(t,"resize",n),e.resize=n)},unbindEvents:function(){var t=this,e=t._listeners;e&&(delete t._listeners,a.each(e,function(e,n){o.removeEventListener(t,n,e)}))},updateHoverStyle:function(t,e,n){var i,a,r,o=n?"setHoverStyle":"removeHoverStyle";for(a=0,r=t.length;a<r;++a)(i=t[a])&&this.getDatasetMeta(i._datasetIndex).controller[o](i)},eventHandler:function(t){var e=this,n=e.tooltip;if(!1!==l.notify(e,"beforeEvent",[t])){e._bufferedRender=!0,e._bufferedRequest=null;var i=e.handleEvent(t);i|=n&&n.handleEvent(t),l.notify(e,"afterEvent",[t]);var a=e._bufferedRequest;return a?e.render(a):i&&!e.animating&&(e.stop(),e.render(e.options.hover.animationDuration,!0)),e._bufferedRender=!1,e._bufferedRequest=null,e}},handleEvent:function(t){var e=this,n=e.options||{},i=n.hover,r=!1;return e.lastActive=e.lastActive||[],"mouseout"===t.type?e.active=[]:e.active=e.getElementsAtEventForMode(t,i.mode,i),a.callback(n.onHover||n.hover.onHover,[t.native,e.active],e),"mouseup"!==t.type&&"click"!==t.type||n.onClick&&n.onClick.call(e,t.native,e.active),e.lastActive.length&&e.updateHoverStyle(e.lastActive,i.mode,!1),e.active.length&&i.mode&&e.updateHoverStyle(e.active,i.mode,!0),r=!a.arrayEquals(e.active,e.lastActive),e.lastActive=e.active,r}}),t.Controller=t}},{25:25,28:28,45:45,48:48}],24:[function(t,e,n){"use strict";var i=t(45);e.exports=function(t){function e(t,e){t._chartjs?t._chartjs.listeners.push(e):(Object.defineProperty(t,"_chartjs",{configurable:!0,enumerable:!1,value:{listeners:[e]}}),a.forEach(function(e){var n="onData"+e.charAt(0).toUpperCase()+e.slice(1),a=t[e];Object.defineProperty(t,e,{configurable:!0,enumerable:!1,value:function(){var e=Array.prototype.slice.call(arguments),r=a.apply(this,e);return i.each(t._chartjs.listeners,function(t){"function"==typeof t[n]&&t[n].apply(t,e)}),r}})}))}function n(t,e){var n=t._chartjs;if(n){var i=n.listeners,r=i.indexOf(e);-1!==r&&i.splice(r,1),i.length>0||(a.forEach(function(e){delete t[e]}),delete t._chartjs)}}var a=["push","pop","shift","splice","unshift"];t.DatasetController=function(t,e){this.initialize(t,e)},i.extend(t.DatasetController.prototype,{datasetElementType:null,dataElementType:null,initialize:function(t,e){var n=this;n.chart=t,n.index=e,n.linkScales(),n.addElements()},updateIndex:function(t){this.index=t},linkScales:function(){var t=this,e=t.getMeta(),n=t.getDataset();null===e.xAxisID&&(e.xAxisID=n.xAxisID||t.chart.options.scales.xAxes[0].id),null===e.yAxisID&&(e.yAxisID=n.yAxisID||t.chart.options.scales.yAxes[0].id)},getDataset:function(){return this.chart.data.datasets[this.index]},getMeta:function(){return this.chart.getDatasetMeta(this.index)},getScaleForId:function(t){return this.chart.scales[t]},reset:function(){this.update(!0)},destroy:function(){this._data&&n(this._data,this)},createMetaDataset:function(){var t=this,e=t.datasetElementType;return e&&new e({_chart:t.chart,_datasetIndex:t.index})},createMetaData:function(t){var e=this,n=e.dataElementType;return n&&new n({_chart:e.chart,_datasetIndex:e.index,_index:t})},addElements:function(){var t,e,n=this,i=n.getMeta(),a=n.getDataset().data||[],r=i.data;for(t=0,e=a.length;t<e;++t)r[t]=r[t]||n.createMetaData(t);i.dataset=i.dataset||n.createMetaDataset()},addElementAndReset:function(t){var e=this.createMetaData(t);this.getMeta().data.splice(t,0,e),this.updateElement(e,t,!0)},buildOrUpdateElements:function(){var t=this,i=t.getDataset(),a=i.data||(i.data=[]);t._data!==a&&(t._data&&n(t._data,t),e(a,t),t._data=a),t.resyncElements()},update:i.noop,transition:function(t){for(var e=this.getMeta(),n=e.data||[],i=n.length,a=0;a<i;++a)n[a].transition(t);e.dataset&&e.dataset.transition(t)},draw:function(){var t=this.getMeta(),e=t.data||[],n=e.length,i=0;for(t.dataset&&t.dataset.draw();i<n;++i)e[i].draw()},removeHoverStyle:function(t,e){var n=this.chart.data.datasets[t._datasetIndex],a=t._index,r=t.custom||{},o=i.valueAtIndexOrDefault,s=t._model;s.backgroundColor=r.backgroundColor?r.backgroundColor:o(n.backgroundColor,a,e.backgroundColor),s.borderColor=r.borderColor?r.borderColor:o(n.borderColor,a,e.borderColor),s.borderWidth=r.borderWidth?r.borderWidth:o(n.borderWidth,a,e.borderWidth)},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t._index,a=t.custom||{},r=i.valueAtIndexOrDefault,o=i.getHoverColor,s=t._model;s.backgroundColor=a.hoverBackgroundColor?a.hoverBackgroundColor:r(e.hoverBackgroundColor,n,o(s.backgroundColor)),s.borderColor=a.hoverBorderColor?a.hoverBorderColor:r(e.hoverBorderColor,n,o(s.borderColor)),s.borderWidth=a.hoverBorderWidth?a.hoverBorderWidth:r(e.hoverBorderWidth,n,s.borderWidth)},resyncElements:function(){var t=this,e=t.getMeta(),n=t.getDataset().data,i=e.data.length,a=n.length;a<i?e.data.splice(a,i-a):a>i&&t.insertElements(i,a-i)},insertElements:function(t,e){for(var n=0;n<e;++n)this.addElementAndReset(t+n)},onDataPush:function(){this.insertElements(this.getDataset().data.length-1,arguments.length)},onDataPop:function(){this.getMeta().data.pop()},onDataShift:function(){this.getMeta().data.shift()},onDataSplice:function(t,e){this.getMeta().data.splice(t,e),this.insertElements(t,arguments.length-2)},onDataUnshift:function(){this.insertElements(0,arguments.length)}}),t.DatasetController.extend=i.inherits}},{45:45}],25:[function(t,e,n){"use strict";var i=t(45);e.exports={_set:function(t,e){return i.merge(this[t]||(this[t]={}),e)}}},{45:45}],26:[function(t,e,n){"use strict";function i(t,e,n,i){var r,o,s,l,u,d,c,h,f,g=Object.keys(n);for(r=0,o=g.length;r<o;++r)if(s=g[r],d=n[s],e.hasOwnProperty(s)||(e[s]=d),(l=e[s])!==d&&"_"!==s[0]){if(t.hasOwnProperty(s)||(t[s]=l),u=t[s],(c=typeof d)===typeof u)if("string"===c){if((h=a(u)).valid&&(f=a(d)).valid){e[s]=f.mix(h,i).rgbString();continue}}else if("number"===c&&isFinite(u)&&isFinite(d)){e[s]=u+(d-u)*i;continue}e[s]=d}}var a=t(2),r=t(45),o=function(t){r.extend(this,t),this.initialize.apply(this,arguments)};r.extend(o.prototype,{initialize:function(){this.hidden=!1},pivot:function(){var t=this;return t._view||(t._view=r.clone(t._model)),t._start={},t},transition:function(t){var e=this,n=e._model,a=e._start,r=e._view;return n&&1!==t?(r||(r=e._view={}),a||(a=e._start={}),i(a,r,n,t),e):(e._view=n,e._start=null,e)},tooltipPosition:function(){return{x:this._model.x,y:this._model.y}},hasValue:function(){return r.isNumber(this._model.x)&&r.isNumber(this._model.y)}}),o.extend=r.inherits,e.exports=o},{2:2,45:45}],27:[function(t,e,n){"use strict";var i=t(2),a=t(25),r=t(45);e.exports=function(t){function e(t,e,n){var i;return"string"==typeof t?(i=parseInt(t,10),-1!==t.indexOf("%")&&(i=i/100*e.parentNode[n])):i=t,i}function n(t){return void 0!==t&&null!==t&&"none"!==t}function o(t,i,a){var r=document.defaultView,o=t.parentNode,s=r.getComputedStyle(t)[i],l=r.getComputedStyle(o)[i],u=n(s),d=n(l),c=Number.POSITIVE_INFINITY;return u||d?Math.min(u?e(s,t,a):c,d?e(l,o,a):c):"none"}r.extend=function(t){for(var e=1,n=arguments.length;e<n;e++)r.each(arguments[e],function(e,n){t[n]=e});return t},r.configMerge=function(){return r.merge(r.clone(arguments[0]),[].slice.call(arguments,1),{merger:function(e,n,i,a){var o=n[e]||{},s=i[e];"scales"===e?n[e]=r.scaleMerge(o,s):"scale"===e?n[e]=r.merge(o,[t.scaleService.getScaleDefaults(s.type),s]):r._merger(e,n,i,a)}})},r.scaleMerge=function(){return r.merge(r.clone(arguments[0]),[].slice.call(arguments,1),{merger:function(e,n,i,a){if("xAxes"===e||"yAxes"===e){var o,s,l,u=i[e].length;for(n[e]||(n[e]=[]),o=0;o<u;++o)l=i[e][o],s=r.valueOrDefault(l.type,"xAxes"===e?"category":"linear"),o>=n[e].length&&n[e].push({}),!n[e][o].type||l.type&&l.type!==n[e][o].type?r.merge(n[e][o],[t.scaleService.getScaleDefaults(s),l]):r.merge(n[e][o],l)}else r._merger(e,n,i,a)}})},r.where=function(t,e){if(r.isArray(t)&&Array.prototype.filter)return t.filter(e);var n=[];return r.each(t,function(t){e(t)&&n.push(t)}),n},r.findIndex=Array.prototype.findIndex?function(t,e,n){return t.findIndex(e,n)}:function(t,e,n){n=void 0===n?t:n;for(var i=0,a=t.length;i<a;++i)if(e.call(n,t[i],i,t))return i;return-1},r.findNextWhere=function(t,e,n){r.isNullOrUndef(n)&&(n=-1);for(var i=n+1;i<t.length;i++){var a=t[i];if(e(a))return a}},r.findPreviousWhere=function(t,e,n){r.isNullOrUndef(n)&&(n=t.length);for(var i=n-1;i>=0;i--){var a=t[i];if(e(a))return a}},r.inherits=function(t){var e=this,n=t&&t.hasOwnProperty("constructor")?t.constructor:function(){return e.apply(this,arguments)},i=function(){this.constructor=n};return i.prototype=e.prototype,n.prototype=new i,n.extend=r.inherits,t&&r.extend(n.prototype,t),n.__super__=e.prototype,n},r.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},r.almostEquals=function(t,e,n){return Math.abs(t-e)<n},r.almostWhole=function(t,e){var n=Math.round(t);return n-e<t&&n+e>t},r.max=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.max(t,e)},Number.NEGATIVE_INFINITY)},r.min=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.min(t,e)},Number.POSITIVE_INFINITY)},r.sign=Math.sign?function(t){return Math.sign(t)}:function(t){return 0==(t=+t)||isNaN(t)?t:t>0?1:-1},r.log10=Math.log10?function(t){return Math.log10(t)}:function(t){return Math.log(t)/Math.LN10},r.toRadians=function(t){return t*(Math.PI/180)},r.toDegrees=function(t){return t*(180/Math.PI)},r.getAngleFromPoint=function(t,e){var n=e.x-t.x,i=e.y-t.y,a=Math.sqrt(n*n+i*i),r=Math.atan2(i,n);return r<-.5*Math.PI&&(r+=2*Math.PI),{angle:r,distance:a}},r.distanceBetweenPoints=function(t,e){return Math.sqrt(Math.pow(e.x-t.x,2)+Math.pow(e.y-t.y,2))},r.aliasPixel=function(t){return t%2==0?0:.5},r.splineCurve=function(t,e,n,i){var a=t.skip?e:t,r=e,o=n.skip?e:n,s=Math.sqrt(Math.pow(r.x-a.x,2)+Math.pow(r.y-a.y,2)),l=Math.sqrt(Math.pow(o.x-r.x,2)+Math.pow(o.y-r.y,2)),u=s/(s+l),d=l/(s+l),c=i*(u=isNaN(u)?0:u),h=i*(d=isNaN(d)?0:d);return{previous:{x:r.x-c*(o.x-a.x),y:r.y-c*(o.y-a.y)},next:{x:r.x+h*(o.x-a.x),y:r.y+h*(o.y-a.y)}}},r.EPSILON=Number.EPSILON||1e-14,r.splineCurveMonotone=function(t){var e,n,i,a,o=(t||[]).map(function(t){return{model:t._model,deltaK:0,mK:0}}),s=o.length;for(e=0;e<s;++e)if(!(i=o[e]).model.skip){if(n=e>0?o[e-1]:null,(a=e<s-1?o[e+1]:null)&&!a.model.skip){var l=a.model.x-i.model.x;i.deltaK=0!==l?(a.model.y-i.model.y)/l:0}!n||n.model.skip?i.mK=i.deltaK:!a||a.model.skip?i.mK=n.deltaK:this.sign(n.deltaK)!==this.sign(i.deltaK)?i.mK=0:i.mK=(n.deltaK+i.deltaK)/2}var u,d,c,h;for(e=0;e<s-1;++e)i=o[e],a=o[e+1],i.model.skip||a.model.skip||(r.almostEquals(i.deltaK,0,this.EPSILON)?i.mK=a.mK=0:(u=i.mK/i.deltaK,d=a.mK/i.deltaK,(h=Math.pow(u,2)+Math.pow(d,2))<=9||(c=3/Math.sqrt(h),i.mK=u*c*i.deltaK,a.mK=d*c*i.deltaK)));var f;for(e=0;e<s;++e)(i=o[e]).model.skip||(n=e>0?o[e-1]:null,a=e<s-1?o[e+1]:null,n&&!n.model.skip&&(f=(i.model.x-n.model.x)/3,i.model.controlPointPreviousX=i.model.x-f,i.model.controlPointPreviousY=i.model.y-f*i.mK),a&&!a.model.skip&&(f=(a.model.x-i.model.x)/3,i.model.controlPointNextX=i.model.x+f,i.model.controlPointNextY=i.model.y+f*i.mK))},r.nextItem=function(t,e,n){return n?e>=t.length-1?t[0]:t[e+1]:e>=t.length-1?t[t.length-1]:t[e+1]},r.previousItem=function(t,e,n){return n?e<=0?t[t.length-1]:t[e-1]:e<=0?t[0]:t[e-1]},r.niceNum=function(t,e){var n=Math.floor(r.log10(t)),i=t/Math.pow(10,n);return(e?i<1.5?1:i<3?2:i<7?5:10:i<=1?1:i<=2?2:i<=5?5:10)*Math.pow(10,n)},r.requestAnimFrame="undefined"==typeof window?function(t){t()}:window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)},r.getRelativePosition=function(t,e){var n,i,a=t.originalEvent||t,o=t.currentTarget||t.srcElement,s=o.getBoundingClientRect(),l=a.touches;l&&l.length>0?(n=l[0].clientX,i=l[0].clientY):(n=a.clientX,i=a.clientY);var u=parseFloat(r.getStyle(o,"padding-left")),d=parseFloat(r.getStyle(o,"padding-top")),c=parseFloat(r.getStyle(o,"padding-right")),h=parseFloat(r.getStyle(o,"padding-bottom")),f=s.right-s.left-u-c,g=s.bottom-s.top-d-h;return n=Math.round((n-s.left-u)/f*o.width/e.currentDevicePixelRatio),i=Math.round((i-s.top-d)/g*o.height/e.currentDevicePixelRatio),{x:n,y:i}},r.getConstraintWidth=function(t){return o(t,"max-width","clientWidth")},r.getConstraintHeight=function(t){return o(t,"max-height","clientHeight")},r.getMaximumWidth=function(t){var e=t.parentNode;if(!e)return t.clientWidth;var n=parseInt(r.getStyle(e,"padding-left"),10),i=parseInt(r.getStyle(e,"padding-right"),10),a=e.clientWidth-n-i,o=r.getConstraintWidth(t);return isNaN(o)?a:Math.min(a,o)},r.getMaximumHeight=function(t){var e=t.parentNode;if(!e)return t.clientHeight;var n=parseInt(r.getStyle(e,"padding-top"),10),i=parseInt(r.getStyle(e,"padding-bottom"),10),a=e.clientHeight-n-i,o=r.getConstraintHeight(t);return isNaN(o)?a:Math.min(a,o)},r.getStyle=function(t,e){return t.currentStyle?t.currentStyle[e]:document.defaultView.getComputedStyle(t,null).getPropertyValue(e)},r.retinaScale=function(t,e){var n=t.currentDevicePixelRatio=e||window.devicePixelRatio||1;if(1!==n){var i=t.canvas,a=t.height,r=t.width;i.height=a*n,i.width=r*n,t.ctx.scale(n,n),i.style.height=a+"px",i.style.width=r+"px"}},r.fontString=function(t,e,n){return e+" "+t+"px "+n},r.longestText=function(t,e,n,i){var a=(i=i||{}).data=i.data||{},o=i.garbageCollect=i.garbageCollect||[];i.font!==e&&(a=i.data={},o=i.garbageCollect=[],i.font=e),t.font=e;var s=0;r.each(n,function(e){void 0!==e&&null!==e&&!0!==r.isArray(e)?s=r.measureText(t,a,o,s,e):r.isArray(e)&&r.each(e,function(e){void 0===e||null===e||r.isArray(e)||(s=r.measureText(t,a,o,s,e))})});var l=o.length/2;if(l>n.length){for(var u=0;u<l;u++)delete a[o[u]];o.splice(0,l)}return s},r.measureText=function(t,e,n,i,a){var r=e[a];return r||(r=e[a]=t.measureText(a).width,n.push(a)),r>i&&(i=r),i},r.numberOfLabelLines=function(t){var e=1;return r.each(t,function(t){r.isArray(t)&&t.length>e&&(e=t.length)}),e},r.color=i?function(t){return t instanceof CanvasGradient&&(t=a.global.defaultColor),i(t)}:function(t){return console.error("Color.js not found!"),t},r.getHoverColor=function(t){return t instanceof CanvasPattern?t:r.color(t).saturate(.5).darken(.1).rgbString()}}},{2:2,25:25,45:45}],28:[function(t,e,n){"use strict";function i(t,e){return t.native?{x:t.x,y:t.y}:u.getRelativePosition(t,e)}function a(t,e){var n,i,a,r,o;for(i=0,r=t.data.datasets.length;i<r;++i)if(t.isDatasetVisible(i))for(a=0,o=(n=t.getDatasetMeta(i)).data.length;a<o;++a){var s=n.data[a];s._view.skip||e(s)}}function r(t,e){var n=[];return a(t,function(t){t.inRange(e.x,e.y)&&n.push(t)}),n}function o(t,e,n,i){var r=Number.POSITIVE_INFINITY,o=[];return a(t,function(t){if(!n||t.inRange(e.x,e.y)){var a=t.getCenterPoint(),s=i(e,a);s<r?(o=[t],r=s):s===r&&o.push(t)}}),o}function s(t){var e=-1!==t.indexOf("x"),n=-1!==t.indexOf("y");return function(t,i){var a=e?Math.abs(t.x-i.x):0,r=n?Math.abs(t.y-i.y):0;return Math.sqrt(Math.pow(a,2)+Math.pow(r,2))}}function l(t,e,n){var a=i(e,t);n.axis=n.axis||"x";var l=s(n.axis),u=n.intersect?r(t,a):o(t,a,!1,l),d=[];return u.length?(t.data.datasets.forEach(function(e,n){if(t.isDatasetVisible(n)){var i=t.getDatasetMeta(n).data[u[0]._index];i&&!i._view.skip&&d.push(i)}}),d):[]}var u=t(45);e.exports={modes:{single:function(t,e){var n=i(e,t),r=[];return a(t,function(t){if(t.inRange(n.x,n.y))return r.push(t),r}),r.slice(0,1)},label:l,index:l,dataset:function(t,e,n){var a=i(e,t);n.axis=n.axis||"xy";var l=s(n.axis),u=n.intersect?r(t,a):o(t,a,!1,l);return u.length>0&&(u=t.getDatasetMeta(u[0]._datasetIndex).data),u},"x-axis":function(t,e){return l(t,e,{intersect:!1})},point:function(t,e){return r(t,i(e,t))},nearest:function(t,e,n){var a=i(e,t);n.axis=n.axis||"xy";var r=s(n.axis),l=o(t,a,n.intersect,r);return l.length>1&&l.sort(function(t,e){var n=t.getArea()-e.getArea();return 0===n&&(n=t._datasetIndex-e._datasetIndex),n}),l.slice(0,1)},x:function(t,e,n){var r=i(e,t),o=[],s=!1;return a(t,function(t){t.inXRange(r.x)&&o.push(t),t.inRange(r.x,r.y)&&(s=!0)}),n.intersect&&!s&&(o=[]),o},y:function(t,e,n){var r=i(e,t),o=[],s=!1;return a(t,function(t){t.inYRange(r.y)&&o.push(t),t.inRange(r.x,r.y)&&(s=!0)}),n.intersect&&!s&&(o=[]),o}}}},{45:45}],29:[function(t,e,n){"use strict";t(25)._set("global",{responsive:!0,responsiveAnimationDuration:0,maintainAspectRatio:!0,events:["mousemove","mouseout","click","touchstart","touchmove"],hover:{onHover:null,mode:"nearest",intersect:!0,animationDuration:400},onClick:null,defaultColor:"rgba(0,0,0,0.1)",defaultFontColor:"#666",defaultFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",defaultFontSize:12,defaultFontStyle:"normal",showLines:!0,elements:{},layout:{padding:{top:0,right:0,bottom:0,left:0}}}),e.exports=function(){var t=function(t,e){return this.construct(t,e),this};return t.Chart=t,t}},{25:25}],30:[function(t,e,n){"use strict";var i=t(45);e.exports=function(t){function e(t,e){return i.where(t,function(t){return t.position===e})}function n(t,e){t.forEach(function(t,e){return t._tmpIndex_=e,t}),t.sort(function(t,n){var i=e?n:t,a=e?t:n;return i.weight===a.weight?i._tmpIndex_-a._tmpIndex_:i.weight-a.weight}),t.forEach(function(t){delete t._tmpIndex_})}t.layoutService={defaults:{},addBox:function(t,e){t.boxes||(t.boxes=[]),e.fullWidth=e.fullWidth||!1,e.position=e.position||"top",e.weight=e.weight||0,t.boxes.push(e)},removeBox:function(t,e){var n=t.boxes?t.boxes.indexOf(e):-1;-1!==n&&t.boxes.splice(n,1)},configure:function(t,e,n){for(var i,a=["fullWidth","position","weight"],r=a.length,o=0;o<r;++o)i=a[o],n.hasOwnProperty(i)&&(e[i]=n[i])},update:function(t,a,r){function o(t){var e=i.findNextWhere(D,function(e){return e.box===t});if(e)if(t.isHorizontal()){var n={left:Math.max(A,C),right:Math.max(O,P),top:0,bottom:0};t.update(t.fullWidth?b:M,x/2,n)}else t.update(e.minSize.width,S)}function s(t){t.isHorizontal()?(t.left=t.fullWidth?d:A,t.right=t.fullWidth?a-c:A+M,t.top=B,t.bottom=B+t.height,B=t.bottom):(t.left=z,t.right=z+t.width,t.top=F,t.bottom=F+S,z=t.right)}if(t){var l=t.options.layout||{},u=i.options.toPadding(l.padding),d=u.left,c=u.right,h=u.top,f=u.bottom,g=e(t.boxes,"left"),m=e(t.boxes,"right"),p=e(t.boxes,"top"),v=e(t.boxes,"bottom"),y=e(t.boxes,"chartArea");n(g,!0),n(m,!1),n(p,!0),n(v,!1);var b=a-d-c,x=r-h-f,_=x/2,k=(a-b/2)/(g.length+m.length),w=(r-_)/(p.length+v.length),M=b,S=x,D=[];i.each(g.concat(m,p,v),function(t){var e,n=t.isHorizontal();n?(e=t.update(t.fullWidth?b:M,w),S-=e.height):(e=t.update(k,_),M-=e.width),D.push({horizontal:n,minSize:e,box:t})});var C=0,P=0,T=0,I=0;i.each(p.concat(v),function(t){if(t.getPadding){var e=t.getPadding();C=Math.max(C,e.left),P=Math.max(P,e.right)}}),i.each(g.concat(m),function(t){if(t.getPadding){var e=t.getPadding();T=Math.max(T,e.top),I=Math.max(I,e.bottom)}});var A=d,O=c,F=h,R=f;i.each(g.concat(m),o),i.each(g,function(t){A+=t.width}),i.each(m,function(t){O+=t.width}),i.each(p.concat(v),o),i.each(p,function(t){F+=t.height}),i.each(v,function(t){R+=t.height}),i.each(g.concat(m),function(t){var e=i.findNextWhere(D,function(e){return e.box===t}),n={left:0,right:0,top:F,bottom:R};e&&t.update(e.minSize.width,S,n)}),A=d,O=c,F=h,R=f,i.each(g,function(t){A+=t.width}),i.each(m,function(t){O+=t.width}),i.each(p,function(t){F+=t.height}),i.each(v,function(t){R+=t.height});var L=Math.max(C-A,0);A+=L,O+=Math.max(P-O,0);var W=Math.max(T-F,0);F+=W,R+=Math.max(I-R,0);var Y=r-F-R,N=a-A-O;N===M&&Y===S||(i.each(g,function(t){t.height=Y}),i.each(m,function(t){t.height=Y}),i.each(p,function(t){t.fullWidth||(t.width=N)}),i.each(v,function(t){t.fullWidth||(t.width=N)}),S=Y,M=N);var z=d+L,B=h+W;i.each(g.concat(p),s),z+=M,B+=S,i.each(m,s),i.each(v,s),t.chartArea={left:A,top:F,right:A+M,bottom:F+S},i.each(y,function(e){e.left=t.chartArea.left,e.top=t.chartArea.top,e.right=t.chartArea.right,e.bottom=t.chartArea.bottom,e.update(M,S)})}}}}},{45:45}],31:[function(t,e,n){"use strict";var i=t(25),a=t(26),r=t(45);i._set("global",{plugins:{}}),e.exports=function(t){t.plugins={_plugins:[],_cacheId:0,register:function(t){var e=this._plugins;[].concat(t).forEach(function(t){-1===e.indexOf(t)&&e.push(t)}),this._cacheId++},unregister:function(t){var e=this._plugins;[].concat(t).forEach(function(t){var n=e.indexOf(t);-1!==n&&e.splice(n,1)}),this._cacheId++},clear:function(){this._plugins=[],this._cacheId++},count:function(){return this._plugins.length},getAll:function(){return this._plugins},notify:function(t,e,n){var i,a,r,o,s,l=this.descriptors(t),u=l.length;for(i=0;i<u;++i)if(a=l[i],r=a.plugin,"function"==typeof(s=r[e])&&((o=[t].concat(n||[])).push(a.options),!1===s.apply(r,o)))return!1;return!0},descriptors:function(t){var e=t._plugins||(t._plugins={});if(e.id===this._cacheId)return e.descriptors;var n=[],a=[],o=t&&t.config||{},s=o.options&&o.options.plugins||{};return this._plugins.concat(o.plugins||[]).forEach(function(t){if(-1===n.indexOf(t)){var e=t.id,o=s[e];!1!==o&&(!0===o&&(o=r.clone(i.global.plugins[e])),n.push(t),a.push({plugin:t,options:o||{}}))}}),e.descriptors=a,e.id=this._cacheId,a}},t.pluginService=t.plugins,t.PluginBase=a.extend({})}},{25:25,26:26,45:45}],32:[function(t,e,n){"use strict";function i(t){var e,n,i=[];for(e=0,n=t.length;e<n;++e)i.push(t[e].label);return i}function a(t,e,n){var i=t.getPixelForTick(e);return n&&(i-=0===e?(t.getPixelForTick(1)-i)/2:(i-t.getPixelForTick(e-1))/2),i}var r=t(25),o=t(26),s=t(45),l=t(34);r._set("scale",{display:!0,position:"left",offset:!1,gridLines:{display:!0,color:"rgba(0, 0, 0, 0.1)",lineWidth:1,drawBorder:!0,drawOnChartArea:!0,drawTicks:!0,tickMarkLength:10,zeroLineWidth:1,zeroLineColor:"rgba(0,0,0,0.25)",zeroLineBorderDash:[],zeroLineBorderDashOffset:0,offsetGridLines:!1,borderDash:[],borderDashOffset:0},scaleLabel:{display:!1,labelString:"",lineHeight:1.2,padding:{top:4,bottom:4}},ticks:{beginAtZero:!1,minRotation:0,maxRotation:50,mirror:!1,padding:0,reverse:!1,display:!0,autoSkip:!0,autoSkipPadding:0,labelOffset:0,callback:l.formatters.values,minor:{},major:{}}}),e.exports=function(t){function e(t,e,n){return s.isArray(e)?s.longestText(t,n,e):t.measureText(e).width}function n(t){var e=s.valueOrDefault,n=r.global,i=e(t.fontSize,n.defaultFontSize),a=e(t.fontStyle,n.defaultFontStyle),o=e(t.fontFamily,n.defaultFontFamily);return{size:i,style:a,family:o,font:s.fontString(i,a,o)}}function l(t){return s.options.toLineHeight(s.valueOrDefault(t.lineHeight,1.2),s.valueOrDefault(t.fontSize,r.global.defaultFontSize))}t.Scale=o.extend({getPadding:function(){var t=this;return{left:t.paddingLeft||0,top:t.paddingTop||0,right:t.paddingRight||0,bottom:t.paddingBottom||0}},getTicks:function(){return this._ticks},mergeTicksOptions:function(){var t=this.options.ticks;!1===t.minor&&(t.minor={display:!1}),!1===t.major&&(t.major={display:!1});for(var e in t)"major"!==e&&"minor"!==e&&(void 0===t.minor[e]&&(t.minor[e]=t[e]),void 0===t.major[e]&&(t.major[e]=t[e]))},beforeUpdate:function(){s.callback(this.options.beforeUpdate,[this])},update:function(t,e,n){var i,a,r,o,l,u,d=this;for(d.beforeUpdate(),d.maxWidth=t,d.maxHeight=e,d.margins=s.extend({left:0,right:0,top:0,bottom:0},n),d.longestTextCache=d.longestTextCache||{},d.beforeSetDimensions(),d.setDimensions(),d.afterSetDimensions(),d.beforeDataLimits(),d.determineDataLimits(),d.afterDataLimits(),d.beforeBuildTicks(),l=d.buildTicks()||[],d.afterBuildTicks(),d.beforeTickToLabelConversion(),r=d.convertTicksToLabels(l)||d.ticks,d.afterTickToLabelConversion(),d.ticks=r,i=0,a=r.length;i<a;++i)o=r[i],(u=l[i])?u.label=o:l.push(u={label:o,major:!1});return d._ticks=l,d.beforeCalculateTickRotation(),d.calculateTickRotation(),d.afterCalculateTickRotation(),d.beforeFit(),d.fit(),d.afterFit(),d.afterUpdate(),d.minSize},afterUpdate:function(){s.callback(this.options.afterUpdate,[this])},beforeSetDimensions:function(){s.callback(this.options.beforeSetDimensions,[this])},setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0},afterSetDimensions:function(){s.callback(this.options.afterSetDimensions,[this])},beforeDataLimits:function(){s.callback(this.options.beforeDataLimits,[this])},determineDataLimits:s.noop,afterDataLimits:function(){s.callback(this.options.afterDataLimits,[this])},beforeBuildTicks:function(){s.callback(this.options.beforeBuildTicks,[this])},buildTicks:s.noop,afterBuildTicks:function(){s.callback(this.options.afterBuildTicks,[this])},beforeTickToLabelConversion:function(){s.callback(this.options.beforeTickToLabelConversion,[this])},convertTicksToLabels:function(){var t=this,e=t.options.ticks;t.ticks=t.ticks.map(e.userCallback||e.callback,this)},afterTickToLabelConversion:function(){s.callback(this.options.afterTickToLabelConversion,[this])},beforeCalculateTickRotation:function(){s.callback(this.options.beforeCalculateTickRotation,[this])},calculateTickRotation:function(){var t=this,e=t.ctx,a=t.options.ticks,r=i(t._ticks),o=n(a);e.font=o.font;var l=a.minRotation||0;if(r.length&&t.options.display&&t.isHorizontal())for(var u,d=s.longestText(e,o.font,r,t.longestTextCache),c=d,h=t.getPixelForTick(1)-t.getPixelForTick(0)-6;c>h&&l<a.maxRotation;){var f=s.toRadians(l);if(u=Math.cos(f),Math.sin(f)*d>t.maxHeight){l--;break}l++,c=u*d}t.labelRotation=l},afterCalculateTickRotation:function(){s.callback(this.options.afterCalculateTickRotation,[this])},beforeFit:function(){s.callback(this.options.beforeFit,[this])},fit:function(){var t=this,a=t.minSize={width:0,height:0},r=i(t._ticks),o=t.options,u=o.ticks,d=o.scaleLabel,c=o.gridLines,h=o.display,f=t.isHorizontal(),g=n(u),m=o.gridLines.tickMarkLength;if(a.width=f?t.isFullWidth()?t.maxWidth-t.margins.left-t.margins.right:t.maxWidth:h&&c.drawTicks?m:0,a.height=f?h&&c.drawTicks?m:0:t.maxHeight,d.display&&h){var p=l(d)+s.options.toPadding(d.padding).height;f?a.height+=p:a.width+=p}if(u.display&&h){var v=s.longestText(t.ctx,g.font,r,t.longestTextCache),y=s.numberOfLabelLines(r),b=.5*g.size,x=t.options.ticks.padding;if(f){t.longestLabelWidth=v;var _=s.toRadians(t.labelRotation),k=Math.cos(_),w=Math.sin(_)*v+g.size*y+b*(y-1)+b;a.height=Math.min(t.maxHeight,a.height+w+x),t.ctx.font=g.font;var M=e(t.ctx,r[0],g.font),S=e(t.ctx,r[r.length-1],g.font);0!==t.labelRotation?(t.paddingLeft="bottom"===o.position?k*M+3:k*b+3,t.paddingRight="bottom"===o.position?k*b+3:k*S+3):(t.paddingLeft=M/2+3,t.paddingRight=S/2+3)}else u.mirror?v=0:v+=x+b,a.width=Math.min(t.maxWidth,a.width+v),t.paddingTop=g.size/2,t.paddingBottom=g.size/2}t.handleMargins(),t.width=a.width,t.height=a.height},handleMargins:function(){var t=this;t.margins&&(t.paddingLeft=Math.max(t.paddingLeft-t.margins.left,0),t.paddingTop=Math.max(t.paddingTop-t.margins.top,0),t.paddingRight=Math.max(t.paddingRight-t.margins.right,0),t.paddingBottom=Math.max(t.paddingBottom-t.margins.bottom,0))},afterFit:function(){s.callback(this.options.afterFit,[this])},isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},isFullWidth:function(){return this.options.fullWidth},getRightValue:function(t){if(s.isNullOrUndef(t))return NaN;if("number"==typeof t&&!isFinite(t))return NaN;if(t)if(this.isHorizontal()){if(void 0!==t.x)return this.getRightValue(t.x)}else if(void 0!==t.y)return this.getRightValue(t.y);return t},getLabelForIndex:s.noop,getPixelForValue:s.noop,getValueForPixel:s.noop,getPixelForTick:function(t){var e=this,n=e.options.offset;if(e.isHorizontal()){var i=(e.width-(e.paddingLeft+e.paddingRight))/Math.max(e._ticks.length-(n?0:1),1),a=i*t+e.paddingLeft;n&&(a+=i/2);var r=e.left+Math.round(a);return r+=e.isFullWidth()?e.margins.left:0}var o=e.height-(e.paddingTop+e.paddingBottom);return e.top+t*(o/(e._ticks.length-1))},getPixelForDecimal:function(t){var e=this;if(e.isHorizontal()){var n=(e.width-(e.paddingLeft+e.paddingRight))*t+e.paddingLeft,i=e.left+Math.round(n);return i+=e.isFullWidth()?e.margins.left:0}return e.top+t*e.height},getBasePixel:function(){return this.getPixelForValue(this.getBaseValue())},getBaseValue:function(){var t=this,e=t.min,n=t.max;return t.beginAtZero?0:e<0&&n<0?n:e>0&&n>0?e:0},_autoSkip:function(t){var e,n,i,a,r=this,o=r.isHorizontal(),l=r.options.ticks.minor,u=t.length,d=s.toRadians(r.labelRotation),c=Math.cos(d),h=r.longestLabelWidth*c,f=[];for(l.maxTicksLimit&&(a=l.maxTicksLimit),o&&(e=!1,(h+l.autoSkipPadding)*u>r.width-(r.paddingLeft+r.paddingRight)&&(e=1+Math.floor((h+l.autoSkipPadding)*u/(r.width-(r.paddingLeft+r.paddingRight)))),a&&u>a&&(e=Math.max(e,Math.floor(u/a)))),n=0;n<u;n++)i=t[n],(e>1&&n%e>0||n%e==0&&n+e>=u)&&n!==u-1&&delete i.label,f.push(i);return f},draw:function(t){var e=this,i=e.options;if(i.display){var o=e.ctx,u=r.global,d=i.ticks.minor,c=i.ticks.major||d,h=i.gridLines,f=i.scaleLabel,g=0!==e.labelRotation,m=e.isHorizontal(),p=d.autoSkip?e._autoSkip(e.getTicks()):e.getTicks(),v=s.valueOrDefault(d.fontColor,u.defaultFontColor),y=n(d),b=s.valueOrDefault(c.fontColor,u.defaultFontColor),x=n(c),_=h.drawTicks?h.tickMarkLength:0,k=s.valueOrDefault(f.fontColor,u.defaultFontColor),w=n(f),M=s.options.toPadding(f.padding),S=s.toRadians(e.labelRotation),D=[],C="right"===i.position?e.left:e.right-_,P="right"===i.position?e.left+_:e.right,T="bottom"===i.position?e.top:e.bottom-_,I="bottom"===i.position?e.top+_:e.bottom;if(s.each(p,function(n,r){if(!s.isNullOrUndef(n.label)){var o,l,c,f,v=n.label;r===e.zeroLineIndex&&i.offset===h.offsetGridLines?(o=h.zeroLineWidth,l=h.zeroLineColor,c=h.zeroLineBorderDash,f=h.zeroLineBorderDashOffset):(o=s.valueAtIndexOrDefault(h.lineWidth,r),l=s.valueAtIndexOrDefault(h.color,r),c=s.valueOrDefault(h.borderDash,u.borderDash),f=s.valueOrDefault(h.borderDashOffset,u.borderDashOffset));var y,b,x,k,w,M,A,O,F,R,L="middle",W="middle",Y=d.padding;if(m){var N=_+Y;"bottom"===i.position?(W=g?"middle":"top",L=g?"right":"center",R=e.top+N):(W=g?"middle":"bottom",L=g?"left":"center",R=e.bottom-N);var z=a(e,r,h.offsetGridLines&&p.length>1);z<e.left&&(l="rgba(0,0,0,0)"),z+=s.aliasPixel(o),F=e.getPixelForTick(r)+d.labelOffset,y=x=w=A=z,b=T,k=I,M=t.top,O=t.bottom}else{var B,V="left"===i.position;d.mirror?(L=V?"left":"right",B=Y):(L=V?"right":"left",B=_+Y),F=V?e.right-B:e.left+B;var H=a(e,r,h.offsetGridLines&&p.length>1);H<e.top&&(l="rgba(0,0,0,0)"),H+=s.aliasPixel(o),R=e.getPixelForTick(r)+d.labelOffset,y=C,x=P,w=t.left,A=t.right,b=k=M=O=H}D.push({tx1:y,ty1:b,tx2:x,ty2:k,x1:w,y1:M,x2:A,y2:O,labelX:F,labelY:R,glWidth:o,glColor:l,glBorderDash:c,glBorderDashOffset:f,rotation:-1*S,label:v,major:n.major,textBaseline:W,textAlign:L})}}),s.each(D,function(t){if(h.display&&(o.save(),o.lineWidth=t.glWidth,o.strokeStyle=t.glColor,o.setLineDash&&(o.setLineDash(t.glBorderDash),o.lineDashOffset=t.glBorderDashOffset),o.beginPath(),h.drawTicks&&(o.moveTo(t.tx1,t.ty1),o.lineTo(t.tx2,t.ty2)),h.drawOnChartArea&&(o.moveTo(t.x1,t.y1),o.lineTo(t.x2,t.y2)),o.stroke(),o.restore()),d.display){o.save(),o.translate(t.labelX,t.labelY),o.rotate(t.rotation),o.font=t.major?x.font:y.font,o.fillStyle=t.major?b:v,o.textBaseline=t.textBaseline,o.textAlign=t.textAlign;var e=t.label;if(s.isArray(e))for(var n=0,i=0;n<e.length;++n)o.fillText(""+e[n],0,i),i+=1.5*y.size;else o.fillText(e,0,0);o.restore()}}),f.display){var A,O,F=0,R=l(f)/2;if(m)A=e.left+(e.right-e.left)/2,O="bottom"===i.position?e.bottom-R-M.bottom:e.top+R+M.top;else{var L="left"===i.position;A=L?e.left+R+M.top:e.right-R-M.top,O=e.top+(e.bottom-e.top)/2,F=L?-.5*Math.PI:.5*Math.PI}o.save(),o.translate(A,O),o.rotate(F),o.textAlign="center",o.textBaseline="middle",o.fillStyle=k,o.font=w.font,o.fillText(f.labelString,0,0),o.restore()}if(h.drawBorder){o.lineWidth=s.valueAtIndexOrDefault(h.lineWidth,0),o.strokeStyle=s.valueAtIndexOrDefault(h.color,0);var W=e.left,Y=e.right,N=e.top,z=e.bottom,B=s.aliasPixel(o.lineWidth);m?(N=z="top"===i.position?e.bottom:e.top,N+=B,z+=B):(W=Y="left"===i.position?e.right:e.left,W+=B,Y+=B),o.beginPath(),o.moveTo(W,N),o.lineTo(Y,z),o.stroke()}}}})}},{25:25,26:26,34:34,45:45}],33:[function(t,e,n){"use strict";var i=t(25),a=t(45);e.exports=function(t){t.scaleService={constructors:{},defaults:{},registerScaleType:function(t,e,n){this.constructors[t]=e,this.defaults[t]=a.clone(n)},getScaleConstructor:function(t){return this.constructors.hasOwnProperty(t)?this.constructors[t]:void 0},getScaleDefaults:function(t){return this.defaults.hasOwnProperty(t)?a.merge({},[i.scale,this.defaults[t]]):{}},updateScaleDefaults:function(t,e){var n=this;n.defaults.hasOwnProperty(t)&&(n.defaults[t]=a.extend(n.defaults[t],e))},addScalesToLayout:function(e){a.each(e.scales,function(n){n.fullWidth=n.options.fullWidth,n.position=n.options.position,n.weight=n.options.weight,t.layoutService.addBox(e,n)})}}}},{25:25,45:45}],34:[function(t,e,n){"use strict";var i=t(45);e.exports={generators:{linear:function(t,e){var n,a=[];if(t.stepSize&&t.stepSize>0)n=t.stepSize;else{var r=i.niceNum(e.max-e.min,!1);n=i.niceNum(r/(t.maxTicks-1),!0)}var o=Math.floor(e.min/n)*n,s=Math.ceil(e.max/n)*n;t.min&&t.max&&t.stepSize&&i.almostWhole((t.max-t.min)/t.stepSize,n/1e3)&&(o=t.min,s=t.max);var l=(s-o)/n;l=i.almostEquals(l,Math.round(l),n/1e3)?Math.round(l):Math.ceil(l),a.push(void 0!==t.min?t.min:o);for(var u=1;u<l;++u)a.push(o+u*n);return a.push(void 0!==t.max?t.max:s),a},logarithmic:function(t,e){var n,a,r=[],o=i.valueOrDefault,s=o(t.min,Math.pow(10,Math.floor(i.log10(e.min)))),l=Math.floor(i.log10(e.max)),u=Math.ceil(e.max/Math.pow(10,l));0===s?(n=Math.floor(i.log10(e.minNotZero)),a=Math.floor(e.minNotZero/Math.pow(10,n)),r.push(s),s=a*Math.pow(10,n)):(n=Math.floor(i.log10(s)),a=Math.floor(s/Math.pow(10,n)));do{r.push(s),10===++a&&(a=1,++n),s=a*Math.pow(10,n)}while(n<l||n===l&&a<u);var d=o(t.max,s);return r.push(d),r}},formatters:{values:function(t){return i.isArray(t)?t:""+t},linear:function(t,e,n){var a=n.length>3?n[2]-n[1]:n[1]-n[0];Math.abs(a)>1&&t!==Math.floor(t)&&(a=t-Math.floor(t));var r=i.log10(Math.abs(a)),o="";if(0!==t){var s=-1*Math.floor(r);s=Math.max(Math.min(s,20),0),o=t.toFixed(s)}else o="0";return o},logarithmic:function(t,e,n){var a=t/Math.pow(10,Math.floor(i.log10(t)));return 0===t?"0":1===a||2===a||5===a||0===e||e===n.length-1?t.toExponential():""}}}},{45:45}],35:[function(t,e,n){"use strict";var i=t(25),a=t(26),r=t(45);i._set("global",{tooltips:{enabled:!0,custom:null,mode:"nearest",position:"average",intersect:!0,backgroundColor:"rgba(0,0,0,0.8)",titleFontStyle:"bold",titleSpacing:2,titleMarginBottom:6,titleFontColor:"#fff",titleAlign:"left",bodySpacing:2,bodyFontColor:"#fff",bodyAlign:"left",footerFontStyle:"bold",footerSpacing:2,footerMarginTop:6,footerFontColor:"#fff",footerAlign:"left",yPadding:6,xPadding:6,caretPadding:2,caretSize:5,cornerRadius:6,multiKeyBackground:"#fff",displayColors:!0,borderColor:"rgba(0,0,0,0)",borderWidth:0,callbacks:{beforeTitle:r.noop,title:function(t,e){var n="",i=e.labels,a=i?i.length:0;if(t.length>0){var r=t[0];r.xLabel?n=r.xLabel:a>0&&r.index<a&&(n=i[r.index])}return n},afterTitle:r.noop,beforeBody:r.noop,beforeLabel:r.noop,label:function(t,e){var n=e.datasets[t.datasetIndex].label||"";return n&&(n+=": "),n+=t.yLabel},labelColor:function(t,e){var n=e.getDatasetMeta(t.datasetIndex).data[t.index]._view;return{borderColor:n.borderColor,backgroundColor:n.backgroundColor}},labelTextColor:function(){return this._options.bodyFontColor},afterLabel:r.noop,afterBody:r.noop,beforeFooter:r.noop,footer:r.noop,afterFooter:r.noop}}}),e.exports=function(t){function e(t,e){var n=r.color(t);return n.alpha(e*n.alpha()).rgbaString()}function n(t,e){return e&&(r.isArray(e)?Array.prototype.push.apply(t,e):t.push(e)),t}function o(t){var e=t._xScale,n=t._yScale||t._scale,i=t._index,a=t._datasetIndex;return{xLabel:e?e.getLabelForIndex(i,a):"",yLabel:n?n.getLabelForIndex(i,a):"",index:i,datasetIndex:a,x:t._model.x,y:t._model.y}}function s(t){var e=i.global,n=r.valueOrDefault;return{xPadding:t.xPadding,yPadding:t.yPadding,xAlign:t.xAlign,yAlign:t.yAlign,bodyFontColor:t.bodyFontColor,_bodyFontFamily:n(t.bodyFontFamily,e.defaultFontFamily),_bodyFontStyle:n(t.bodyFontStyle,e.defaultFontStyle),_bodyAlign:t.bodyAlign,bodyFontSize:n(t.bodyFontSize,e.defaultFontSize),bodySpacing:t.bodySpacing,titleFontColor:t.titleFontColor,_titleFontFamily:n(t.titleFontFamily,e.defaultFontFamily),_titleFontStyle:n(t.titleFontStyle,e.defaultFontStyle),titleFontSize:n(t.titleFontSize,e.defaultFontSize),_titleAlign:t.titleAlign,titleSpacing:t.titleSpacing,titleMarginBottom:t.titleMarginBottom,footerFontColor:t.footerFontColor,_footerFontFamily:n(t.footerFontFamily,e.defaultFontFamily),_footerFontStyle:n(t.footerFontStyle,e.defaultFontStyle),footerFontSize:n(t.footerFontSize,e.defaultFontSize),_footerAlign:t.footerAlign,footerSpacing:t.footerSpacing,footerMarginTop:t.footerMarginTop,caretSize:t.caretSize,cornerRadius:t.cornerRadius,backgroundColor:t.backgroundColor,opacity:0,legendColorBackground:t.multiKeyBackground,displayColors:t.displayColors,borderColor:t.borderColor,borderWidth:t.borderWidth}}function l(t,e){var n=t._chart.ctx,i=2*e.yPadding,a=0,o=e.body,s=o.reduce(function(t,e){return t+e.before.length+e.lines.length+e.after.length},0);s+=e.beforeBody.length+e.afterBody.length;var l=e.title.length,u=e.footer.length,d=e.titleFontSize,c=e.bodyFontSize,h=e.footerFontSize;i+=l*d,i+=l?(l-1)*e.titleSpacing:0,i+=l?e.titleMarginBottom:0,i+=s*c,i+=s?(s-1)*e.bodySpacing:0,i+=u?e.footerMarginTop:0,i+=u*h,i+=u?(u-1)*e.footerSpacing:0;var f=0,g=function(t){a=Math.max(a,n.measureText(t).width+f)};return n.font=r.fontString(d,e._titleFontStyle,e._titleFontFamily),r.each(e.title,g),n.font=r.fontString(c,e._bodyFontStyle,e._bodyFontFamily),r.each(e.beforeBody.concat(e.afterBody),g),f=e.displayColors?c+2:0,r.each(o,function(t){r.each(t.before,g),r.each(t.lines,g),r.each(t.after,g)}),f=0,n.font=r.fontString(h,e._footerFontStyle,e._footerFontFamily),r.each(e.footer,g),a+=2*e.xPadding,{width:a,height:i}}function u(t,e){var n=t._model,i=t._chart,a=t._chart.chartArea,r="center",o="center";n.y<e.height?o="top":n.y>i.height-e.height&&(o="bottom");var s,l,u,d,c,h=(a.left+a.right)/2,f=(a.top+a.bottom)/2;"center"===o?(s=function(t){return t<=h},l=function(t){return t>h}):(s=function(t){return t<=e.width/2},l=function(t){return t>=i.width-e.width/2}),u=function(t){return t+e.width>i.width},d=function(t){return t-e.width<0},c=function(t){return t<=f?"top":"bottom"},s(n.x)?(r="left",u(n.x)&&(r="center",o=c(n.y))):l(n.x)&&(r="right",d(n.x)&&(r="center",o=c(n.y)));var g=t._options;return{xAlign:g.xAlign?g.xAlign:r,yAlign:g.yAlign?g.yAlign:o}}function d(t,e,n){var i=t.x,a=t.y,r=t.caretSize,o=t.caretPadding,s=t.cornerRadius,l=n.xAlign,u=n.yAlign,d=r+o,c=s+o;return"right"===l?i-=e.width:"center"===l&&(i-=e.width/2),"top"===u?a+=d:a-="bottom"===u?e.height+d:e.height/2,"center"===u?"left"===l?i+=d:"right"===l&&(i-=d):"left"===l?i-=c:"right"===l&&(i+=c),{x:i,y:a}}t.Tooltip=a.extend({initialize:function(){this._model=s(this._options)},getTitle:function(){var t=this,e=t._options.callbacks,i=e.beforeTitle.apply(t,arguments),a=e.title.apply(t,arguments),r=e.afterTitle.apply(t,arguments),o=[];return o=n(o,i),o=n(o,a),o=n(o,r)},getBeforeBody:function(){var t=this._options.callbacks.beforeBody.apply(this,arguments);return r.isArray(t)?t:void 0!==t?[t]:[]},getBody:function(t,e){var i=this,a=i._options.callbacks,o=[];return r.each(t,function(t){var r={before:[],lines:[],after:[]};n(r.before,a.beforeLabel.call(i,t,e)),n(r.lines,a.label.call(i,t,e)),n(r.after,a.afterLabel.call(i,t,e)),o.push(r)}),o},getAfterBody:function(){var t=this._options.callbacks.afterBody.apply(this,arguments);return r.isArray(t)?t:void 0!==t?[t]:[]},getFooter:function(){var t=this,e=t._options.callbacks,i=e.beforeFooter.apply(t,arguments),a=e.footer.apply(t,arguments),r=e.afterFooter.apply(t,arguments),o=[];return o=n(o,i),o=n(o,a),o=n(o,r)},update:function(e){var n,i,a=this,c=a._options,h=a._model,f=a._model=s(c),g=a._active,m=a._data,p={xAlign:h.xAlign,yAlign:h.yAlign},v={x:h.x,y:h.y},y={width:h.width,height:h.height},b={x:h.caretX,y:h.caretY};if(g.length){f.opacity=1;var x=[],_=[];b=t.Tooltip.positioners[c.position](g,a._eventPosition);var k=[];for(n=0,i=g.length;n<i;++n)k.push(o(g[n]));c.filter&&(k=k.filter(function(t){return c.filter(t,m)})),c.itemSort&&(k=k.sort(function(t,e){return c.itemSort(t,e,m)})),r.each(k,function(t){x.push(c.callbacks.labelColor.call(a,t,a._chart)),_.push(c.callbacks.labelTextColor.call(a,t,a._chart))}),f.title=a.getTitle(k,m),f.beforeBody=a.getBeforeBody(k,m),f.body=a.getBody(k,m),f.afterBody=a.getAfterBody(k,m),f.footer=a.getFooter(k,m),f.x=Math.round(b.x),f.y=Math.round(b.y),f.caretPadding=c.caretPadding,f.labelColors=x,f.labelTextColors=_,f.dataPoints=k,v=d(f,y=l(this,f),p=u(this,y))}else f.opacity=0;return f.xAlign=p.xAlign,f.yAlign=p.yAlign,f.x=v.x,f.y=v.y,f.width=y.width,f.height=y.height,f.caretX=b.x,f.caretY=b.y,a._model=f,e&&c.custom&&c.custom.call(a,f),a},drawCaret:function(t,e){var n=this._chart.ctx,i=this._view,a=this.getCaretPosition(t,e,i);n.lineTo(a.x1,a.y1),n.lineTo(a.x2,a.y2),n.lineTo(a.x3,a.y3)},getCaretPosition:function(t,e,n){var i,a,r,o,s,l,u=n.caretSize,d=n.cornerRadius,c=n.xAlign,h=n.yAlign,f=t.x,g=t.y,m=e.width,p=e.height;if("center"===h)s=g+p/2,"left"===c?(a=(i=f)-u,r=i,o=s+u,l=s-u):(a=(i=f+m)+u,r=i,o=s-u,l=s+u);else if("left"===c?(i=(a=f+d+u)-u,r=a+u):"right"===c?(i=(a=f+m-d-u)-u,r=a+u):(i=(a=f+m/2)-u,r=a+u),"top"===h)s=(o=g)-u,l=o;else{s=(o=g+p)+u,l=o;var v=r;r=i,i=v}return{x1:i,x2:a,x3:r,y1:o,y2:s,y3:l}},drawTitle:function(t,n,i,a){var o=n.title;if(o.length){i.textAlign=n._titleAlign,i.textBaseline="top";var s=n.titleFontSize,l=n.titleSpacing;i.fillStyle=e(n.titleFontColor,a),i.font=r.fontString(s,n._titleFontStyle,n._titleFontFamily);var u,d;for(u=0,d=o.length;u<d;++u)i.fillText(o[u],t.x,t.y),t.y+=s+l,u+1===o.length&&(t.y+=n.titleMarginBottom-l)}},drawBody:function(t,n,i,a){var o=n.bodyFontSize,s=n.bodySpacing,l=n.body;i.textAlign=n._bodyAlign,i.textBaseline="top",i.font=r.fontString(o,n._bodyFontStyle,n._bodyFontFamily);var u=0,d=function(e){i.fillText(e,t.x+u,t.y),t.y+=o+s};i.fillStyle=e(n.bodyFontColor,a),r.each(n.beforeBody,d);var c=n.displayColors;u=c?o+2:0,r.each(l,function(s,l){var u=e(n.labelTextColors[l],a);i.fillStyle=u,r.each(s.before,d),r.each(s.lines,function(r){c&&(i.fillStyle=e(n.legendColorBackground,a),i.fillRect(t.x,t.y,o,o),i.lineWidth=1,i.strokeStyle=e(n.labelColors[l].borderColor,a),i.strokeRect(t.x,t.y,o,o),i.fillStyle=e(n.labelColors[l].backgroundColor,a),i.fillRect(t.x+1,t.y+1,o-2,o-2),i.fillStyle=u),d(r)}),r.each(s.after,d)}),u=0,r.each(n.afterBody,d),t.y-=s},drawFooter:function(t,n,i,a){var o=n.footer;o.length&&(t.y+=n.footerMarginTop,i.textAlign=n._footerAlign,i.textBaseline="top",i.fillStyle=e(n.footerFontColor,a),i.font=r.fontString(n.footerFontSize,n._footerFontStyle,n._footerFontFamily),r.each(o,function(e){i.fillText(e,t.x,t.y),t.y+=n.footerFontSize+n.footerSpacing}))},drawBackground:function(t,n,i,a,r){i.fillStyle=e(n.backgroundColor,r),i.strokeStyle=e(n.borderColor,r),i.lineWidth=n.borderWidth;var o=n.xAlign,s=n.yAlign,l=t.x,u=t.y,d=a.width,c=a.height,h=n.cornerRadius;i.beginPath(),i.moveTo(l+h,u),"top"===s&&this.drawCaret(t,a),i.lineTo(l+d-h,u),i.quadraticCurveTo(l+d,u,l+d,u+h),"center"===s&&"right"===o&&this.drawCaret(t,a),i.lineTo(l+d,u+c-h),i.quadraticCurveTo(l+d,u+c,l+d-h,u+c),"bottom"===s&&this.drawCaret(t,a),i.lineTo(l+h,u+c),i.quadraticCurveTo(l,u+c,l,u+c-h),"center"===s&&"left"===o&&this.drawCaret(t,a),i.lineTo(l,u+h),i.quadraticCurveTo(l,u,l+h,u),i.closePath(),i.fill(),n.borderWidth>0&&i.stroke()},draw:function(){var t=this._chart.ctx,e=this._view;if(0!==e.opacity){var n={width:e.width,height:e.height},i={x:e.x,y:e.y},a=Math.abs(e.opacity<.001)?0:e.opacity,r=e.title.length||e.beforeBody.length||e.body.length||e.afterBody.length||e.footer.length;this._options.enabled&&r&&(this.drawBackground(i,e,t,n,a),i.x+=e.xPadding,i.y+=e.yPadding,this.drawTitle(i,e,t,a),this.drawBody(i,e,t,a),this.drawFooter(i,e,t,a))}},handleEvent:function(t){var e=this,n=e._options,i=!1;if(e._lastActive=e._lastActive||[],"mouseout"===t.type?e._active=[]:e._active=e._chart.getElementsAtEventForMode(t,n.mode,n),!(i=!r.arrayEquals(e._active,e._lastActive)))return!1;if(e._lastActive=e._active,n.enabled||n.custom){e._eventPosition={x:t.x,y:t.y};var a=e._model;e.update(!0),e.pivot(),i|=a.x!==e._model.x||a.y!==e._model.y}return i}}),t.Tooltip.positioners={average:function(t){if(!t.length)return!1;var e,n,i=0,a=0,r=0;for(e=0,n=t.length;e<n;++e){var o=t[e];if(o&&o.hasValue()){var s=o.tooltipPosition();i+=s.x,a+=s.y,++r}}return{x:Math.round(i/r),y:Math.round(a/r)}},nearest:function(t,e){var n,i,a,o=e.x,s=e.y,l=Number.POSITIVE_INFINITY;for(n=0,i=t.length;n<i;++n){var u=t[n];if(u&&u.hasValue()){var d=u.getCenterPoint(),c=r.distanceBetweenPoints(e,d);c<l&&(l=c,a=u)}}if(a){var h=a.tooltipPosition();o=h.x,s=h.y}return{x:o,y:s}}}}},{25:25,26:26,45:45}],36:[function(t,e,n){"use strict";var i=t(25),a=t(26),r=t(45);i._set("global",{elements:{arc:{backgroundColor:i.global.defaultColor,borderColor:"#fff",borderWidth:2}}}),e.exports=a.extend({inLabelRange:function(t){var e=this._view;return!!e&&Math.pow(t-e.x,2)<Math.pow(e.radius+e.hoverRadius,2)},inRange:function(t,e){var n=this._view;if(n){for(var i=r.getAngleFromPoint(n,{x:t,y:e}),a=i.angle,o=i.distance,s=n.startAngle,l=n.endAngle;l<s;)l+=2*Math.PI;for(;a>l;)a-=2*Math.PI;for(;a<s;)a+=2*Math.PI;var u=a>=s&&a<=l,d=o>=n.innerRadius&&o<=n.outerRadius;return u&&d}return!1},getCenterPoint:function(){var t=this._view,e=(t.startAngle+t.endAngle)/2,n=(t.innerRadius+t.outerRadius)/2;return{x:t.x+Math.cos(e)*n,y:t.y+Math.sin(e)*n}},getArea:function(){var t=this._view;return Math.PI*((t.endAngle-t.startAngle)/(2*Math.PI))*(Math.pow(t.outerRadius,2)-Math.pow(t.innerRadius,2))},tooltipPosition:function(){var t=this._view,e=t.startAngle+(t.endAngle-t.startAngle)/2,n=(t.outerRadius-t.innerRadius)/2+t.innerRadius;return{x:t.x+Math.cos(e)*n,y:t.y+Math.sin(e)*n}},draw:function(){var t=this._chart.ctx,e=this._view,n=e.startAngle,i=e.endAngle;t.beginPath(),t.arc(e.x,e.y,e.outerRadius,n,i),t.arc(e.x,e.y,e.innerRadius,i,n,!0),t.closePath(),t.strokeStyle=e.borderColor,t.lineWidth=e.borderWidth,t.fillStyle=e.backgroundColor,t.fill(),t.lineJoin="bevel",e.borderWidth&&t.stroke()}})},{25:25,26:26,45:45}],37:[function(t,e,n){"use strict";var i=t(25),a=t(26),r=t(45),o=i.global;i._set("global",{elements:{line:{tension:.4,backgroundColor:o.defaultColor,borderWidth:3,borderColor:o.defaultColor,borderCapStyle:"butt",borderDash:[],borderDashOffset:0,borderJoinStyle:"miter",capBezierPoints:!0,fill:!0}}}),e.exports=a.extend({draw:function(){var t,e,n,i,a=this,s=a._view,l=a._chart.ctx,u=s.spanGaps,d=a._children.slice(),c=o.elements.line,h=-1;for(a._loop&&d.length&&d.push(d[0]),l.save(),l.lineCap=s.borderCapStyle||c.borderCapStyle,l.setLineDash&&l.setLineDash(s.borderDash||c.borderDash),l.lineDashOffset=s.borderDashOffset||c.borderDashOffset,l.lineJoin=s.borderJoinStyle||c.borderJoinStyle,l.lineWidth=s.borderWidth||c.borderWidth,l.strokeStyle=s.borderColor||o.defaultColor,l.beginPath(),h=-1,t=0;t<d.length;++t)e=d[t],n=r.previousItem(d,t),i=e._view,0===t?i.skip||(l.moveTo(i.x,i.y),h=t):(n=-1===h?n:d[h],i.skip||(h!==t-1&&!u||-1===h?l.moveTo(i.x,i.y):r.canvas.lineTo(l,n._view,e._view),h=t));l.stroke(),l.restore()}})},{25:25,26:26,45:45}],38:[function(t,e,n){"use strict";function i(t){var e=this._view;return!!e&&Math.pow(t-e.x,2)<Math.pow(e.radius+e.hitRadius,2)}var a=t(25),r=t(26),o=t(45),s=a.global.defaultColor;a._set("global",{elements:{point:{radius:3,pointStyle:"circle",backgroundColor:s,borderColor:s,borderWidth:1,hitRadius:1,hoverRadius:4,hoverBorderWidth:1}}}),e.exports=r.extend({inRange:function(t,e){var n=this._view;return!!n&&Math.pow(t-n.x,2)+Math.pow(e-n.y,2)<Math.pow(n.hitRadius+n.radius,2)},inLabelRange:i,inXRange:i,inYRange:function(t){var e=this._view;return!!e&&Math.pow(t-e.y,2)<Math.pow(e.radius+e.hitRadius,2)},getCenterPoint:function(){var t=this._view;return{x:t.x,y:t.y}},getArea:function(){return Math.PI*Math.pow(this._view.radius,2)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y,padding:t.radius+t.borderWidth}},draw:function(t){var e=this._view,n=this._model,i=this._chart.ctx,r=e.pointStyle,l=e.radius,u=e.x,d=e.y,c=o.color,h=0;e.skip||(i.strokeStyle=e.borderColor||s,i.lineWidth=o.valueOrDefault(e.borderWidth,a.global.elements.point.borderWidth),i.fillStyle=e.backgroundColor||s,void 0!==t&&(n.x<t.left||1.01*t.right<n.x||n.y<t.top||1.01*t.bottom<n.y)&&(n.x<t.left?h=(u-n.x)/(t.left-n.x):1.01*t.right<n.x?h=(n.x-u)/(n.x-t.right):n.y<t.top?h=(d-n.y)/(t.top-n.y):1.01*t.bottom<n.y&&(h=(n.y-d)/(n.y-t.bottom)),h=Math.round(100*h)/100,i.strokeStyle=c(i.strokeStyle).alpha(h).rgbString(),i.fillStyle=c(i.fillStyle).alpha(h).rgbString()),o.canvas.drawPoint(i,r,l,u,d))}})},{25:25,26:26,45:45}],39:[function(t,e,n){"use strict";function i(t){return void 0!==t._view.width}function a(t){var e,n,a,r,o=t._view;if(i(t)){var s=o.width/2;e=o.x-s,n=o.x+s,a=Math.min(o.y,o.base),r=Math.max(o.y,o.base)}else{var l=o.height/2;e=Math.min(o.x,o.base),n=Math.max(o.x,o.base),a=o.y-l,r=o.y+l}return{left:e,top:a,right:n,bottom:r}}var r=t(25),o=t(26);r._set("global",{elements:{rectangle:{backgroundColor:r.global.defaultColor,borderColor:r.global.defaultColor,borderSkipped:"bottom",borderWidth:0}}}),e.exports=o.extend({draw:function(){function t(t){return v[(y+t)%4]}var e,n,i,a,r,o,s,l=this._chart.ctx,u=this._view,d=u.borderWidth;if(u.horizontal?(e=u.base,n=u.x,i=u.y-u.height/2,a=u.y+u.height/2,r=n>e?1:-1,o=1,s=u.borderSkipped||"left"):(e=u.x-u.width/2,n=u.x+u.width/2,i=u.y,r=1,o=(a=u.base)>i?1:-1,s=u.borderSkipped||"bottom"),d){var c=Math.min(Math.abs(e-n),Math.abs(i-a)),h=(d=d>c?c:d)/2,f=e+("left"!==s?h*r:0),g=n+("right"!==s?-h*r:0),m=i+("top"!==s?h*o:0),p=a+("bottom"!==s?-h*o:0);f!==g&&(i=m,a=p),m!==p&&(e=f,n=g)}l.beginPath(),l.fillStyle=u.backgroundColor,l.strokeStyle=u.borderColor,l.lineWidth=d;var v=[[e,a],[e,i],[n,i],[n,a]],y=["bottom","left","top","right"].indexOf(s,0);-1===y&&(y=0);var b=t(0);l.moveTo(b[0],b[1]);for(var x=1;x<4;x++)b=t(x),l.lineTo(b[0],b[1]);l.fill(),d&&l.stroke()},height:function(){var t=this._view;return t.base-t.y},inRange:function(t,e){var n=!1;if(this._view){var i=a(this);n=t>=i.left&&t<=i.right&&e>=i.top&&e<=i.bottom}return n},inLabelRange:function(t,e){var n=this;if(!n._view)return!1;var r=a(n);return i(n)?t>=r.left&&t<=r.right:e>=r.top&&e<=r.bottom},inXRange:function(t){var e=a(this);return t>=e.left&&t<=e.right},inYRange:function(t){var e=a(this);return t>=e.top&&t<=e.bottom},getCenterPoint:function(){var t,e,n=this._view;return i(this)?(t=n.x,e=(n.y+n.base)/2):(t=(n.x+n.base)/2,e=n.y),{x:t,y:e}},getArea:function(){var t=this._view;return t.width*Math.abs(t.y-t.base)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y}}})},{25:25,26:26}],40:[function(t,e,n){"use strict";e.exports={},e.exports.Arc=t(36),e.exports.Line=t(37),e.exports.Point=t(38),e.exports.Rectangle=t(39)},{36:36,37:37,38:38,39:39}],41:[function(t,e,n){"use strict";var i=t(42),n=e.exports={clear:function(t){t.ctx.clearRect(0,0,t.width,t.height)},roundedRect:function(t,e,n,i,a,r){if(r){var o=Math.min(r,i/2),s=Math.min(r,a/2);t.moveTo(e+o,n),t.lineTo(e+i-o,n),t.quadraticCurveTo(e+i,n,e+i,n+s),t.lineTo(e+i,n+a-s),t.quadraticCurveTo(e+i,n+a,e+i-o,n+a),t.lineTo(e+o,n+a),t.quadraticCurveTo(e,n+a,e,n+a-s),t.lineTo(e,n+s),t.quadraticCurveTo(e,n,e+o,n)}else t.rect(e,n,i,a)},drawPoint:function(t,e,n,i,a){var r,o,s,l,u,d;if(!e||"object"!=typeof e||"[object HTMLImageElement]"!==(r=e.toString())&&"[object HTMLCanvasElement]"!==r){if(!(isNaN(n)||n<=0)){switch(e){default:t.beginPath(),t.arc(i,a,n,0,2*Math.PI),t.closePath(),t.fill();break;case"triangle":t.beginPath(),u=(o=3*n/Math.sqrt(3))*Math.sqrt(3)/2,t.moveTo(i-o/2,a+u/3),t.lineTo(i+o/2,a+u/3),t.lineTo(i,a-2*u/3),t.closePath(),t.fill();break;case"rect":d=1/Math.SQRT2*n,t.beginPath(),t.fillRect(i-d,a-d,2*d,2*d),t.strokeRect(i-d,a-d,2*d,2*d);break;case"rectRounded":var c=n/Math.SQRT2,h=i-c,f=a-c,g=Math.SQRT2*n;t.beginPath(),this.roundedRect(t,h,f,g,g,n/2),t.closePath(),t.fill();break;case"rectRot":d=1/Math.SQRT2*n,t.beginPath(),t.moveTo(i-d,a),t.lineTo(i,a+d),t.lineTo(i+d,a),t.lineTo(i,a-d),t.closePath(),t.fill();break;case"cross":t.beginPath(),t.moveTo(i,a+n),t.lineTo(i,a-n),t.moveTo(i-n,a),t.lineTo(i+n,a),t.closePath();break;case"crossRot":t.beginPath(),s=Math.cos(Math.PI/4)*n,l=Math.sin(Math.PI/4)*n,t.moveTo(i-s,a-l),t.lineTo(i+s,a+l),t.moveTo(i-s,a+l),t.lineTo(i+s,a-l),t.closePath();break;case"star":t.beginPath(),t.moveTo(i,a+n),t.lineTo(i,a-n),t.moveTo(i-n,a),t.lineTo(i+n,a),s=Math.cos(Math.PI/4)*n,l=Math.sin(Math.PI/4)*n,t.moveTo(i-s,a-l),t.lineTo(i+s,a+l),t.moveTo(i-s,a+l),t.lineTo(i+s,a-l),t.closePath();break;case"line":t.beginPath(),t.moveTo(i-n,a),t.lineTo(i+n,a),t.closePath();break;case"dash":t.beginPath(),t.moveTo(i,a),t.lineTo(i+n,a),t.closePath()}t.stroke()}}else t.drawImage(e,i-e.width/2,a-e.height/2,e.width,e.height)},clipArea:function(t,e){t.save(),t.beginPath(),t.rect(e.left,e.top,e.right-e.left,e.bottom-e.top),t.clip()},unclipArea:function(t){t.restore()},lineTo:function(t,e,n,i){if(n.steppedLine)return"after"===n.steppedLine&&!i||"after"!==n.steppedLine&&i?t.lineTo(e.x,n.y):t.lineTo(n.x,e.y),void t.lineTo(n.x,n.y);n.tension?t.bezierCurveTo(i?e.controlPointPreviousX:e.controlPointNextX,i?e.controlPointPreviousY:e.controlPointNextY,i?n.controlPointNextX:n.controlPointPreviousX,i?n.controlPointNextY:n.controlPointPreviousY,n.x,n.y):t.lineTo(n.x,n.y)}};i.clear=n.clear,i.drawRoundedRectangle=function(t){t.beginPath(),n.roundedRect.apply(n,arguments),t.closePath()}},{42:42}],42:[function(t,e,n){"use strict";var i={noop:function(){},uid:function(){var t=0;return function(){return t++}}(),isNullOrUndef:function(t){return null===t||void 0===t},isArray:Array.isArray?Array.isArray:function(t){return"[object Array]"===Object.prototype.toString.call(t)},isObject:function(t){return null!==t&&"[object Object]"===Object.prototype.toString.call(t)},valueOrDefault:function(t,e){return void 0===t?e:t},valueAtIndexOrDefault:function(t,e,n){return i.valueOrDefault(i.isArray(t)?t[e]:t,n)},callback:function(t,e,n){if(t&&"function"==typeof t.call)return t.apply(n,e)},each:function(t,e,n,a){var r,o,s;if(i.isArray(t))if(o=t.length,a)for(r=o-1;r>=0;r--)e.call(n,t[r],r);else for(r=0;r<o;r++)e.call(n,t[r],r);else if(i.isObject(t))for(o=(s=Object.keys(t)).length,r=0;r<o;r++)e.call(n,t[s[r]],s[r])},arrayEquals:function(t,e){var n,a,r,o;if(!t||!e||t.length!==e.length)return!1;for(n=0,a=t.length;n<a;++n)if(r=t[n],o=e[n],r instanceof Array&&o instanceof Array){if(!i.arrayEquals(r,o))return!1}else if(r!==o)return!1;return!0},clone:function(t){if(i.isArray(t))return t.map(i.clone);if(i.isObject(t)){for(var e={},n=Object.keys(t),a=n.length,r=0;r<a;++r)e[n[r]]=i.clone(t[n[r]]);return e}return t},_merger:function(t,e,n,a){var r=e[t],o=n[t];i.isObject(r)&&i.isObject(o)?i.merge(r,o,a):e[t]=i.clone(o)},_mergerIf:function(t,e,n){var a=e[t],r=n[t];i.isObject(a)&&i.isObject(r)?i.mergeIf(a,r):e.hasOwnProperty(t)||(e[t]=i.clone(r))},merge:function(t,e,n){var a,r,o,s,l,u=i.isArray(e)?e:[e],d=u.length;if(!i.isObject(t))return t;for(a=(n=n||{}).merger||i._merger,r=0;r<d;++r)if(e=u[r],i.isObject(e))for(l=0,s=(o=Object.keys(e)).length;l<s;++l)a(o[l],t,e,n);return t},mergeIf:function(t,e){return i.merge(t,e,{merger:i._mergerIf})}};e.exports=i,i.callCallback=i.callback,i.indexOf=function(t,e,n){return Array.prototype.indexOf.call(t,e,n)},i.getValueOrDefault=i.valueOrDefault,i.getValueAtIndexOrDefault=i.valueAtIndexOrDefault},{}],43:[function(t,e,n){"use strict";var i=t(42),a={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return-t*(t-2)},easeInOutQuad:function(t){return(t/=.5)<1?.5*t*t:-.5*(--t*(t-2)-1)},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return(t-=1)*t*t+1},easeInOutCubic:function(t){return(t/=.5)<1?.5*t*t*t:.5*((t-=2)*t*t+2)},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return-((t-=1)*t*t*t-1)},easeInOutQuart:function(t){return(t/=.5)<1?.5*t*t*t*t:-.5*((t-=2)*t*t*t-2)},easeInQuint:function(t){return t*t*t*t*t},easeOutQuint:function(t){return(t-=1)*t*t*t*t+1},easeInOutQuint:function(t){return(t/=.5)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)},easeInSine:function(t){return 1-Math.cos(t*(Math.PI/2))},easeOutSine:function(t){return Math.sin(t*(Math.PI/2))},easeInOutSine:function(t){return-.5*(Math.cos(Math.PI*t)-1)},easeInExpo:function(t){return 0===t?0:Math.pow(2,10*(t-1))},easeOutExpo:function(t){return 1===t?1:1-Math.pow(2,-10*t)},easeInOutExpo:function(t){return 0===t?0:1===t?1:(t/=.5)<1?.5*Math.pow(2,10*(t-1)):.5*(2-Math.pow(2,-10*--t))},easeInCirc:function(t){return t>=1?t:-(Math.sqrt(1-t*t)-1)},easeOutCirc:function(t){return Math.sqrt(1-(t-=1)*t)},easeInOutCirc:function(t){return(t/=.5)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:1===t?1:(n||(n=.3),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),-i*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n))},easeOutElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:1===t?1:(n||(n=.3),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),i*Math.pow(2,-10*t)*Math.sin((t-e)*(2*Math.PI)/n)+1)},easeInOutElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:2==(t/=.5)?1:(n||(n=.45),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),t<1?i*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n)*-.5:i*Math.pow(2,-10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n)*.5+1)},easeInBack:function(t){var e=1.70158;return t*t*((e+1)*t-e)},easeOutBack:function(t){var e=1.70158;return(t-=1)*t*((e+1)*t+e)+1},easeInOutBack:function(t){var e=1.70158;return(t/=.5)<1?t*t*((1+(e*=1.525))*t-e)*.5:.5*((t-=2)*t*((1+(e*=1.525))*t+e)+2)},easeInBounce:function(t){return 1-a.easeOutBounce(1-t)},easeOutBounce:function(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375},easeInOutBounce:function(t){return t<.5?.5*a.easeInBounce(2*t):.5*a.easeOutBounce(2*t-1)+.5}};e.exports={effects:a},i.easingEffects=a},{42:42}],44:[function(t,e,n){"use strict";var i=t(42);e.exports={toLineHeight:function(t,e){var n=(""+t).match(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/);if(!n||"normal"===n[1])return 1.2*e;switch(t=+n[2],n[3]){case"px":return t;case"%":t/=100}return e*t},toPadding:function(t){var e,n,a,r;return i.isObject(t)?(e=+t.top||0,n=+t.right||0,a=+t.bottom||0,r=+t.left||0):e=n=a=r=+t||0,{top:e,right:n,bottom:a,left:r,height:e+a,width:r+n}},resolve:function(t,e,n){var a,r,o;for(a=0,r=t.length;a<r;++a)if(void 0!==(o=t[a])&&(void 0!==e&&"function"==typeof o&&(o=o(e)),void 0!==n&&i.isArray(o)&&(o=o[n]),void 0!==o))return o}}},{42:42}],45:[function(t,e,n){"use strict";e.exports=t(42),e.exports.easing=t(43),e.exports.canvas=t(41),e.exports.options=t(44)},{41:41,42:42,43:43,44:44}],46:[function(t,e,n){e.exports={acquireContext:function(t){return t&&t.canvas&&(t=t.canvas),t&&t.getContext("2d")||null}}},{}],47:[function(t,e,n){"use strict";function i(t,e){var n=p.getStyle(t,e),i=n&&n.match(/^(\d+)(\.\d+)?px$/);return i?Number(i[1]):void 0}function a(t,e){var n=t.style,a=t.getAttribute("height"),r=t.getAttribute("width");if(t[v]={initial:{height:a,width:r,style:{display:n.display,height:n.height,width:n.width}}},n.display=n.display||"block",null===r||""===r){var o=i(t,"width");void 0!==o&&(t.width=o)}if(null===a||""===a)if(""===t.style.height)t.height=t.width/(e.options.aspectRatio||2);else{var s=i(t,"height");void 0!==o&&(t.height=s)}return t}function r(t,e,n){t.addEventListener(e,n,w)}function o(t,e,n){t.removeEventListener(e,n,w)}function s(t,e,n,i,a){return{type:t,chart:e,native:a||null,x:void 0!==n?n:null,y:void 0!==i?i:null}}function l(t,e){var n=k[t.type]||t.type,i=p.getRelativePosition(t,e);return s(n,e,i.x,i.y,t)}function u(t,e){var n=!1,i=[];return function(){i=Array.prototype.slice.call(arguments),e=e||this,n||(n=!0,p.requestAnimFrame.call(window,function(){n=!1,t.apply(e,i)}))}}function d(t){var e=document.createElement("div"),n=y+"size-monitor",i="position:absolute;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1;";e.style.cssText=i,e.className=n,e.innerHTML='<div class="'+n+'-expand" style="'+i+'"><div style="position:absolute;width:1000000px;height:1000000px;left:0;top:0"></div></div><div class="'+n+'-shrink" style="'+i+'"><div style="position:absolute;width:200%;height:200%;left:0; top:0"></div></div>';var a=e.childNodes[0],o=e.childNodes[1];e._reset=function(){a.scrollLeft=1e6,a.scrollTop=1e6,o.scrollLeft=1e6,o.scrollTop=1e6};var s=function(){e._reset(),t()};return r(a,"scroll",s.bind(a,"expand")),r(o,"scroll",s.bind(o,"shrink")),e}function c(t,e){var n=(t[v]||(t[v]={})).renderProxy=function(t){t.animationName===x&&e()};p.each(_,function(e){r(t,e,n)}),t.classList.add(b)}function h(t){var e=t[v]||{},n=e.renderProxy;n&&(p.each(_,function(e){o(t,e,n)}),delete e.renderProxy),t.classList.remove(b)}function f(t,e,n){var i=t[v]||(t[v]={}),a=i.resizer=d(u(function(){if(i.resizer)return e(s("resize",n))}));c(t,function(){if(i.resizer){var e=t.parentNode;e&&e!==a.parentNode&&e.insertBefore(a,e.firstChild),a._reset()}})}function g(t){var e=t[v]||{},n=e.resizer;delete e.resizer,h(t),n&&n.parentNode&&n.parentNode.removeChild(n)}function m(t,e){var n=t._style||document.createElement("style");t._style||(t._style=n,e="/* Chart.js */\n"+e,n.setAttribute("type","text/css"),document.getElementsByTagName("head")[0].appendChild(n)),n.appendChild(document.createTextNode(e))}var p=t(45),v="$chartjs",y="chartjs-",b=y+"render-monitor",x=y+"render-animation",_=["animationstart","webkitAnimationStart"],k={touchstart:"mousedown",touchmove:"mousemove",touchend:"mouseup",pointerenter:"mouseenter",pointerdown:"mousedown",pointermove:"mousemove",pointerup:"mouseup",pointerleave:"mouseout",pointerout:"mouseout"},w=!!function(){var t=!1;try{var e=Object.defineProperty({},"passive",{get:function(){t=!0}});window.addEventListener("e",null,e)}catch(t){}return t}()&&{passive:!0};e.exports={_enabled:"undefined"!=typeof window&&"undefined"!=typeof document,initialize:function(){var t="from{opacity:0.99}to{opacity:1}";m(this,"@-webkit-keyframes "+x+"{"+t+"}@keyframes "+x+"{"+t+"}."+b+"{-webkit-animation:"+x+" 0.001s;animation:"+x+" 0.001s;}")},acquireContext:function(t,e){"string"==typeof t?t=document.getElementById(t):t.length&&(t=t[0]),t&&t.canvas&&(t=t.canvas);var n=t&&t.getContext&&t.getContext("2d");return n&&n.canvas===t?(a(t,e),n):null},releaseContext:function(t){var e=t.canvas;if(e[v]){var n=e[v].initial;["height","width"].forEach(function(t){var i=n[t];p.isNullOrUndef(i)?e.removeAttribute(t):e.setAttribute(t,i)}),p.each(n.style||{},function(t,n){e.style[n]=t}),e.width=e.width,delete e[v]}},addEventListener:function(t,e,n){var i=t.canvas;if("resize"!==e){var a=n[v]||(n[v]={});r(i,e,(a.proxies||(a.proxies={}))[t.id+"_"+e]=function(e){n(l(e,t))})}else f(i,n,t)},removeEventListener:function(t,e,n){var i=t.canvas;if("resize"!==e){var a=((n[v]||{}).proxies||{})[t.id+"_"+e];a&&o(i,e,a)}else g(i)}},p.addEvent=r,p.removeEvent=o},{45:45}],48:[function(t,e,n){"use strict";var i=t(45),a=t(46),r=t(47),o=r._enabled?r:a;e.exports=i.extend({initialize:function(){},acquireContext:function(){},releaseContext:function(){},addEventListener:function(){},removeEventListener:function(){}},o)},{45:45,46:46,47:47}],49:[function(t,e,n){"use strict";var i=t(25),a=t(40),r=t(45);i._set("global",{plugins:{filler:{propagate:!0}}}),e.exports=function(){function t(t,e,n){var i,a=t._model||{},r=a.fill;if(void 0===r&&(r=!!a.backgroundColor),!1===r||null===r)return!1;if(!0===r)return"origin";if(i=parseFloat(r,10),isFinite(i)&&Math.floor(i)===i)return"-"!==r[0]&&"+"!==r[0]||(i=e+i),!(i===e||i<0||i>=n)&&i;switch(r){case"bottom":return"start";case"top":return"end";case"zero":return"origin";case"origin":case"start":case"end":return r;default:return!1}}function e(t){var e,n=t.el._model||{},i=t.el._scale||{},a=t.fill,r=null;if(isFinite(a))return null;if("start"===a?r=void 0===n.scaleBottom?i.bottom:n.scaleBottom:"end"===a?r=void 0===n.scaleTop?i.top:n.scaleTop:void 0!==n.scaleZero?r=n.scaleZero:i.getBasePosition?r=i.getBasePosition():i.getBasePixel&&(r=i.getBasePixel()),void 0!==r&&null!==r){if(void 0!==r.x&&void 0!==r.y)return r;if("number"==typeof r&&isFinite(r))return e=i.isHorizontal(),{x:e?r:null,y:e?null:r}}return null}function n(t,e,n){var i,a=t[e].fill,r=[e];if(!n)return a;for(;!1!==a&&-1===r.indexOf(a);){if(!isFinite(a))return a;if(!(i=t[a]))return!1;if(i.visible)return a;r.push(a),a=i.fill}return!1}function o(t){var e=t.fill,n="dataset";return!1===e?null:(isFinite(e)||(n="boundary"),d[n](t))}function s(t){return t&&!t.skip}function l(t,e,n,i,a){var o;if(i&&a){for(t.moveTo(e[0].x,e[0].y),o=1;o<i;++o)r.canvas.lineTo(t,e[o-1],e[o]);for(t.lineTo(n[a-1].x,n[a-1].y),o=a-1;o>0;--o)r.canvas.lineTo(t,n[o],n[o-1],!0)}}function u(t,e,n,i,a,r){var o,u,d,c,h,f,g,m=e.length,p=i.spanGaps,v=[],y=[],b=0,x=0;for(t.beginPath(),o=0,u=m+!!r;o<u;++o)h=n(c=e[d=o%m]._view,d,i),f=s(c),g=s(h),f&&g?(b=v.push(c),x=y.push(h)):b&&x&&(p?(f&&v.push(c),g&&y.push(h)):(l(t,v,y,b,x),b=x=0,v=[],y=[]));l(t,v,y,b,x),t.closePath(),t.fillStyle=a,t.fill()}var d={dataset:function(t){var e=t.fill,n=t.chart,i=n.getDatasetMeta(e),a=i&&n.isDatasetVisible(e)&&i.dataset._children||[],r=a.length||0;return r?function(t,e){return e<r&&a[e]._view||null}:null},boundary:function(t){var e=t.boundary,n=e?e.x:null,i=e?e.y:null;return function(t){return{x:null===n?t.x:n,y:null===i?t.y:i}}}};return{id:"filler",afterDatasetsUpdate:function(i,r){var s,l,u,d,c=(i.data.datasets||[]).length,h=r.propagate,f=[];for(l=0;l<c;++l)d=null,(u=(s=i.getDatasetMeta(l)).dataset)&&u._model&&u instanceof a.Line&&(d={visible:i.isDatasetVisible(l),fill:t(u,l,c),chart:i,el:u}),s.$filler=d,f.push(d);for(l=0;l<c;++l)(d=f[l])&&(d.fill=n(f,l,h),d.boundary=e(d),d.mapper=o(d))},beforeDatasetDraw:function(t,e){var n=e.meta.$filler;if(n){var a=t.ctx,o=n.el,s=o._view,l=o._children||[],d=n.mapper,c=s.backgroundColor||i.global.defaultColor;d&&c&&l.length&&(r.canvas.clipArea(a,t.chartArea),u(a,l,d,s,c,o._loop),r.canvas.unclipArea(a))}}}}},{25:25,40:40,45:45}],50:[function(t,e,n){"use strict";var i=t(25),a=t(26),r=t(45);i._set("global",{legend:{display:!0,position:"top",fullWidth:!0,reverse:!1,weight:1e3,onClick:function(t,e){var n=e.datasetIndex,i=this.chart,a=i.getDatasetMeta(n);a.hidden=null===a.hidden?!i.data.datasets[n].hidden:null,i.update()},onHover:null,labels:{boxWidth:40,padding:10,generateLabels:function(t){var e=t.data;return r.isArray(e.datasets)?e.datasets.map(function(e,n){return{text:e.label,fillStyle:r.isArray(e.backgroundColor)?e.backgroundColor[0]:e.backgroundColor,hidden:!t.isDatasetVisible(n),lineCap:e.borderCapStyle,lineDash:e.borderDash,lineDashOffset:e.borderDashOffset,lineJoin:e.borderJoinStyle,lineWidth:e.borderWidth,strokeStyle:e.borderColor,pointStyle:e.pointStyle,datasetIndex:n}},this):[]}}},legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');for(var n=0;n<t.data.datasets.length;n++)e.push('<li><span style="background-color:'+t.data.datasets[n].backgroundColor+'"></span>'),t.data.datasets[n].label&&e.push(t.data.datasets[n].label),e.push("</li>");return e.push("</ul>"),e.join("")}}),e.exports=function(t){function e(t,e){return t.usePointStyle?e*Math.SQRT2:t.boxWidth}function n(e,n){var i=new t.Legend({ctx:e.ctx,options:n,chart:e});o.configure(e,i,n),o.addBox(e,i),e.legend=i}var o=t.layoutService,s=r.noop;return t.Legend=a.extend({initialize:function(t){r.extend(this,t),this.legendHitBoxes=[],this.doughnutMode=!1},beforeUpdate:s,update:function(t,e,n){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=n,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:s,beforeSetDimensions:s,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:s,beforeBuildLabels:s,buildLabels:function(){var t=this,e=t.options.labels||{},n=r.callback(e.generateLabels,[t.chart],t)||[];e.filter&&(n=n.filter(function(n){return e.filter(n,t.chart.data)})),t.options.reverse&&n.reverse(),t.legendItems=n},afterBuildLabels:s,beforeFit:s,fit:function(){var t=this,n=t.options,a=n.labels,o=n.display,s=t.ctx,l=i.global,u=r.valueOrDefault,d=u(a.fontSize,l.defaultFontSize),c=u(a.fontStyle,l.defaultFontStyle),h=u(a.fontFamily,l.defaultFontFamily),f=r.fontString(d,c,h),g=t.legendHitBoxes=[],m=t.minSize,p=t.isHorizontal();if(p?(m.width=t.maxWidth,m.height=o?10:0):(m.width=o?10:0,m.height=t.maxHeight),o)if(s.font=f,p){var v=t.lineWidths=[0],y=t.legendItems.length?d+a.padding:0;s.textAlign="left",s.textBaseline="top",r.each(t.legendItems,function(n,i){var r=e(a,d)+d/2+s.measureText(n.text).width;v[v.length-1]+r+a.padding>=t.width&&(y+=d+a.padding,v[v.length]=t.left),g[i]={left:0,top:0,width:r,height:d},v[v.length-1]+=r+a.padding}),m.height+=y}else{var b=a.padding,x=t.columnWidths=[],_=a.padding,k=0,w=0,M=d+b;r.each(t.legendItems,function(t,n){var i=e(a,d)+d/2+s.measureText(t.text).width;w+M>m.height&&(_+=k+a.padding,x.push(k),k=0,w=0),k=Math.max(k,i),w+=M,g[n]={left:0,top:0,width:i,height:d}}),_+=k,x.push(k),m.width+=_}t.width=m.width,t.height=m.height},afterFit:s,isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},draw:function(){var t=this,n=t.options,a=n.labels,o=i.global,s=o.elements.line,l=t.width,u=t.lineWidths;if(n.display){var d,c=t.ctx,h=r.valueOrDefault,f=h(a.fontColor,o.defaultFontColor),g=h(a.fontSize,o.defaultFontSize),m=h(a.fontStyle,o.defaultFontStyle),p=h(a.fontFamily,o.defaultFontFamily),v=r.fontString(g,m,p);c.textAlign="left",c.textBaseline="middle",c.lineWidth=.5,c.strokeStyle=f,c.fillStyle=f,c.font=v;var y=e(a,g),b=t.legendHitBoxes,x=function(t,e,i){if(!(isNaN(y)||y<=0)){c.save(),c.fillStyle=h(i.fillStyle,o.defaultColor),c.lineCap=h(i.lineCap,s.borderCapStyle),c.lineDashOffset=h(i.lineDashOffset,s.borderDashOffset),c.lineJoin=h(i.lineJoin,s.borderJoinStyle),c.lineWidth=h(i.lineWidth,s.borderWidth),c.strokeStyle=h(i.strokeStyle,o.defaultColor);var a=0===h(i.lineWidth,s.borderWidth);if(c.setLineDash&&c.setLineDash(h(i.lineDash,s.borderDash)),n.labels&&n.labels.usePointStyle){var l=g*Math.SQRT2/2,u=l/Math.SQRT2,d=t+u,f=e+u;r.canvas.drawPoint(c,i.pointStyle,l,d,f)}else a||c.strokeRect(t,e,y,g),c.fillRect(t,e,y,g);c.restore()}},_=function(t,e,n,i){var a=g/2,r=y+a+t,o=e+a;c.fillText(n.text,r,o),n.hidden&&(c.beginPath(),c.lineWidth=2,c.moveTo(r,o),c.lineTo(r+i,o),c.stroke())},k=t.isHorizontal();d=k?{x:t.left+(l-u[0])/2,y:t.top+a.padding,line:0}:{x:t.left+a.padding,y:t.top+a.padding,line:0};var w=g+a.padding;r.each(t.legendItems,function(e,n){var i=c.measureText(e.text).width,r=y+g/2+i,o=d.x,s=d.y;k?o+r>=l&&(s=d.y+=w,d.line++,o=d.x=t.left+(l-u[d.line])/2):s+w>t.bottom&&(o=d.x=o+t.columnWidths[d.line]+a.padding,s=d.y=t.top+a.padding,d.line++),x(o,s,e),b[n].left=o,b[n].top=s,_(o,s,e,i),k?d.x+=r+a.padding:d.y+=w})}},handleEvent:function(t){var e=this,n=e.options,i="mouseup"===t.type?"click":t.type,a=!1;if("mousemove"===i){if(!n.onHover)return}else{if("click"!==i)return;if(!n.onClick)return}var r=t.x,o=t.y;if(r>=e.left&&r<=e.right&&o>=e.top&&o<=e.bottom)for(var s=e.legendHitBoxes,l=0;l<s.length;++l){var u=s[l];if(r>=u.left&&r<=u.left+u.width&&o>=u.top&&o<=u.top+u.height){if("click"===i){n.onClick.call(e,t.native,e.legendItems[l]),a=!0;break}if("mousemove"===i){n.onHover.call(e,t.native,e.legendItems[l]),a=!0;break}}}return a}}),{id:"legend",beforeInit:function(t){var e=t.options.legend;e&&n(t,e)},beforeUpdate:function(t){var e=t.options.legend,a=t.legend;e?(r.mergeIf(e,i.global.legend),a?(o.configure(t,a,e),a.options=e):n(t,e)):a&&(o.removeBox(t,a),delete t.legend)},afterEvent:function(t,e){var n=t.legend;n&&n.handleEvent(e)}}}},{25:25,26:26,45:45}],51:[function(t,e,n){"use strict";var i=t(25),a=t(26),r=t(45);i._set("global",{title:{display:!1,fontStyle:"bold",fullWidth:!0,lineHeight:1.2,padding:10,position:"top",text:"",weight:2e3}}),e.exports=function(t){function e(e,i){var a=new t.Title({ctx:e.ctx,options:i,chart:e});n.configure(e,a,i),n.addBox(e,a),e.titleBlock=a}var n=t.layoutService,o=r.noop;return t.Title=a.extend({initialize:function(t){var e=this;r.extend(e,t),e.legendHitBoxes=[]},beforeUpdate:o,update:function(t,e,n){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=n,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:o,beforeSetDimensions:o,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:o,beforeBuildLabels:o,buildLabels:o,afterBuildLabels:o,beforeFit:o,fit:function(){var t=this,e=r.valueOrDefault,n=t.options,a=n.display,o=e(n.fontSize,i.global.defaultFontSize),s=t.minSize,l=r.isArray(n.text)?n.text.length:1,u=r.options.toLineHeight(n.lineHeight,o),d=a?l*u+2*n.padding:0;t.isHorizontal()?(s.width=t.maxWidth,s.height=d):(s.width=d,s.height=t.maxHeight),t.width=s.width,t.height=s.height},afterFit:o,isHorizontal:function(){var t=this.options.position;return"top"===t||"bottom"===t},draw:function(){var t=this,e=t.ctx,n=r.valueOrDefault,a=t.options,o=i.global;if(a.display){var s,l,u,d=n(a.fontSize,o.defaultFontSize),c=n(a.fontStyle,o.defaultFontStyle),h=n(a.fontFamily,o.defaultFontFamily),f=r.fontString(d,c,h),g=r.options.toLineHeight(a.lineHeight,d),m=g/2+a.padding,p=0,v=t.top,y=t.left,b=t.bottom,x=t.right;e.fillStyle=n(a.fontColor,o.defaultFontColor),e.font=f,t.isHorizontal()?(l=y+(x-y)/2,u=v+m,s=x-y):(l="left"===a.position?y+m:x-m,u=v+(b-v)/2,s=b-v,p=Math.PI*("left"===a.position?-.5:.5)),e.save(),e.translate(l,u),e.rotate(p),e.textAlign="center",e.textBaseline="middle";var _=a.text;if(r.isArray(_))for(var k=0,w=0;w<_.length;++w)e.fillText(_[w],0,k,s),k+=g;else e.fillText(_,0,0,s);e.restore()}}}),{id:"title",beforeInit:function(t){var n=t.options.title;n&&e(t,n)},beforeUpdate:function(a){var o=a.options.title,s=a.titleBlock;o?(r.mergeIf(o,i.global.title),s?(n.configure(a,s,o),s.options=o):e(a,o)):s&&(t.layoutService.removeBox(a,s),delete a.titleBlock)}}}},{25:25,26:26,45:45}],52:[function(t,e,n){"use strict";e.exports=function(t){var e={position:"bottom"},n=t.Scale.extend({getLabels:function(){var t=this.chart.data;return this.options.labels||(this.isHorizontal()?t.xLabels:t.yLabels)||t.labels},determineDataLimits:function(){var t=this,e=t.getLabels();t.minIndex=0,t.maxIndex=e.length-1;var n;void 0!==t.options.ticks.min&&(n=e.indexOf(t.options.ticks.min),t.minIndex=-1!==n?n:t.minIndex),void 0!==t.options.ticks.max&&(n=e.indexOf(t.options.ticks.max),t.maxIndex=-1!==n?n:t.maxIndex),t.min=e[t.minIndex],t.max=e[t.maxIndex]},buildTicks:function(){var t=this,e=t.getLabels();t.ticks=0===t.minIndex&&t.maxIndex===e.length-1?e:e.slice(t.minIndex,t.maxIndex+1)},getLabelForIndex:function(t,e){var n=this,i=n.chart.data,a=n.isHorizontal();return i.yLabels&&!a?n.getRightValue(i.datasets[e].data[t]):n.ticks[t-n.minIndex]},getPixelForValue:function(t,e){var n,i=this,a=i.options.offset,r=Math.max(i.maxIndex+1-i.minIndex-(a?0:1),1);if(void 0!==t&&null!==t&&(n=i.isHorizontal()?t.x:t.y),void 0!==n||void 0!==t&&isNaN(e)){var o=i.getLabels();t=n||t;var s=o.indexOf(t);e=-1!==s?s:e}if(i.isHorizontal()){var l=i.width/r,u=l*(e-i.minIndex);return a&&(u+=l/2),i.left+Math.round(u)}var d=i.height/r,c=d*(e-i.minIndex);return a&&(c+=d/2),i.top+Math.round(c)},getPixelForTick:function(t){return this.getPixelForValue(this.ticks[t],t+this.minIndex,null)},getValueForPixel:function(t){var e=this,n=e.options.offset,i=Math.max(e._ticks.length-(n?0:1),1),a=e.isHorizontal(),r=(a?e.width:e.height)/i;return t-=a?e.left:e.top,n&&(t-=r/2),(t<=0?0:Math.round(t/r))+e.minIndex},getBasePixel:function(){return this.bottom}});t.scaleService.registerScaleType("category",n,e)}},{}],53:[function(t,e,n){"use strict";var i=t(25),a=t(45),r=t(34);e.exports=function(t){var e={position:"left",ticks:{callback:r.formatters.linear}},n=t.LinearScaleBase.extend({determineDataLimits:function(){function t(t){return o?t.xAxisID===e.id:t.yAxisID===e.id}var e=this,n=e.options,i=e.chart,r=i.data.datasets,o=e.isHorizontal();e.min=null,e.max=null;var s=n.stacked;if(void 0===s&&a.each(r,function(e,n){if(!s){var a=i.getDatasetMeta(n);i.isDatasetVisible(n)&&t(a)&&void 0!==a.stack&&(s=!0)}}),n.stacked||s){var l={};a.each(r,function(r,o){var s=i.getDatasetMeta(o),u=[s.type,void 0===n.stacked&&void 0===s.stack?o:"",s.stack].join(".");void 0===l[u]&&(l[u]={positiveValues:[],negativeValues:[]});var d=l[u].positiveValues,c=l[u].negativeValues;i.isDatasetVisible(o)&&t(s)&&a.each(r.data,function(t,i){var a=+e.getRightValue(t);isNaN(a)||s.data[i].hidden||(d[i]=d[i]||0,c[i]=c[i]||0,n.relativePoints?d[i]=100:a<0?c[i]+=a:d[i]+=a)})}),a.each(l,function(t){var n=t.positiveValues.concat(t.negativeValues),i=a.min(n),r=a.max(n);e.min=null===e.min?i:Math.min(e.min,i),e.max=null===e.max?r:Math.max(e.max,r)})}else a.each(r,function(n,r){var o=i.getDatasetMeta(r);i.isDatasetVisible(r)&&t(o)&&a.each(n.data,function(t,n){var i=+e.getRightValue(t);isNaN(i)||o.data[n].hidden||(null===e.min?e.min=i:i<e.min&&(e.min=i),null===e.max?e.max=i:i>e.max&&(e.max=i))})});e.min=isFinite(e.min)&&!isNaN(e.min)?e.min:0,e.max=isFinite(e.max)&&!isNaN(e.max)?e.max:1,this.handleTickRangeOptions()},getTickLimit:function(){var t,e=this,n=e.options.ticks;if(e.isHorizontal())t=Math.min(n.maxTicksLimit?n.maxTicksLimit:11,Math.ceil(e.width/50));else{var r=a.valueOrDefault(n.fontSize,i.global.defaultFontSize);t=Math.min(n.maxTicksLimit?n.maxTicksLimit:11,Math.ceil(e.height/(2*r)))}return t},handleDirectionalChanges:function(){this.isHorizontal()||this.ticks.reverse()},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForValue:function(t){var e,n=this,i=n.start,a=+n.getRightValue(t),r=n.end-i;return n.isHorizontal()?(e=n.left+n.width/r*(a-i),Math.round(e)):(e=n.bottom-n.height/r*(a-i),Math.round(e))},getValueForPixel:function(t){var e=this,n=e.isHorizontal(),i=n?e.width:e.height,a=(n?t-e.left:e.bottom-t)/i;return e.start+(e.end-e.start)*a},getPixelForTick:function(t){return this.getPixelForValue(this.ticksAsNumbers[t])}});t.scaleService.registerScaleType("linear",n,e)}},{25:25,34:34,45:45}],54:[function(t,e,n){"use strict";var i=t(45),a=t(34);e.exports=function(t){var e=i.noop;t.LinearScaleBase=t.Scale.extend({getRightValue:function(e){return"string"==typeof e?+e:t.Scale.prototype.getRightValue.call(this,e)},handleTickRangeOptions:function(){var t=this,e=t.options.ticks;if(e.beginAtZero){var n=i.sign(t.min),a=i.sign(t.max);n<0&&a<0?t.max=0:n>0&&a>0&&(t.min=0)}var r=void 0!==e.min||void 0!==e.suggestedMin,o=void 0!==e.max||void 0!==e.suggestedMax;void 0!==e.min?t.min=e.min:void 0!==e.suggestedMin&&(null===t.min?t.min=e.suggestedMin:t.min=Math.min(t.min,e.suggestedMin)),void 0!==e.max?t.max=e.max:void 0!==e.suggestedMax&&(null===t.max?t.max=e.suggestedMax:t.max=Math.max(t.max,e.suggestedMax)),r!==o&&t.min>=t.max&&(r?t.max=t.min+1:t.min=t.max-1),t.min===t.max&&(t.max++,e.beginAtZero||t.min--)},getTickLimit:e,handleDirectionalChanges:e,buildTicks:function(){var t=this,e=t.options.ticks,n=t.getTickLimit(),r={maxTicks:n=Math.max(2,n),min:e.min,max:e.max,stepSize:i.valueOrDefault(e.fixedStepSize,e.stepSize)},o=t.ticks=a.generators.linear(r,t);t.handleDirectionalChanges(),t.max=i.max(o),t.min=i.min(o),e.reverse?(o.reverse(),t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max)},convertTicksToLabels:function(){var e=this;e.ticksAsNumbers=e.ticks.slice(),e.zeroLineIndex=e.ticks.indexOf(0),t.Scale.prototype.convertTicksToLabels.call(e)}})}},{34:34,45:45}],55:[function(t,e,n){"use strict";var i=t(45),a=t(34);e.exports=function(t){var e={position:"left",ticks:{callback:a.formatters.logarithmic}},n=t.Scale.extend({determineDataLimits:function(){function t(t){return l?t.xAxisID===e.id:t.yAxisID===e.id}var e=this,n=e.options,a=n.ticks,r=e.chart,o=r.data.datasets,s=i.valueOrDefault,l=e.isHorizontal();e.min=null,e.max=null,e.minNotZero=null;var u=n.stacked;if(void 0===u&&i.each(o,function(e,n){if(!u){var i=r.getDatasetMeta(n);r.isDatasetVisible(n)&&t(i)&&void 0!==i.stack&&(u=!0)}}),n.stacked||u){var d={};i.each(o,function(a,o){var s=r.getDatasetMeta(o),l=[s.type,void 0===n.stacked&&void 0===s.stack?o:"",s.stack].join(".");r.isDatasetVisible(o)&&t(s)&&(void 0===d[l]&&(d[l]=[]),i.each(a.data,function(t,i){var a=d[l],r=+e.getRightValue(t);isNaN(r)||s.data[i].hidden||(a[i]=a[i]||0,n.relativePoints?a[i]=100:a[i]+=r)}))}),i.each(d,function(t){var n=i.min(t),a=i.max(t);e.min=null===e.min?n:Math.min(e.min,n),e.max=null===e.max?a:Math.max(e.max,a)})}else i.each(o,function(n,a){var o=r.getDatasetMeta(a);r.isDatasetVisible(a)&&t(o)&&i.each(n.data,function(t,n){var i=+e.getRightValue(t);isNaN(i)||o.data[n].hidden||(null===e.min?e.min=i:i<e.min&&(e.min=i),null===e.max?e.max=i:i>e.max&&(e.max=i),0!==i&&(null===e.minNotZero||i<e.minNotZero)&&(e.minNotZero=i))})});e.min=s(a.min,e.min),e.max=s(a.max,e.max),e.min===e.max&&(0!==e.min&&null!==e.min?(e.min=Math.pow(10,Math.floor(i.log10(e.min))-1),e.max=Math.pow(10,Math.floor(i.log10(e.max))+1)):(e.min=1,e.max=10))},buildTicks:function(){var t=this,e=t.options.ticks,n={min:e.min,max:e.max},r=t.ticks=a.generators.logarithmic(n,t);t.isHorizontal()||r.reverse(),t.max=i.max(r),t.min=i.min(r),e.reverse?(r.reverse(),t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max)},convertTicksToLabels:function(){this.tickValues=this.ticks.slice(),t.Scale.prototype.convertTicksToLabels.call(this)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForTick:function(t){return this.getPixelForValue(this.tickValues[t])},getPixelForValue:function(t){var e,n,a,r=this,o=r.start,s=+r.getRightValue(t),l=r.options.ticks;return r.isHorizontal()?(a=i.log10(r.end)-i.log10(o),0===s?n=r.left:(e=r.width,n=r.left+e/a*(i.log10(s)-i.log10(o)))):(e=r.height,0!==o||l.reverse?0===r.end&&l.reverse?(a=i.log10(r.start)-i.log10(r.minNotZero),n=s===r.end?r.top:s===r.minNotZero?r.top+.02*e:r.top+.02*e+.98*e/a*(i.log10(s)-i.log10(r.minNotZero))):0===s?n=l.reverse?r.top:r.bottom:(a=i.log10(r.end)-i.log10(o),e=r.height,n=r.bottom-e/a*(i.log10(s)-i.log10(o))):(a=i.log10(r.end)-i.log10(r.minNotZero),n=s===o?r.bottom:s===r.minNotZero?r.bottom-.02*e:r.bottom-.02*e-.98*e/a*(i.log10(s)-i.log10(r.minNotZero)))),n},getValueForPixel:function(t){var e,n,a=this,r=i.log10(a.end)-i.log10(a.start);return a.isHorizontal()?(n=a.width,e=a.start*Math.pow(10,(t-a.left)*r/n)):(n=a.height,e=Math.pow(10,(a.bottom-t)*r/n)/a.start),e}});t.scaleService.registerScaleType("logarithmic",n,e)}},{34:34,45:45}],56:[function(t,e,n){"use strict";var i=t(25),a=t(45),r=t(34);e.exports=function(t){function e(t){var e=t.options;return e.angleLines.display||e.pointLabels.display?t.chart.data.labels.length:0}function n(t){var e=t.options.pointLabels,n=a.valueOrDefault(e.fontSize,p.defaultFontSize),i=a.valueOrDefault(e.fontStyle,p.defaultFontStyle),r=a.valueOrDefault(e.fontFamily,p.defaultFontFamily);return{size:n,style:i,family:r,font:a.fontString(n,i,r)}}function o(t,e,n){return a.isArray(n)?{w:a.longestText(t,t.font,n),h:n.length*e+1.5*(n.length-1)*e}:{w:t.measureText(n).width,h:e}}function s(t,e,n,i,a){return t===i||t===a?{start:e-n/2,end:e+n/2}:t<i||t>a?{start:e-n-5,end:e}:{start:e,end:e+n+5}}function l(t){var i,r,l,u=n(t),d=Math.min(t.height/2,t.width/2),c={r:t.width,l:0,t:t.height,b:0},h={};t.ctx.font=u.font,t._pointLabelSizes=[];var f=e(t);for(i=0;i<f;i++){l=t.getPointPosition(i,d),r=o(t.ctx,u.size,t.pointLabels[i]||""),t._pointLabelSizes[i]=r;var g=t.getIndexAngle(i),m=a.toDegrees(g)%360,p=s(m,l.x,r.w,0,180),v=s(m,l.y,r.h,90,270);p.start<c.l&&(c.l=p.start,h.l=g),p.end>c.r&&(c.r=p.end,h.r=g),v.start<c.t&&(c.t=v.start,h.t=g),v.end>c.b&&(c.b=v.end,h.b=g)}t.setReductions(d,c,h)}function u(t){var e=Math.min(t.height/2,t.width/2);t.drawingArea=Math.round(e),t.setCenterPoint(0,0,0,0)}function d(t){return 0===t||180===t?"center":t<180?"left":"right"}function c(t,e,n,i){if(a.isArray(e))for(var r=n.y,o=1.5*i,s=0;s<e.length;++s)t.fillText(e[s],n.x,r),r+=o;else t.fillText(e,n.x,n.y)}function h(t,e,n){90===t||270===t?n.y-=e.h/2:(t>270||t<90)&&(n.y-=e.h)}function f(t){var i=t.ctx,r=a.valueOrDefault,o=t.options,s=o.angleLines,l=o.pointLabels;i.lineWidth=s.lineWidth,i.strokeStyle=s.color;var u=t.getDistanceFromCenterForValue(o.ticks.reverse?t.min:t.max),f=n(t);i.textBaseline="top";for(var g=e(t)-1;g>=0;g--){if(s.display){var m=t.getPointPosition(g,u);i.beginPath(),i.moveTo(t.xCenter,t.yCenter),i.lineTo(m.x,m.y),i.stroke(),i.closePath()}if(l.display){var v=t.getPointPosition(g,u+5),y=r(l.fontColor,p.defaultFontColor);i.font=f.font,i.fillStyle=y;var b=t.getIndexAngle(g),x=a.toDegrees(b);i.textAlign=d(x),h(x,t._pointLabelSizes[g],v),c(i,t.pointLabels[g]||"",v,f.size)}}}function g(t,n,i,r){var o=t.ctx;if(o.strokeStyle=a.valueAtIndexOrDefault(n.color,r-1),o.lineWidth=a.valueAtIndexOrDefault(n.lineWidth,r-1),t.options.gridLines.circular)o.beginPath(),o.arc(t.xCenter,t.yCenter,i,0,2*Math.PI),o.closePath(),o.stroke();else{var s=e(t);if(0===s)return;o.beginPath();var l=t.getPointPosition(0,i);o.moveTo(l.x,l.y);for(var u=1;u<s;u++)l=t.getPointPosition(u,i),o.lineTo(l.x,l.y);o.closePath(),o.stroke()}}function m(t){return a.isNumber(t)?t:0}var p=i.global,v={display:!0,animate:!0,position:"chartArea",angleLines:{display:!0,color:"rgba(0, 0, 0, 0.1)",lineWidth:1},gridLines:{circular:!1},ticks:{showLabelBackdrop:!0,backdropColor:"rgba(255,255,255,0.75)",backdropPaddingY:2,backdropPaddingX:2,callback:r.formatters.linear},pointLabels:{display:!0,fontSize:10,callback:function(t){return t}}},y=t.LinearScaleBase.extend({setDimensions:function(){var t=this,e=t.options,n=e.ticks;t.width=t.maxWidth,t.height=t.maxHeight,t.xCenter=Math.round(t.width/2),t.yCenter=Math.round(t.height/2);var i=a.min([t.height,t.width]),r=a.valueOrDefault(n.fontSize,p.defaultFontSize);t.drawingArea=e.display?i/2-(r/2+n.backdropPaddingY):i/2},determineDataLimits:function(){var t=this,e=t.chart,n=Number.POSITIVE_INFINITY,i=Number.NEGATIVE_INFINITY;a.each(e.data.datasets,function(r,o){if(e.isDatasetVisible(o)){var s=e.getDatasetMeta(o);a.each(r.data,function(e,a){var r=+t.getRightValue(e);isNaN(r)||s.data[a].hidden||(n=Math.min(r,n),i=Math.max(r,i))})}}),t.min=n===Number.POSITIVE_INFINITY?0:n,t.max=i===Number.NEGATIVE_INFINITY?0:i,t.handleTickRangeOptions()},getTickLimit:function(){var t=this.options.ticks,e=a.valueOrDefault(t.fontSize,p.defaultFontSize);return Math.min(t.maxTicksLimit?t.maxTicksLimit:11,Math.ceil(this.drawingArea/(1.5*e)))},convertTicksToLabels:function(){var e=this;t.LinearScaleBase.prototype.convertTicksToLabels.call(e),e.pointLabels=e.chart.data.labels.map(e.options.pointLabels.callback,e)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},fit:function(){this.options.pointLabels.display?l(this):u(this)},setReductions:function(t,e,n){var i=this,a=e.l/Math.sin(n.l),r=Math.max(e.r-i.width,0)/Math.sin(n.r),o=-e.t/Math.cos(n.t),s=-Math.max(e.b-i.height,0)/Math.cos(n.b);a=m(a),r=m(r),o=m(o),s=m(s),i.drawingArea=Math.min(Math.round(t-(a+r)/2),Math.round(t-(o+s)/2)),i.setCenterPoint(a,r,o,s)},setCenterPoint:function(t,e,n,i){var a=this,r=a.width-e-a.drawingArea,o=t+a.drawingArea,s=n+a.drawingArea,l=a.height-i-a.drawingArea;a.xCenter=Math.round((o+r)/2+a.left),a.yCenter=Math.round((s+l)/2+a.top)},getIndexAngle:function(t){return t*(2*Math.PI/e(this))+(this.chart.options&&this.chart.options.startAngle?this.chart.options.startAngle:0)*Math.PI*2/360},getDistanceFromCenterForValue:function(t){var e=this;if(null===t)return 0;var n=e.drawingArea/(e.max-e.min);return e.options.ticks.reverse?(e.max-t)*n:(t-e.min)*n},getPointPosition:function(t,e){var n=this,i=n.getIndexAngle(t)-Math.PI/2;return{x:Math.round(Math.cos(i)*e)+n.xCenter,y:Math.round(Math.sin(i)*e)+n.yCenter}},getPointPositionForValue:function(t,e){return this.getPointPosition(t,this.getDistanceFromCenterForValue(e))},getBasePosition:function(){var t=this,e=t.min,n=t.max;return t.getPointPositionForValue(0,t.beginAtZero?0:e<0&&n<0?n:e>0&&n>0?e:0)},draw:function(){var t=this,e=t.options,n=e.gridLines,i=e.ticks,r=a.valueOrDefault;if(e.display){var o=t.ctx,s=this.getIndexAngle(0),l=r(i.fontSize,p.defaultFontSize),u=r(i.fontStyle,p.defaultFontStyle),d=r(i.fontFamily,p.defaultFontFamily),c=a.fontString(l,u,d);a.each(t.ticks,function(e,a){if(a>0||i.reverse){var u=t.getDistanceFromCenterForValue(t.ticksAsNumbers[a]);if(n.display&&0!==a&&g(t,n,u,a),i.display){var d=r(i.fontColor,p.defaultFontColor);if(o.font=c,o.save(),o.translate(t.xCenter,t.yCenter),o.rotate(s),i.showLabelBackdrop){var h=o.measureText(e).width;o.fillStyle=i.backdropColor,o.fillRect(-h/2-i.backdropPaddingX,-u-l/2-i.backdropPaddingY,h+2*i.backdropPaddingX,l+2*i.backdropPaddingY)}o.textAlign="center",o.textBaseline="middle",o.fillStyle=d,o.fillText(e,0,-u),o.restore()}}}),(e.angleLines.display||e.pointLabels.display)&&f(t)}}});t.scaleService.registerScaleType("radialLinear",y,v)}},{25:25,34:34,45:45}],57:[function(t,e,n){"use strict";function i(t,e){return t-e}function a(t){var e,n,i,a={},r=[];for(e=0,n=t.length;e<n;++e)a[i=t[e]]||(a[i]=!0,r.push(i));return r}function r(t,e,n,i){if("linear"===i||!t.length)return[{time:e,pos:0},{time:n,pos:1}];var a,r,o,s,l,u=[],d=[e];for(a=0,r=t.length;a<r;++a)(s=t[a])>e&&s<n&&d.push(s);for(d.push(n),a=0,r=d.length;a<r;++a)l=d[a+1],o=d[a-1],s=d[a],void 0!==o&&void 0!==l&&Math.round((l+o)/2)===s||u.push({time:s,pos:a/(r-1)});return u}function o(t,e,n){for(var i,a,r,o=0,s=t.length-1;o>=0&&o<=s;){if(i=o+s>>1,a=t[i-1]||null,r=t[i],!a)return{lo:null,hi:r};if(r[e]<n)o=i+1;else{if(!(a[e]>n))return{lo:a,hi:r};s=i-1}}return{lo:r,hi:null}}function s(t,e,n,i){var a=o(t,e,n),r=a.lo?a.hi?a.lo:t[t.length-2]:t[0],s=a.lo?a.hi?a.hi:t[t.length-1]:t[1],l=s[e]-r[e],u=l?(n-r[e])/l:0,d=(s[i]-r[i])*u;return r[i]+d}function l(t,e){var n=e.parser,i=e.parser||e.format;return"function"==typeof n?n(t):"string"==typeof t&&"string"==typeof i?p(t,i):(t instanceof p||(t=p(t)),t.isValid()?t:"function"==typeof i?i(t):t)}function u(t,e){if(y.isNullOrUndef(t))return null;var n=e.options.time,i=l(e.getRightValue(t),n);return i.isValid()?(n.round&&i.startOf(n.round),i.valueOf()):null}function d(t,e,n,i){var a,r,o,s=e-t,l=_[n],u=l.size,d=l.steps;if(!d)return Math.ceil(s/((i||1)*u));for(a=0,r=d.length;a<r&&(o=d[a],!(Math.ceil(s/(u*o))<=i));++a);return o}function c(t,e,n,i){var a,r,o,s=k.length;for(a=k.indexOf(t);a<s-1;++a)if(r=_[k[a]],o=r.steps?r.steps[r.steps.length-1]:x,r.common&&Math.ceil((n-e)/(o*r.size))<=i)return k[a];return k[s-1]}function h(t){for(var e=k.indexOf(t)+1,n=k.length;e<n;++e)if(_[k[e]].common)return k[e]}function f(t,e,n,i,a,r){var o,s=r.time,l=y.valueOrDefault(s.stepSize,s.unitStepSize),u="week"===n&&s.isoWeekday,c=r.ticks.major.enabled,h=_[n],f=p(t),g=p(e),m=[];for(l||(l=d(t,e,n,a)),u&&(f=f.isoWeekday(u),g=g.isoWeekday(u)),f=f.startOf(u?"day":n),(g=g.startOf(u?"day":n))<e&&g.add(1,n),o=p(f),c&&i&&!u&&!s.round&&(o.startOf(i),o.add(~~((f-o)/(h.size*l))*l,n));o<g;o.add(l,n))m.push(+o);return m.push(+o),m}function g(t,e,n,i,a){var r,o,l=0,u=0;return a.offset&&e.length&&(a.time.min||(r=e.length>1?e[1]:i,o=e[0],l=(s(t,"time",r,"pos")-s(t,"time",o,"pos"))/2),a.time.max||(r=e[e.length-1],o=e.length>1?e[e.length-2]:n,u=(s(t,"time",r,"pos")-s(t,"time",o,"pos"))/2)),{left:l,right:u}}function m(t,e){var n,i,a,r,o=[];for(n=0,i=t.length;n<i;++n)a=t[n],r=!!e&&a===+p(a).startOf(e),o.push({value:a,major:r});return o}var p=t(6);p="function"==typeof p?p:window.moment;var v=t(25),y=t(45),b=Number.MIN_SAFE_INTEGER||-9007199254740991,x=Number.MAX_SAFE_INTEGER||9007199254740991,_={millisecond:{common:!0,size:1,steps:[1,2,5,10,20,50,100,250,500]},second:{common:!0,size:1e3,steps:[1,2,5,10,30]},minute:{common:!0,size:6e4,steps:[1,2,5,10,30]},hour:{common:!0,size:36e5,steps:[1,2,3,6,12]},day:{common:!0,size:864e5,steps:[1,2,5]},week:{common:!1,size:6048e5,steps:[1,2,3,4]},month:{common:!0,size:2628e6,steps:[1,2,3]},quarter:{common:!1,size:7884e6,steps:[1,2,3,4]},year:{common:!0,size:3154e7}},k=Object.keys(_);e.exports=function(t){var e={position:"bottom",distribution:"linear",bounds:"data",time:{parser:!1,format:!1,unit:!1,round:!1,displayFormat:!1,isoWeekday:!1,minUnit:"millisecond",displayFormats:{millisecond:"h:mm:ss.SSS a",second:"h:mm:ss a",minute:"h:mm a",hour:"hA",day:"MMM D",week:"ll",month:"MMM YYYY",quarter:"[Q]Q - YYYY",year:"YYYY"}},ticks:{autoSkip:!1,source:"auto",major:{enabled:!1}}},n=t.Scale.extend({initialize:function(){if(!p)throw new Error("Chart.js - Moment.js could not be found! You must include it before Chart.js to use the time scale. Download at https://momentjs.com");this.mergeTicksOptions(),t.Scale.prototype.initialize.call(this)},update:function(){var e=this,n=e.options;return n.time&&n.time.format&&console.warn("options.time.format is deprecated and replaced by options.time.parser."),t.Scale.prototype.update.apply(e,arguments)},getRightValue:function(e){return e&&void 0!==e.t&&(e=e.t),t.Scale.prototype.getRightValue.call(this,e)},determineDataLimits:function(){var t,e,n,r,o,s,l=this,d=l.chart,c=l.options.time,h=u(c.min,l)||x,f=u(c.max,l)||b,g=[],m=[],v=[];for(t=0,n=d.data.labels.length;t<n;++t)v.push(u(d.data.labels[t],l));for(t=0,n=(d.data.datasets||[]).length;t<n;++t)if(d.isDatasetVisible(t))if(o=d.data.datasets[t].data,y.isObject(o[0]))for(m[t]=[],e=0,r=o.length;e<r;++e)s=u(o[e],l),g.push(s),m[t][e]=s;else g.push.apply(g,v),m[t]=v.slice(0);else m[t]=[];v.length&&(v=a(v).sort(i),h=Math.min(h,v[0]),f=Math.max(f,v[v.length-1])),g.length&&(g=a(g).sort(i),h=Math.min(h,g[0]),f=Math.max(f,g[g.length-1])),h=h===x?+p().startOf("day"):h,f=f===b?+p().endOf("day")+1:f,l.min=Math.min(h,f),l.max=Math.max(h+1,f),l._horizontal=l.isHorizontal(),l._table=[],l._timestamps={data:g,datasets:m,labels:v}},buildTicks:function(){var t,e,n,i=this,a=i.min,o=i.max,s=i.options,l=s.time,d=l.displayFormats,p=i.getLabelCapacity(a),v=l.unit||c(l.minUnit,a,o,p),y=h(v),b=[],x=[];switch(s.ticks.source){case"data":b=i._timestamps.data;break;case"labels":b=i._timestamps.labels;break;case"auto":default:b=f(a,o,v,y,p,s)}for("ticks"===s.bounds&&b.length&&(a=b[0],o=b[b.length-1]),a=u(l.min,i)||a,o=u(l.max,i)||o,t=0,e=b.length;t<e;++t)(n=b[t])>=a&&n<=o&&x.push(n);return i.min=a,i.max=o,i._unit=v,i._majorUnit=y,i._minorFormat=d[v],i._majorFormat=d[y],i._table=r(i._timestamps.data,a,o,s.distribution),i._offsets=g(i._table,x,a,o,s),m(x,y)},getLabelForIndex:function(t,e){var n=this,i=n.chart.data,a=n.options.time,r=i.labels&&t<i.labels.length?i.labels[t]:"",o=i.datasets[e].data[t];return y.isObject(o)&&(r=n.getRightValue(o)),a.tooltipFormat&&(r=l(r,a).format(a.tooltipFormat)),r},tickFormatFunction:function(t,e,n){var i=this,a=i.options,r=t.valueOf(),o=i._majorUnit,s=i._majorFormat,l=t.clone().startOf(i._majorUnit).valueOf(),u=a.ticks.major,d=u.enabled&&o&&s&&r===l,c=t.format(d?s:i._minorFormat),h=d?u:a.ticks.minor,f=y.valueOrDefault(h.callback,h.userCallback);return f?f(c,e,n):c},convertTicksToLabels:function(t){var e,n,i=[];for(e=0,n=t.length;e<n;++e)i.push(this.tickFormatFunction(p(t[e].value),e,t));return i},getPixelForOffset:function(t){var e=this,n=e._horizontal?e.width:e.height,i=e._horizontal?e.left:e.top,a=s(e._table,"time",t,"pos");return i+n*(e._offsets.left+a)/(e._offsets.left+1+e._offsets.right)},getPixelForValue:function(t,e,n){var i=this,a=null;if(void 0!==e&&void 0!==n&&(a=i._timestamps.datasets[n][e]),null===a&&(a=u(t,i)),null!==a)return i.getPixelForOffset(a)},getPixelForTick:function(t){var e=this.getTicks();return t>=0&&t<e.length?this.getPixelForOffset(e[t].value):null},getValueForPixel:function(t){var e=this,n=e._horizontal?e.width:e.height,i=e._horizontal?e.left:e.top,a=(n?(t-i)/n:0)*(e._offsets.left+1+e._offsets.left)-e._offsets.right,r=s(e._table,"pos",a,"time");return p(r)},getLabelWidth:function(t){var e=this,n=e.options.ticks,i=e.ctx.measureText(t).width,a=y.toRadians(n.maxRotation),r=Math.cos(a),o=Math.sin(a);return i*r+y.valueOrDefault(n.fontSize,v.global.defaultFontSize)*o},getLabelCapacity:function(t){var e=this;e._minorFormat=e.options.time.displayFormats.millisecond;var n=e.tickFormatFunction(p(t),0,[]),i=e.getLabelWidth(n),a=e.isHorizontal()?e.width:e.height;return Math.floor(a/i)}});t.scaleService.registerScaleType("time",n,e)}},{25:25,45:45,6:6}]},{},[7])(7)});
1
+ /*!
2
+ * Chart.js
3
+ * http://chartjs.org/
4
+ * Version: 2.7.0
5
+ *
6
+ * Copyright 2017 Nick Downie
7
+ * Released under the MIT license
8
+ * https://github.com/chartjs/Chart.js/blob/master/LICENSE.md
9
+ */
10
  !function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).Chart=t()}}(function(){return function t(e,n,i){function a(o,s){if(!n[o]){if(!e[o]){var l="function"==typeof require&&require;if(!s&&l)return l(o,!0);if(r)return r(o,!0);var u=new Error("Cannot find module '"+o+"'");throw u.code="MODULE_NOT_FOUND",u}var d=n[o]={exports:{}};e[o][0].call(d.exports,function(t){var n=e[o][1][t];return a(n||t)},d,d.exports,t,e,n,i)}return n[o].exports}for(var r="function"==typeof require&&require,o=0;o<i.length;o++)a(i[o]);return a}({1:[function(t,e,n){function i(t){if(t){var e=/^#([a-fA-F0-9]{3})$/i,n=/^#([a-fA-F0-9]{6})$/i,i=/^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i,a=/^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i,r=/(\w+)/,o=[0,0,0],s=1,l=t.match(e);if(l){l=l[1];for(d=0;d<o.length;d++)o[d]=parseInt(l[d]+l[d],16)}else if(l=t.match(n)){l=l[1];for(d=0;d<o.length;d++)o[d]=parseInt(l.slice(2*d,2*d+2),16)}else if(l=t.match(i)){for(d=0;d<o.length;d++)o[d]=parseInt(l[d+1]);s=parseFloat(l[4])}else if(l=t.match(a)){for(d=0;d<o.length;d++)o[d]=Math.round(2.55*parseFloat(l[d+1]));s=parseFloat(l[4])}else if(l=t.match(r)){if("transparent"==l[1])return[0,0,0,0];if(!(o=c[l[1]]))return}for(var d=0;d<o.length;d++)o[d]=u(o[d],0,255);return s=s||0==s?u(s,0,1):1,o[3]=s,o}}function a(t){if(t){var e=/^hsla?\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/,n=t.match(e);if(n){var i=parseFloat(n[4]);return[u(parseInt(n[1]),0,360),u(parseFloat(n[2]),0,100),u(parseFloat(n[3]),0,100),u(isNaN(i)?1:i,0,1)]}}}function r(t){if(t){var e=/^hwb\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/,n=t.match(e);if(n){var i=parseFloat(n[4]);return[u(parseInt(n[1]),0,360),u(parseFloat(n[2]),0,100),u(parseFloat(n[3]),0,100),u(isNaN(i)?1:i,0,1)]}}}function o(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"rgba("+t[0]+", "+t[1]+", "+t[2]+", "+e+")"}function s(t,e){return"rgba("+Math.round(t[0]/255*100)+"%, "+Math.round(t[1]/255*100)+"%, "+Math.round(t[2]/255*100)+"%, "+(e||t[3]||1)+")"}function l(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"hsla("+t[0]+", "+t[1]+"%, "+t[2]+"%, "+e+")"}function u(t,e,n){return Math.min(Math.max(e,t),n)}function d(t){var e=t.toString(16).toUpperCase();return e.length<2?"0"+e:e}var c=t(5);e.exports={getRgba:i,getHsla:a,getRgb:function(t){var e=i(t);return e&&e.slice(0,3)},getHsl:function(t){var e=a(t);return e&&e.slice(0,3)},getHwb:r,getAlpha:function(t){var e=i(t);return e?e[3]:(e=a(t))?e[3]:(e=r(t))?e[3]:void 0},hexString:function(t){return"#"+d(t[0])+d(t[1])+d(t[2])},rgbString:function(t,e){return e<1||t[3]&&t[3]<1?o(t,e):"rgb("+t[0]+", "+t[1]+", "+t[2]+")"},rgbaString:o,percentString:function(t,e){return e<1||t[3]&&t[3]<1?s(t,e):"rgb("+Math.round(t[0]/255*100)+"%, "+Math.round(t[1]/255*100)+"%, "+Math.round(t[2]/255*100)+"%)"},percentaString:s,hslString:function(t,e){return e<1||t[3]&&t[3]<1?l(t,e):"hsl("+t[0]+", "+t[1]+"%, "+t[2]+"%)"},hslaString:l,hwbString:function(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"hwb("+t[0]+", "+t[1]+"%, "+t[2]+"%"+(void 0!==e&&1!==e?", "+e:"")+")"},keyword:function(t){return h[t.slice(0,3)]}};var h={};for(var f in c)h[c[f]]=f},{5:5}],2:[function(t,e,n){var i=t(4),a=t(1),r=function(t){if(t instanceof r)return t;if(!(this instanceof r))return new r(t);this.valid=!1,this.values={rgb:[0,0,0],hsl:[0,0,0],hsv:[0,0,0],hwb:[0,0,0],cmyk:[0,0,0,0],alpha:1};var e;"string"==typeof t?(e=a.getRgba(t))?this.setValues("rgb",e):(e=a.getHsla(t))?this.setValues("hsl",e):(e=a.getHwb(t))&&this.setValues("hwb",e):"object"==typeof t&&(void 0!==(e=t).r||void 0!==e.red?this.setValues("rgb",e):void 0!==e.l||void 0!==e.lightness?this.setValues("hsl",e):void 0!==e.v||void 0!==e.value?this.setValues("hsv",e):void 0!==e.w||void 0!==e.whiteness?this.setValues("hwb",e):void 0===e.c&&void 0===e.cyan||this.setValues("cmyk",e))};r.prototype={isValid:function(){return this.valid},rgb:function(){return this.setSpace("rgb",arguments)},hsl:function(){return this.setSpace("hsl",arguments)},hsv:function(){return this.setSpace("hsv",arguments)},hwb:function(){return this.setSpace("hwb",arguments)},cmyk:function(){return this.setSpace("cmyk",arguments)},rgbArray:function(){return this.values.rgb},hslArray:function(){return this.values.hsl},hsvArray:function(){return this.values.hsv},hwbArray:function(){var t=this.values;return 1!==t.alpha?t.hwb.concat([t.alpha]):t.hwb},cmykArray:function(){return this.values.cmyk},rgbaArray:function(){var t=this.values;return t.rgb.concat([t.alpha])},hslaArray:function(){var t=this.values;return t.hsl.concat([t.alpha])},alpha:function(t){return void 0===t?this.values.alpha:(this.setValues("alpha",t),this)},red:function(t){return this.setChannel("rgb",0,t)},green:function(t){return this.setChannel("rgb",1,t)},blue:function(t){return this.setChannel("rgb",2,t)},hue:function(t){return t&&(t=(t%=360)<0?360+t:t),this.setChannel("hsl",0,t)},saturation:function(t){return this.setChannel("hsl",1,t)},lightness:function(t){return this.setChannel("hsl",2,t)},saturationv:function(t){return this.setChannel("hsv",1,t)},whiteness:function(t){return this.setChannel("hwb",1,t)},blackness:function(t){return this.setChannel("hwb",2,t)},value:function(t){return this.setChannel("hsv",2,t)},cyan:function(t){return this.setChannel("cmyk",0,t)},magenta:function(t){return this.setChannel("cmyk",1,t)},yellow:function(t){return this.setChannel("cmyk",2,t)},black:function(t){return this.setChannel("cmyk",3,t)},hexString:function(){return a.hexString(this.values.rgb)},rgbString:function(){return a.rgbString(this.values.rgb,this.values.alpha)},rgbaString:function(){return a.rgbaString(this.values.rgb,this.values.alpha)},percentString:function(){return a.percentString(this.values.rgb,this.values.alpha)},hslString:function(){return a.hslString(this.values.hsl,this.values.alpha)},hslaString:function(){return a.hslaString(this.values.hsl,this.values.alpha)},hwbString:function(){return a.hwbString(this.values.hwb,this.values.alpha)},keyword:function(){return a.keyword(this.values.rgb,this.values.alpha)},rgbNumber:function(){var t=this.values.rgb;return t[0]<<16|t[1]<<8|t[2]},luminosity:function(){for(var t=this.values.rgb,e=[],n=0;n<t.length;n++){var i=t[n]/255;e[n]=i<=.03928?i/12.92:Math.pow((i+.055)/1.055,2.4)}return.2126*e[0]+.7152*e[1]+.0722*e[2]},contrast:function(t){var e=this.luminosity(),n=t.luminosity();return e>n?(e+.05)/(n+.05):(n+.05)/(e+.05)},level:function(t){var e=this.contrast(t);return e>=7.1?"AAA":e>=4.5?"AA":""},dark:function(){var t=this.values.rgb;return(299*t[0]+587*t[1]+114*t[2])/1e3<128},light:function(){return!this.dark()},negate:function(){for(var t=[],e=0;e<3;e++)t[e]=255-this.values.rgb[e];return this.setValues("rgb",t),this},lighten:function(t){var e=this.values.hsl;return e[2]+=e[2]*t,this.setValues("hsl",e),this},darken:function(t){var e=this.values.hsl;return e[2]-=e[2]*t,this.setValues("hsl",e),this},saturate:function(t){var e=this.values.hsl;return e[1]+=e[1]*t,this.setValues("hsl",e),this},desaturate:function(t){var e=this.values.hsl;return e[1]-=e[1]*t,this.setValues("hsl",e),this},whiten:function(t){var e=this.values.hwb;return e[1]+=e[1]*t,this.setValues("hwb",e),this},blacken:function(t){var e=this.values.hwb;return e[2]+=e[2]*t,this.setValues("hwb",e),this},greyscale:function(){var t=this.values.rgb,e=.3*t[0]+.59*t[1]+.11*t[2];return this.setValues("rgb",[e,e,e]),this},clearer:function(t){var e=this.values.alpha;return this.setValues("alpha",e-e*t),this},opaquer:function(t){var e=this.values.alpha;return this.setValues("alpha",e+e*t),this},rotate:function(t){var e=this.values.hsl,n=(e[0]+t)%360;return e[0]=n<0?360+n:n,this.setValues("hsl",e),this},mix:function(t,e){var n=this,i=t,a=void 0===e?.5:e,r=2*a-1,o=n.alpha()-i.alpha(),s=((r*o==-1?r:(r+o)/(1+r*o))+1)/2,l=1-s;return this.rgb(s*n.red()+l*i.red(),s*n.green()+l*i.green(),s*n.blue()+l*i.blue()).alpha(n.alpha()*a+i.alpha()*(1-a))},toJSON:function(){return this.rgb()},clone:function(){var t,e,n=new r,i=this.values,a=n.values;for(var o in i)i.hasOwnProperty(o)&&(t=i[o],"[object Array]"===(e={}.toString.call(t))?a[o]=t.slice(0):"[object Number]"===e?a[o]=t:console.error("unexpected color value:",t));return n}},r.prototype.spaces={rgb:["red","green","blue"],hsl:["hue","saturation","lightness"],hsv:["hue","saturation","value"],hwb:["hue","whiteness","blackness"],cmyk:["cyan","magenta","yellow","black"]},r.prototype.maxes={rgb:[255,255,255],hsl:[360,100,100],hsv:[360,100,100],hwb:[360,100,100],cmyk:[100,100,100,100]},r.prototype.getValues=function(t){for(var e=this.values,n={},i=0;i<t.length;i++)n[t.charAt(i)]=e[t][i];return 1!==e.alpha&&(n.a=e.alpha),n},r.prototype.setValues=function(t,e){var n,a=this.values,r=this.spaces,o=this.maxes,s=1;if(this.valid=!0,"alpha"===t)s=e;else if(e.length)a[t]=e.slice(0,t.length),s=e[t.length];else if(void 0!==e[t.charAt(0)]){for(n=0;n<t.length;n++)a[t][n]=e[t.charAt(n)];s=e.a}else if(void 0!==e[r[t][0]]){var l=r[t];for(n=0;n<t.length;n++)a[t][n]=e[l[n]];s=e.alpha}if(a.alpha=Math.max(0,Math.min(1,void 0===s?a.alpha:s)),"alpha"===t)return!1;var u;for(n=0;n<t.length;n++)u=Math.max(0,Math.min(o[t][n],a[t][n])),a[t][n]=Math.round(u);for(var d in r)d!==t&&(a[d]=i[t][d](a[t]));return!0},r.prototype.setSpace=function(t,e){var n=e[0];return void 0===n?this.getValues(t):("number"==typeof n&&(n=Array.prototype.slice.call(e)),this.setValues(t,n),this)},r.prototype.setChannel=function(t,e,n){var i=this.values[t];return void 0===n?i[e]:n===i[e]?this:(i[e]=n,this.setValues(t,i),this)},"undefined"!=typeof window&&(window.Color=r),e.exports=r},{1:1,4:4}],3:[function(t,e,n){function i(t){var e,n,i,a=t[0]/255,r=t[1]/255,o=t[2]/255,s=Math.min(a,r,o),l=Math.max(a,r,o),u=l-s;return l==s?e=0:a==l?e=(r-o)/u:r==l?e=2+(o-a)/u:o==l&&(e=4+(a-r)/u),(e=Math.min(60*e,360))<0&&(e+=360),i=(s+l)/2,n=l==s?0:i<=.5?u/(l+s):u/(2-l-s),[e,100*n,100*i]}function a(t){var e,n,i,a=t[0],r=t[1],o=t[2],s=Math.min(a,r,o),l=Math.max(a,r,o),u=l-s;return n=0==l?0:u/l*1e3/10,l==s?e=0:a==l?e=(r-o)/u:r==l?e=2+(o-a)/u:o==l&&(e=4+(a-r)/u),(e=Math.min(60*e,360))<0&&(e+=360),i=l/255*1e3/10,[e,n,i]}function o(t){var e=t[0],n=t[1],a=t[2];return[i(t)[0],100*(1/255*Math.min(e,Math.min(n,a))),100*(a=1-1/255*Math.max(e,Math.max(n,a)))]}function s(t){var e,n,i,a,r=t[0]/255,o=t[1]/255,s=t[2]/255;return a=Math.min(1-r,1-o,1-s),e=(1-r-a)/(1-a)||0,n=(1-o-a)/(1-a)||0,i=(1-s-a)/(1-a)||0,[100*e,100*n,100*i,100*a]}function l(t){return S[JSON.stringify(t)]}function u(t){var e=t[0]/255,n=t[1]/255,i=t[2]/255;return[100*(.4124*(e=e>.04045?Math.pow((e+.055)/1.055,2.4):e/12.92)+.3576*(n=n>.04045?Math.pow((n+.055)/1.055,2.4):n/12.92)+.1805*(i=i>.04045?Math.pow((i+.055)/1.055,2.4):i/12.92)),100*(.2126*e+.7152*n+.0722*i),100*(.0193*e+.1192*n+.9505*i)]}function d(t){var e,n,i,a=u(t),r=a[0],o=a[1],s=a[2];return r/=95.047,o/=100,s/=108.883,r=r>.008856?Math.pow(r,1/3):7.787*r+16/116,o=o>.008856?Math.pow(o,1/3):7.787*o+16/116,s=s>.008856?Math.pow(s,1/3):7.787*s+16/116,e=116*o-16,n=500*(r-o),i=200*(o-s),[e,n,i]}function c(t){var e,n,i,a,r,o=t[0]/360,s=t[1]/100,l=t[2]/100;if(0==s)return r=255*l,[r,r,r];e=2*l-(n=l<.5?l*(1+s):l+s-l*s),a=[0,0,0];for(var u=0;u<3;u++)(i=o+1/3*-(u-1))<0&&i++,i>1&&i--,r=6*i<1?e+6*(n-e)*i:2*i<1?n:3*i<2?e+(n-e)*(2/3-i)*6:e,a[u]=255*r;return a}function h(t){var e=t[0]/60,n=t[1]/100,i=t[2]/100,a=Math.floor(e)%6,r=e-Math.floor(e),o=255*i*(1-n),s=255*i*(1-n*r),l=255*i*(1-n*(1-r)),i=255*i;switch(a){case 0:return[i,l,o];case 1:return[s,i,o];case 2:return[o,i,l];case 3:return[o,s,i];case 4:return[l,o,i];case 5:return[i,o,s]}}function f(t){var e,n,i,a,o=t[0]/360,s=t[1]/100,l=t[2]/100,u=s+l;switch(u>1&&(s/=u,l/=u),e=Math.floor(6*o),n=1-l,i=6*o-e,0!=(1&e)&&(i=1-i),a=s+i*(n-s),e){default:case 6:case 0:r=n,g=a,b=s;break;case 1:r=a,g=n,b=s;break;case 2:r=s,g=n,b=a;break;case 3:r=s,g=a,b=n;break;case 4:r=a,g=s,b=n;break;case 5:r=n,g=s,b=a}return[255*r,255*g,255*b]}function m(t){var e,n,i,a=t[0]/100,r=t[1]/100,o=t[2]/100,s=t[3]/100;return e=1-Math.min(1,a*(1-s)+s),n=1-Math.min(1,r*(1-s)+s),i=1-Math.min(1,o*(1-s)+s),[255*e,255*n,255*i]}function p(t){var e,n,i,a=t[0]/100,r=t[1]/100,o=t[2]/100;return e=3.2406*a+-1.5372*r+-.4986*o,n=-.9689*a+1.8758*r+.0415*o,i=.0557*a+-.204*r+1.057*o,e=e>.0031308?1.055*Math.pow(e,1/2.4)-.055:e*=12.92,n=n>.0031308?1.055*Math.pow(n,1/2.4)-.055:n*=12.92,i=i>.0031308?1.055*Math.pow(i,1/2.4)-.055:i*=12.92,e=Math.min(Math.max(0,e),1),n=Math.min(Math.max(0,n),1),i=Math.min(Math.max(0,i),1),[255*e,255*n,255*i]}function v(t){var e,n,i,a=t[0],r=t[1],o=t[2];return a/=95.047,r/=100,o/=108.883,a=a>.008856?Math.pow(a,1/3):7.787*a+16/116,r=r>.008856?Math.pow(r,1/3):7.787*r+16/116,o=o>.008856?Math.pow(o,1/3):7.787*o+16/116,e=116*r-16,n=500*(a-r),i=200*(r-o),[e,n,i]}function y(t){var e,n,i,a,r=t[0],o=t[1],s=t[2];return r<=8?a=(n=100*r/903.3)/100*7.787+16/116:(n=100*Math.pow((r+16)/116,3),a=Math.pow(n/100,1/3)),e=e/95.047<=.008856?e=95.047*(o/500+a-16/116)/7.787:95.047*Math.pow(o/500+a,3),i=i/108.883<=.008859?i=108.883*(a-s/200-16/116)/7.787:108.883*Math.pow(a-s/200,3),[e,n,i]}function x(t){var e,n,i,a=t[0],r=t[1],o=t[2];return e=Math.atan2(o,r),(n=360*e/2/Math.PI)<0&&(n+=360),i=Math.sqrt(r*r+o*o),[a,i,n]}function _(t){return p(y(t))}function k(t){var e,n,i,a=t[0],r=t[1];return i=t[2]/360*2*Math.PI,e=r*Math.cos(i),n=r*Math.sin(i),[a,e,n]}function w(t){return M[t]}e.exports={rgb2hsl:i,rgb2hsv:a,rgb2hwb:o,rgb2cmyk:s,rgb2keyword:l,rgb2xyz:u,rgb2lab:d,rgb2lch:function(t){return x(d(t))},hsl2rgb:c,hsl2hsv:function(t){var e,n,i=t[0],a=t[1]/100,r=t[2]/100;return 0===r?[0,0,0]:(r*=2,a*=r<=1?r:2-r,n=(r+a)/2,e=2*a/(r+a),[i,100*e,100*n])},hsl2hwb:function(t){return o(c(t))},hsl2cmyk:function(t){return s(c(t))},hsl2keyword:function(t){return l(c(t))},hsv2rgb:h,hsv2hsl:function(t){var e,n,i=t[0],a=t[1]/100,r=t[2]/100;return n=(2-a)*r,e=a*r,e/=n<=1?n:2-n,e=e||0,n/=2,[i,100*e,100*n]},hsv2hwb:function(t){return o(h(t))},hsv2cmyk:function(t){return s(h(t))},hsv2keyword:function(t){return l(h(t))},hwb2rgb:f,hwb2hsl:function(t){return i(f(t))},hwb2hsv:function(t){return a(f(t))},hwb2cmyk:function(t){return s(f(t))},hwb2keyword:function(t){return l(f(t))},cmyk2rgb:m,cmyk2hsl:function(t){return i(m(t))},cmyk2hsv:function(t){return a(m(t))},cmyk2hwb:function(t){return o(m(t))},cmyk2keyword:function(t){return l(m(t))},keyword2rgb:w,keyword2hsl:function(t){return i(w(t))},keyword2hsv:function(t){return a(w(t))},keyword2hwb:function(t){return o(w(t))},keyword2cmyk:function(t){return s(w(t))},keyword2lab:function(t){return d(w(t))},keyword2xyz:function(t){return u(w(t))},xyz2rgb:p,xyz2lab:v,xyz2lch:function(t){return x(v(t))},lab2xyz:y,lab2rgb:_,lab2lch:x,lch2lab:k,lch2xyz:function(t){return y(k(t))},lch2rgb:function(t){return _(k(t))}};var M={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]},S={};for(var D in M)S[JSON.stringify(M[D])]=D},{}],4:[function(t,e,n){var i=t(3),a=function(){return new u};for(var r in i){a[r+"Raw"]=function(t){return function(e){return"number"==typeof e&&(e=Array.prototype.slice.call(arguments)),i[t](e)}}(r);var o=/(\w+)2(\w+)/.exec(r),s=o[1],l=o[2];(a[s]=a[s]||{})[l]=a[r]=function(t){return function(e){"number"==typeof e&&(e=Array.prototype.slice.call(arguments));var n=i[t](e);if("string"==typeof n||void 0===n)return n;for(var a=0;a<n.length;a++)n[a]=Math.round(n[a]);return n}}(r)}var u=function(){this.convs={}};u.prototype.routeSpace=function(t,e){var n=e[0];return void 0===n?this.getValues(t):("number"==typeof n&&(n=Array.prototype.slice.call(e)),this.setValues(t,n))},u.prototype.setValues=function(t,e){return this.space=t,this.convs={},this.convs[t]=e,this},u.prototype.getValues=function(t){var e=this.convs[t];if(!e){var n=this.space,i=this.convs[n];e=a[n][t](i),this.convs[t]=e}return e},["rgb","hsl","hsv","cmyk","keyword"].forEach(function(t){u.prototype[t]=function(e){return this.routeSpace(t,arguments)}}),e.exports=a},{3:3}],5:[function(t,e,n){"use strict";e.exports={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]}},{}],6:[function(t,e,n){!function(t,i){"object"==typeof n&&void 0!==e?e.exports=i():t.moment=i()}(this,function(){"use strict";function n(){return xe.apply(null,arguments)}function i(t){return t instanceof Array||"[object Array]"===Object.prototype.toString.call(t)}function a(t){return null!=t&&"[object Object]"===Object.prototype.toString.call(t)}function r(t){var e;for(e in t)return!1;return!0}function o(t){return void 0===t}function s(t){return"number"==typeof t||"[object Number]"===Object.prototype.toString.call(t)}function l(t){return t instanceof Date||"[object Date]"===Object.prototype.toString.call(t)}function u(t,e){var n,i=[];for(n=0;n<t.length;++n)i.push(e(t[n],n));return i}function d(t,e){return Object.prototype.hasOwnProperty.call(t,e)}function c(t,e){for(var n in e)d(e,n)&&(t[n]=e[n]);return d(e,"toString")&&(t.toString=e.toString),d(e,"valueOf")&&(t.valueOf=e.valueOf),t}function h(t,e,n,i){return Yt(t,e,n,i,!0).utc()}function f(){return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1,parsedDateParts:[],meridiem:null,rfc2822:!1,weekdayMismatch:!1}}function g(t){return null==t._pf&&(t._pf=f()),t._pf}function m(t){if(null==t._isValid){var e=g(t),n=ke.call(e.parsedDateParts,function(t){return null!=t}),i=!isNaN(t._d.getTime())&&e.overflow<0&&!e.empty&&!e.invalidMonth&&!e.invalidWeekday&&!e.nullInput&&!e.invalidFormat&&!e.userInvalidated&&(!e.meridiem||e.meridiem&&n);if(t._strict&&(i=i&&0===e.charsLeftOver&&0===e.unusedTokens.length&&void 0===e.bigHour),null!=Object.isFrozen&&Object.isFrozen(t))return i;t._isValid=i}return t._isValid}function p(t){var e=h(NaN);return null!=t?c(g(e),t):g(e).userInvalidated=!0,e}function v(t,e){var n,i,a;if(o(e._isAMomentObject)||(t._isAMomentObject=e._isAMomentObject),o(e._i)||(t._i=e._i),o(e._f)||(t._f=e._f),o(e._l)||(t._l=e._l),o(e._strict)||(t._strict=e._strict),o(e._tzm)||(t._tzm=e._tzm),o(e._isUTC)||(t._isUTC=e._isUTC),o(e._offset)||(t._offset=e._offset),o(e._pf)||(t._pf=g(e)),o(e._locale)||(t._locale=e._locale),we.length>0)for(n=0;n<we.length;n++)o(a=e[i=we[n]])||(t[i]=a);return t}function y(t){v(this,t),this._d=new Date(null!=t._d?t._d.getTime():NaN),this.isValid()||(this._d=new Date(NaN)),!1===Me&&(Me=!0,n.updateOffset(this),Me=!1)}function b(t){return t instanceof y||null!=t&&null!=t._isAMomentObject}function x(t){return t<0?Math.ceil(t)||0:Math.floor(t)}function _(t){var e=+t,n=0;return 0!==e&&isFinite(e)&&(n=x(e)),n}function k(t,e,n){var i,a=Math.min(t.length,e.length),r=Math.abs(t.length-e.length),o=0;for(i=0;i<a;i++)(n&&t[i]!==e[i]||!n&&_(t[i])!==_(e[i]))&&o++;return o+r}function w(t){!1===n.suppressDeprecationWarnings&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+t)}function M(t,e){var i=!0;return c(function(){if(null!=n.deprecationHandler&&n.deprecationHandler(null,t),i){for(var a,r=[],o=0;o<arguments.length;o++){if(a="","object"==typeof arguments[o]){a+="\n["+o+"] ";for(var s in arguments[0])a+=s+": "+arguments[0][s]+", ";a=a.slice(0,-2)}else a=arguments[o];r.push(a)}w(t+"\nArguments: "+Array.prototype.slice.call(r).join("")+"\n"+(new Error).stack),i=!1}return e.apply(this,arguments)},e)}function S(t,e){null!=n.deprecationHandler&&n.deprecationHandler(t,e),Se[t]||(w(e),Se[t]=!0)}function D(t){return t instanceof Function||"[object Function]"===Object.prototype.toString.call(t)}function C(t,e){var n,i=c({},t);for(n in e)d(e,n)&&(a(t[n])&&a(e[n])?(i[n]={},c(i[n],t[n]),c(i[n],e[n])):null!=e[n]?i[n]=e[n]:delete i[n]);for(n in t)d(t,n)&&!d(e,n)&&a(t[n])&&(i[n]=c({},i[n]));return i}function P(t){null!=t&&this.set(t)}function T(t,e){var n=t.toLowerCase();Fe[n]=Fe[n+"s"]=Fe[e]=t}function I(t){return"string"==typeof t?Fe[t]||Fe[t.toLowerCase()]:void 0}function A(t){var e,n,i={};for(n in t)d(t,n)&&(e=I(n))&&(i[e]=t[n]);return i}function O(t,e){Re[t]=e}function F(t){var e=[];for(var n in t)e.push({unit:n,priority:Re[n]});return e.sort(function(t,e){return t.priority-e.priority}),e}function R(t,e){return function(i){return null!=i?(W(this,t,i),n.updateOffset(this,e),this):L(this,t)}}function L(t,e){return t.isValid()?t._d["get"+(t._isUTC?"UTC":"")+e]():NaN}function W(t,e,n){t.isValid()&&t._d["set"+(t._isUTC?"UTC":"")+e](n)}function Y(t,e,n){var i=""+Math.abs(t),a=e-i.length;return(t>=0?n?"+":"":"-")+Math.pow(10,Math.max(0,a)).toString().substr(1)+i}function N(t,e,n,i){var a=i;"string"==typeof i&&(a=function(){return this[i]()}),t&&(Ne[t]=a),e&&(Ne[e[0]]=function(){return Y(a.apply(this,arguments),e[1],e[2])}),n&&(Ne[n]=function(){return this.localeData().ordinal(a.apply(this,arguments),t)})}function z(t){return t.match(/\[[\s\S]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"")}function B(t){var e,n,i=t.match(Le);for(e=0,n=i.length;e<n;e++)Ne[i[e]]?i[e]=Ne[i[e]]:i[e]=z(i[e]);return function(e){var a,r="";for(a=0;a<n;a++)r+=D(i[a])?i[a].call(e,t):i[a];return r}}function V(t,e){return t.isValid()?(e=H(e,t.localeData()),Ye[e]=Ye[e]||B(e),Ye[e](t)):t.localeData().invalidDate()}function H(t,e){var n=5;for(We.lastIndex=0;n>=0&&We.test(t);)t=t.replace(We,function(t){return e.longDateFormat(t)||t}),We.lastIndex=0,n-=1;return t}function E(t,e,n){nn[t]=D(e)?e:function(t,i){return t&&n?n:e}}function j(t,e){return d(nn,t)?nn[t](e._strict,e._locale):new RegExp(U(t))}function U(t){return q(t.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(t,e,n,i,a){return e||n||i||a}))}function q(t){return t.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function G(t,e){var n,i=e;for("string"==typeof t&&(t=[t]),s(e)&&(i=function(t,n){n[e]=_(t)}),n=0;n<t.length;n++)an[t[n]]=i}function Z(t,e){G(t,function(t,n,i,a){i._w=i._w||{},e(t,i._w,i,a)})}function X(t,e,n){null!=e&&d(an,t)&&an[t](e,n._a,n,t)}function J(t,e){return new Date(Date.UTC(t,e+1,0)).getUTCDate()}function K(t,e,n){var i,a,r,o=t.toLocaleLowerCase();if(!this._monthsParse)for(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[],i=0;i<12;++i)r=h([2e3,i]),this._shortMonthsParse[i]=this.monthsShort(r,"").toLocaleLowerCase(),this._longMonthsParse[i]=this.months(r,"").toLocaleLowerCase();return n?"MMM"===e?-1!==(a=gn.call(this._shortMonthsParse,o))?a:null:-1!==(a=gn.call(this._longMonthsParse,o))?a:null:"MMM"===e?-1!==(a=gn.call(this._shortMonthsParse,o))?a:-1!==(a=gn.call(this._longMonthsParse,o))?a:null:-1!==(a=gn.call(this._longMonthsParse,o))?a:-1!==(a=gn.call(this._shortMonthsParse,o))?a:null}function Q(t,e){var n;if(!t.isValid())return t;if("string"==typeof e)if(/^\d+$/.test(e))e=_(e);else if(e=t.localeData().monthsParse(e),!s(e))return t;return n=Math.min(t.date(),J(t.year(),e)),t._d["set"+(t._isUTC?"UTC":"")+"Month"](e,n),t}function $(t){return null!=t?(Q(this,t),n.updateOffset(this,!0),this):L(this,"Month")}function tt(){function t(t,e){return e.length-t.length}var e,n,i=[],a=[],r=[];for(e=0;e<12;e++)n=h([2e3,e]),i.push(this.monthsShort(n,"")),a.push(this.months(n,"")),r.push(this.months(n,"")),r.push(this.monthsShort(n,""));for(i.sort(t),a.sort(t),r.sort(t),e=0;e<12;e++)i[e]=q(i[e]),a[e]=q(a[e]);for(e=0;e<24;e++)r[e]=q(r[e]);this._monthsRegex=new RegExp("^("+r.join("|")+")","i"),this._monthsShortRegex=this._monthsRegex,this._monthsStrictRegex=new RegExp("^("+a.join("|")+")","i"),this._monthsShortStrictRegex=new RegExp("^("+i.join("|")+")","i")}function et(t){return nt(t)?366:365}function nt(t){return t%4==0&&t%100!=0||t%400==0}function it(t,e,n,i,a,r,o){var s=new Date(t,e,n,i,a,r,o);return t<100&&t>=0&&isFinite(s.getFullYear())&&s.setFullYear(t),s}function at(t){var e=new Date(Date.UTC.apply(null,arguments));return t<100&&t>=0&&isFinite(e.getUTCFullYear())&&e.setUTCFullYear(t),e}function rt(t,e,n){var i=7+e-n;return-((7+at(t,0,i).getUTCDay()-e)%7)+i-1}function ot(t,e,n,i,a){var r,o,s=1+7*(e-1)+(7+n-i)%7+rt(t,i,a);return s<=0?o=et(r=t-1)+s:s>et(t)?(r=t+1,o=s-et(t)):(r=t,o=s),{year:r,dayOfYear:o}}function st(t,e,n){var i,a,r=rt(t.year(),e,n),o=Math.floor((t.dayOfYear()-r-1)/7)+1;return o<1?i=o+lt(a=t.year()-1,e,n):o>lt(t.year(),e,n)?(i=o-lt(t.year(),e,n),a=t.year()+1):(a=t.year(),i=o),{week:i,year:a}}function lt(t,e,n){var i=rt(t,e,n),a=rt(t+1,e,n);return(et(t)-i+a)/7}function ut(t,e){return"string"!=typeof t?t:isNaN(t)?"number"==typeof(t=e.weekdaysParse(t))?t:null:parseInt(t,10)}function dt(t,e){return"string"==typeof t?e.weekdaysParse(t)%7||7:isNaN(t)?null:t}function ct(t,e,n){var i,a,r,o=t.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],i=0;i<7;++i)r=h([2e3,1]).day(i),this._minWeekdaysParse[i]=this.weekdaysMin(r,"").toLocaleLowerCase(),this._shortWeekdaysParse[i]=this.weekdaysShort(r,"").toLocaleLowerCase(),this._weekdaysParse[i]=this.weekdays(r,"").toLocaleLowerCase();return n?"dddd"===e?-1!==(a=gn.call(this._weekdaysParse,o))?a:null:"ddd"===e?-1!==(a=gn.call(this._shortWeekdaysParse,o))?a:null:-1!==(a=gn.call(this._minWeekdaysParse,o))?a:null:"dddd"===e?-1!==(a=gn.call(this._weekdaysParse,o))?a:-1!==(a=gn.call(this._shortWeekdaysParse,o))?a:-1!==(a=gn.call(this._minWeekdaysParse,o))?a:null:"ddd"===e?-1!==(a=gn.call(this._shortWeekdaysParse,o))?a:-1!==(a=gn.call(this._weekdaysParse,o))?a:-1!==(a=gn.call(this._minWeekdaysParse,o))?a:null:-1!==(a=gn.call(this._minWeekdaysParse,o))?a:-1!==(a=gn.call(this._weekdaysParse,o))?a:-1!==(a=gn.call(this._shortWeekdaysParse,o))?a:null}function ht(){function t(t,e){return e.length-t.length}var e,n,i,a,r,o=[],s=[],l=[],u=[];for(e=0;e<7;e++)n=h([2e3,1]).day(e),i=this.weekdaysMin(n,""),a=this.weekdaysShort(n,""),r=this.weekdays(n,""),o.push(i),s.push(a),l.push(r),u.push(i),u.push(a),u.push(r);for(o.sort(t),s.sort(t),l.sort(t),u.sort(t),e=0;e<7;e++)s[e]=q(s[e]),l[e]=q(l[e]),u[e]=q(u[e]);this._weekdaysRegex=new RegExp("^("+u.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+l.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+s.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+o.join("|")+")","i")}function ft(){return this.hours()%12||12}function gt(t,e){N(t,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),e)})}function mt(t,e){return e._meridiemParse}function pt(t){return t?t.toLowerCase().replace("_","-"):t}function vt(t){for(var e,n,i,a,r=0;r<t.length;){for(e=(a=pt(t[r]).split("-")).length,n=(n=pt(t[r+1]))?n.split("-"):null;e>0;){if(i=yt(a.slice(0,e).join("-")))return i;if(n&&n.length>=e&&k(a,n,!0)>=e-1)break;e--}r++}return null}function yt(n){var i=null;if(!On[n]&&void 0!==e&&e&&e.exports)try{i=Pn._abbr,t("./locale/"+n),bt(i)}catch(t){}return On[n]}function bt(t,e){var n;return t&&(n=o(e)?_t(t):xt(t,e))&&(Pn=n),Pn._abbr}function xt(t,e){if(null!==e){var n=An;if(e.abbr=t,null!=On[t])S("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),n=On[t]._config;else if(null!=e.parentLocale){if(null==On[e.parentLocale])return Fn[e.parentLocale]||(Fn[e.parentLocale]=[]),Fn[e.parentLocale].push({name:t,config:e}),null;n=On[e.parentLocale]._config}return On[t]=new P(C(n,e)),Fn[t]&&Fn[t].forEach(function(t){xt(t.name,t.config)}),bt(t),On[t]}return delete On[t],null}function _t(t){var e;if(t&&t._locale&&t._locale._abbr&&(t=t._locale._abbr),!t)return Pn;if(!i(t)){if(e=yt(t))return e;t=[t]}return vt(t)}function kt(t){var e,n=t._a;return n&&-2===g(t).overflow&&(e=n[on]<0||n[on]>11?on:n[sn]<1||n[sn]>J(n[rn],n[on])?sn:n[ln]<0||n[ln]>24||24===n[ln]&&(0!==n[un]||0!==n[dn]||0!==n[cn])?ln:n[un]<0||n[un]>59?un:n[dn]<0||n[dn]>59?dn:n[cn]<0||n[cn]>999?cn:-1,g(t)._overflowDayOfYear&&(e<rn||e>sn)&&(e=sn),g(t)._overflowWeeks&&-1===e&&(e=hn),g(t)._overflowWeekday&&-1===e&&(e=fn),g(t).overflow=e),t}function wt(t){var e,n,i,a,r,o,s=t._i,l=Rn.exec(s)||Ln.exec(s);if(l){for(g(t).iso=!0,e=0,n=Yn.length;e<n;e++)if(Yn[e][1].exec(l[1])){a=Yn[e][0],i=!1!==Yn[e][2];break}if(null==a)return void(t._isValid=!1);if(l[3]){for(e=0,n=Nn.length;e<n;e++)if(Nn[e][1].exec(l[3])){r=(l[2]||" ")+Nn[e][0];break}if(null==r)return void(t._isValid=!1)}if(!i&&null!=r)return void(t._isValid=!1);if(l[4]){if(!Wn.exec(l[4]))return void(t._isValid=!1);o="Z"}t._f=a+(r||"")+(o||""),It(t)}else t._isValid=!1}function Mt(t){var e,n,i,a,r,o,s,l,u={" GMT":" +0000"," EDT":" -0400"," EST":" -0500"," CDT":" -0500"," CST":" -0600"," MDT":" -0600"," MST":" -0700"," PDT":" -0700"," PST":" -0800"};if(e=t._i.replace(/\([^\)]*\)|[\n\t]/g," ").replace(/(\s\s+)/g," ").replace(/^\s|\s$/g,""),n=Bn.exec(e)){if(i=n[1]?"ddd"+(5===n[1].length?", ":" "):"",a="D MMM "+(n[2].length>10?"YYYY ":"YY "),r="HH:mm"+(n[4]?":ss":""),n[1]){var d=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"][new Date(n[2]).getDay()];if(n[1].substr(0,3)!==d)return g(t).weekdayMismatch=!0,void(t._isValid=!1)}switch(n[5].length){case 2:s=0===l?" +0000":((l="YXWVUTSRQPONZABCDEFGHIKLM".indexOf(n[5][1].toUpperCase())-12)<0?" -":" +")+(""+l).replace(/^-?/,"0").match(/..$/)[0]+"00";break;case 4:s=u[n[5]];break;default:s=u[" GMT"]}n[5]=s,t._i=n.splice(1).join(""),o=" ZZ",t._f=i+a+r+o,It(t),g(t).rfc2822=!0}else t._isValid=!1}function St(t){var e=zn.exec(t._i);null===e?(wt(t),!1===t._isValid&&(delete t._isValid,Mt(t),!1===t._isValid&&(delete t._isValid,n.createFromInputFallback(t)))):t._d=new Date(+e[1])}function Dt(t,e,n){return null!=t?t:null!=e?e:n}function Ct(t){var e=new Date(n.now());return t._useUTC?[e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()]:[e.getFullYear(),e.getMonth(),e.getDate()]}function Pt(t){var e,n,i,a,r=[];if(!t._d){for(i=Ct(t),t._w&&null==t._a[sn]&&null==t._a[on]&&Tt(t),null!=t._dayOfYear&&(a=Dt(t._a[rn],i[rn]),(t._dayOfYear>et(a)||0===t._dayOfYear)&&(g(t)._overflowDayOfYear=!0),n=at(a,0,t._dayOfYear),t._a[on]=n.getUTCMonth(),t._a[sn]=n.getUTCDate()),e=0;e<3&&null==t._a[e];++e)t._a[e]=r[e]=i[e];for(;e<7;e++)t._a[e]=r[e]=null==t._a[e]?2===e?1:0:t._a[e];24===t._a[ln]&&0===t._a[un]&&0===t._a[dn]&&0===t._a[cn]&&(t._nextDay=!0,t._a[ln]=0),t._d=(t._useUTC?at:it).apply(null,r),null!=t._tzm&&t._d.setUTCMinutes(t._d.getUTCMinutes()-t._tzm),t._nextDay&&(t._a[ln]=24)}}function Tt(t){var e,n,i,a,r,o,s,l;if(null!=(e=t._w).GG||null!=e.W||null!=e.E)r=1,o=4,n=Dt(e.GG,t._a[rn],st(Nt(),1,4).year),i=Dt(e.W,1),((a=Dt(e.E,1))<1||a>7)&&(l=!0);else{r=t._locale._week.dow,o=t._locale._week.doy;var u=st(Nt(),r,o);n=Dt(e.gg,t._a[rn],u.year),i=Dt(e.w,u.week),null!=e.d?((a=e.d)<0||a>6)&&(l=!0):null!=e.e?(a=e.e+r,(e.e<0||e.e>6)&&(l=!0)):a=r}i<1||i>lt(n,r,o)?g(t)._overflowWeeks=!0:null!=l?g(t)._overflowWeekday=!0:(s=ot(n,i,a,r,o),t._a[rn]=s.year,t._dayOfYear=s.dayOfYear)}function It(t){if(t._f!==n.ISO_8601)if(t._f!==n.RFC_2822){t._a=[],g(t).empty=!0;var e,i,a,r,o,s=""+t._i,l=s.length,u=0;for(a=H(t._f,t._locale).match(Le)||[],e=0;e<a.length;e++)r=a[e],(i=(s.match(j(r,t))||[])[0])&&((o=s.substr(0,s.indexOf(i))).length>0&&g(t).unusedInput.push(o),s=s.slice(s.indexOf(i)+i.length),u+=i.length),Ne[r]?(i?g(t).empty=!1:g(t).unusedTokens.push(r),X(r,i,t)):t._strict&&!i&&g(t).unusedTokens.push(r);g(t).charsLeftOver=l-u,s.length>0&&g(t).unusedInput.push(s),t._a[ln]<=12&&!0===g(t).bigHour&&t._a[ln]>0&&(g(t).bigHour=void 0),g(t).parsedDateParts=t._a.slice(0),g(t).meridiem=t._meridiem,t._a[ln]=At(t._locale,t._a[ln],t._meridiem),Pt(t),kt(t)}else Mt(t);else wt(t)}function At(t,e,n){var i;return null==n?e:null!=t.meridiemHour?t.meridiemHour(e,n):null!=t.isPM?((i=t.isPM(n))&&e<12&&(e+=12),i||12!==e||(e=0),e):e}function Ot(t){var e,n,i,a,r;if(0===t._f.length)return g(t).invalidFormat=!0,void(t._d=new Date(NaN));for(a=0;a<t._f.length;a++)r=0,e=v({},t),null!=t._useUTC&&(e._useUTC=t._useUTC),e._f=t._f[a],It(e),m(e)&&(r+=g(e).charsLeftOver,r+=10*g(e).unusedTokens.length,g(e).score=r,(null==i||r<i)&&(i=r,n=e));c(t,n||e)}function Ft(t){if(!t._d){var e=A(t._i);t._a=u([e.year,e.month,e.day||e.date,e.hour,e.minute,e.second,e.millisecond],function(t){return t&&parseInt(t,10)}),Pt(t)}}function Rt(t){var e=new y(kt(Lt(t)));return e._nextDay&&(e.add(1,"d"),e._nextDay=void 0),e}function Lt(t){var e=t._i,n=t._f;return t._locale=t._locale||_t(t._l),null===e||void 0===n&&""===e?p({nullInput:!0}):("string"==typeof e&&(t._i=e=t._locale.preparse(e)),b(e)?new y(kt(e)):(l(e)?t._d=e:i(n)?Ot(t):n?It(t):Wt(t),m(t)||(t._d=null),t))}function Wt(t){var e=t._i;o(e)?t._d=new Date(n.now()):l(e)?t._d=new Date(e.valueOf()):"string"==typeof e?St(t):i(e)?(t._a=u(e.slice(0),function(t){return parseInt(t,10)}),Pt(t)):a(e)?Ft(t):s(e)?t._d=new Date(e):n.createFromInputFallback(t)}function Yt(t,e,n,o,s){var l={};return!0!==n&&!1!==n||(o=n,n=void 0),(a(t)&&r(t)||i(t)&&0===t.length)&&(t=void 0),l._isAMomentObject=!0,l._useUTC=l._isUTC=s,l._l=n,l._i=t,l._f=e,l._strict=o,Rt(l)}function Nt(t,e,n,i){return Yt(t,e,n,i,!1)}function zt(t,e){var n,a;if(1===e.length&&i(e[0])&&(e=e[0]),!e.length)return Nt();for(n=e[0],a=1;a<e.length;++a)e[a].isValid()&&!e[a][t](n)||(n=e[a]);return n}function Bt(t){for(var e in t)if(-1===En.indexOf(e)||null!=t[e]&&isNaN(t[e]))return!1;for(var n=!1,i=0;i<En.length;++i)if(t[En[i]]){if(n)return!1;parseFloat(t[En[i]])!==_(t[En[i]])&&(n=!0)}return!0}function Vt(t){var e=A(t),n=e.year||0,i=e.quarter||0,a=e.month||0,r=e.week||0,o=e.day||0,s=e.hour||0,l=e.minute||0,u=e.second||0,d=e.millisecond||0;this._isValid=Bt(e),this._milliseconds=+d+1e3*u+6e4*l+1e3*s*60*60,this._days=+o+7*r,this._months=+a+3*i+12*n,this._data={},this._locale=_t(),this._bubble()}function Ht(t){return t instanceof Vt}function Et(t){return t<0?-1*Math.round(-1*t):Math.round(t)}function jt(t,e){N(t,0,0,function(){var t=this.utcOffset(),n="+";return t<0&&(t=-t,n="-"),n+Y(~~(t/60),2)+e+Y(~~t%60,2)})}function Ut(t,e){var n=(e||"").match(t);if(null===n)return null;var i=((n[n.length-1]||[])+"").match(jn)||["-",0,0],a=60*i[1]+_(i[2]);return 0===a?0:"+"===i[0]?a:-a}function qt(t,e){var i,a;return e._isUTC?(i=e.clone(),a=(b(t)||l(t)?t.valueOf():Nt(t).valueOf())-i.valueOf(),i._d.setTime(i._d.valueOf()+a),n.updateOffset(i,!1),i):Nt(t).local()}function Gt(t){return 15*-Math.round(t._d.getTimezoneOffset()/15)}function Zt(){return!!this.isValid()&&(this._isUTC&&0===this._offset)}function Xt(t,e){var n,i,a,r=t,o=null;return Ht(t)?r={ms:t._milliseconds,d:t._days,M:t._months}:s(t)?(r={},e?r[e]=t:r.milliseconds=t):(o=Un.exec(t))?(n="-"===o[1]?-1:1,r={y:0,d:_(o[sn])*n,h:_(o[ln])*n,m:_(o[un])*n,s:_(o[dn])*n,ms:_(Et(1e3*o[cn]))*n}):(o=qn.exec(t))?(n="-"===o[1]?-1:1,r={y:Jt(o[2],n),M:Jt(o[3],n),w:Jt(o[4],n),d:Jt(o[5],n),h:Jt(o[6],n),m:Jt(o[7],n),s:Jt(o[8],n)}):null==r?r={}:"object"==typeof r&&("from"in r||"to"in r)&&(a=Qt(Nt(r.from),Nt(r.to)),(r={}).ms=a.milliseconds,r.M=a.months),i=new Vt(r),Ht(t)&&d(t,"_locale")&&(i._locale=t._locale),i}function Jt(t,e){var n=t&&parseFloat(t.replace(",","."));return(isNaN(n)?0:n)*e}function Kt(t,e){var n={milliseconds:0,months:0};return n.months=e.month()-t.month()+12*(e.year()-t.year()),t.clone().add(n.months,"M").isAfter(e)&&--n.months,n.milliseconds=+e-+t.clone().add(n.months,"M"),n}function Qt(t,e){var n;return t.isValid()&&e.isValid()?(e=qt(e,t),t.isBefore(e)?n=Kt(t,e):((n=Kt(e,t)).milliseconds=-n.milliseconds,n.months=-n.months),n):{milliseconds:0,months:0}}function $t(t,e){return function(n,i){var a,r;return null===i||isNaN(+i)||(S(e,"moment()."+e+"(period, number) is deprecated. Please use moment()."+e+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),r=n,n=i,i=r),n="string"==typeof n?+n:n,a=Xt(n,i),te(this,a,t),this}}function te(t,e,i,a){var r=e._milliseconds,o=Et(e._days),s=Et(e._months);t.isValid()&&(a=null==a||a,r&&t._d.setTime(t._d.valueOf()+r*i),o&&W(t,"Date",L(t,"Date")+o*i),s&&Q(t,L(t,"Month")+s*i),a&&n.updateOffset(t,o||s))}function ee(t,e){var n,i=12*(e.year()-t.year())+(e.month()-t.month()),a=t.clone().add(i,"months");return n=e-a<0?(e-a)/(a-t.clone().add(i-1,"months")):(e-a)/(t.clone().add(i+1,"months")-a),-(i+n)||0}function ne(t){var e;return void 0===t?this._locale._abbr:(null!=(e=_t(t))&&(this._locale=e),this)}function ie(){return this._locale}function ae(t,e){N(0,[t,t.length],0,e)}function re(t,e,n,i,a){var r;return null==t?st(this,i,a).year:(r=lt(t,i,a),e>r&&(e=r),oe.call(this,t,e,n,i,a))}function oe(t,e,n,i,a){var r=ot(t,e,n,i,a),o=at(r.year,0,r.dayOfYear);return this.year(o.getUTCFullYear()),this.month(o.getUTCMonth()),this.date(o.getUTCDate()),this}function se(t){return t}function le(t,e,n,i){var a=_t(),r=h().set(i,e);return a[n](r,t)}function ue(t,e,n){if(s(t)&&(e=t,t=void 0),t=t||"",null!=e)return le(t,e,n,"month");var i,a=[];for(i=0;i<12;i++)a[i]=le(t,i,n,"month");return a}function de(t,e,n,i){"boolean"==typeof t?(s(e)&&(n=e,e=void 0),e=e||""):(n=e=t,t=!1,s(e)&&(n=e,e=void 0),e=e||"");var a=_t(),r=t?a._week.dow:0;if(null!=n)return le(e,(n+r)%7,i,"day");var o,l=[];for(o=0;o<7;o++)l[o]=le(e,(o+r)%7,i,"day");return l}function ce(t,e,n,i){var a=Xt(e,n);return t._milliseconds+=i*a._milliseconds,t._days+=i*a._days,t._months+=i*a._months,t._bubble()}function he(t){return t<0?Math.floor(t):Math.ceil(t)}function fe(t){return 4800*t/146097}function ge(t){return 146097*t/4800}function me(t){return function(){return this.as(t)}}function pe(t){return function(){return this.isValid()?this._data[t]:NaN}}function ve(t,e,n,i,a){return a.relativeTime(e||1,!!n,t,i)}function ye(t,e,n){var i=Xt(t).abs(),a=bi(i.as("s")),r=bi(i.as("m")),o=bi(i.as("h")),s=bi(i.as("d")),l=bi(i.as("M")),u=bi(i.as("y")),d=a<=xi.ss&&["s",a]||a<xi.s&&["ss",a]||r<=1&&["m"]||r<xi.m&&["mm",r]||o<=1&&["h"]||o<xi.h&&["hh",o]||s<=1&&["d"]||s<xi.d&&["dd",s]||l<=1&&["M"]||l<xi.M&&["MM",l]||u<=1&&["y"]||["yy",u];return d[2]=e,d[3]=+t>0,d[4]=n,ve.apply(null,d)}function be(){if(!this.isValid())return this.localeData().invalidDate();var t,e,n,i=_i(this._milliseconds)/1e3,a=_i(this._days),r=_i(this._months);e=x((t=x(i/60))/60),i%=60,t%=60;var o=n=x(r/12),s=r%=12,l=a,u=e,d=t,c=i,h=this.asSeconds();return h?(h<0?"-":"")+"P"+(o?o+"Y":"")+(s?s+"M":"")+(l?l+"D":"")+(u||d||c?"T":"")+(u?u+"H":"")+(d?d+"M":"")+(c?c+"S":""):"P0D"}var xe,_e,ke=_e=Array.prototype.some?Array.prototype.some:function(t){for(var e=Object(this),n=e.length>>>0,i=0;i<n;i++)if(i in e&&t.call(this,e[i],i,e))return!0;return!1},we=n.momentProperties=[],Me=!1,Se={};n.suppressDeprecationWarnings=!1,n.deprecationHandler=null;var De,Ce,Pe=De=Object.keys?Object.keys:function(t){var e,n=[];for(e in t)d(t,e)&&n.push(e);return n},Te={sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},Ie={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},Ae=/\d{1,2}/,Oe={future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},Fe={},Re={},Le=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,We=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,Ye={},Ne={},ze=/\d/,Be=/\d\d/,Ve=/\d{3}/,He=/\d{4}/,Ee=/[+-]?\d{6}/,je=/\d\d?/,Ue=/\d\d\d\d?/,qe=/\d\d\d\d\d\d?/,Ge=/\d{1,3}/,Ze=/\d{1,4}/,Xe=/[+-]?\d{1,6}/,Je=/\d+/,Ke=/[+-]?\d+/,Qe=/Z|[+-]\d\d:?\d\d/gi,$e=/Z|[+-]\d\d(?::?\d\d)?/gi,tn=/[+-]?\d+(\.\d{1,3})?/,en=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,nn={},an={},rn=0,on=1,sn=2,ln=3,un=4,dn=5,cn=6,hn=7,fn=8,gn=Ce=Array.prototype.indexOf?Array.prototype.indexOf:function(t){var e;for(e=0;e<this.length;++e)if(this[e]===t)return e;return-1};N("M",["MM",2],"Mo",function(){return this.month()+1}),N("MMM",0,0,function(t){return this.localeData().monthsShort(this,t)}),N("MMMM",0,0,function(t){return this.localeData().months(this,t)}),T("month","M"),O("month",8),E("M",je),E("MM",je,Be),E("MMM",function(t,e){return e.monthsShortRegex(t)}),E("MMMM",function(t,e){return e.monthsRegex(t)}),G(["M","MM"],function(t,e){e[on]=_(t)-1}),G(["MMM","MMMM"],function(t,e,n,i){var a=n._locale.monthsParse(t,i,n._strict);null!=a?e[on]=a:g(n).invalidMonth=t});var mn=/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/,pn="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),vn="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),yn=en,bn=en;N("Y",0,0,function(){var t=this.year();return t<=9999?""+t:"+"+t}),N(0,["YY",2],0,function(){return this.year()%100}),N(0,["YYYY",4],0,"year"),N(0,["YYYYY",5],0,"year"),N(0,["YYYYYY",6,!0],0,"year"),T("year","y"),O("year",1),E("Y",Ke),E("YY",je,Be),E("YYYY",Ze,He),E("YYYYY",Xe,Ee),E("YYYYYY",Xe,Ee),G(["YYYYY","YYYYYY"],rn),G("YYYY",function(t,e){e[rn]=2===t.length?n.parseTwoDigitYear(t):_(t)}),G("YY",function(t,e){e[rn]=n.parseTwoDigitYear(t)}),G("Y",function(t,e){e[rn]=parseInt(t,10)}),n.parseTwoDigitYear=function(t){return _(t)+(_(t)>68?1900:2e3)};var xn=R("FullYear",!0);N("w",["ww",2],"wo","week"),N("W",["WW",2],"Wo","isoWeek"),T("week","w"),T("isoWeek","W"),O("week",5),O("isoWeek",5),E("w",je),E("ww",je,Be),E("W",je),E("WW",je,Be),Z(["w","ww","W","WW"],function(t,e,n,i){e[i.substr(0,1)]=_(t)});var _n={dow:0,doy:6};N("d",0,"do","day"),N("dd",0,0,function(t){return this.localeData().weekdaysMin(this,t)}),N("ddd",0,0,function(t){return this.localeData().weekdaysShort(this,t)}),N("dddd",0,0,function(t){return this.localeData().weekdays(this,t)}),N("e",0,0,"weekday"),N("E",0,0,"isoWeekday"),T("day","d"),T("weekday","e"),T("isoWeekday","E"),O("day",11),O("weekday",11),O("isoWeekday",11),E("d",je),E("e",je),E("E",je),E("dd",function(t,e){return e.weekdaysMinRegex(t)}),E("ddd",function(t,e){return e.weekdaysShortRegex(t)}),E("dddd",function(t,e){return e.weekdaysRegex(t)}),Z(["dd","ddd","dddd"],function(t,e,n,i){var a=n._locale.weekdaysParse(t,i,n._strict);null!=a?e.d=a:g(n).invalidWeekday=t}),Z(["d","e","E"],function(t,e,n,i){e[i]=_(t)});var kn="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),wn="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),Mn="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),Sn=en,Dn=en,Cn=en;N("H",["HH",2],0,"hour"),N("h",["hh",2],0,ft),N("k",["kk",2],0,function(){return this.hours()||24}),N("hmm",0,0,function(){return""+ft.apply(this)+Y(this.minutes(),2)}),N("hmmss",0,0,function(){return""+ft.apply(this)+Y(this.minutes(),2)+Y(this.seconds(),2)}),N("Hmm",0,0,function(){return""+this.hours()+Y(this.minutes(),2)}),N("Hmmss",0,0,function(){return""+this.hours()+Y(this.minutes(),2)+Y(this.seconds(),2)}),gt("a",!0),gt("A",!1),T("hour","h"),O("hour",13),E("a",mt),E("A",mt),E("H",je),E("h",je),E("k",je),E("HH",je,Be),E("hh",je,Be),E("kk",je,Be),E("hmm",Ue),E("hmmss",qe),E("Hmm",Ue),E("Hmmss",qe),G(["H","HH"],ln),G(["k","kk"],function(t,e,n){var i=_(t);e[ln]=24===i?0:i}),G(["a","A"],function(t,e,n){n._isPm=n._locale.isPM(t),n._meridiem=t}),G(["h","hh"],function(t,e,n){e[ln]=_(t),g(n).bigHour=!0}),G("hmm",function(t,e,n){var i=t.length-2;e[ln]=_(t.substr(0,i)),e[un]=_(t.substr(i)),g(n).bigHour=!0}),G("hmmss",function(t,e,n){var i=t.length-4,a=t.length-2;e[ln]=_(t.substr(0,i)),e[un]=_(t.substr(i,2)),e[dn]=_(t.substr(a)),g(n).bigHour=!0}),G("Hmm",function(t,e,n){var i=t.length-2;e[ln]=_(t.substr(0,i)),e[un]=_(t.substr(i))}),G("Hmmss",function(t,e,n){var i=t.length-4,a=t.length-2;e[ln]=_(t.substr(0,i)),e[un]=_(t.substr(i,2)),e[dn]=_(t.substr(a))});var Pn,Tn=/[ap]\.?m?\.?/i,In=R("Hours",!0),An={calendar:Te,longDateFormat:Ie,invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:Ae,relativeTime:Oe,months:pn,monthsShort:vn,week:_n,weekdays:kn,weekdaysMin:Mn,weekdaysShort:wn,meridiemParse:Tn},On={},Fn={},Rn=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,Ln=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,Wn=/Z|[+-]\d\d(?::?\d\d)?/,Yn=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],Nn=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],zn=/^\/?Date\((\-?\d+)/i,Bn=/^((?:Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d?\d\s(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(?:\d\d)?\d\d\s)(\d\d:\d\d)(\:\d\d)?(\s(?:UT|GMT|[ECMP][SD]T|[A-IK-Za-ik-z]|[+-]\d{4}))$/;n.createFromInputFallback=M("value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.",function(t){t._d=new Date(t._i+(t._useUTC?" UTC":""))}),n.ISO_8601=function(){},n.RFC_2822=function(){};var Vn=M("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var t=Nt.apply(null,arguments);return this.isValid()&&t.isValid()?t<this?this:t:p()}),Hn=M("moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var t=Nt.apply(null,arguments);return this.isValid()&&t.isValid()?t>this?this:t:p()}),En=["year","quarter","month","week","day","hour","minute","second","millisecond"];jt("Z",":"),jt("ZZ",""),E("Z",$e),E("ZZ",$e),G(["Z","ZZ"],function(t,e,n){n._useUTC=!0,n._tzm=Ut($e,t)});var jn=/([\+\-]|\d\d)/gi;n.updateOffset=function(){};var Un=/^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/,qn=/^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/;Xt.fn=Vt.prototype,Xt.invalid=function(){return Xt(NaN)};var Gn=$t(1,"add"),Zn=$t(-1,"subtract");n.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",n.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var Xn=M("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(t){return void 0===t?this.localeData():this.locale(t)});N(0,["gg",2],0,function(){return this.weekYear()%100}),N(0,["GG",2],0,function(){return this.isoWeekYear()%100}),ae("gggg","weekYear"),ae("ggggg","weekYear"),ae("GGGG","isoWeekYear"),ae("GGGGG","isoWeekYear"),T("weekYear","gg"),T("isoWeekYear","GG"),O("weekYear",1),O("isoWeekYear",1),E("G",Ke),E("g",Ke),E("GG",je,Be),E("gg",je,Be),E("GGGG",Ze,He),E("gggg",Ze,He),E("GGGGG",Xe,Ee),E("ggggg",Xe,Ee),Z(["gggg","ggggg","GGGG","GGGGG"],function(t,e,n,i){e[i.substr(0,2)]=_(t)}),Z(["gg","GG"],function(t,e,i,a){e[a]=n.parseTwoDigitYear(t)}),N("Q",0,"Qo","quarter"),T("quarter","Q"),O("quarter",7),E("Q",ze),G("Q",function(t,e){e[on]=3*(_(t)-1)}),N("D",["DD",2],"Do","date"),T("date","D"),O("date",9),E("D",je),E("DD",je,Be),E("Do",function(t,e){return t?e._dayOfMonthOrdinalParse||e._ordinalParse:e._dayOfMonthOrdinalParseLenient}),G(["D","DD"],sn),G("Do",function(t,e){e[sn]=_(t.match(je)[0],10)});var Jn=R("Date",!0);N("DDD",["DDDD",3],"DDDo","dayOfYear"),T("dayOfYear","DDD"),O("dayOfYear",4),E("DDD",Ge),E("DDDD",Ve),G(["DDD","DDDD"],function(t,e,n){n._dayOfYear=_(t)}),N("m",["mm",2],0,"minute"),T("minute","m"),O("minute",14),E("m",je),E("mm",je,Be),G(["m","mm"],un);var Kn=R("Minutes",!1);N("s",["ss",2],0,"second"),T("second","s"),O("second",15),E("s",je),E("ss",je,Be),G(["s","ss"],dn);var Qn=R("Seconds",!1);N("S",0,0,function(){return~~(this.millisecond()/100)}),N(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),N(0,["SSS",3],0,"millisecond"),N(0,["SSSS",4],0,function(){return 10*this.millisecond()}),N(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),N(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),N(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),N(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),N(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),T("millisecond","ms"),O("millisecond",16),E("S",Ge,ze),E("SS",Ge,Be),E("SSS",Ge,Ve);var $n;for($n="SSSS";$n.length<=9;$n+="S")E($n,Je);for($n="S";$n.length<=9;$n+="S")G($n,function(t,e){e[cn]=_(1e3*("0."+t))});var ti=R("Milliseconds",!1);N("z",0,0,"zoneAbbr"),N("zz",0,0,"zoneName");var ei=y.prototype;ei.add=Gn,ei.calendar=function(t,e){var i=t||Nt(),a=qt(i,this).startOf("day"),r=n.calendarFormat(this,a)||"sameElse",o=e&&(D(e[r])?e[r].call(this,i):e[r]);return this.format(o||this.localeData().calendar(r,this,Nt(i)))},ei.clone=function(){return new y(this)},ei.diff=function(t,e,n){var i,a,r,o;return this.isValid()&&(i=qt(t,this)).isValid()?(a=6e4*(i.utcOffset()-this.utcOffset()),"year"===(e=I(e))||"month"===e||"quarter"===e?(o=ee(this,i),"quarter"===e?o/=3:"year"===e&&(o/=12)):(r=this-i,o="second"===e?r/1e3:"minute"===e?r/6e4:"hour"===e?r/36e5:"day"===e?(r-a)/864e5:"week"===e?(r-a)/6048e5:r),n?o:x(o)):NaN},ei.endOf=function(t){return void 0===(t=I(t))||"millisecond"===t?this:("date"===t&&(t="day"),this.startOf(t).add(1,"isoWeek"===t?"week":t).subtract(1,"ms"))},ei.format=function(t){t||(t=this.isUtc()?n.defaultFormatUtc:n.defaultFormat);var e=V(this,t);return this.localeData().postformat(e)},ei.from=function(t,e){return this.isValid()&&(b(t)&&t.isValid()||Nt(t).isValid())?Xt({to:this,from:t}).locale(this.locale()).humanize(!e):this.localeData().invalidDate()},ei.fromNow=function(t){return this.from(Nt(),t)},ei.to=function(t,e){return this.isValid()&&(b(t)&&t.isValid()||Nt(t).isValid())?Xt({from:this,to:t}).locale(this.locale()).humanize(!e):this.localeData().invalidDate()},ei.toNow=function(t){return this.to(Nt(),t)},ei.get=function(t){return t=I(t),D(this[t])?this[t]():this},ei.invalidAt=function(){return g(this).overflow},ei.isAfter=function(t,e){var n=b(t)?t:Nt(t);return!(!this.isValid()||!n.isValid())&&("millisecond"===(e=I(o(e)?"millisecond":e))?this.valueOf()>n.valueOf():n.valueOf()<this.clone().startOf(e).valueOf())},ei.isBefore=function(t,e){var n=b(t)?t:Nt(t);return!(!this.isValid()||!n.isValid())&&("millisecond"===(e=I(o(e)?"millisecond":e))?this.valueOf()<n.valueOf():this.clone().endOf(e).valueOf()<n.valueOf())},ei.isBetween=function(t,e,n,i){return("("===(i=i||"()")[0]?this.isAfter(t,n):!this.isBefore(t,n))&&(")"===i[1]?this.isBefore(e,n):!this.isAfter(e,n))},ei.isSame=function(t,e){var n,i=b(t)?t:Nt(t);return!(!this.isValid()||!i.isValid())&&("millisecond"===(e=I(e||"millisecond"))?this.valueOf()===i.valueOf():(n=i.valueOf(),this.clone().startOf(e).valueOf()<=n&&n<=this.clone().endOf(e).valueOf()))},ei.isSameOrAfter=function(t,e){return this.isSame(t,e)||this.isAfter(t,e)},ei.isSameOrBefore=function(t,e){return this.isSame(t,e)||this.isBefore(t,e)},ei.isValid=function(){return m(this)},ei.lang=Xn,ei.locale=ne,ei.localeData=ie,ei.max=Hn,ei.min=Vn,ei.parsingFlags=function(){return c({},g(this))},ei.set=function(t,e){if("object"==typeof t)for(var n=F(t=A(t)),i=0;i<n.length;i++)this[n[i].unit](t[n[i].unit]);else if(t=I(t),D(this[t]))return this[t](e);return this},ei.startOf=function(t){switch(t=I(t)){case"year":this.month(0);case"quarter":case"month":this.date(1);case"week":case"isoWeek":case"day":case"date":this.hours(0);case"hour":this.minutes(0);case"minute":this.seconds(0);case"second":this.milliseconds(0)}return"week"===t&&this.weekday(0),"isoWeek"===t&&this.isoWeekday(1),"quarter"===t&&this.month(3*Math.floor(this.month()/3)),this},ei.subtract=Zn,ei.toArray=function(){var t=this;return[t.year(),t.month(),t.date(),t.hour(),t.minute(),t.second(),t.millisecond()]},ei.toObject=function(){var t=this;return{years:t.year(),months:t.month(),date:t.date(),hours:t.hours(),minutes:t.minutes(),seconds:t.seconds(),milliseconds:t.milliseconds()}},ei.toDate=function(){return new Date(this.valueOf())},ei.toISOString=function(){if(!this.isValid())return null;var t=this.clone().utc();return t.year()<0||t.year()>9999?V(t,"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]"):D(Date.prototype.toISOString)?this.toDate().toISOString():V(t,"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]")},ei.inspect=function(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var t="moment",e="";this.isLocal()||(t=0===this.utcOffset()?"moment.utc":"moment.parseZone",e="Z");var n="["+t+'("]',i=0<=this.year()&&this.year()<=9999?"YYYY":"YYYYYY",a=e+'[")]';return this.format(n+i+"-MM-DD[T]HH:mm:ss.SSS"+a)},ei.toJSON=function(){return this.isValid()?this.toISOString():null},ei.toString=function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},ei.unix=function(){return Math.floor(this.valueOf()/1e3)},ei.valueOf=function(){return this._d.valueOf()-6e4*(this._offset||0)},ei.creationData=function(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}},ei.year=xn,ei.isLeapYear=function(){return nt(this.year())},ei.weekYear=function(t){return re.call(this,t,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)},ei.isoWeekYear=function(t){return re.call(this,t,this.isoWeek(),this.isoWeekday(),1,4)},ei.quarter=ei.quarters=function(t){return null==t?Math.ceil((this.month()+1)/3):this.month(3*(t-1)+this.month()%3)},ei.month=$,ei.daysInMonth=function(){return J(this.year(),this.month())},ei.week=ei.weeks=function(t){var e=this.localeData().week(this);return null==t?e:this.add(7*(t-e),"d")},ei.isoWeek=ei.isoWeeks=function(t){var e=st(this,1,4).week;return null==t?e:this.add(7*(t-e),"d")},ei.weeksInYear=function(){var t=this.localeData()._week;return lt(this.year(),t.dow,t.doy)},ei.isoWeeksInYear=function(){return lt(this.year(),1,4)},ei.date=Jn,ei.day=ei.days=function(t){if(!this.isValid())return null!=t?this:NaN;var e=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=t?(t=ut(t,this.localeData()),this.add(t-e,"d")):e},ei.weekday=function(t){if(!this.isValid())return null!=t?this:NaN;var e=(this.day()+7-this.localeData()._week.dow)%7;return null==t?e:this.add(t-e,"d")},ei.isoWeekday=function(t){if(!this.isValid())return null!=t?this:NaN;if(null!=t){var e=dt(t,this.localeData());return this.day(this.day()%7?e:e-7)}return this.day()||7},ei.dayOfYear=function(t){var e=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==t?e:this.add(t-e,"d")},ei.hour=ei.hours=In,ei.minute=ei.minutes=Kn,ei.second=ei.seconds=Qn,ei.millisecond=ei.milliseconds=ti,ei.utcOffset=function(t,e,i){var a,r=this._offset||0;if(!this.isValid())return null!=t?this:NaN;if(null!=t){if("string"==typeof t){if(null===(t=Ut($e,t)))return this}else Math.abs(t)<16&&!i&&(t*=60);return!this._isUTC&&e&&(a=Gt(this)),this._offset=t,this._isUTC=!0,null!=a&&this.add(a,"m"),r!==t&&(!e||this._changeInProgress?te(this,Xt(t-r,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,n.updateOffset(this,!0),this._changeInProgress=null)),this}return this._isUTC?r:Gt(this)},ei.utc=function(t){return this.utcOffset(0,t)},ei.local=function(t){return this._isUTC&&(this.utcOffset(0,t),this._isUTC=!1,t&&this.subtract(Gt(this),"m")),this},ei.parseZone=function(){if(null!=this._tzm)this.utcOffset(this._tzm,!1,!0);else if("string"==typeof this._i){var t=Ut(Qe,this._i);null!=t?this.utcOffset(t):this.utcOffset(0,!0)}return this},ei.hasAlignedHourOffset=function(t){return!!this.isValid()&&(t=t?Nt(t).utcOffset():0,(this.utcOffset()-t)%60==0)},ei.isDST=function(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},ei.isLocal=function(){return!!this.isValid()&&!this._isUTC},ei.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},ei.isUtc=Zt,ei.isUTC=Zt,ei.zoneAbbr=function(){return this._isUTC?"UTC":""},ei.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},ei.dates=M("dates accessor is deprecated. Use date instead.",Jn),ei.months=M("months accessor is deprecated. Use month instead",$),ei.years=M("years accessor is deprecated. Use year instead",xn),ei.zone=M("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",function(t,e){return null!=t?("string"!=typeof t&&(t=-t),this.utcOffset(t,e),this):-this.utcOffset()}),ei.isDSTShifted=M("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",function(){if(!o(this._isDSTShifted))return this._isDSTShifted;var t={};if(v(t,this),(t=Lt(t))._a){var e=t._isUTC?h(t._a):Nt(t._a);this._isDSTShifted=this.isValid()&&k(t._a,e.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted});var ni=P.prototype;ni.calendar=function(t,e,n){var i=this._calendar[t]||this._calendar.sameElse;return D(i)?i.call(e,n):i},ni.longDateFormat=function(t){var e=this._longDateFormat[t],n=this._longDateFormat[t.toUpperCase()];return e||!n?e:(this._longDateFormat[t]=n.replace(/MMMM|MM|DD|dddd/g,function(t){return t.slice(1)}),this._longDateFormat[t])},ni.invalidDate=function(){return this._invalidDate},ni.ordinal=function(t){return this._ordinal.replace("%d",t)},ni.preparse=se,ni.postformat=se,ni.relativeTime=function(t,e,n,i){var a=this._relativeTime[n];return D(a)?a(t,e,n,i):a.replace(/%d/i,t)},ni.pastFuture=function(t,e){var n=this._relativeTime[t>0?"future":"past"];return D(n)?n(e):n.replace(/%s/i,e)},ni.set=function(t){var e,n;for(n in t)D(e=t[n])?this[n]=e:this["_"+n]=e;this._config=t,this._dayOfMonthOrdinalParseLenient=new RegExp((this._dayOfMonthOrdinalParse.source||this._ordinalParse.source)+"|"+/\d{1,2}/.source)},ni.months=function(t,e){return t?i(this._months)?this._months[t.month()]:this._months[(this._months.isFormat||mn).test(e)?"format":"standalone"][t.month()]:i(this._months)?this._months:this._months.standalone},ni.monthsShort=function(t,e){return t?i(this._monthsShort)?this._monthsShort[t.month()]:this._monthsShort[mn.test(e)?"format":"standalone"][t.month()]:i(this._monthsShort)?this._monthsShort:this._monthsShort.standalone},ni.monthsParse=function(t,e,n){var i,a,r;if(this._monthsParseExact)return K.call(this,t,e,n);for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),i=0;i<12;i++){if(a=h([2e3,i]),n&&!this._longMonthsParse[i]&&(this._longMonthsParse[i]=new RegExp("^"+this.months(a,"").replace(".","")+"$","i"),this._shortMonthsParse[i]=new RegExp("^"+this.monthsShort(a,"").replace(".","")+"$","i")),n||this._monthsParse[i]||(r="^"+this.months(a,"")+"|^"+this.monthsShort(a,""),this._monthsParse[i]=new RegExp(r.replace(".",""),"i")),n&&"MMMM"===e&&this._longMonthsParse[i].test(t))return i;if(n&&"MMM"===e&&this._shortMonthsParse[i].test(t))return i;if(!n&&this._monthsParse[i].test(t))return i}},ni.monthsRegex=function(t){return this._monthsParseExact?(d(this,"_monthsRegex")||tt.call(this),t?this._monthsStrictRegex:this._monthsRegex):(d(this,"_monthsRegex")||(this._monthsRegex=bn),this._monthsStrictRegex&&t?this._monthsStrictRegex:this._monthsRegex)},ni.monthsShortRegex=function(t){return this._monthsParseExact?(d(this,"_monthsRegex")||tt.call(this),t?this._monthsShortStrictRegex:this._monthsShortRegex):(d(this,"_monthsShortRegex")||(this._monthsShortRegex=yn),this._monthsShortStrictRegex&&t?this._monthsShortStrictRegex:this._monthsShortRegex)},ni.week=function(t){return st(t,this._week.dow,this._week.doy).week},ni.firstDayOfYear=function(){return this._week.doy},ni.firstDayOfWeek=function(){return this._week.dow},ni.weekdays=function(t,e){return t?i(this._weekdays)?this._weekdays[t.day()]:this._weekdays[this._weekdays.isFormat.test(e)?"format":"standalone"][t.day()]:i(this._weekdays)?this._weekdays:this._weekdays.standalone},ni.weekdaysMin=function(t){return t?this._weekdaysMin[t.day()]:this._weekdaysMin},ni.weekdaysShort=function(t){return t?this._weekdaysShort[t.day()]:this._weekdaysShort},ni.weekdaysParse=function(t,e,n){var i,a,r;if(this._weekdaysParseExact)return ct.call(this,t,e,n);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),i=0;i<7;i++){if(a=h([2e3,1]).day(i),n&&!this._fullWeekdaysParse[i]&&(this._fullWeekdaysParse[i]=new RegExp("^"+this.weekdays(a,"").replace(".",".?")+"$","i"),this._shortWeekdaysParse[i]=new RegExp("^"+this.weekdaysShort(a,"").replace(".",".?")+"$","i"),this._minWeekdaysParse[i]=new RegExp("^"+this.weekdaysMin(a,"").replace(".",".?")+"$","i")),this._weekdaysParse[i]||(r="^"+this.weekdays(a,"")+"|^"+this.weekdaysShort(a,"")+"|^"+this.weekdaysMin(a,""),this._weekdaysParse[i]=new RegExp(r.replace(".",""),"i")),n&&"dddd"===e&&this._fullWeekdaysParse[i].test(t))return i;if(n&&"ddd"===e&&this._shortWeekdaysParse[i].test(t))return i;if(n&&"dd"===e&&this._minWeekdaysParse[i].test(t))return i;if(!n&&this._weekdaysParse[i].test(t))return i}},ni.weekdaysRegex=function(t){return this._weekdaysParseExact?(d(this,"_weekdaysRegex")||ht.call(this),t?this._weekdaysStrictRegex:this._weekdaysRegex):(d(this,"_weekdaysRegex")||(this._weekdaysRegex=Sn),this._weekdaysStrictRegex&&t?this._weekdaysStrictRegex:this._weekdaysRegex)},ni.weekdaysShortRegex=function(t){return this._weekdaysParseExact?(d(this,"_weekdaysRegex")||ht.call(this),t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(d(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=Dn),this._weekdaysShortStrictRegex&&t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)},ni.weekdaysMinRegex=function(t){return this._weekdaysParseExact?(d(this,"_weekdaysRegex")||ht.call(this),t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(d(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=Cn),this._weekdaysMinStrictRegex&&t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)},ni.isPM=function(t){return"p"===(t+"").toLowerCase().charAt(0)},ni.meridiem=function(t,e,n){return t>11?n?"pm":"PM":n?"am":"AM"},bt("en",{dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(t){var e=t%10;return t+(1===_(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th")}}),n.lang=M("moment.lang is deprecated. Use moment.locale instead.",bt),n.langData=M("moment.langData is deprecated. Use moment.localeData instead.",_t);var ii=Math.abs,ai=me("ms"),ri=me("s"),oi=me("m"),si=me("h"),li=me("d"),ui=me("w"),di=me("M"),ci=me("y"),hi=pe("milliseconds"),fi=pe("seconds"),gi=pe("minutes"),mi=pe("hours"),pi=pe("days"),vi=pe("months"),yi=pe("years"),bi=Math.round,xi={ss:44,s:45,m:45,h:22,d:26,M:11},_i=Math.abs,ki=Vt.prototype;return ki.isValid=function(){return this._isValid},ki.abs=function(){var t=this._data;return this._milliseconds=ii(this._milliseconds),this._days=ii(this._days),this._months=ii(this._months),t.milliseconds=ii(t.milliseconds),t.seconds=ii(t.seconds),t.minutes=ii(t.minutes),t.hours=ii(t.hours),t.months=ii(t.months),t.years=ii(t.years),this},ki.add=function(t,e){return ce(this,t,e,1)},ki.subtract=function(t,e){return ce(this,t,e,-1)},ki.as=function(t){if(!this.isValid())return NaN;var e,n,i=this._milliseconds;if("month"===(t=I(t))||"year"===t)return e=this._days+i/864e5,n=this._months+fe(e),"month"===t?n:n/12;switch(e=this._days+Math.round(ge(this._months)),t){case"week":return e/7+i/6048e5;case"day":return e+i/864e5;case"hour":return 24*e+i/36e5;case"minute":return 1440*e+i/6e4;case"second":return 86400*e+i/1e3;case"millisecond":return Math.floor(864e5*e)+i;default:throw new Error("Unknown unit "+t)}},ki.asMilliseconds=ai,ki.asSeconds=ri,ki.asMinutes=oi,ki.asHours=si,ki.asDays=li,ki.asWeeks=ui,ki.asMonths=di,ki.asYears=ci,ki.valueOf=function(){return this.isValid()?this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*_(this._months/12):NaN},ki._bubble=function(){var t,e,n,i,a,r=this._milliseconds,o=this._days,s=this._months,l=this._data;return r>=0&&o>=0&&s>=0||r<=0&&o<=0&&s<=0||(r+=864e5*he(ge(s)+o),o=0,s=0),l.milliseconds=r%1e3,t=x(r/1e3),l.seconds=t%60,e=x(t/60),l.minutes=e%60,n=x(e/60),l.hours=n%24,o+=x(n/24),a=x(fe(o)),s+=a,o-=he(ge(a)),i=x(s/12),s%=12,l.days=o,l.months=s,l.years=i,this},ki.get=function(t){return t=I(t),this.isValid()?this[t+"s"]():NaN},ki.milliseconds=hi,ki.seconds=fi,ki.minutes=gi,ki.hours=mi,ki.days=pi,ki.weeks=function(){return x(this.days()/7)},ki.months=vi,ki.years=yi,ki.humanize=function(t){if(!this.isValid())return this.localeData().invalidDate();var e=this.localeData(),n=ye(this,!t,e);return t&&(n=e.pastFuture(+this,n)),e.postformat(n)},ki.toISOString=be,ki.toString=be,ki.toJSON=be,ki.locale=ne,ki.localeData=ie,ki.toIsoString=M("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",be),ki.lang=Xn,N("X",0,0,"unix"),N("x",0,0,"valueOf"),E("x",Ke),E("X",tn),G("X",function(t,e,n){n._d=new Date(1e3*parseFloat(t,10))}),G("x",function(t,e,n){n._d=new Date(_(t))}),n.version="2.18.1",function(t){xe=t}(Nt),n.fn=ei,n.min=function(){return zt("isBefore",[].slice.call(arguments,0))},n.max=function(){return zt("isAfter",[].slice.call(arguments,0))},n.now=function(){return Date.now?Date.now():+new Date},n.utc=h,n.unix=function(t){return Nt(1e3*t)},n.months=function(t,e){return ue(t,e,"months")},n.isDate=l,n.locale=bt,n.invalid=p,n.duration=Xt,n.isMoment=b,n.weekdays=function(t,e,n){return de(t,e,n,"weekdays")},n.parseZone=function(){return Nt.apply(null,arguments).parseZone()},n.localeData=_t,n.isDuration=Ht,n.monthsShort=function(t,e){return ue(t,e,"monthsShort")},n.weekdaysMin=function(t,e,n){return de(t,e,n,"weekdaysMin")},n.defineLocale=xt,n.updateLocale=function(t,e){if(null!=e){var n,i=An;null!=On[t]&&(i=On[t]._config),(n=new P(e=C(i,e))).parentLocale=On[t],On[t]=n,bt(t)}else null!=On[t]&&(null!=On[t].parentLocale?On[t]=On[t].parentLocale:null!=On[t]&&delete On[t]);return On[t]},n.locales=function(){return Pe(On)},n.weekdaysShort=function(t,e,n){return de(t,e,n,"weekdaysShort")},n.normalizeUnits=I,n.relativeTimeRounding=function(t){return void 0===t?bi:"function"==typeof t&&(bi=t,!0)},n.relativeTimeThreshold=function(t,e){return void 0!==xi[t]&&(void 0===e?xi[t]:(xi[t]=e,"s"===t&&(xi.ss=e-1),!0))},n.calendarFormat=function(t,e){var n=t.diff(e,"days",!0);return n<-6?"sameElse":n<-1?"lastWeek":n<0?"lastDay":n<1?"sameDay":n<2?"nextDay":n<7?"nextWeek":"sameElse"},n.prototype=ei,n})},{}],7:[function(t,e,n){var i=t(29)();i.helpers=t(45),t(27)(i),i.defaults=t(25),i.Element=t(26),i.elements=t(40),i.Interaction=t(28),i.platform=t(48),t(31)(i),t(22)(i),t(23)(i),t(24)(i),t(30)(i),t(33)(i),t(32)(i),t(35)(i),t(54)(i),t(52)(i),t(53)(i),t(55)(i),t(56)(i),t(57)(i),t(15)(i),t(16)(i),t(17)(i),t(18)(i),t(19)(i),t(20)(i),t(21)(i),t(8)(i),t(9)(i),t(10)(i),t(11)(i),t(12)(i),t(13)(i),t(14)(i);var a=[];a.push(t(49)(i),t(50)(i),t(51)(i)),i.plugins.register(a),i.platform.initialize(),e.exports=i,"undefined"!=typeof window&&(window.Chart=i),i.canvasHelpers=i.helpers.canvas},{10:10,11:11,12:12,13:13,14:14,15:15,16:16,17:17,18:18,19:19,20:20,21:21,22:22,23:23,24:24,25:25,26:26,27:27,28:28,29:29,30:30,31:31,32:32,33:33,35:35,40:40,45:45,48:48,49:49,50:50,51:51,52:52,53:53,54:54,55:55,56:56,57:57,8:8,9:9}],8:[function(t,e,n){"use strict";e.exports=function(t){t.Bar=function(e,n){return n.type="bar",new t(e,n)}}},{}],9:[function(t,e,n){"use strict";e.exports=function(t){t.Bubble=function(e,n){return n.type="bubble",new t(e,n)}}},{}],10:[function(t,e,n){"use strict";e.exports=function(t){t.Doughnut=function(e,n){return n.type="doughnut",new t(e,n)}}},{}],11:[function(t,e,n){"use strict";e.exports=function(t){t.Line=function(e,n){return n.type="line",new t(e,n)}}},{}],12:[function(t,e,n){"use strict";e.exports=function(t){t.PolarArea=function(e,n){return n.type="polarArea",new t(e,n)}}},{}],13:[function(t,e,n){"use strict";e.exports=function(t){t.Radar=function(e,n){return n.type="radar",new t(e,n)}}},{}],14:[function(t,e,n){"use strict";e.exports=function(t){t.Scatter=function(e,n){return n.type="scatter",new t(e,n)}}},{}],15:[function(t,e,n){"use strict";var i=t(25),a=t(40),r=t(45);i._set("bar",{hover:{mode:"label"},scales:{xAxes:[{type:"category",categoryPercentage:.8,barPercentage:.9,offset:!0,gridLines:{offsetGridLines:!0}}],yAxes:[{type:"linear"}]}}),i._set("horizontalBar",{hover:{mode:"index",axis:"y"},scales:{xAxes:[{type:"linear",position:"bottom"}],yAxes:[{position:"left",type:"category",categoryPercentage:.8,barPercentage:.9,offset:!0,gridLines:{offsetGridLines:!0}}]},elements:{rectangle:{borderSkipped:"left"}},tooltips:{callbacks:{title:function(t,e){var n="";return t.length>0&&(t[0].yLabel?n=t[0].yLabel:e.labels.length>0&&t[0].index<e.labels.length&&(n=e.labels[t[0].index])),n},label:function(t,e){return(e.datasets[t.datasetIndex].label||"")+": "+t.xLabel}},mode:"index",axis:"y"}}),e.exports=function(t){t.controllers.bar=t.DatasetController.extend({dataElementType:a.Rectangle,initialize:function(){var e,n=this;t.DatasetController.prototype.initialize.apply(n,arguments),(e=n.getMeta()).stack=n.getDataset().stack,e.bar=!0},update:function(t){var e,n,i=this,a=i.getMeta().data;for(i._ruler=i.getRuler(),e=0,n=a.length;e<n;++e)i.updateElement(a[e],e,t)},updateElement:function(t,e,n){var i=this,a=i.chart,o=i.getMeta(),s=i.getDataset(),l=t.custom||{},u=a.options.elements.rectangle;t._xScale=i.getScaleForId(o.xAxisID),t._yScale=i.getScaleForId(o.yAxisID),t._datasetIndex=i.index,t._index=e,t._model={datasetLabel:s.label,label:a.data.labels[e],borderSkipped:l.borderSkipped?l.borderSkipped:u.borderSkipped,backgroundColor:l.backgroundColor?l.backgroundColor:r.valueAtIndexOrDefault(s.backgroundColor,e,u.backgroundColor),borderColor:l.borderColor?l.borderColor:r.valueAtIndexOrDefault(s.borderColor,e,u.borderColor),borderWidth:l.borderWidth?l.borderWidth:r.valueAtIndexOrDefault(s.borderWidth,e,u.borderWidth)},i.updateElementGeometry(t,e,n),t.pivot()},updateElementGeometry:function(t,e,n){var i=this,a=t._model,r=i.getValueScale(),o=r.getBasePixel(),s=r.isHorizontal(),l=i._ruler||i.getRuler(),u=i.calculateBarValuePixels(i.index,e),d=i.calculateBarIndexPixels(i.index,e,l);a.horizontal=s,a.base=n?o:u.base,a.x=s?n?o:u.head:d.center,a.y=s?d.center:n?o:u.head,a.height=s?d.size:void 0,a.width=s?void 0:d.size},getValueScaleId:function(){return this.getMeta().yAxisID},getIndexScaleId:function(){return this.getMeta().xAxisID},getValueScale:function(){return this.getScaleForId(this.getValueScaleId())},getIndexScale:function(){return this.getScaleForId(this.getIndexScaleId())},getStackCount:function(t){var e,n,i=this,a=i.chart,r=i.getIndexScale().options.stacked,o=void 0===t?a.data.datasets.length:t+1,s=[];for(e=0;e<o;++e)(n=a.getDatasetMeta(e)).bar&&a.isDatasetVisible(e)&&(!1===r||!0===r&&-1===s.indexOf(n.stack)||void 0===r&&(void 0===n.stack||-1===s.indexOf(n.stack)))&&s.push(n.stack);return s.length},getStackIndex:function(t){return this.getStackCount(t)-1},getRuler:function(){var t,e,n=this,i=n.getIndexScale(),a=n.getStackCount(),r=n.index,o=[],s=i.isHorizontal(),l=s?i.left:i.top,u=l+(s?i.width:i.height);for(t=0,e=n.getMeta().data.length;t<e;++t)o.push(i.getPixelForValue(null,t,r));return{pixels:o,start:l,end:u,stackCount:a,scale:i}},calculateBarValuePixels:function(t,e){var n,i,a,r,o,s,l=this,u=l.chart,d=l.getMeta(),c=l.getValueScale(),h=u.data.datasets,f=c.getRightValue(h[t].data[e]),g=c.options.stacked,m=d.stack,p=0;if(g||void 0===g&&void 0!==m)for(n=0;n<t;++n)(i=u.getDatasetMeta(n)).bar&&i.stack===m&&i.controller.getValueScaleId()===c.id&&u.isDatasetVisible(n)&&(a=c.getRightValue(h[n].data[e]),(f<0&&a<0||f>=0&&a>0)&&(p+=a));return r=c.getPixelForValue(p),o=c.getPixelForValue(p+f),s=(o-r)/2,{size:s,base:r,head:o,center:o+s/2}},calculateBarIndexPixels:function(t,e,n){var i,a,o,s,l,u,d=this,c=n.scale.options,h=d.getStackIndex(t),f=n.pixels,g=f[e],m=f.length,p=n.start,v=n.end;return 1===m?(i=g>p?g-p:v-g,a=g<v?v-g:g-p):(e>0&&(i=(g-f[e-1])/2,e===m-1&&(a=i)),e<m-1&&(a=(f[e+1]-g)/2,0===e&&(i=a))),o=i*c.categoryPercentage,s=a*c.categoryPercentage,l=(o+s)/n.stackCount,u=l*c.barPercentage,u=Math.min(r.valueOrDefault(c.barThickness,u),r.valueOrDefault(c.maxBarThickness,1/0)),g-=o,g+=l*h,g+=(l-u)/2,{size:u,base:g,head:g+u,center:g+u/2}},draw:function(){var t=this,e=t.chart,n=t.getValueScale(),i=t.getMeta().data,a=t.getDataset(),o=i.length,s=0;for(r.canvas.clipArea(e.ctx,e.chartArea);s<o;++s)isNaN(n.getRightValue(a.data[s]))||i[s].draw();r.canvas.unclipArea(e.ctx)},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t._index,i=t.custom||{},a=t._model;a.backgroundColor=i.hoverBackgroundColor?i.hoverBackgroundColor:r.valueAtIndexOrDefault(e.hoverBackgroundColor,n,r.getHoverColor(a.backgroundColor)),a.borderColor=i.hoverBorderColor?i.hoverBorderColor:r.valueAtIndexOrDefault(e.hoverBorderColor,n,r.getHoverColor(a.borderColor)),a.borderWidth=i.hoverBorderWidth?i.hoverBorderWidth:r.valueAtIndexOrDefault(e.hoverBorderWidth,n,a.borderWidth)},removeHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t._index,i=t.custom||{},a=t._model,o=this.chart.options.elements.rectangle;a.backgroundColor=i.backgroundColor?i.backgroundColor:r.valueAtIndexOrDefault(e.backgroundColor,n,o.backgroundColor),a.borderColor=i.borderColor?i.borderColor:r.valueAtIndexOrDefault(e.borderColor,n,o.borderColor),a.borderWidth=i.borderWidth?i.borderWidth:r.valueAtIndexOrDefault(e.borderWidth,n,o.borderWidth)}}),t.controllers.horizontalBar=t.controllers.bar.extend({getValueScaleId:function(){return this.getMeta().xAxisID},getIndexScaleId:function(){return this.getMeta().yAxisID}})}},{25:25,40:40,45:45}],16:[function(t,e,n){"use strict";var i=t(25),a=t(40),r=t(45);i._set("bubble",{hover:{mode:"single"},scales:{xAxes:[{type:"linear",position:"bottom",id:"x-axis-0"}],yAxes:[{type:"linear",position:"left",id:"y-axis-0"}]},tooltips:{callbacks:{title:function(){return""},label:function(t,e){var n=e.datasets[t.datasetIndex].label||"",i=e.datasets[t.datasetIndex].data[t.index];return n+": ("+t.xLabel+", "+t.yLabel+", "+i.r+")"}}}}),e.exports=function(t){t.controllers.bubble=t.DatasetController.extend({dataElementType:a.Point,update:function(t){var e=this,n=e.getMeta().data;r.each(n,function(n,i){e.updateElement(n,i,t)})},updateElement:function(t,e,n){var i=this,a=i.getMeta(),r=t.custom||{},o=i.getScaleForId(a.xAxisID),s=i.getScaleForId(a.yAxisID),l=i._resolveElementOptions(t,e),u=i.getDataset().data[e],d=i.index,c=n?o.getPixelForDecimal(.5):o.getPixelForValue("object"==typeof u?u:NaN,e,d),h=n?s.getBasePixel():s.getPixelForValue(u,e,d);t._xScale=o,t._yScale=s,t._options=l,t._datasetIndex=d,t._index=e,t._model={backgroundColor:l.backgroundColor,borderColor:l.borderColor,borderWidth:l.borderWidth,hitRadius:l.hitRadius,pointStyle:l.pointStyle,radius:n?0:l.radius,skip:r.skip||isNaN(c)||isNaN(h),x:c,y:h},t.pivot()},setHoverStyle:function(t){var e=t._model,n=t._options;e.backgroundColor=r.valueOrDefault(n.hoverBackgroundColor,r.getHoverColor(n.backgroundColor)),e.borderColor=r.valueOrDefault(n.hoverBorderColor,r.getHoverColor(n.borderColor)),e.borderWidth=r.valueOrDefault(n.hoverBorderWidth,n.borderWidth),e.radius=n.radius+n.hoverRadius},removeHoverStyle:function(t){var e=t._model,n=t._options;e.backgroundColor=n.backgroundColor,e.borderColor=n.borderColor,e.borderWidth=n.borderWidth,e.radius=n.radius},_resolveElementOptions:function(t,e){var n,i,a,o=this,s=o.chart,l=s.data.datasets[o.index],u=t.custom||{},d=s.options.elements.point,c=r.options.resolve,h=l.data[e],f={},g={chart:s,dataIndex:e,dataset:l,datasetIndex:o.index},m=["backgroundColor","borderColor","borderWidth","hoverBackgroundColor","hoverBorderColor","hoverBorderWidth","hoverRadius","hitRadius","pointStyle"];for(n=0,i=m.length;n<i;++n)f[a=m[n]]=c([u[a],l[a],d[a]],g,e);return f.radius=c([u.radius,h?h.r:void 0,l.radius,d.radius],g,e),f}})}},{25:25,40:40,45:45}],17:[function(t,e,n){"use strict";var i=t(25),a=t(40),r=t(45);i._set("doughnut",{animation:{animateRotate:!0,animateScale:!1},hover:{mode:"single"},legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');var n=t.data,i=n.datasets,a=n.labels;if(i.length)for(var r=0;r<i[0].data.length;++r)e.push('<li><span style="background-color:'+i[0].backgroundColor[r]+'"></span>'),a[r]&&e.push(a[r]),e.push("</li>");return e.push("</ul>"),e.join("")},legend:{labels:{generateLabels:function(t){var e=t.data;return e.labels.length&&e.datasets.length?e.labels.map(function(n,i){var a=t.getDatasetMeta(0),o=e.datasets[0],s=a.data[i],l=s&&s.custom||{},u=r.valueAtIndexOrDefault,d=t.options.elements.arc;return{text:n,fillStyle:l.backgroundColor?l.backgroundColor:u(o.backgroundColor,i,d.backgroundColor),strokeStyle:l.borderColor?l.borderColor:u(o.borderColor,i,d.borderColor),lineWidth:l.borderWidth?l.borderWidth:u(o.borderWidth,i,d.borderWidth),hidden:isNaN(o.data[i])||a.data[i].hidden,index:i}}):[]}},onClick:function(t,e){var n,i,a,r=e.index,o=this.chart;for(n=0,i=(o.data.datasets||[]).length;n<i;++n)(a=o.getDatasetMeta(n)).data[r]&&(a.data[r].hidden=!a.data[r].hidden);o.update()}},cutoutPercentage:50,rotation:-.5*Math.PI,circumference:2*Math.PI,tooltips:{callbacks:{title:function(){return""},label:function(t,e){var n=e.labels[t.index],i=": "+e.datasets[t.datasetIndex].data[t.index];return r.isArray(n)?(n=n.slice())[0]+=i:n+=i,n}}}}),i._set("pie",r.clone(i.doughnut)),i._set("pie",{cutoutPercentage:0}),e.exports=function(t){t.controllers.doughnut=t.controllers.pie=t.DatasetController.extend({dataElementType:a.Arc,linkScales:r.noop,getRingIndex:function(t){for(var e=0,n=0;n<t;++n)this.chart.isDatasetVisible(n)&&++e;return e},update:function(t){var e=this,n=e.chart,i=n.chartArea,a=n.options,o=a.elements.arc,s=i.right-i.left-o.borderWidth,l=i.bottom-i.top-o.borderWidth,u=Math.min(s,l),d={x:0,y:0},c=e.getMeta(),h=a.cutoutPercentage,f=a.circumference;if(f<2*Math.PI){var g=a.rotation%(2*Math.PI),m=(g+=2*Math.PI*(g>=Math.PI?-1:g<-Math.PI?1:0))+f,p={x:Math.cos(g),y:Math.sin(g)},v={x:Math.cos(m),y:Math.sin(m)},y=g<=0&&m>=0||g<=2*Math.PI&&2*Math.PI<=m,b=g<=.5*Math.PI&&.5*Math.PI<=m||g<=2.5*Math.PI&&2.5*Math.PI<=m,x=g<=-Math.PI&&-Math.PI<=m||g<=Math.PI&&Math.PI<=m,_=g<=.5*-Math.PI&&.5*-Math.PI<=m||g<=1.5*Math.PI&&1.5*Math.PI<=m,k=h/100,w={x:x?-1:Math.min(p.x*(p.x<0?1:k),v.x*(v.x<0?1:k)),y:_?-1:Math.min(p.y*(p.y<0?1:k),v.y*(v.y<0?1:k))},M={x:y?1:Math.max(p.x*(p.x>0?1:k),v.x*(v.x>0?1:k)),y:b?1:Math.max(p.y*(p.y>0?1:k),v.y*(v.y>0?1:k))},S={width:.5*(M.x-w.x),height:.5*(M.y-w.y)};u=Math.min(s/S.width,l/S.height),d={x:-.5*(M.x+w.x),y:-.5*(M.y+w.y)}}n.borderWidth=e.getMaxBorderWidth(c.data),n.outerRadius=Math.max((u-n.borderWidth)/2,0),n.innerRadius=Math.max(h?n.outerRadius/100*h:0,0),n.radiusLength=(n.outerRadius-n.innerRadius)/n.getVisibleDatasetCount(),n.offsetX=d.x*n.outerRadius,n.offsetY=d.y*n.outerRadius,c.total=e.calculateTotal(),e.outerRadius=n.outerRadius-n.radiusLength*e.getRingIndex(e.index),e.innerRadius=Math.max(e.outerRadius-n.radiusLength,0),r.each(c.data,function(n,i){e.updateElement(n,i,t)})},updateElement:function(t,e,n){var i=this,a=i.chart,o=a.chartArea,s=a.options,l=s.animation,u=(o.left+o.right)/2,d=(o.top+o.bottom)/2,c=s.rotation,h=s.rotation,f=i.getDataset(),g=n&&l.animateRotate?0:t.hidden?0:i.calculateCircumference(f.data[e])*(s.circumference/(2*Math.PI)),m=n&&l.animateScale?0:i.innerRadius,p=n&&l.animateScale?0:i.outerRadius,v=r.valueAtIndexOrDefault;r.extend(t,{_datasetIndex:i.index,_index:e,_model:{x:u+a.offsetX,y:d+a.offsetY,startAngle:c,endAngle:h,circumference:g,outerRadius:p,innerRadius:m,label:v(f.label,e,a.data.labels[e])}});var y=t._model;this.removeHoverStyle(t),n&&l.animateRotate||(y.startAngle=0===e?s.rotation:i.getMeta().data[e-1]._model.endAngle,y.endAngle=y.startAngle+y.circumference),t.pivot()},removeHoverStyle:function(e){t.DatasetController.prototype.removeHoverStyle.call(this,e,this.chart.options.elements.arc)},calculateTotal:function(){var t,e=this.getDataset(),n=this.getMeta(),i=0;return r.each(n.data,function(n,a){t=e.data[a],isNaN(t)||n.hidden||(i+=Math.abs(t))}),i},calculateCircumference:function(t){var e=this.getMeta().total;return e>0&&!isNaN(t)?2*Math.PI*(t/e):0},getMaxBorderWidth:function(t){for(var e,n,i=0,a=this.index,r=t.length,o=0;o<r;o++)e=t[o]._model?t[o]._model.borderWidth:0,i=(n=t[o]._chart?t[o]._chart.config.data.datasets[a].hoverBorderWidth:0)>(i=e>i?e:i)?n:i;return i}})}},{25:25,40:40,45:45}],18:[function(t,e,n){"use strict";var i=t(25),a=t(40),r=t(45);i._set("line",{showLines:!0,spanGaps:!1,hover:{mode:"label"},scales:{xAxes:[{type:"category",id:"x-axis-0"}],yAxes:[{type:"linear",id:"y-axis-0"}]}}),e.exports=function(t){function e(t,e){return r.valueOrDefault(t.showLine,e.showLines)}t.controllers.line=t.DatasetController.extend({datasetElementType:a.Line,dataElementType:a.Point,update:function(t){var n,i,a,o=this,s=o.getMeta(),l=s.dataset,u=s.data||[],d=o.chart.options,c=d.elements.line,h=o.getScaleForId(s.yAxisID),f=o.getDataset(),g=e(f,d);for(g&&(a=l.custom||{},void 0!==f.tension&&void 0===f.lineTension&&(f.lineTension=f.tension),l._scale=h,l._datasetIndex=o.index,l._children=u,l._model={spanGaps:f.spanGaps?f.spanGaps:d.spanGaps,tension:a.tension?a.tension:r.valueOrDefault(f.lineTension,c.tension),backgroundColor:a.backgroundColor?a.backgroundColor:f.backgroundColor||c.backgroundColor,borderWidth:a.borderWidth?a.borderWidth:f.borderWidth||c.borderWidth,borderColor:a.borderColor?a.borderColor:f.borderColor||c.borderColor,borderCapStyle:a.borderCapStyle?a.borderCapStyle:f.borderCapStyle||c.borderCapStyle,borderDash:a.borderDash?a.borderDash:f.borderDash||c.borderDash,borderDashOffset:a.borderDashOffset?a.borderDashOffset:f.borderDashOffset||c.borderDashOffset,borderJoinStyle:a.borderJoinStyle?a.borderJoinStyle:f.borderJoinStyle||c.borderJoinStyle,fill:a.fill?a.fill:void 0!==f.fill?f.fill:c.fill,steppedLine:a.steppedLine?a.steppedLine:r.valueOrDefault(f.steppedLine,c.stepped),cubicInterpolationMode:a.cubicInterpolationMode?a.cubicInterpolationMode:r.valueOrDefault(f.cubicInterpolationMode,c.cubicInterpolationMode)},l.pivot()),n=0,i=u.length;n<i;++n)o.updateElement(u[n],n,t);for(g&&0!==l._model.tension&&o.updateBezierControlPoints(),n=0,i=u.length;n<i;++n)u[n].pivot()},getPointBackgroundColor:function(t,e){var n=this.chart.options.elements.point.backgroundColor,i=this.getDataset(),a=t.custom||{};return a.backgroundColor?n=a.backgroundColor:i.pointBackgroundColor?n=r.valueAtIndexOrDefault(i.pointBackgroundColor,e,n):i.backgroundColor&&(n=i.backgroundColor),n},getPointBorderColor:function(t,e){var n=this.chart.options.elements.point.borderColor,i=this.getDataset(),a=t.custom||{};return a.borderColor?n=a.borderColor:i.pointBorderColor?n=r.valueAtIndexOrDefault(i.pointBorderColor,e,n):i.borderColor&&(n=i.borderColor),n},getPointBorderWidth:function(t,e){var n=this.chart.options.elements.point.borderWidth,i=this.getDataset(),a=t.custom||{};return isNaN(a.borderWidth)?!isNaN(i.pointBorderWidth)||r.isArray(i.pointBorderWidth)?n=r.valueAtIndexOrDefault(i.pointBorderWidth,e,n):isNaN(i.borderWidth)||(n=i.borderWidth):n=a.borderWidth,n},updateElement:function(t,e,n){var i,a,o=this,s=o.getMeta(),l=t.custom||{},u=o.getDataset(),d=o.index,c=u.data[e],h=o.getScaleForId(s.yAxisID),f=o.getScaleForId(s.xAxisID),g=o.chart.options.elements.point;void 0!==u.radius&&void 0===u.pointRadius&&(u.pointRadius=u.radius),void 0!==u.hitRadius&&void 0===u.pointHitRadius&&(u.pointHitRadius=u.hitRadius),i=f.getPixelForValue("object"==typeof c?c:NaN,e,d),a=n?h.getBasePixel():o.calculatePointY(c,e,d),t._xScale=f,t._yScale=h,t._datasetIndex=d,t._index=e,t._model={x:i,y:a,skip:l.skip||isNaN(i)||isNaN(a),radius:l.radius||r.valueAtIndexOrDefault(u.pointRadius,e,g.radius),pointStyle:l.pointStyle||r.valueAtIndexOrDefault(u.pointStyle,e,g.pointStyle),backgroundColor:o.getPointBackgroundColor(t,e),borderColor:o.getPointBorderColor(t,e),borderWidth:o.getPointBorderWidth(t,e),tension:s.dataset._model?s.dataset._model.tension:0,steppedLine:!!s.dataset._model&&s.dataset._model.steppedLine,hitRadius:l.hitRadius||r.valueAtIndexOrDefault(u.pointHitRadius,e,g.hitRadius)}},calculatePointY:function(t,e,n){var i,a,r,o=this,s=o.chart,l=o.getMeta(),u=o.getScaleForId(l.yAxisID),d=0,c=0;if(u.options.stacked){for(i=0;i<n;i++)if(a=s.data.datasets[i],"line"===(r=s.getDatasetMeta(i)).type&&r.yAxisID===u.id&&s.isDatasetVisible(i)){var h=Number(u.getRightValue(a.data[e]));h<0?c+=h||0:d+=h||0}var f=Number(u.getRightValue(t));return f<0?u.getPixelForValue(c+f):u.getPixelForValue(d+f)}return u.getPixelForValue(t)},updateBezierControlPoints:function(){function t(t,e,n){return Math.max(Math.min(t,n),e)}var e,n,i,a,o=this,s=o.getMeta(),l=o.chart.chartArea,u=s.data||[];if(s.dataset._model.spanGaps&&(u=u.filter(function(t){return!t._model.skip})),"monotone"===s.dataset._model.cubicInterpolationMode)r.splineCurveMonotone(u);else for(e=0,n=u.length;e<n;++e)i=u[e]._model,a=r.splineCurve(r.previousItem(u,e)._model,i,r.nextItem(u,e)._model,s.dataset._model.tension),i.controlPointPreviousX=a.previous.x,i.controlPointPreviousY=a.previous.y,i.controlPointNextX=a.next.x,i.controlPointNextY=a.next.y;if(o.chart.options.elements.line.capBezierPoints)for(e=0,n=u.length;e<n;++e)(i=u[e]._model).controlPointPreviousX=t(i.controlPointPreviousX,l.left,l.right),i.controlPointPreviousY=t(i.controlPointPreviousY,l.top,l.bottom),i.controlPointNextX=t(i.controlPointNextX,l.left,l.right),i.controlPointNextY=t(i.controlPointNextY,l.top,l.bottom)},draw:function(){var t=this,n=t.chart,i=t.getMeta(),a=i.data||[],o=n.chartArea,s=a.length,l=0;for(r.canvas.clipArea(n.ctx,o),e(t.getDataset(),n.options)&&i.dataset.draw(),r.canvas.unclipArea(n.ctx);l<s;++l)a[l].draw(o)},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t._index,i=t.custom||{},a=t._model;a.radius=i.hoverRadius||r.valueAtIndexOrDefault(e.pointHoverRadius,n,this.chart.options.elements.point.hoverRadius),a.backgroundColor=i.hoverBackgroundColor||r.valueAtIndexOrDefault(e.pointHoverBackgroundColor,n,r.getHoverColor(a.backgroundColor)),a.borderColor=i.hoverBorderColor||r.valueAtIndexOrDefault(e.pointHoverBorderColor,n,r.getHoverColor(a.borderColor)),a.borderWidth=i.hoverBorderWidth||r.valueAtIndexOrDefault(e.pointHoverBorderWidth,n,a.borderWidth)},removeHoverStyle:function(t){var e=this,n=e.chart.data.datasets[t._datasetIndex],i=t._index,a=t.custom||{},o=t._model;void 0!==n.radius&&void 0===n.pointRadius&&(n.pointRadius=n.radius),o.radius=a.radius||r.valueAtIndexOrDefault(n.pointRadius,i,e.chart.options.elements.point.radius),o.backgroundColor=e.getPointBackgroundColor(t,i),o.borderColor=e.getPointBorderColor(t,i),o.borderWidth=e.getPointBorderWidth(t,i)}})}},{25:25,40:40,45:45}],19:[function(t,e,n){"use strict";var i=t(25),a=t(40),r=t(45);i._set("polarArea",{scale:{type:"radialLinear",angleLines:{display:!1},gridLines:{circular:!0},pointLabels:{display:!1},ticks:{beginAtZero:!0}},animation:{animateRotate:!0,animateScale:!0},startAngle:-.5*Math.PI,legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');var n=t.data,i=n.datasets,a=n.labels;if(i.length)for(var r=0;r<i[0].data.length;++r)e.push('<li><span style="background-color:'+i[0].backgroundColor[r]+'"></span>'),a[r]&&e.push(a[r]),e.push("</li>");return e.push("</ul>"),e.join("")},legend:{labels:{generateLabels:function(t){var e=t.data;return e.labels.length&&e.datasets.length?e.labels.map(function(n,i){var a=t.getDatasetMeta(0),o=e.datasets[0],s=a.data[i].custom||{},l=r.valueAtIndexOrDefault,u=t.options.elements.arc;return{text:n,fillStyle:s.backgroundColor?s.backgroundColor:l(o.backgroundColor,i,u.backgroundColor),strokeStyle:s.borderColor?s.borderColor:l(o.borderColor,i,u.borderColor),lineWidth:s.borderWidth?s.borderWidth:l(o.borderWidth,i,u.borderWidth),hidden:isNaN(o.data[i])||a.data[i].hidden,index:i}}):[]}},onClick:function(t,e){var n,i,a,r=e.index,o=this.chart;for(n=0,i=(o.data.datasets||[]).length;n<i;++n)(a=o.getDatasetMeta(n)).data[r].hidden=!a.data[r].hidden;o.update()}},tooltips:{callbacks:{title:function(){return""},label:function(t,e){return e.labels[t.index]+": "+t.yLabel}}}}),e.exports=function(t){t.controllers.polarArea=t.DatasetController.extend({dataElementType:a.Arc,linkScales:r.noop,update:function(t){var e=this,n=e.chart,i=n.chartArea,a=e.getMeta(),o=n.options,s=o.elements.arc,l=Math.min(i.right-i.left,i.bottom-i.top);n.outerRadius=Math.max((l-s.borderWidth/2)/2,0),n.innerRadius=Math.max(o.cutoutPercentage?n.outerRadius/100*o.cutoutPercentage:1,0),n.radiusLength=(n.outerRadius-n.innerRadius)/n.getVisibleDatasetCount(),e.outerRadius=n.outerRadius-n.radiusLength*e.index,e.innerRadius=e.outerRadius-n.radiusLength,a.count=e.countVisibleElements(),r.each(a.data,function(n,i){e.updateElement(n,i,t)})},updateElement:function(t,e,n){for(var i=this,a=i.chart,o=i.getDataset(),s=a.options,l=s.animation,u=a.scale,d=a.data.labels,c=i.calculateCircumference(o.data[e]),h=u.xCenter,f=u.yCenter,g=0,m=i.getMeta(),p=0;p<e;++p)isNaN(o.data[p])||m.data[p].hidden||++g;var v=s.startAngle,y=t.hidden?0:u.getDistanceFromCenterForValue(o.data[e]),b=v+c*g,x=b+(t.hidden?0:c),_=l.animateScale?0:u.getDistanceFromCenterForValue(o.data[e]);r.extend(t,{_datasetIndex:i.index,_index:e,_scale:u,_model:{x:h,y:f,innerRadius:0,outerRadius:n?_:y,startAngle:n&&l.animateRotate?v:b,endAngle:n&&l.animateRotate?v:x,label:r.valueAtIndexOrDefault(d,e,d[e])}}),i.removeHoverStyle(t),t.pivot()},removeHoverStyle:function(e){t.DatasetController.prototype.removeHoverStyle.call(this,e,this.chart.options.elements.arc)},countVisibleElements:function(){var t=this.getDataset(),e=this.getMeta(),n=0;return r.each(e.data,function(e,i){isNaN(t.data[i])||e.hidden||n++}),n},calculateCircumference:function(t){var e=this.getMeta().count;return e>0&&!isNaN(t)?2*Math.PI/e:0}})}},{25:25,40:40,45:45}],20:[function(t,e,n){"use strict";var i=t(25),a=t(40),r=t(45);i._set("radar",{scale:{type:"radialLinear"},elements:{line:{tension:0}}}),e.exports=function(t){t.controllers.radar=t.DatasetController.extend({datasetElementType:a.Line,dataElementType:a.Point,linkScales:r.noop,update:function(t){var e=this,n=e.getMeta(),i=n.dataset,a=n.data,o=i.custom||{},s=e.getDataset(),l=e.chart.options.elements.line,u=e.chart.scale;void 0!==s.tension&&void 0===s.lineTension&&(s.lineTension=s.tension),r.extend(n.dataset,{_datasetIndex:e.index,_scale:u,_children:a,_loop:!0,_model:{tension:o.tension?o.tension:r.valueOrDefault(s.lineTension,l.tension),backgroundColor:o.backgroundColor?o.backgroundColor:s.backgroundColor||l.backgroundColor,borderWidth:o.borderWidth?o.borderWidth:s.borderWidth||l.borderWidth,borderColor:o.borderColor?o.borderColor:s.borderColor||l.borderColor,fill:o.fill?o.fill:void 0!==s.fill?s.fill:l.fill,borderCapStyle:o.borderCapStyle?o.borderCapStyle:s.borderCapStyle||l.borderCapStyle,borderDash:o.borderDash?o.borderDash:s.borderDash||l.borderDash,borderDashOffset:o.borderDashOffset?o.borderDashOffset:s.borderDashOffset||l.borderDashOffset,borderJoinStyle:o.borderJoinStyle?o.borderJoinStyle:s.borderJoinStyle||l.borderJoinStyle}}),n.dataset.pivot(),r.each(a,function(n,i){e.updateElement(n,i,t)},e),e.updateBezierControlPoints()},updateElement:function(t,e,n){var i=this,a=t.custom||{},o=i.getDataset(),s=i.chart.scale,l=i.chart.options.elements.point,u=s.getPointPositionForValue(e,o.data[e]);void 0!==o.radius&&void 0===o.pointRadius&&(o.pointRadius=o.radius),void 0!==o.hitRadius&&void 0===o.pointHitRadius&&(o.pointHitRadius=o.hitRadius),r.extend(t,{_datasetIndex:i.index,_index:e,_scale:s,_model:{x:n?s.xCenter:u.x,y:n?s.yCenter:u.y,tension:a.tension?a.tension:r.valueOrDefault(o.lineTension,i.chart.options.elements.line.tension),radius:a.radius?a.radius:r.valueAtIndexOrDefault(o.pointRadius,e,l.radius),backgroundColor:a.backgroundColor?a.backgroundColor:r.valueAtIndexOrDefault(o.pointBackgroundColor,e,l.backgroundColor),borderColor:a.borderColor?a.borderColor:r.valueAtIndexOrDefault(o.pointBorderColor,e,l.borderColor),borderWidth:a.borderWidth?a.borderWidth:r.valueAtIndexOrDefault(o.pointBorderWidth,e,l.borderWidth),pointStyle:a.pointStyle?a.pointStyle:r.valueAtIndexOrDefault(o.pointStyle,e,l.pointStyle),hitRadius:a.hitRadius?a.hitRadius:r.valueAtIndexOrDefault(o.pointHitRadius,e,l.hitRadius)}}),t._model.skip=a.skip?a.skip:isNaN(t._model.x)||isNaN(t._model.y)},updateBezierControlPoints:function(){var t=this.chart.chartArea,e=this.getMeta();r.each(e.data,function(n,i){var a=n._model,o=r.splineCurve(r.previousItem(e.data,i,!0)._model,a,r.nextItem(e.data,i,!0)._model,a.tension);a.controlPointPreviousX=Math.max(Math.min(o.previous.x,t.right),t.left),a.controlPointPreviousY=Math.max(Math.min(o.previous.y,t.bottom),t.top),a.controlPointNextX=Math.max(Math.min(o.next.x,t.right),t.left),a.controlPointNextY=Math.max(Math.min(o.next.y,t.bottom),t.top),n.pivot()})},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t.custom||{},i=t._index,a=t._model;a.radius=n.hoverRadius?n.hoverRadius:r.valueAtIndexOrDefault(e.pointHoverRadius,i,this.chart.options.elements.point.hoverRadius),a.backgroundColor=n.hoverBackgroundColor?n.hoverBackgroundColor:r.valueAtIndexOrDefault(e.pointHoverBackgroundColor,i,r.getHoverColor(a.backgroundColor)),a.borderColor=n.hoverBorderColor?n.hoverBorderColor:r.valueAtIndexOrDefault(e.pointHoverBorderColor,i,r.getHoverColor(a.borderColor)),a.borderWidth=n.hoverBorderWidth?n.hoverBorderWidth:r.valueAtIndexOrDefault(e.pointHoverBorderWidth,i,a.borderWidth)},removeHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t.custom||{},i=t._index,a=t._model,o=this.chart.options.elements.point;a.radius=n.radius?n.radius:r.valueAtIndexOrDefault(e.pointRadius,i,o.radius),a.backgroundColor=n.backgroundColor?n.backgroundColor:r.valueAtIndexOrDefault(e.pointBackgroundColor,i,o.backgroundColor),a.borderColor=n.borderColor?n.borderColor:r.valueAtIndexOrDefault(e.pointBorderColor,i,o.borderColor),a.borderWidth=n.borderWidth?n.borderWidth:r.valueAtIndexOrDefault(e.pointBorderWidth,i,o.borderWidth)}})}},{25:25,40:40,45:45}],21:[function(t,e,n){"use strict";t(25)._set("scatter",{hover:{mode:"single"},scales:{xAxes:[{id:"x-axis-1",type:"linear",position:"bottom"}],yAxes:[{id:"y-axis-1",type:"linear",position:"left"}]},showLines:!1,tooltips:{callbacks:{title:function(){return""},label:function(t){return"("+t.xLabel+", "+t.yLabel+")"}}}}),e.exports=function(t){t.controllers.scatter=t.controllers.line}},{25:25}],22:[function(t,e,n){"use strict";var i=t(25),a=t(26),r=t(45);i._set("global",{animation:{duration:1e3,easing:"easeOutQuart",onProgress:r.noop,onComplete:r.noop}}),e.exports=function(t){t.Animation=a.extend({chart:null,currentStep:0,numSteps:60,easing:"",render:null,onAnimationProgress:null,onAnimationComplete:null}),t.animationService={frameDuration:17,animations:[],dropFrames:0,request:null,addAnimation:function(t,e,n,i){var a,r,o=this.animations;for(e.chart=t,i||(t.animating=!0),a=0,r=o.length;a<r;++a)if(o[a].chart===t)return void(o[a]=e);o.push(e),1===o.length&&this.requestAnimationFrame()},cancelAnimation:function(t){var e=r.findIndex(this.animations,function(e){return e.chart===t});-1!==e&&(this.animations.splice(e,1),t.animating=!1)},requestAnimationFrame:function(){var t=this;null===t.request&&(t.request=r.requestAnimFrame.call(window,function(){t.request=null,t.startDigest()}))},startDigest:function(){var t=this,e=Date.now(),n=0;t.dropFrames>1&&(n=Math.floor(t.dropFrames),t.dropFrames=t.dropFrames%1),t.advance(1+n);var i=Date.now();t.dropFrames+=(i-e)/t.frameDuration,t.animations.length>0&&t.requestAnimationFrame()},advance:function(t){for(var e,n,i=this.animations,a=0;a<i.length;)n=(e=i[a]).chart,e.currentStep=(e.currentStep||0)+t,e.currentStep=Math.min(e.currentStep,e.numSteps),r.callback(e.render,[n,e],n),r.callback(e.onAnimationProgress,[e],n),e.currentStep>=e.numSteps?(r.callback(e.onAnimationComplete,[e],n),n.animating=!1,i.splice(a,1)):++a}},Object.defineProperty(t.Animation.prototype,"animationObject",{get:function(){return this}}),Object.defineProperty(t.Animation.prototype,"chartInstance",{get:function(){return this.chart},set:function(t){this.chart=t}})}},{25:25,26:26,45:45}],23:[function(t,e,n){"use strict";var i=t(25),a=t(45),r=t(28),o=t(48);e.exports=function(t){function e(t){var e=(t=t||{}).data=t.data||{};return e.datasets=e.datasets||[],e.labels=e.labels||[],t.options=a.configMerge(i.global,i[t.type],t.options||{}),t}function n(t){var e=t.options;e.scale?t.scale.options=e.scale:e.scales&&e.scales.xAxes.concat(e.scales.yAxes).forEach(function(e){t.scales[e.id].options=e}),t.tooltip._options=e.tooltips}function s(t){return"top"===t||"bottom"===t}var l=t.plugins;t.types={},t.instances={},t.controllers={},a.extend(t.prototype,{construct:function(n,i){var r=this;i=e(i);var s=o.acquireContext(n,i),l=s&&s.canvas,u=l&&l.height,d=l&&l.width;r.id=a.uid(),r.ctx=s,r.canvas=l,r.config=i,r.width=d,r.height=u,r.aspectRatio=u?d/u:null,r.options=i.options,r._bufferedRender=!1,r.chart=r,r.controller=r,t.instances[r.id]=r,Object.defineProperty(r,"data",{get:function(){return r.config.data},set:function(t){r.config.data=t}}),s&&l?(r.initialize(),r.update()):console.error("Failed to create chart: can't acquire context from the given item")},initialize:function(){var t=this;return l.notify(t,"beforeInit"),a.retinaScale(t,t.options.devicePixelRatio),t.bindEvents(),t.options.responsive&&t.resize(!0),t.ensureScalesHaveIDs(),t.buildScales(),t.initToolTip(),l.notify(t,"afterInit"),t},clear:function(){return a.canvas.clear(this),this},stop:function(){return t.animationService.cancelAnimation(this),this},resize:function(t){var e=this,n=e.options,i=e.canvas,r=n.maintainAspectRatio&&e.aspectRatio||null,o=Math.max(0,Math.floor(a.getMaximumWidth(i))),s=Math.max(0,Math.floor(r?o/r:a.getMaximumHeight(i)));if((e.width!==o||e.height!==s)&&(i.width=e.width=o,i.height=e.height=s,i.style.width=o+"px",i.style.height=s+"px",a.retinaScale(e,n.devicePixelRatio),!t)){var u={width:o,height:s};l.notify(e,"resize",[u]),e.options.onResize&&e.options.onResize(e,u),e.stop(),e.update(e.options.responsiveAnimationDuration)}},ensureScalesHaveIDs:function(){var t=this.options,e=t.scales||{},n=t.scale;a.each(e.xAxes,function(t,e){t.id=t.id||"x-axis-"+e}),a.each(e.yAxes,function(t,e){t.id=t.id||"y-axis-"+e}),n&&(n.id=n.id||"scale")},buildScales:function(){var e=this,n=e.options,i=e.scales={},r=[];n.scales&&(r=r.concat((n.scales.xAxes||[]).map(function(t){return{options:t,dtype:"category",dposition:"bottom"}}),(n.scales.yAxes||[]).map(function(t){return{options:t,dtype:"linear",dposition:"left"}}))),n.scale&&r.push({options:n.scale,dtype:"radialLinear",isDefault:!0,dposition:"chartArea"}),a.each(r,function(n){var r=n.options,o=a.valueOrDefault(r.type,n.dtype),l=t.scaleService.getScaleConstructor(o);if(l){s(r.position)!==s(n.dposition)&&(r.position=n.dposition);var u=new l({id:r.id,options:r,ctx:e.ctx,chart:e});i[u.id]=u,u.mergeTicksOptions(),n.isDefault&&(e.scale=u)}}),t.scaleService.addScalesToLayout(this)},buildOrUpdateControllers:function(){var e=this,n=[],i=[];return a.each(e.data.datasets,function(a,r){var o=e.getDatasetMeta(r),s=a.type||e.config.type;if(o.type&&o.type!==s&&(e.destroyDatasetMeta(r),o=e.getDatasetMeta(r)),o.type=s,n.push(o.type),o.controller)o.controller.updateIndex(r);else{var l=t.controllers[o.type];if(void 0===l)throw new Error('"'+o.type+'" is not a chart type.');o.controller=new l(e,r),i.push(o.controller)}},e),i},resetElements:function(){var t=this;a.each(t.data.datasets,function(e,n){t.getDatasetMeta(n).controller.reset()},t)},reset:function(){this.resetElements(),this.tooltip.initialize()},update:function(t){var e=this;if(t&&"object"==typeof t||(t={duration:t,lazy:arguments[1]}),n(e),!1!==l.notify(e,"beforeUpdate")){e.tooltip._data=e.data;var i=e.buildOrUpdateControllers();a.each(e.data.datasets,function(t,n){e.getDatasetMeta(n).controller.buildOrUpdateElements()},e),e.updateLayout(),a.each(i,function(t){t.reset()}),e.updateDatasets(),l.notify(e,"afterUpdate"),e._bufferedRender?e._bufferedRequest={duration:t.duration,easing:t.easing,lazy:t.lazy}:e.render(t)}},updateLayout:function(){var e=this;!1!==l.notify(e,"beforeLayout")&&(t.layoutService.update(this,this.width,this.height),l.notify(e,"afterScaleUpdate"),l.notify(e,"afterLayout"))},updateDatasets:function(){var t=this;if(!1!==l.notify(t,"beforeDatasetsUpdate")){for(var e=0,n=t.data.datasets.length;e<n;++e)t.updateDataset(e);l.notify(t,"afterDatasetsUpdate")}},updateDataset:function(t){var e=this,n=e.getDatasetMeta(t),i={meta:n,index:t};!1!==l.notify(e,"beforeDatasetUpdate",[i])&&(n.controller.update(),l.notify(e,"afterDatasetUpdate",[i]))},render:function(e){var n=this;e&&"object"==typeof e||(e={duration:e,lazy:arguments[1]});var i=e.duration,r=e.lazy;if(!1!==l.notify(n,"beforeRender")){var o=n.options.animation,s=function(t){l.notify(n,"afterRender"),a.callback(o&&o.onComplete,[t],n)};if(o&&(void 0!==i&&0!==i||void 0===i&&0!==o.duration)){var u=new t.Animation({numSteps:(i||o.duration)/16.66,easing:e.easing||o.easing,render:function(t,e){var n=a.easing.effects[e.easing],i=e.currentStep,r=i/e.numSteps;t.draw(n(r),r,i)},onAnimationProgress:o.onProgress,onAnimationComplete:s});t.animationService.addAnimation(n,u,i,r)}else n.draw(),s(new t.Animation({numSteps:0,chart:n}));return n}},draw:function(t){var e=this;e.clear(),a.isNullOrUndef(t)&&(t=1),e.transition(t),!1!==l.notify(e,"beforeDraw",[t])&&(a.each(e.boxes,function(t){t.draw(e.chartArea)},e),e.scale&&e.scale.draw(),e.drawDatasets(t),e.tooltip.draw(),l.notify(e,"afterDraw",[t]))},transition:function(t){for(var e=this,n=0,i=(e.data.datasets||[]).length;n<i;++n)e.isDatasetVisible(n)&&e.getDatasetMeta(n).controller.transition(t);e.tooltip.transition(t)},drawDatasets:function(t){var e=this;if(!1!==l.notify(e,"beforeDatasetsDraw",[t])){for(var n=(e.data.datasets||[]).length-1;n>=0;--n)e.isDatasetVisible(n)&&e.drawDataset(n,t);l.notify(e,"afterDatasetsDraw",[t])}},drawDataset:function(t,e){var n=this,i=n.getDatasetMeta(t),a={meta:i,index:t,easingValue:e};!1!==l.notify(n,"beforeDatasetDraw",[a])&&(i.controller.draw(e),l.notify(n,"afterDatasetDraw",[a]))},getElementAtEvent:function(t){return r.modes.single(this,t)},getElementsAtEvent:function(t){return r.modes.label(this,t,{intersect:!0})},getElementsAtXAxis:function(t){return r.modes["x-axis"](this,t,{intersect:!0})},getElementsAtEventForMode:function(t,e,n){var i=r.modes[e];return"function"==typeof i?i(this,t,n):[]},getDatasetAtEvent:function(t){return r.modes.dataset(this,t,{intersect:!0})},getDatasetMeta:function(t){var e=this,n=e.data.datasets[t];n._meta||(n._meta={});var i=n._meta[e.id];return i||(i=n._meta[e.id]={type:null,data:[],dataset:null,controller:null,hidden:null,xAxisID:null,yAxisID:null}),i},getVisibleDatasetCount:function(){for(var t=0,e=0,n=this.data.datasets.length;e<n;++e)this.isDatasetVisible(e)&&t++;return t},isDatasetVisible:function(t){var e=this.getDatasetMeta(t);return"boolean"==typeof e.hidden?!e.hidden:!this.data.datasets[t].hidden},generateLegend:function(){return this.options.legendCallback(this)},destroyDatasetMeta:function(t){var e=this.id,n=this.data.datasets[t],i=n._meta&&n._meta[e];i&&(i.controller.destroy(),delete n._meta[e])},destroy:function(){var e,n,i=this,r=i.canvas;for(i.stop(),e=0,n=i.data.datasets.length;e<n;++e)i.destroyDatasetMeta(e);r&&(i.unbindEvents(),a.canvas.clear(i),o.releaseContext(i.ctx),i.canvas=null,i.ctx=null),l.notify(i,"destroy"),delete t.instances[i.id]},toBase64Image:function(){return this.canvas.toDataURL.apply(this.canvas,arguments)},initToolTip:function(){var e=this;e.tooltip=new t.Tooltip({_chart:e,_chartInstance:e,_data:e.data,_options:e.options.tooltips},e)},bindEvents:function(){var t=this,e=t._listeners={},n=function(){t.eventHandler.apply(t,arguments)};a.each(t.options.events,function(i){o.addEventListener(t,i,n),e[i]=n}),t.options.responsive&&(n=function(){t.resize()},o.addEventListener(t,"resize",n),e.resize=n)},unbindEvents:function(){var t=this,e=t._listeners;e&&(delete t._listeners,a.each(e,function(e,n){o.removeEventListener(t,n,e)}))},updateHoverStyle:function(t,e,n){var i,a,r,o=n?"setHoverStyle":"removeHoverStyle";for(a=0,r=t.length;a<r;++a)(i=t[a])&&this.getDatasetMeta(i._datasetIndex).controller[o](i)},eventHandler:function(t){var e=this,n=e.tooltip;if(!1!==l.notify(e,"beforeEvent",[t])){e._bufferedRender=!0,e._bufferedRequest=null;var i=e.handleEvent(t);i|=n&&n.handleEvent(t),l.notify(e,"afterEvent",[t]);var a=e._bufferedRequest;return a?e.render(a):i&&!e.animating&&(e.stop(),e.render(e.options.hover.animationDuration,!0)),e._bufferedRender=!1,e._bufferedRequest=null,e}},handleEvent:function(t){var e=this,n=e.options||{},i=n.hover,r=!1;return e.lastActive=e.lastActive||[],"mouseout"===t.type?e.active=[]:e.active=e.getElementsAtEventForMode(t,i.mode,i),a.callback(n.onHover||n.hover.onHover,[t.native,e.active],e),"mouseup"!==t.type&&"click"!==t.type||n.onClick&&n.onClick.call(e,t.native,e.active),e.lastActive.length&&e.updateHoverStyle(e.lastActive,i.mode,!1),e.active.length&&i.mode&&e.updateHoverStyle(e.active,i.mode,!0),r=!a.arrayEquals(e.active,e.lastActive),e.lastActive=e.active,r}}),t.Controller=t}},{25:25,28:28,45:45,48:48}],24:[function(t,e,n){"use strict";var i=t(45);e.exports=function(t){function e(t,e){t._chartjs?t._chartjs.listeners.push(e):(Object.defineProperty(t,"_chartjs",{configurable:!0,enumerable:!1,value:{listeners:[e]}}),a.forEach(function(e){var n="onData"+e.charAt(0).toUpperCase()+e.slice(1),a=t[e];Object.defineProperty(t,e,{configurable:!0,enumerable:!1,value:function(){var e=Array.prototype.slice.call(arguments),r=a.apply(this,e);return i.each(t._chartjs.listeners,function(t){"function"==typeof t[n]&&t[n].apply(t,e)}),r}})}))}function n(t,e){var n=t._chartjs;if(n){var i=n.listeners,r=i.indexOf(e);-1!==r&&i.splice(r,1),i.length>0||(a.forEach(function(e){delete t[e]}),delete t._chartjs)}}var a=["push","pop","shift","splice","unshift"];t.DatasetController=function(t,e){this.initialize(t,e)},i.extend(t.DatasetController.prototype,{datasetElementType:null,dataElementType:null,initialize:function(t,e){var n=this;n.chart=t,n.index=e,n.linkScales(),n.addElements()},updateIndex:function(t){this.index=t},linkScales:function(){var t=this,e=t.getMeta(),n=t.getDataset();null===e.xAxisID&&(e.xAxisID=n.xAxisID||t.chart.options.scales.xAxes[0].id),null===e.yAxisID&&(e.yAxisID=n.yAxisID||t.chart.options.scales.yAxes[0].id)},getDataset:function(){return this.chart.data.datasets[this.index]},getMeta:function(){return this.chart.getDatasetMeta(this.index)},getScaleForId:function(t){return this.chart.scales[t]},reset:function(){this.update(!0)},destroy:function(){this._data&&n(this._data,this)},createMetaDataset:function(){var t=this,e=t.datasetElementType;return e&&new e({_chart:t.chart,_datasetIndex:t.index})},createMetaData:function(t){var e=this,n=e.dataElementType;return n&&new n({_chart:e.chart,_datasetIndex:e.index,_index:t})},addElements:function(){var t,e,n=this,i=n.getMeta(),a=n.getDataset().data||[],r=i.data;for(t=0,e=a.length;t<e;++t)r[t]=r[t]||n.createMetaData(t);i.dataset=i.dataset||n.createMetaDataset()},addElementAndReset:function(t){var e=this.createMetaData(t);this.getMeta().data.splice(t,0,e),this.updateElement(e,t,!0)},buildOrUpdateElements:function(){var t=this,i=t.getDataset(),a=i.data||(i.data=[]);t._data!==a&&(t._data&&n(t._data,t),e(a,t),t._data=a),t.resyncElements()},update:i.noop,transition:function(t){for(var e=this.getMeta(),n=e.data||[],i=n.length,a=0;a<i;++a)n[a].transition(t);e.dataset&&e.dataset.transition(t)},draw:function(){var t=this.getMeta(),e=t.data||[],n=e.length,i=0;for(t.dataset&&t.dataset.draw();i<n;++i)e[i].draw()},removeHoverStyle:function(t,e){var n=this.chart.data.datasets[t._datasetIndex],a=t._index,r=t.custom||{},o=i.valueAtIndexOrDefault,s=t._model;s.backgroundColor=r.backgroundColor?r.backgroundColor:o(n.backgroundColor,a,e.backgroundColor),s.borderColor=r.borderColor?r.borderColor:o(n.borderColor,a,e.borderColor),s.borderWidth=r.borderWidth?r.borderWidth:o(n.borderWidth,a,e.borderWidth)},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t._index,a=t.custom||{},r=i.valueAtIndexOrDefault,o=i.getHoverColor,s=t._model;s.backgroundColor=a.hoverBackgroundColor?a.hoverBackgroundColor:r(e.hoverBackgroundColor,n,o(s.backgroundColor)),s.borderColor=a.hoverBorderColor?a.hoverBorderColor:r(e.hoverBorderColor,n,o(s.borderColor)),s.borderWidth=a.hoverBorderWidth?a.hoverBorderWidth:r(e.hoverBorderWidth,n,s.borderWidth)},resyncElements:function(){var t=this,e=t.getMeta(),n=t.getDataset().data,i=e.data.length,a=n.length;a<i?e.data.splice(a,i-a):a>i&&t.insertElements(i,a-i)},insertElements:function(t,e){for(var n=0;n<e;++n)this.addElementAndReset(t+n)},onDataPush:function(){this.insertElements(this.getDataset().data.length-1,arguments.length)},onDataPop:function(){this.getMeta().data.pop()},onDataShift:function(){this.getMeta().data.shift()},onDataSplice:function(t,e){this.getMeta().data.splice(t,e),this.insertElements(t,arguments.length-2)},onDataUnshift:function(){this.insertElements(0,arguments.length)}}),t.DatasetController.extend=i.inherits}},{45:45}],25:[function(t,e,n){"use strict";var i=t(45);e.exports={_set:function(t,e){return i.merge(this[t]||(this[t]={}),e)}}},{45:45}],26:[function(t,e,n){"use strict";function i(t,e,n,i){var r,o,s,l,u,d,c,h,f,g=Object.keys(n);for(r=0,o=g.length;r<o;++r)if(s=g[r],d=n[s],e.hasOwnProperty(s)||(e[s]=d),(l=e[s])!==d&&"_"!==s[0]){if(t.hasOwnProperty(s)||(t[s]=l),u=t[s],(c=typeof d)===typeof u)if("string"===c){if((h=a(u)).valid&&(f=a(d)).valid){e[s]=f.mix(h,i).rgbString();continue}}else if("number"===c&&isFinite(u)&&isFinite(d)){e[s]=u+(d-u)*i;continue}e[s]=d}}var a=t(2),r=t(45),o=function(t){r.extend(this,t),this.initialize.apply(this,arguments)};r.extend(o.prototype,{initialize:function(){this.hidden=!1},pivot:function(){var t=this;return t._view||(t._view=r.clone(t._model)),t._start={},t},transition:function(t){var e=this,n=e._model,a=e._start,r=e._view;return n&&1!==t?(r||(r=e._view={}),a||(a=e._start={}),i(a,r,n,t),e):(e._view=n,e._start=null,e)},tooltipPosition:function(){return{x:this._model.x,y:this._model.y}},hasValue:function(){return r.isNumber(this._model.x)&&r.isNumber(this._model.y)}}),o.extend=r.inherits,e.exports=o},{2:2,45:45}],27:[function(t,e,n){"use strict";var i=t(2),a=t(25),r=t(45);e.exports=function(t){function e(t,e,n){var i;return"string"==typeof t?(i=parseInt(t,10),-1!==t.indexOf("%")&&(i=i/100*e.parentNode[n])):i=t,i}function n(t){return void 0!==t&&null!==t&&"none"!==t}function o(t,i,a){var r=document.defaultView,o=t.parentNode,s=r.getComputedStyle(t)[i],l=r.getComputedStyle(o)[i],u=n(s),d=n(l),c=Number.POSITIVE_INFINITY;return u||d?Math.min(u?e(s,t,a):c,d?e(l,o,a):c):"none"}r.extend=function(t){for(var e=1,n=arguments.length;e<n;e++)r.each(arguments[e],function(e,n){t[n]=e});return t},r.configMerge=function(){return r.merge(r.clone(arguments[0]),[].slice.call(arguments,1),{merger:function(e,n,i,a){var o=n[e]||{},s=i[e];"scales"===e?n[e]=r.scaleMerge(o,s):"scale"===e?n[e]=r.merge(o,[t.scaleService.getScaleDefaults(s.type),s]):r._merger(e,n,i,a)}})},r.scaleMerge=function(){return r.merge(r.clone(arguments[0]),[].slice.call(arguments,1),{merger:function(e,n,i,a){if("xAxes"===e||"yAxes"===e){var o,s,l,u=i[e].length;for(n[e]||(n[e]=[]),o=0;o<u;++o)l=i[e][o],s=r.valueOrDefault(l.type,"xAxes"===e?"category":"linear"),o>=n[e].length&&n[e].push({}),!n[e][o].type||l.type&&l.type!==n[e][o].type?r.merge(n[e][o],[t.scaleService.getScaleDefaults(s),l]):r.merge(n[e][o],l)}else r._merger(e,n,i,a)}})},r.where=function(t,e){if(r.isArray(t)&&Array.prototype.filter)return t.filter(e);var n=[];return r.each(t,function(t){e(t)&&n.push(t)}),n},r.findIndex=Array.prototype.findIndex?function(t,e,n){return t.findIndex(e,n)}:function(t,e,n){n=void 0===n?t:n;for(var i=0,a=t.length;i<a;++i)if(e.call(n,t[i],i,t))return i;return-1},r.findNextWhere=function(t,e,n){r.isNullOrUndef(n)&&(n=-1);for(var i=n+1;i<t.length;i++){var a=t[i];if(e(a))return a}},r.findPreviousWhere=function(t,e,n){r.isNullOrUndef(n)&&(n=t.length);for(var i=n-1;i>=0;i--){var a=t[i];if(e(a))return a}},r.inherits=function(t){var e=this,n=t&&t.hasOwnProperty("constructor")?t.constructor:function(){return e.apply(this,arguments)},i=function(){this.constructor=n};return i.prototype=e.prototype,n.prototype=new i,n.extend=r.inherits,t&&r.extend(n.prototype,t),n.__super__=e.prototype,n},r.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},r.almostEquals=function(t,e,n){return Math.abs(t-e)<n},r.almostWhole=function(t,e){var n=Math.round(t);return n-e<t&&n+e>t},r.max=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.max(t,e)},Number.NEGATIVE_INFINITY)},r.min=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.min(t,e)},Number.POSITIVE_INFINITY)},r.sign=Math.sign?function(t){return Math.sign(t)}:function(t){return 0==(t=+t)||isNaN(t)?t:t>0?1:-1},r.log10=Math.log10?function(t){return Math.log10(t)}:function(t){return Math.log(t)/Math.LN10},r.toRadians=function(t){return t*(Math.PI/180)},r.toDegrees=function(t){return t*(180/Math.PI)},r.getAngleFromPoint=function(t,e){var n=e.x-t.x,i=e.y-t.y,a=Math.sqrt(n*n+i*i),r=Math.atan2(i,n);return r<-.5*Math.PI&&(r+=2*Math.PI),{angle:r,distance:a}},r.distanceBetweenPoints=function(t,e){return Math.sqrt(Math.pow(e.x-t.x,2)+Math.pow(e.y-t.y,2))},r.aliasPixel=function(t){return t%2==0?0:.5},r.splineCurve=function(t,e,n,i){var a=t.skip?e:t,r=e,o=n.skip?e:n,s=Math.sqrt(Math.pow(r.x-a.x,2)+Math.pow(r.y-a.y,2)),l=Math.sqrt(Math.pow(o.x-r.x,2)+Math.pow(o.y-r.y,2)),u=s/(s+l),d=l/(s+l),c=i*(u=isNaN(u)?0:u),h=i*(d=isNaN(d)?0:d);return{previous:{x:r.x-c*(o.x-a.x),y:r.y-c*(o.y-a.y)},next:{x:r.x+h*(o.x-a.x),y:r.y+h*(o.y-a.y)}}},r.EPSILON=Number.EPSILON||1e-14,r.splineCurveMonotone=function(t){var e,n,i,a,o=(t||[]).map(function(t){return{model:t._model,deltaK:0,mK:0}}),s=o.length;for(e=0;e<s;++e)if(!(i=o[e]).model.skip){if(n=e>0?o[e-1]:null,(a=e<s-1?o[e+1]:null)&&!a.model.skip){var l=a.model.x-i.model.x;i.deltaK=0!==l?(a.model.y-i.model.y)/l:0}!n||n.model.skip?i.mK=i.deltaK:!a||a.model.skip?i.mK=n.deltaK:this.sign(n.deltaK)!==this.sign(i.deltaK)?i.mK=0:i.mK=(n.deltaK+i.deltaK)/2}var u,d,c,h;for(e=0;e<s-1;++e)i=o[e],a=o[e+1],i.model.skip||a.model.skip||(r.almostEquals(i.deltaK,0,this.EPSILON)?i.mK=a.mK=0:(u=i.mK/i.deltaK,d=a.mK/i.deltaK,(h=Math.pow(u,2)+Math.pow(d,2))<=9||(c=3/Math.sqrt(h),i.mK=u*c*i.deltaK,a.mK=d*c*i.deltaK)));var f;for(e=0;e<s;++e)(i=o[e]).model.skip||(n=e>0?o[e-1]:null,a=e<s-1?o[e+1]:null,n&&!n.model.skip&&(f=(i.model.x-n.model.x)/3,i.model.controlPointPreviousX=i.model.x-f,i.model.controlPointPreviousY=i.model.y-f*i.mK),a&&!a.model.skip&&(f=(a.model.x-i.model.x)/3,i.model.controlPointNextX=i.model.x+f,i.model.controlPointNextY=i.model.y+f*i.mK))},r.nextItem=function(t,e,n){return n?e>=t.length-1?t[0]:t[e+1]:e>=t.length-1?t[t.length-1]:t[e+1]},r.previousItem=function(t,e,n){return n?e<=0?t[t.length-1]:t[e-1]:e<=0?t[0]:t[e-1]},r.niceNum=function(t,e){var n=Math.floor(r.log10(t)),i=t/Math.pow(10,n);return(e?i<1.5?1:i<3?2:i<7?5:10:i<=1?1:i<=2?2:i<=5?5:10)*Math.pow(10,n)},r.requestAnimFrame="undefined"==typeof window?function(t){t()}:window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)},r.getRelativePosition=function(t,e){var n,i,a=t.originalEvent||t,o=t.currentTarget||t.srcElement,s=o.getBoundingClientRect(),l=a.touches;l&&l.length>0?(n=l[0].clientX,i=l[0].clientY):(n=a.clientX,i=a.clientY);var u=parseFloat(r.getStyle(o,"padding-left")),d=parseFloat(r.getStyle(o,"padding-top")),c=parseFloat(r.getStyle(o,"padding-right")),h=parseFloat(r.getStyle(o,"padding-bottom")),f=s.right-s.left-u-c,g=s.bottom-s.top-d-h;return n=Math.round((n-s.left-u)/f*o.width/e.currentDevicePixelRatio),i=Math.round((i-s.top-d)/g*o.height/e.currentDevicePixelRatio),{x:n,y:i}},r.getConstraintWidth=function(t){return o(t,"max-width","clientWidth")},r.getConstraintHeight=function(t){return o(t,"max-height","clientHeight")},r.getMaximumWidth=function(t){var e=t.parentNode;if(!e)return t.clientWidth;var n=parseInt(r.getStyle(e,"padding-left"),10),i=parseInt(r.getStyle(e,"padding-right"),10),a=e.clientWidth-n-i,o=r.getConstraintWidth(t);return isNaN(o)?a:Math.min(a,o)},r.getMaximumHeight=function(t){var e=t.parentNode;if(!e)return t.clientHeight;var n=parseInt(r.getStyle(e,"padding-top"),10),i=parseInt(r.getStyle(e,"padding-bottom"),10),a=e.clientHeight-n-i,o=r.getConstraintHeight(t);return isNaN(o)?a:Math.min(a,o)},r.getStyle=function(t,e){return t.currentStyle?t.currentStyle[e]:document.defaultView.getComputedStyle(t,null).getPropertyValue(e)},r.retinaScale=function(t,e){var n=t.currentDevicePixelRatio=e||window.devicePixelRatio||1;if(1!==n){var i=t.canvas,a=t.height,r=t.width;i.height=a*n,i.width=r*n,t.ctx.scale(n,n),i.style.height=a+"px",i.style.width=r+"px"}},r.fontString=function(t,e,n){return e+" "+t+"px "+n},r.longestText=function(t,e,n,i){var a=(i=i||{}).data=i.data||{},o=i.garbageCollect=i.garbageCollect||[];i.font!==e&&(a=i.data={},o=i.garbageCollect=[],i.font=e),t.font=e;var s=0;r.each(n,function(e){void 0!==e&&null!==e&&!0!==r.isArray(e)?s=r.measureText(t,a,o,s,e):r.isArray(e)&&r.each(e,function(e){void 0===e||null===e||r.isArray(e)||(s=r.measureText(t,a,o,s,e))})});var l=o.length/2;if(l>n.length){for(var u=0;u<l;u++)delete a[o[u]];o.splice(0,l)}return s},r.measureText=function(t,e,n,i,a){var r=e[a];return r||(r=e[a]=t.measureText(a).width,n.push(a)),r>i&&(i=r),i},r.numberOfLabelLines=function(t){var e=1;return r.each(t,function(t){r.isArray(t)&&t.length>e&&(e=t.length)}),e},r.color=i?function(t){return t instanceof CanvasGradient&&(t=a.global.defaultColor),i(t)}:function(t){return console.error("Color.js not found!"),t},r.getHoverColor=function(t){return t instanceof CanvasPattern?t:r.color(t).saturate(.5).darken(.1).rgbString()}}},{2:2,25:25,45:45}],28:[function(t,e,n){"use strict";function i(t,e){return t.native?{x:t.x,y:t.y}:u.getRelativePosition(t,e)}function a(t,e){var n,i,a,r,o;for(i=0,r=t.data.datasets.length;i<r;++i)if(t.isDatasetVisible(i))for(a=0,o=(n=t.getDatasetMeta(i)).data.length;a<o;++a){var s=n.data[a];s._view.skip||e(s)}}function r(t,e){var n=[];return a(t,function(t){t.inRange(e.x,e.y)&&n.push(t)}),n}function o(t,e,n,i){var r=Number.POSITIVE_INFINITY,o=[];return a(t,function(t){if(!n||t.inRange(e.x,e.y)){var a=t.getCenterPoint(),s=i(e,a);s<r?(o=[t],r=s):s===r&&o.push(t)}}),o}function s(t){var e=-1!==t.indexOf("x"),n=-1!==t.indexOf("y");return function(t,i){var a=e?Math.abs(t.x-i.x):0,r=n?Math.abs(t.y-i.y):0;return Math.sqrt(Math.pow(a,2)+Math.pow(r,2))}}function l(t,e,n){var a=i(e,t);n.axis=n.axis||"x";var l=s(n.axis),u=n.intersect?r(t,a):o(t,a,!1,l),d=[];return u.length?(t.data.datasets.forEach(function(e,n){if(t.isDatasetVisible(n)){var i=t.getDatasetMeta(n).data[u[0]._index];i&&!i._view.skip&&d.push(i)}}),d):[]}var u=t(45);e.exports={modes:{single:function(t,e){var n=i(e,t),r=[];return a(t,function(t){if(t.inRange(n.x,n.y))return r.push(t),r}),r.slice(0,1)},label:l,index:l,dataset:function(t,e,n){var a=i(e,t);n.axis=n.axis||"xy";var l=s(n.axis),u=n.intersect?r(t,a):o(t,a,!1,l);return u.length>0&&(u=t.getDatasetMeta(u[0]._datasetIndex).data),u},"x-axis":function(t,e){return l(t,e,{intersect:!1})},point:function(t,e){return r(t,i(e,t))},nearest:function(t,e,n){var a=i(e,t);n.axis=n.axis||"xy";var r=s(n.axis),l=o(t,a,n.intersect,r);return l.length>1&&l.sort(function(t,e){var n=t.getArea()-e.getArea();return 0===n&&(n=t._datasetIndex-e._datasetIndex),n}),l.slice(0,1)},x:function(t,e,n){var r=i(e,t),o=[],s=!1;return a(t,function(t){t.inXRange(r.x)&&o.push(t),t.inRange(r.x,r.y)&&(s=!0)}),n.intersect&&!s&&(o=[]),o},y:function(t,e,n){var r=i(e,t),o=[],s=!1;return a(t,function(t){t.inYRange(r.y)&&o.push(t),t.inRange(r.x,r.y)&&(s=!0)}),n.intersect&&!s&&(o=[]),o}}}},{45:45}],29:[function(t,e,n){"use strict";t(25)._set("global",{responsive:!0,responsiveAnimationDuration:0,maintainAspectRatio:!0,events:["mousemove","mouseout","click","touchstart","touchmove"],hover:{onHover:null,mode:"nearest",intersect:!0,animationDuration:400},onClick:null,defaultColor:"rgba(0,0,0,0.1)",defaultFontColor:"#666",defaultFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",defaultFontSize:12,defaultFontStyle:"normal",showLines:!0,elements:{},layout:{padding:{top:0,right:0,bottom:0,left:0}}}),e.exports=function(){var t=function(t,e){return this.construct(t,e),this};return t.Chart=t,t}},{25:25}],30:[function(t,e,n){"use strict";var i=t(45);e.exports=function(t){function e(t,e){return i.where(t,function(t){return t.position===e})}function n(t,e){t.forEach(function(t,e){return t._tmpIndex_=e,t}),t.sort(function(t,n){var i=e?n:t,a=e?t:n;return i.weight===a.weight?i._tmpIndex_-a._tmpIndex_:i.weight-a.weight}),t.forEach(function(t){delete t._tmpIndex_})}t.layoutService={defaults:{},addBox:function(t,e){t.boxes||(t.boxes=[]),e.fullWidth=e.fullWidth||!1,e.position=e.position||"top",e.weight=e.weight||0,t.boxes.push(e)},removeBox:function(t,e){var n=t.boxes?t.boxes.indexOf(e):-1;-1!==n&&t.boxes.splice(n,1)},configure:function(t,e,n){for(var i,a=["fullWidth","position","weight"],r=a.length,o=0;o<r;++o)i=a[o],n.hasOwnProperty(i)&&(e[i]=n[i])},update:function(t,a,r){function o(t){var e=i.findNextWhere(D,function(e){return e.box===t});if(e)if(t.isHorizontal()){var n={left:Math.max(A,C),right:Math.max(O,P),top:0,bottom:0};t.update(t.fullWidth?b:M,x/2,n)}else t.update(e.minSize.width,S)}function s(t){t.isHorizontal()?(t.left=t.fullWidth?d:A,t.right=t.fullWidth?a-c:A+M,t.top=B,t.bottom=B+t.height,B=t.bottom):(t.left=z,t.right=z+t.width,t.top=F,t.bottom=F+S,z=t.right)}if(t){var l=t.options.layout||{},u=i.options.toPadding(l.padding),d=u.left,c=u.right,h=u.top,f=u.bottom,g=e(t.boxes,"left"),m=e(t.boxes,"right"),p=e(t.boxes,"top"),v=e(t.boxes,"bottom"),y=e(t.boxes,"chartArea");n(g,!0),n(m,!1),n(p,!0),n(v,!1);var b=a-d-c,x=r-h-f,_=x/2,k=(a-b/2)/(g.length+m.length),w=(r-_)/(p.length+v.length),M=b,S=x,D=[];i.each(g.concat(m,p,v),function(t){var e,n=t.isHorizontal();n?(e=t.update(t.fullWidth?b:M,w),S-=e.height):(e=t.update(k,_),M-=e.width),D.push({horizontal:n,minSize:e,box:t})});var C=0,P=0,T=0,I=0;i.each(p.concat(v),function(t){if(t.getPadding){var e=t.getPadding();C=Math.max(C,e.left),P=Math.max(P,e.right)}}),i.each(g.concat(m),function(t){if(t.getPadding){var e=t.getPadding();T=Math.max(T,e.top),I=Math.max(I,e.bottom)}});var A=d,O=c,F=h,R=f;i.each(g.concat(m),o),i.each(g,function(t){A+=t.width}),i.each(m,function(t){O+=t.width}),i.each(p.concat(v),o),i.each(p,function(t){F+=t.height}),i.each(v,function(t){R+=t.height}),i.each(g.concat(m),function(t){var e=i.findNextWhere(D,function(e){return e.box===t}),n={left:0,right:0,top:F,bottom:R};e&&t.update(e.minSize.width,S,n)}),A=d,O=c,F=h,R=f,i.each(g,function(t){A+=t.width}),i.each(m,function(t){O+=t.width}),i.each(p,function(t){F+=t.height}),i.each(v,function(t){R+=t.height});var L=Math.max(C-A,0);A+=L,O+=Math.max(P-O,0);var W=Math.max(T-F,0);F+=W,R+=Math.max(I-R,0);var Y=r-F-R,N=a-A-O;N===M&&Y===S||(i.each(g,function(t){t.height=Y}),i.each(m,function(t){t.height=Y}),i.each(p,function(t){t.fullWidth||(t.width=N)}),i.each(v,function(t){t.fullWidth||(t.width=N)}),S=Y,M=N);var z=d+L,B=h+W;i.each(g.concat(p),s),z+=M,B+=S,i.each(m,s),i.each(v,s),t.chartArea={left:A,top:F,right:A+M,bottom:F+S},i.each(y,function(e){e.left=t.chartArea.left,e.top=t.chartArea.top,e.right=t.chartArea.right,e.bottom=t.chartArea.bottom,e.update(M,S)})}}}}},{45:45}],31:[function(t,e,n){"use strict";var i=t(25),a=t(26),r=t(45);i._set("global",{plugins:{}}),e.exports=function(t){t.plugins={_plugins:[],_cacheId:0,register:function(t){var e=this._plugins;[].concat(t).forEach(function(t){-1===e.indexOf(t)&&e.push(t)}),this._cacheId++},unregister:function(t){var e=this._plugins;[].concat(t).forEach(function(t){var n=e.indexOf(t);-1!==n&&e.splice(n,1)}),this._cacheId++},clear:function(){this._plugins=[],this._cacheId++},count:function(){return this._plugins.length},getAll:function(){return this._plugins},notify:function(t,e,n){var i,a,r,o,s,l=this.descriptors(t),u=l.length;for(i=0;i<u;++i)if(a=l[i],r=a.plugin,"function"==typeof(s=r[e])&&((o=[t].concat(n||[])).push(a.options),!1===s.apply(r,o)))return!1;return!0},descriptors:function(t){var e=t._plugins||(t._plugins={});if(e.id===this._cacheId)return e.descriptors;var n=[],a=[],o=t&&t.config||{},s=o.options&&o.options.plugins||{};return this._plugins.concat(o.plugins||[]).forEach(function(t){if(-1===n.indexOf(t)){var e=t.id,o=s[e];!1!==o&&(!0===o&&(o=r.clone(i.global.plugins[e])),n.push(t),a.push({plugin:t,options:o||{}}))}}),e.descriptors=a,e.id=this._cacheId,a}},t.pluginService=t.plugins,t.PluginBase=a.extend({})}},{25:25,26:26,45:45}],32:[function(t,e,n){"use strict";function i(t){var e,n,i=[];for(e=0,n=t.length;e<n;++e)i.push(t[e].label);return i}function a(t,e,n){var i=t.getPixelForTick(e);return n&&(i-=0===e?(t.getPixelForTick(1)-i)/2:(i-t.getPixelForTick(e-1))/2),i}var r=t(25),o=t(26),s=t(45),l=t(34);r._set("scale",{display:!0,position:"left",offset:!1,gridLines:{display:!0,color:"rgba(0, 0, 0, 0.1)",lineWidth:1,drawBorder:!0,drawOnChartArea:!0,drawTicks:!0,tickMarkLength:10,zeroLineWidth:1,zeroLineColor:"rgba(0,0,0,0.25)",zeroLineBorderDash:[],zeroLineBorderDashOffset:0,offsetGridLines:!1,borderDash:[],borderDashOffset:0},scaleLabel:{display:!1,labelString:"",lineHeight:1.2,padding:{top:4,bottom:4}},ticks:{beginAtZero:!1,minRotation:0,maxRotation:50,mirror:!1,padding:0,reverse:!1,display:!0,autoSkip:!0,autoSkipPadding:0,labelOffset:0,callback:l.formatters.values,minor:{},major:{}}}),e.exports=function(t){function e(t,e,n){return s.isArray(e)?s.longestText(t,n,e):t.measureText(e).width}function n(t){var e=s.valueOrDefault,n=r.global,i=e(t.fontSize,n.defaultFontSize),a=e(t.fontStyle,n.defaultFontStyle),o=e(t.fontFamily,n.defaultFontFamily);return{size:i,style:a,family:o,font:s.fontString(i,a,o)}}function l(t){return s.options.toLineHeight(s.valueOrDefault(t.lineHeight,1.2),s.valueOrDefault(t.fontSize,r.global.defaultFontSize))}t.Scale=o.extend({getPadding:function(){var t=this;return{left:t.paddingLeft||0,top:t.paddingTop||0,right:t.paddingRight||0,bottom:t.paddingBottom||0}},getTicks:function(){return this._ticks},mergeTicksOptions:function(){var t=this.options.ticks;!1===t.minor&&(t.minor={display:!1}),!1===t.major&&(t.major={display:!1});for(var e in t)"major"!==e&&"minor"!==e&&(void 0===t.minor[e]&&(t.minor[e]=t[e]),void 0===t.major[e]&&(t.major[e]=t[e]))},beforeUpdate:function(){s.callback(this.options.beforeUpdate,[this])},update:function(t,e,n){var i,a,r,o,l,u,d=this;for(d.beforeUpdate(),d.maxWidth=t,d.maxHeight=e,d.margins=s.extend({left:0,right:0,top:0,bottom:0},n),d.longestTextCache=d.longestTextCache||{},d.beforeSetDimensions(),d.setDimensions(),d.afterSetDimensions(),d.beforeDataLimits(),d.determineDataLimits(),d.afterDataLimits(),d.beforeBuildTicks(),l=d.buildTicks()||[],d.afterBuildTicks(),d.beforeTickToLabelConversion(),r=d.convertTicksToLabels(l)||d.ticks,d.afterTickToLabelConversion(),d.ticks=r,i=0,a=r.length;i<a;++i)o=r[i],(u=l[i])?u.label=o:l.push(u={label:o,major:!1});return d._ticks=l,d.beforeCalculateTickRotation(),d.calculateTickRotation(),d.afterCalculateTickRotation(),d.beforeFit(),d.fit(),d.afterFit(),d.afterUpdate(),d.minSize},afterUpdate:function(){s.callback(this.options.afterUpdate,[this])},beforeSetDimensions:function(){s.callback(this.options.beforeSetDimensions,[this])},setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0},afterSetDimensions:function(){s.callback(this.options.afterSetDimensions,[this])},beforeDataLimits:function(){s.callback(this.options.beforeDataLimits,[this])},determineDataLimits:s.noop,afterDataLimits:function(){s.callback(this.options.afterDataLimits,[this])},beforeBuildTicks:function(){s.callback(this.options.beforeBuildTicks,[this])},buildTicks:s.noop,afterBuildTicks:function(){s.callback(this.options.afterBuildTicks,[this])},beforeTickToLabelConversion:function(){s.callback(this.options.beforeTickToLabelConversion,[this])},convertTicksToLabels:function(){var t=this,e=t.options.ticks;t.ticks=t.ticks.map(e.userCallback||e.callback,this)},afterTickToLabelConversion:function(){s.callback(this.options.afterTickToLabelConversion,[this])},beforeCalculateTickRotation:function(){s.callback(this.options.beforeCalculateTickRotation,[this])},calculateTickRotation:function(){var t=this,e=t.ctx,a=t.options.ticks,r=i(t._ticks),o=n(a);e.font=o.font;var l=a.minRotation||0;if(r.length&&t.options.display&&t.isHorizontal())for(var u,d=s.longestText(e,o.font,r,t.longestTextCache),c=d,h=t.getPixelForTick(1)-t.getPixelForTick(0)-6;c>h&&l<a.maxRotation;){var f=s.toRadians(l);if(u=Math.cos(f),Math.sin(f)*d>t.maxHeight){l--;break}l++,c=u*d}t.labelRotation=l},afterCalculateTickRotation:function(){s.callback(this.options.afterCalculateTickRotation,[this])},beforeFit:function(){s.callback(this.options.beforeFit,[this])},fit:function(){var t=this,a=t.minSize={width:0,height:0},r=i(t._ticks),o=t.options,u=o.ticks,d=o.scaleLabel,c=o.gridLines,h=o.display,f=t.isHorizontal(),g=n(u),m=o.gridLines.tickMarkLength;if(a.width=f?t.isFullWidth()?t.maxWidth-t.margins.left-t.margins.right:t.maxWidth:h&&c.drawTicks?m:0,a.height=f?h&&c.drawTicks?m:0:t.maxHeight,d.display&&h){var p=l(d)+s.options.toPadding(d.padding).height;f?a.height+=p:a.width+=p}if(u.display&&h){var v=s.longestText(t.ctx,g.font,r,t.longestTextCache),y=s.numberOfLabelLines(r),b=.5*g.size,x=t.options.ticks.padding;if(f){t.longestLabelWidth=v;var _=s.toRadians(t.labelRotation),k=Math.cos(_),w=Math.sin(_)*v+g.size*y+b*(y-1)+b;a.height=Math.min(t.maxHeight,a.height+w+x),t.ctx.font=g.font;var M=e(t.ctx,r[0],g.font),S=e(t.ctx,r[r.length-1],g.font);0!==t.labelRotation?(t.paddingLeft="bottom"===o.position?k*M+3:k*b+3,t.paddingRight="bottom"===o.position?k*b+3:k*S+3):(t.paddingLeft=M/2+3,t.paddingRight=S/2+3)}else u.mirror?v=0:v+=x+b,a.width=Math.min(t.maxWidth,a.width+v),t.paddingTop=g.size/2,t.paddingBottom=g.size/2}t.handleMargins(),t.width=a.width,t.height=a.height},handleMargins:function(){var t=this;t.margins&&(t.paddingLeft=Math.max(t.paddingLeft-t.margins.left,0),t.paddingTop=Math.max(t.paddingTop-t.margins.top,0),t.paddingRight=Math.max(t.paddingRight-t.margins.right,0),t.paddingBottom=Math.max(t.paddingBottom-t.margins.bottom,0))},afterFit:function(){s.callback(this.options.afterFit,[this])},isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},isFullWidth:function(){return this.options.fullWidth},getRightValue:function(t){if(s.isNullOrUndef(t))return NaN;if("number"==typeof t&&!isFinite(t))return NaN;if(t)if(this.isHorizontal()){if(void 0!==t.x)return this.getRightValue(t.x)}else if(void 0!==t.y)return this.getRightValue(t.y);return t},getLabelForIndex:s.noop,getPixelForValue:s.noop,getValueForPixel:s.noop,getPixelForTick:function(t){var e=this,n=e.options.offset;if(e.isHorizontal()){var i=(e.width-(e.paddingLeft+e.paddingRight))/Math.max(e._ticks.length-(n?0:1),1),a=i*t+e.paddingLeft;n&&(a+=i/2);var r=e.left+Math.round(a);return r+=e.isFullWidth()?e.margins.left:0}var o=e.height-(e.paddingTop+e.paddingBottom);return e.top+t*(o/(e._ticks.length-1))},getPixelForDecimal:function(t){var e=this;if(e.isHorizontal()){var n=(e.width-(e.paddingLeft+e.paddingRight))*t+e.paddingLeft,i=e.left+Math.round(n);return i+=e.isFullWidth()?e.margins.left:0}return e.top+t*e.height},getBasePixel:function(){return this.getPixelForValue(this.getBaseValue())},getBaseValue:function(){var t=this,e=t.min,n=t.max;return t.beginAtZero?0:e<0&&n<0?n:e>0&&n>0?e:0},_autoSkip:function(t){var e,n,i,a,r=this,o=r.isHorizontal(),l=r.options.ticks.minor,u=t.length,d=s.toRadians(r.labelRotation),c=Math.cos(d),h=r.longestLabelWidth*c,f=[];for(l.maxTicksLimit&&(a=l.maxTicksLimit),o&&(e=!1,(h+l.autoSkipPadding)*u>r.width-(r.paddingLeft+r.paddingRight)&&(e=1+Math.floor((h+l.autoSkipPadding)*u/(r.width-(r.paddingLeft+r.paddingRight)))),a&&u>a&&(e=Math.max(e,Math.floor(u/a)))),n=0;n<u;n++)i=t[n],(e>1&&n%e>0||n%e==0&&n+e>=u)&&n!==u-1&&delete i.label,f.push(i);return f},draw:function(t){var e=this,i=e.options;if(i.display){var o=e.ctx,u=r.global,d=i.ticks.minor,c=i.ticks.major||d,h=i.gridLines,f=i.scaleLabel,g=0!==e.labelRotation,m=e.isHorizontal(),p=d.autoSkip?e._autoSkip(e.getTicks()):e.getTicks(),v=s.valueOrDefault(d.fontColor,u.defaultFontColor),y=n(d),b=s.valueOrDefault(c.fontColor,u.defaultFontColor),x=n(c),_=h.drawTicks?h.tickMarkLength:0,k=s.valueOrDefault(f.fontColor,u.defaultFontColor),w=n(f),M=s.options.toPadding(f.padding),S=s.toRadians(e.labelRotation),D=[],C="right"===i.position?e.left:e.right-_,P="right"===i.position?e.left+_:e.right,T="bottom"===i.position?e.top:e.bottom-_,I="bottom"===i.position?e.top+_:e.bottom;if(s.each(p,function(n,r){if(!s.isNullOrUndef(n.label)){var o,l,c,f,v=n.label;r===e.zeroLineIndex&&i.offset===h.offsetGridLines?(o=h.zeroLineWidth,l=h.zeroLineColor,c=h.zeroLineBorderDash,f=h.zeroLineBorderDashOffset):(o=s.valueAtIndexOrDefault(h.lineWidth,r),l=s.valueAtIndexOrDefault(h.color,r),c=s.valueOrDefault(h.borderDash,u.borderDash),f=s.valueOrDefault(h.borderDashOffset,u.borderDashOffset));var y,b,x,k,w,M,A,O,F,R,L="middle",W="middle",Y=d.padding;if(m){var N=_+Y;"bottom"===i.position?(W=g?"middle":"top",L=g?"right":"center",R=e.top+N):(W=g?"middle":"bottom",L=g?"left":"center",R=e.bottom-N);var z=a(e,r,h.offsetGridLines&&p.length>1);z<e.left&&(l="rgba(0,0,0,0)"),z+=s.aliasPixel(o),F=e.getPixelForTick(r)+d.labelOffset,y=x=w=A=z,b=T,k=I,M=t.top,O=t.bottom}else{var B,V="left"===i.position;d.mirror?(L=V?"left":"right",B=Y):(L=V?"right":"left",B=_+Y),F=V?e.right-B:e.left+B;var H=a(e,r,h.offsetGridLines&&p.length>1);H<e.top&&(l="rgba(0,0,0,0)"),H+=s.aliasPixel(o),R=e.getPixelForTick(r)+d.labelOffset,y=C,x=P,w=t.left,A=t.right,b=k=M=O=H}D.push({tx1:y,ty1:b,tx2:x,ty2:k,x1:w,y1:M,x2:A,y2:O,labelX:F,labelY:R,glWidth:o,glColor:l,glBorderDash:c,glBorderDashOffset:f,rotation:-1*S,label:v,major:n.major,textBaseline:W,textAlign:L})}}),s.each(D,function(t){if(h.display&&(o.save(),o.lineWidth=t.glWidth,o.strokeStyle=t.glColor,o.setLineDash&&(o.setLineDash(t.glBorderDash),o.lineDashOffset=t.glBorderDashOffset),o.beginPath(),h.drawTicks&&(o.moveTo(t.tx1,t.ty1),o.lineTo(t.tx2,t.ty2)),h.drawOnChartArea&&(o.moveTo(t.x1,t.y1),o.lineTo(t.x2,t.y2)),o.stroke(),o.restore()),d.display){o.save(),o.translate(t.labelX,t.labelY),o.rotate(t.rotation),o.font=t.major?x.font:y.font,o.fillStyle=t.major?b:v,o.textBaseline=t.textBaseline,o.textAlign=t.textAlign;var e=t.label;if(s.isArray(e))for(var n=0,i=0;n<e.length;++n)o.fillText(""+e[n],0,i),i+=1.5*y.size;else o.fillText(e,0,0);o.restore()}}),f.display){var A,O,F=0,R=l(f)/2;if(m)A=e.left+(e.right-e.left)/2,O="bottom"===i.position?e.bottom-R-M.bottom:e.top+R+M.top;else{var L="left"===i.position;A=L?e.left+R+M.top:e.right-R-M.top,O=e.top+(e.bottom-e.top)/2,F=L?-.5*Math.PI:.5*Math.PI}o.save(),o.translate(A,O),o.rotate(F),o.textAlign="center",o.textBaseline="middle",o.fillStyle=k,o.font=w.font,o.fillText(f.labelString,0,0),o.restore()}if(h.drawBorder){o.lineWidth=s.valueAtIndexOrDefault(h.lineWidth,0),o.strokeStyle=s.valueAtIndexOrDefault(h.color,0);var W=e.left,Y=e.right,N=e.top,z=e.bottom,B=s.aliasPixel(o.lineWidth);m?(N=z="top"===i.position?e.bottom:e.top,N+=B,z+=B):(W=Y="left"===i.position?e.right:e.left,W+=B,Y+=B),o.beginPath(),o.moveTo(W,N),o.lineTo(Y,z),o.stroke()}}}})}},{25:25,26:26,34:34,45:45}],33:[function(t,e,n){"use strict";var i=t(25),a=t(45);e.exports=function(t){t.scaleService={constructors:{},defaults:{},registerScaleType:function(t,e,n){this.constructors[t]=e,this.defaults[t]=a.clone(n)},getScaleConstructor:function(t){return this.constructors.hasOwnProperty(t)?this.constructors[t]:void 0},getScaleDefaults:function(t){return this.defaults.hasOwnProperty(t)?a.merge({},[i.scale,this.defaults[t]]):{}},updateScaleDefaults:function(t,e){var n=this;n.defaults.hasOwnProperty(t)&&(n.defaults[t]=a.extend(n.defaults[t],e))},addScalesToLayout:function(e){a.each(e.scales,function(n){n.fullWidth=n.options.fullWidth,n.position=n.options.position,n.weight=n.options.weight,t.layoutService.addBox(e,n)})}}}},{25:25,45:45}],34:[function(t,e,n){"use strict";var i=t(45);e.exports={generators:{linear:function(t,e){var n,a=[];if(t.stepSize&&t.stepSize>0)n=t.stepSize;else{var r=i.niceNum(e.max-e.min,!1);n=i.niceNum(r/(t.maxTicks-1),!0)}var o=Math.floor(e.min/n)*n,s=Math.ceil(e.max/n)*n;t.min&&t.max&&t.stepSize&&i.almostWhole((t.max-t.min)/t.stepSize,n/1e3)&&(o=t.min,s=t.max);var l=(s-o)/n;l=i.almostEquals(l,Math.round(l),n/1e3)?Math.round(l):Math.ceil(l),a.push(void 0!==t.min?t.min:o);for(var u=1;u<l;++u)a.push(o+u*n);return a.push(void 0!==t.max?t.max:s),a},logarithmic:function(t,e){var n,a,r=[],o=i.valueOrDefault,s=o(t.min,Math.pow(10,Math.floor(i.log10(e.min)))),l=Math.floor(i.log10(e.max)),u=Math.ceil(e.max/Math.pow(10,l));0===s?(n=Math.floor(i.log10(e.minNotZero)),a=Math.floor(e.minNotZero/Math.pow(10,n)),r.push(s),s=a*Math.pow(10,n)):(n=Math.floor(i.log10(s)),a=Math.floor(s/Math.pow(10,n)));do{r.push(s),10===++a&&(a=1,++n),s=a*Math.pow(10,n)}while(n<l||n===l&&a<u);var d=o(t.max,s);return r.push(d),r}},formatters:{values:function(t){return i.isArray(t)?t:""+t},linear:function(t,e,n){var a=n.length>3?n[2]-n[1]:n[1]-n[0];Math.abs(a)>1&&t!==Math.floor(t)&&(a=t-Math.floor(t));var r=i.log10(Math.abs(a)),o="";if(0!==t){var s=-1*Math.floor(r);s=Math.max(Math.min(s,20),0),o=t.toFixed(s)}else o="0";return o},logarithmic:function(t,e,n){var a=t/Math.pow(10,Math.floor(i.log10(t)));return 0===t?"0":1===a||2===a||5===a||0===e||e===n.length-1?t.toExponential():""}}}},{45:45}],35:[function(t,e,n){"use strict";var i=t(25),a=t(26),r=t(45);i._set("global",{tooltips:{enabled:!0,custom:null,mode:"nearest",position:"average",intersect:!0,backgroundColor:"rgba(0,0,0,0.8)",titleFontStyle:"bold",titleSpacing:2,titleMarginBottom:6,titleFontColor:"#fff",titleAlign:"left",bodySpacing:2,bodyFontColor:"#fff",bodyAlign:"left",footerFontStyle:"bold",footerSpacing:2,footerMarginTop:6,footerFontColor:"#fff",footerAlign:"left",yPadding:6,xPadding:6,caretPadding:2,caretSize:5,cornerRadius:6,multiKeyBackground:"#fff",displayColors:!0,borderColor:"rgba(0,0,0,0)",borderWidth:0,callbacks:{beforeTitle:r.noop,title:function(t,e){var n="",i=e.labels,a=i?i.length:0;if(t.length>0){var r=t[0];r.xLabel?n=r.xLabel:a>0&&r.index<a&&(n=i[r.index])}return n},afterTitle:r.noop,beforeBody:r.noop,beforeLabel:r.noop,label:function(t,e){var n=e.datasets[t.datasetIndex].label||"";return n&&(n+=": "),n+=t.yLabel},labelColor:function(t,e){var n=e.getDatasetMeta(t.datasetIndex).data[t.index]._view;return{borderColor:n.borderColor,backgroundColor:n.backgroundColor}},labelTextColor:function(){return this._options.bodyFontColor},afterLabel:r.noop,afterBody:r.noop,beforeFooter:r.noop,footer:r.noop,afterFooter:r.noop}}}),e.exports=function(t){function e(t,e){var n=r.color(t);return n.alpha(e*n.alpha()).rgbaString()}function n(t,e){return e&&(r.isArray(e)?Array.prototype.push.apply(t,e):t.push(e)),t}function o(t){var e=t._xScale,n=t._yScale||t._scale,i=t._index,a=t._datasetIndex;return{xLabel:e?e.getLabelForIndex(i,a):"",yLabel:n?n.getLabelForIndex(i,a):"",index:i,datasetIndex:a,x:t._model.x,y:t._model.y}}function s(t){var e=i.global,n=r.valueOrDefault;return{xPadding:t.xPadding,yPadding:t.yPadding,xAlign:t.xAlign,yAlign:t.yAlign,bodyFontColor:t.bodyFontColor,_bodyFontFamily:n(t.bodyFontFamily,e.defaultFontFamily),_bodyFontStyle:n(t.bodyFontStyle,e.defaultFontStyle),_bodyAlign:t.bodyAlign,bodyFontSize:n(t.bodyFontSize,e.defaultFontSize),bodySpacing:t.bodySpacing,titleFontColor:t.titleFontColor,_titleFontFamily:n(t.titleFontFamily,e.defaultFontFamily),_titleFontStyle:n(t.titleFontStyle,e.defaultFontStyle),titleFontSize:n(t.titleFontSize,e.defaultFontSize),_titleAlign:t.titleAlign,titleSpacing:t.titleSpacing,titleMarginBottom:t.titleMarginBottom,footerFontColor:t.footerFontColor,_footerFontFamily:n(t.footerFontFamily,e.defaultFontFamily),_footerFontStyle:n(t.footerFontStyle,e.defaultFontStyle),footerFontSize:n(t.footerFontSize,e.defaultFontSize),_footerAlign:t.footerAlign,footerSpacing:t.footerSpacing,footerMarginTop:t.footerMarginTop,caretSize:t.caretSize,cornerRadius:t.cornerRadius,backgroundColor:t.backgroundColor,opacity:0,legendColorBackground:t.multiKeyBackground,displayColors:t.displayColors,borderColor:t.borderColor,borderWidth:t.borderWidth}}function l(t,e){var n=t._chart.ctx,i=2*e.yPadding,a=0,o=e.body,s=o.reduce(function(t,e){return t+e.before.length+e.lines.length+e.after.length},0);s+=e.beforeBody.length+e.afterBody.length;var l=e.title.length,u=e.footer.length,d=e.titleFontSize,c=e.bodyFontSize,h=e.footerFontSize;i+=l*d,i+=l?(l-1)*e.titleSpacing:0,i+=l?e.titleMarginBottom:0,i+=s*c,i+=s?(s-1)*e.bodySpacing:0,i+=u?e.footerMarginTop:0,i+=u*h,i+=u?(u-1)*e.footerSpacing:0;var f=0,g=function(t){a=Math.max(a,n.measureText(t).width+f)};return n.font=r.fontString(d,e._titleFontStyle,e._titleFontFamily),r.each(e.title,g),n.font=r.fontString(c,e._bodyFontStyle,e._bodyFontFamily),r.each(e.beforeBody.concat(e.afterBody),g),f=e.displayColors?c+2:0,r.each(o,function(t){r.each(t.before,g),r.each(t.lines,g),r.each(t.after,g)}),f=0,n.font=r.fontString(h,e._footerFontStyle,e._footerFontFamily),r.each(e.footer,g),a+=2*e.xPadding,{width:a,height:i}}function u(t,e){var n=t._model,i=t._chart,a=t._chart.chartArea,r="center",o="center";n.y<e.height?o="top":n.y>i.height-e.height&&(o="bottom");var s,l,u,d,c,h=(a.left+a.right)/2,f=(a.top+a.bottom)/2;"center"===o?(s=function(t){return t<=h},l=function(t){return t>h}):(s=function(t){return t<=e.width/2},l=function(t){return t>=i.width-e.width/2}),u=function(t){return t+e.width>i.width},d=function(t){return t-e.width<0},c=function(t){return t<=f?"top":"bottom"},s(n.x)?(r="left",u(n.x)&&(r="center",o=c(n.y))):l(n.x)&&(r="right",d(n.x)&&(r="center",o=c(n.y)));var g=t._options;return{xAlign:g.xAlign?g.xAlign:r,yAlign:g.yAlign?g.yAlign:o}}function d(t,e,n){var i=t.x,a=t.y,r=t.caretSize,o=t.caretPadding,s=t.cornerRadius,l=n.xAlign,u=n.yAlign,d=r+o,c=s+o;return"right"===l?i-=e.width:"center"===l&&(i-=e.width/2),"top"===u?a+=d:a-="bottom"===u?e.height+d:e.height/2,"center"===u?"left"===l?i+=d:"right"===l&&(i-=d):"left"===l?i-=c:"right"===l&&(i+=c),{x:i,y:a}}t.Tooltip=a.extend({initialize:function(){this._model=s(this._options)},getTitle:function(){var t=this,e=t._options.callbacks,i=e.beforeTitle.apply(t,arguments),a=e.title.apply(t,arguments),r=e.afterTitle.apply(t,arguments),o=[];return o=n(o,i),o=n(o,a),o=n(o,r)},getBeforeBody:function(){var t=this._options.callbacks.beforeBody.apply(this,arguments);return r.isArray(t)?t:void 0!==t?[t]:[]},getBody:function(t,e){var i=this,a=i._options.callbacks,o=[];return r.each(t,function(t){var r={before:[],lines:[],after:[]};n(r.before,a.beforeLabel.call(i,t,e)),n(r.lines,a.label.call(i,t,e)),n(r.after,a.afterLabel.call(i,t,e)),o.push(r)}),o},getAfterBody:function(){var t=this._options.callbacks.afterBody.apply(this,arguments);return r.isArray(t)?t:void 0!==t?[t]:[]},getFooter:function(){var t=this,e=t._options.callbacks,i=e.beforeFooter.apply(t,arguments),a=e.footer.apply(t,arguments),r=e.afterFooter.apply(t,arguments),o=[];return o=n(o,i),o=n(o,a),o=n(o,r)},update:function(e){var n,i,a=this,c=a._options,h=a._model,f=a._model=s(c),g=a._active,m=a._data,p={xAlign:h.xAlign,yAlign:h.yAlign},v={x:h.x,y:h.y},y={width:h.width,height:h.height},b={x:h.caretX,y:h.caretY};if(g.length){f.opacity=1;var x=[],_=[];b=t.Tooltip.positioners[c.position](g,a._eventPosition);var k=[];for(n=0,i=g.length;n<i;++n)k.push(o(g[n]));c.filter&&(k=k.filter(function(t){return c.filter(t,m)})),c.itemSort&&(k=k.sort(function(t,e){return c.itemSort(t,e,m)})),r.each(k,function(t){x.push(c.callbacks.labelColor.call(a,t,a._chart)),_.push(c.callbacks.labelTextColor.call(a,t,a._chart))}),f.title=a.getTitle(k,m),f.beforeBody=a.getBeforeBody(k,m),f.body=a.getBody(k,m),f.afterBody=a.getAfterBody(k,m),f.footer=a.getFooter(k,m),f.x=Math.round(b.x),f.y=Math.round(b.y),f.caretPadding=c.caretPadding,f.labelColors=x,f.labelTextColors=_,f.dataPoints=k,v=d(f,y=l(this,f),p=u(this,y))}else f.opacity=0;return f.xAlign=p.xAlign,f.yAlign=p.yAlign,f.x=v.x,f.y=v.y,f.width=y.width,f.height=y.height,f.caretX=b.x,f.caretY=b.y,a._model=f,e&&c.custom&&c.custom.call(a,f),a},drawCaret:function(t,e){var n=this._chart.ctx,i=this._view,a=this.getCaretPosition(t,e,i);n.lineTo(a.x1,a.y1),n.lineTo(a.x2,a.y2),n.lineTo(a.x3,a.y3)},getCaretPosition:function(t,e,n){var i,a,r,o,s,l,u=n.caretSize,d=n.cornerRadius,c=n.xAlign,h=n.yAlign,f=t.x,g=t.y,m=e.width,p=e.height;if("center"===h)s=g+p/2,"left"===c?(a=(i=f)-u,r=i,o=s+u,l=s-u):(a=(i=f+m)+u,r=i,o=s-u,l=s+u);else if("left"===c?(i=(a=f+d+u)-u,r=a+u):"right"===c?(i=(a=f+m-d-u)-u,r=a+u):(i=(a=f+m/2)-u,r=a+u),"top"===h)s=(o=g)-u,l=o;else{s=(o=g+p)+u,l=o;var v=r;r=i,i=v}return{x1:i,x2:a,x3:r,y1:o,y2:s,y3:l}},drawTitle:function(t,n,i,a){var o=n.title;if(o.length){i.textAlign=n._titleAlign,i.textBaseline="top";var s=n.titleFontSize,l=n.titleSpacing;i.fillStyle=e(n.titleFontColor,a),i.font=r.fontString(s,n._titleFontStyle,n._titleFontFamily);var u,d;for(u=0,d=o.length;u<d;++u)i.fillText(o[u],t.x,t.y),t.y+=s+l,u+1===o.length&&(t.y+=n.titleMarginBottom-l)}},drawBody:function(t,n,i,a){var o=n.bodyFontSize,s=n.bodySpacing,l=n.body;i.textAlign=n._bodyAlign,i.textBaseline="top",i.font=r.fontString(o,n._bodyFontStyle,n._bodyFontFamily);var u=0,d=function(e){i.fillText(e,t.x+u,t.y),t.y+=o+s};i.fillStyle=e(n.bodyFontColor,a),r.each(n.beforeBody,d);var c=n.displayColors;u=c?o+2:0,r.each(l,function(s,l){var u=e(n.labelTextColors[l],a);i.fillStyle=u,r.each(s.before,d),r.each(s.lines,function(r){c&&(i.fillStyle=e(n.legendColorBackground,a),i.fillRect(t.x,t.y,o,o),i.lineWidth=1,i.strokeStyle=e(n.labelColors[l].borderColor,a),i.strokeRect(t.x,t.y,o,o),i.fillStyle=e(n.labelColors[l].backgroundColor,a),i.fillRect(t.x+1,t.y+1,o-2,o-2),i.fillStyle=u),d(r)}),r.each(s.after,d)}),u=0,r.each(n.afterBody,d),t.y-=s},drawFooter:function(t,n,i,a){var o=n.footer;o.length&&(t.y+=n.footerMarginTop,i.textAlign=n._footerAlign,i.textBaseline="top",i.fillStyle=e(n.footerFontColor,a),i.font=r.fontString(n.footerFontSize,n._footerFontStyle,n._footerFontFamily),r.each(o,function(e){i.fillText(e,t.x,t.y),t.y+=n.footerFontSize+n.footerSpacing}))},drawBackground:function(t,n,i,a,r){i.fillStyle=e(n.backgroundColor,r),i.strokeStyle=e(n.borderColor,r),i.lineWidth=n.borderWidth;var o=n.xAlign,s=n.yAlign,l=t.x,u=t.y,d=a.width,c=a.height,h=n.cornerRadius;i.beginPath(),i.moveTo(l+h,u),"top"===s&&this.drawCaret(t,a),i.lineTo(l+d-h,u),i.quadraticCurveTo(l+d,u,l+d,u+h),"center"===s&&"right"===o&&this.drawCaret(t,a),i.lineTo(l+d,u+c-h),i.quadraticCurveTo(l+d,u+c,l+d-h,u+c),"bottom"===s&&this.drawCaret(t,a),i.lineTo(l+h,u+c),i.quadraticCurveTo(l,u+c,l,u+c-h),"center"===s&&"left"===o&&this.drawCaret(t,a),i.lineTo(l,u+h),i.quadraticCurveTo(l,u,l+h,u),i.closePath(),i.fill(),n.borderWidth>0&&i.stroke()},draw:function(){var t=this._chart.ctx,e=this._view;if(0!==e.opacity){var n={width:e.width,height:e.height},i={x:e.x,y:e.y},a=Math.abs(e.opacity<.001)?0:e.opacity,r=e.title.length||e.beforeBody.length||e.body.length||e.afterBody.length||e.footer.length;this._options.enabled&&r&&(this.drawBackground(i,e,t,n,a),i.x+=e.xPadding,i.y+=e.yPadding,this.drawTitle(i,e,t,a),this.drawBody(i,e,t,a),this.drawFooter(i,e,t,a))}},handleEvent:function(t){var e=this,n=e._options,i=!1;if(e._lastActive=e._lastActive||[],"mouseout"===t.type?e._active=[]:e._active=e._chart.getElementsAtEventForMode(t,n.mode,n),!(i=!r.arrayEquals(e._active,e._lastActive)))return!1;if(e._lastActive=e._active,n.enabled||n.custom){e._eventPosition={x:t.x,y:t.y};var a=e._model;e.update(!0),e.pivot(),i|=a.x!==e._model.x||a.y!==e._model.y}return i}}),t.Tooltip.positioners={average:function(t){if(!t.length)return!1;var e,n,i=0,a=0,r=0;for(e=0,n=t.length;e<n;++e){var o=t[e];if(o&&o.hasValue()){var s=o.tooltipPosition();i+=s.x,a+=s.y,++r}}return{x:Math.round(i/r),y:Math.round(a/r)}},nearest:function(t,e){var n,i,a,o=e.x,s=e.y,l=Number.POSITIVE_INFINITY;for(n=0,i=t.length;n<i;++n){var u=t[n];if(u&&u.hasValue()){var d=u.getCenterPoint(),c=r.distanceBetweenPoints(e,d);c<l&&(l=c,a=u)}}if(a){var h=a.tooltipPosition();o=h.x,s=h.y}return{x:o,y:s}}}}},{25:25,26:26,45:45}],36:[function(t,e,n){"use strict";var i=t(25),a=t(26),r=t(45);i._set("global",{elements:{arc:{backgroundColor:i.global.defaultColor,borderColor:"#fff",borderWidth:2}}}),e.exports=a.extend({inLabelRange:function(t){var e=this._view;return!!e&&Math.pow(t-e.x,2)<Math.pow(e.radius+e.hoverRadius,2)},inRange:function(t,e){var n=this._view;if(n){for(var i=r.getAngleFromPoint(n,{x:t,y:e}),a=i.angle,o=i.distance,s=n.startAngle,l=n.endAngle;l<s;)l+=2*Math.PI;for(;a>l;)a-=2*Math.PI;for(;a<s;)a+=2*Math.PI;var u=a>=s&&a<=l,d=o>=n.innerRadius&&o<=n.outerRadius;return u&&d}return!1},getCenterPoint:function(){var t=this._view,e=(t.startAngle+t.endAngle)/2,n=(t.innerRadius+t.outerRadius)/2;return{x:t.x+Math.cos(e)*n,y:t.y+Math.sin(e)*n}},getArea:function(){var t=this._view;return Math.PI*((t.endAngle-t.startAngle)/(2*Math.PI))*(Math.pow(t.outerRadius,2)-Math.pow(t.innerRadius,2))},tooltipPosition:function(){var t=this._view,e=t.startAngle+(t.endAngle-t.startAngle)/2,n=(t.outerRadius-t.innerRadius)/2+t.innerRadius;return{x:t.x+Math.cos(e)*n,y:t.y+Math.sin(e)*n}},draw:function(){var t=this._chart.ctx,e=this._view,n=e.startAngle,i=e.endAngle;t.beginPath(),t.arc(e.x,e.y,e.outerRadius,n,i),t.arc(e.x,e.y,e.innerRadius,i,n,!0),t.closePath(),t.strokeStyle=e.borderColor,t.lineWidth=e.borderWidth,t.fillStyle=e.backgroundColor,t.fill(),t.lineJoin="bevel",e.borderWidth&&t.stroke()}})},{25:25,26:26,45:45}],37:[function(t,e,n){"use strict";var i=t(25),a=t(26),r=t(45),o=i.global;i._set("global",{elements:{line:{tension:.4,backgroundColor:o.defaultColor,borderWidth:3,borderColor:o.defaultColor,borderCapStyle:"butt",borderDash:[],borderDashOffset:0,borderJoinStyle:"miter",capBezierPoints:!0,fill:!0}}}),e.exports=a.extend({draw:function(){var t,e,n,i,a=this,s=a._view,l=a._chart.ctx,u=s.spanGaps,d=a._children.slice(),c=o.elements.line,h=-1;for(a._loop&&d.length&&d.push(d[0]),l.save(),l.lineCap=s.borderCapStyle||c.borderCapStyle,l.setLineDash&&l.setLineDash(s.borderDash||c.borderDash),l.lineDashOffset=s.borderDashOffset||c.borderDashOffset,l.lineJoin=s.borderJoinStyle||c.borderJoinStyle,l.lineWidth=s.borderWidth||c.borderWidth,l.strokeStyle=s.borderColor||o.defaultColor,l.beginPath(),h=-1,t=0;t<d.length;++t)e=d[t],n=r.previousItem(d,t),i=e._view,0===t?i.skip||(l.moveTo(i.x,i.y),h=t):(n=-1===h?n:d[h],i.skip||(h!==t-1&&!u||-1===h?l.moveTo(i.x,i.y):r.canvas.lineTo(l,n._view,e._view),h=t));l.stroke(),l.restore()}})},{25:25,26:26,45:45}],38:[function(t,e,n){"use strict";function i(t){var e=this._view;return!!e&&Math.pow(t-e.x,2)<Math.pow(e.radius+e.hitRadius,2)}var a=t(25),r=t(26),o=t(45),s=a.global.defaultColor;a._set("global",{elements:{point:{radius:3,pointStyle:"circle",backgroundColor:s,borderColor:s,borderWidth:1,hitRadius:1,hoverRadius:4,hoverBorderWidth:1}}}),e.exports=r.extend({inRange:function(t,e){var n=this._view;return!!n&&Math.pow(t-n.x,2)+Math.pow(e-n.y,2)<Math.pow(n.hitRadius+n.radius,2)},inLabelRange:i,inXRange:i,inYRange:function(t){var e=this._view;return!!e&&Math.pow(t-e.y,2)<Math.pow(e.radius+e.hitRadius,2)},getCenterPoint:function(){var t=this._view;return{x:t.x,y:t.y}},getArea:function(){return Math.PI*Math.pow(this._view.radius,2)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y,padding:t.radius+t.borderWidth}},draw:function(t){var e=this._view,n=this._model,i=this._chart.ctx,r=e.pointStyle,l=e.radius,u=e.x,d=e.y,c=o.color,h=0;e.skip||(i.strokeStyle=e.borderColor||s,i.lineWidth=o.valueOrDefault(e.borderWidth,a.global.elements.point.borderWidth),i.fillStyle=e.backgroundColor||s,void 0!==t&&(n.x<t.left||1.01*t.right<n.x||n.y<t.top||1.01*t.bottom<n.y)&&(n.x<t.left?h=(u-n.x)/(t.left-n.x):1.01*t.right<n.x?h=(n.x-u)/(n.x-t.right):n.y<t.top?h=(d-n.y)/(t.top-n.y):1.01*t.bottom<n.y&&(h=(n.y-d)/(n.y-t.bottom)),h=Math.round(100*h)/100,i.strokeStyle=c(i.strokeStyle).alpha(h).rgbString(),i.fillStyle=c(i.fillStyle).alpha(h).rgbString()),o.canvas.drawPoint(i,r,l,u,d))}})},{25:25,26:26,45:45}],39:[function(t,e,n){"use strict";function i(t){return void 0!==t._view.width}function a(t){var e,n,a,r,o=t._view;if(i(t)){var s=o.width/2;e=o.x-s,n=o.x+s,a=Math.min(o.y,o.base),r=Math.max(o.y,o.base)}else{var l=o.height/2;e=Math.min(o.x,o.base),n=Math.max(o.x,o.base),a=o.y-l,r=o.y+l}return{left:e,top:a,right:n,bottom:r}}var r=t(25),o=t(26);r._set("global",{elements:{rectangle:{backgroundColor:r.global.defaultColor,borderColor:r.global.defaultColor,borderSkipped:"bottom",borderWidth:0}}}),e.exports=o.extend({draw:function(){function t(t){return v[(y+t)%4]}var e,n,i,a,r,o,s,l=this._chart.ctx,u=this._view,d=u.borderWidth;if(u.horizontal?(e=u.base,n=u.x,i=u.y-u.height/2,a=u.y+u.height/2,r=n>e?1:-1,o=1,s=u.borderSkipped||"left"):(e=u.x-u.width/2,n=u.x+u.width/2,i=u.y,r=1,o=(a=u.base)>i?1:-1,s=u.borderSkipped||"bottom"),d){var c=Math.min(Math.abs(e-n),Math.abs(i-a)),h=(d=d>c?c:d)/2,f=e+("left"!==s?h*r:0),g=n+("right"!==s?-h*r:0),m=i+("top"!==s?h*o:0),p=a+("bottom"!==s?-h*o:0);f!==g&&(i=m,a=p),m!==p&&(e=f,n=g)}l.beginPath(),l.fillStyle=u.backgroundColor,l.strokeStyle=u.borderColor,l.lineWidth=d;var v=[[e,a],[e,i],[n,i],[n,a]],y=["bottom","left","top","right"].indexOf(s,0);-1===y&&(y=0);var b=t(0);l.moveTo(b[0],b[1]);for(var x=1;x<4;x++)b=t(x),l.lineTo(b[0],b[1]);l.fill(),d&&l.stroke()},height:function(){var t=this._view;return t.base-t.y},inRange:function(t,e){var n=!1;if(this._view){var i=a(this);n=t>=i.left&&t<=i.right&&e>=i.top&&e<=i.bottom}return n},inLabelRange:function(t,e){var n=this;if(!n._view)return!1;var r=a(n);return i(n)?t>=r.left&&t<=r.right:e>=r.top&&e<=r.bottom},inXRange:function(t){var e=a(this);return t>=e.left&&t<=e.right},inYRange:function(t){var e=a(this);return t>=e.top&&t<=e.bottom},getCenterPoint:function(){var t,e,n=this._view;return i(this)?(t=n.x,e=(n.y+n.base)/2):(t=(n.x+n.base)/2,e=n.y),{x:t,y:e}},getArea:function(){var t=this._view;return t.width*Math.abs(t.y-t.base)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y}}})},{25:25,26:26}],40:[function(t,e,n){"use strict";e.exports={},e.exports.Arc=t(36),e.exports.Line=t(37),e.exports.Point=t(38),e.exports.Rectangle=t(39)},{36:36,37:37,38:38,39:39}],41:[function(t,e,n){"use strict";var i=t(42),n=e.exports={clear:function(t){t.ctx.clearRect(0,0,t.width,t.height)},roundedRect:function(t,e,n,i,a,r){if(r){var o=Math.min(r,i/2),s=Math.min(r,a/2);t.moveTo(e+o,n),t.lineTo(e+i-o,n),t.quadraticCurveTo(e+i,n,e+i,n+s),t.lineTo(e+i,n+a-s),t.quadraticCurveTo(e+i,n+a,e+i-o,n+a),t.lineTo(e+o,n+a),t.quadraticCurveTo(e,n+a,e,n+a-s),t.lineTo(e,n+s),t.quadraticCurveTo(e,n,e+o,n)}else t.rect(e,n,i,a)},drawPoint:function(t,e,n,i,a){var r,o,s,l,u,d;if(!e||"object"!=typeof e||"[object HTMLImageElement]"!==(r=e.toString())&&"[object HTMLCanvasElement]"!==r){if(!(isNaN(n)||n<=0)){switch(e){default:t.beginPath(),t.arc(i,a,n,0,2*Math.PI),t.closePath(),t.fill();break;case"triangle":t.beginPath(),u=(o=3*n/Math.sqrt(3))*Math.sqrt(3)/2,t.moveTo(i-o/2,a+u/3),t.lineTo(i+o/2,a+u/3),t.lineTo(i,a-2*u/3),t.closePath(),t.fill();break;case"rect":d=1/Math.SQRT2*n,t.beginPath(),t.fillRect(i-d,a-d,2*d,2*d),t.strokeRect(i-d,a-d,2*d,2*d);break;case"rectRounded":var c=n/Math.SQRT2,h=i-c,f=a-c,g=Math.SQRT2*n;t.beginPath(),this.roundedRect(t,h,f,g,g,n/2),t.closePath(),t.fill();break;case"rectRot":d=1/Math.SQRT2*n,t.beginPath(),t.moveTo(i-d,a),t.lineTo(i,a+d),t.lineTo(i+d,a),t.lineTo(i,a-d),t.closePath(),t.fill();break;case"cross":t.beginPath(),t.moveTo(i,a+n),t.lineTo(i,a-n),t.moveTo(i-n,a),t.lineTo(i+n,a),t.closePath();break;case"crossRot":t.beginPath(),s=Math.cos(Math.PI/4)*n,l=Math.sin(Math.PI/4)*n,t.moveTo(i-s,a-l),t.lineTo(i+s,a+l),t.moveTo(i-s,a+l),t.lineTo(i+s,a-l),t.closePath();break;case"star":t.beginPath(),t.moveTo(i,a+n),t.lineTo(i,a-n),t.moveTo(i-n,a),t.lineTo(i+n,a),s=Math.cos(Math.PI/4)*n,l=Math.sin(Math.PI/4)*n,t.moveTo(i-s,a-l),t.lineTo(i+s,a+l),t.moveTo(i-s,a+l),t.lineTo(i+s,a-l),t.closePath();break;case"line":t.beginPath(),t.moveTo(i-n,a),t.lineTo(i+n,a),t.closePath();break;case"dash":t.beginPath(),t.moveTo(i,a),t.lineTo(i+n,a),t.closePath()}t.stroke()}}else t.drawImage(e,i-e.width/2,a-e.height/2,e.width,e.height)},clipArea:function(t,e){t.save(),t.beginPath(),t.rect(e.left,e.top,e.right-e.left,e.bottom-e.top),t.clip()},unclipArea:function(t){t.restore()},lineTo:function(t,e,n,i){if(n.steppedLine)return"after"===n.steppedLine&&!i||"after"!==n.steppedLine&&i?t.lineTo(e.x,n.y):t.lineTo(n.x,e.y),void t.lineTo(n.x,n.y);n.tension?t.bezierCurveTo(i?e.controlPointPreviousX:e.controlPointNextX,i?e.controlPointPreviousY:e.controlPointNextY,i?n.controlPointNextX:n.controlPointPreviousX,i?n.controlPointNextY:n.controlPointPreviousY,n.x,n.y):t.lineTo(n.x,n.y)}};i.clear=n.clear,i.drawRoundedRectangle=function(t){t.beginPath(),n.roundedRect.apply(n,arguments),t.closePath()}},{42:42}],42:[function(t,e,n){"use strict";var i={noop:function(){},uid:function(){var t=0;return function(){return t++}}(),isNullOrUndef:function(t){return null===t||void 0===t},isArray:Array.isArray?Array.isArray:function(t){return"[object Array]"===Object.prototype.toString.call(t)},isObject:function(t){return null!==t&&"[object Object]"===Object.prototype.toString.call(t)},valueOrDefault:function(t,e){return void 0===t?e:t},valueAtIndexOrDefault:function(t,e,n){return i.valueOrDefault(i.isArray(t)?t[e]:t,n)},callback:function(t,e,n){if(t&&"function"==typeof t.call)return t.apply(n,e)},each:function(t,e,n,a){var r,o,s;if(i.isArray(t))if(o=t.length,a)for(r=o-1;r>=0;r--)e.call(n,t[r],r);else for(r=0;r<o;r++)e.call(n,t[r],r);else if(i.isObject(t))for(o=(s=Object.keys(t)).length,r=0;r<o;r++)e.call(n,t[s[r]],s[r])},arrayEquals:function(t,e){var n,a,r,o;if(!t||!e||t.length!==e.length)return!1;for(n=0,a=t.length;n<a;++n)if(r=t[n],o=e[n],r instanceof Array&&o instanceof Array){if(!i.arrayEquals(r,o))return!1}else if(r!==o)return!1;return!0},clone:function(t){if(i.isArray(t))return t.map(i.clone);if(i.isObject(t)){for(var e={},n=Object.keys(t),a=n.length,r=0;r<a;++r)e[n[r]]=i.clone(t[n[r]]);return e}return t},_merger:function(t,e,n,a){var r=e[t],o=n[t];i.isObject(r)&&i.isObject(o)?i.merge(r,o,a):e[t]=i.clone(o)},_mergerIf:function(t,e,n){var a=e[t],r=n[t];i.isObject(a)&&i.isObject(r)?i.mergeIf(a,r):e.hasOwnProperty(t)||(e[t]=i.clone(r))},merge:function(t,e,n){var a,r,o,s,l,u=i.isArray(e)?e:[e],d=u.length;if(!i.isObject(t))return t;for(a=(n=n||{}).merger||i._merger,r=0;r<d;++r)if(e=u[r],i.isObject(e))for(l=0,s=(o=Object.keys(e)).length;l<s;++l)a(o[l],t,e,n);return t},mergeIf:function(t,e){return i.merge(t,e,{merger:i._mergerIf})}};e.exports=i,i.callCallback=i.callback,i.indexOf=function(t,e,n){return Array.prototype.indexOf.call(t,e,n)},i.getValueOrDefault=i.valueOrDefault,i.getValueAtIndexOrDefault=i.valueAtIndexOrDefault},{}],43:[function(t,e,n){"use strict";var i=t(42),a={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return-t*(t-2)},easeInOutQuad:function(t){return(t/=.5)<1?.5*t*t:-.5*(--t*(t-2)-1)},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return(t-=1)*t*t+1},easeInOutCubic:function(t){return(t/=.5)<1?.5*t*t*t:.5*((t-=2)*t*t+2)},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return-((t-=1)*t*t*t-1)},easeInOutQuart:function(t){return(t/=.5)<1?.5*t*t*t*t:-.5*((t-=2)*t*t*t-2)},easeInQuint:function(t){return t*t*t*t*t},easeOutQuint:function(t){return(t-=1)*t*t*t*t+1},easeInOutQuint:function(t){return(t/=.5)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)},easeInSine:function(t){return 1-Math.cos(t*(Math.PI/2))},easeOutSine:function(t){return Math.sin(t*(Math.PI/2))},easeInOutSine:function(t){return-.5*(Math.cos(Math.PI*t)-1)},easeInExpo:function(t){return 0===t?0:Math.pow(2,10*(t-1))},easeOutExpo:function(t){return 1===t?1:1-Math.pow(2,-10*t)},easeInOutExpo:function(t){return 0===t?0:1===t?1:(t/=.5)<1?.5*Math.pow(2,10*(t-1)):.5*(2-Math.pow(2,-10*--t))},easeInCirc:function(t){return t>=1?t:-(Math.sqrt(1-t*t)-1)},easeOutCirc:function(t){return Math.sqrt(1-(t-=1)*t)},easeInOutCirc:function(t){return(t/=.5)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:1===t?1:(n||(n=.3),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),-i*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n))},easeOutElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:1===t?1:(n||(n=.3),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),i*Math.pow(2,-10*t)*Math.sin((t-e)*(2*Math.PI)/n)+1)},easeInOutElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:2==(t/=.5)?1:(n||(n=.45),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),t<1?i*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n)*-.5:i*Math.pow(2,-10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n)*.5+1)},easeInBack:function(t){var e=1.70158;return t*t*((e+1)*t-e)},easeOutBack:function(t){var e=1.70158;return(t-=1)*t*((e+1)*t+e)+1},easeInOutBack:function(t){var e=1.70158;return(t/=.5)<1?t*t*((1+(e*=1.525))*t-e)*.5:.5*((t-=2)*t*((1+(e*=1.525))*t+e)+2)},easeInBounce:function(t){return 1-a.easeOutBounce(1-t)},easeOutBounce:function(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375},easeInOutBounce:function(t){return t<.5?.5*a.easeInBounce(2*t):.5*a.easeOutBounce(2*t-1)+.5}};e.exports={effects:a},i.easingEffects=a},{42:42}],44:[function(t,e,n){"use strict";var i=t(42);e.exports={toLineHeight:function(t,e){var n=(""+t).match(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/);if(!n||"normal"===n[1])return 1.2*e;switch(t=+n[2],n[3]){case"px":return t;case"%":t/=100}return e*t},toPadding:function(t){var e,n,a,r;return i.isObject(t)?(e=+t.top||0,n=+t.right||0,a=+t.bottom||0,r=+t.left||0):e=n=a=r=+t||0,{top:e,right:n,bottom:a,left:r,height:e+a,width:r+n}},resolve:function(t,e,n){var a,r,o;for(a=0,r=t.length;a<r;++a)if(void 0!==(o=t[a])&&(void 0!==e&&"function"==typeof o&&(o=o(e)),void 0!==n&&i.isArray(o)&&(o=o[n]),void 0!==o))return o}}},{42:42}],45:[function(t,e,n){"use strict";e.exports=t(42),e.exports.easing=t(43),e.exports.canvas=t(41),e.exports.options=t(44)},{41:41,42:42,43:43,44:44}],46:[function(t,e,n){e.exports={acquireContext:function(t){return t&&t.canvas&&(t=t.canvas),t&&t.getContext("2d")||null}}},{}],47:[function(t,e,n){"use strict";function i(t,e){var n=p.getStyle(t,e),i=n&&n.match(/^(\d+)(\.\d+)?px$/);return i?Number(i[1]):void 0}function a(t,e){var n=t.style,a=t.getAttribute("height"),r=t.getAttribute("width");if(t[v]={initial:{height:a,width:r,style:{display:n.display,height:n.height,width:n.width}}},n.display=n.display||"block",null===r||""===r){var o=i(t,"width");void 0!==o&&(t.width=o)}if(null===a||""===a)if(""===t.style.height)t.height=t.width/(e.options.aspectRatio||2);else{var s=i(t,"height");void 0!==o&&(t.height=s)}return t}function r(t,e,n){t.addEventListener(e,n,w)}function o(t,e,n){t.removeEventListener(e,n,w)}function s(t,e,n,i,a){return{type:t,chart:e,native:a||null,x:void 0!==n?n:null,y:void 0!==i?i:null}}function l(t,e){var n=k[t.type]||t.type,i=p.getRelativePosition(t,e);return s(n,e,i.x,i.y,t)}function u(t,e){var n=!1,i=[];return function(){i=Array.prototype.slice.call(arguments),e=e||this,n||(n=!0,p.requestAnimFrame.call(window,function(){n=!1,t.apply(e,i)}))}}function d(t){var e=document.createElement("div"),n=y+"size-monitor",i="position:absolute;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1;";e.style.cssText=i,e.className=n,e.innerHTML='<div class="'+n+'-expand" style="'+i+'"><div style="position:absolute;width:1000000px;height:1000000px;left:0;top:0"></div></div><div class="'+n+'-shrink" style="'+i+'"><div style="position:absolute;width:200%;height:200%;left:0; top:0"></div></div>';var a=e.childNodes[0],o=e.childNodes[1];e._reset=function(){a.scrollLeft=1e6,a.scrollTop=1e6,o.scrollLeft=1e6,o.scrollTop=1e6};var s=function(){e._reset(),t()};return r(a,"scroll",s.bind(a,"expand")),r(o,"scroll",s.bind(o,"shrink")),e}function c(t,e){var n=(t[v]||(t[v]={})).renderProxy=function(t){t.animationName===x&&e()};p.each(_,function(e){r(t,e,n)}),t.classList.add(b)}function h(t){var e=t[v]||{},n=e.renderProxy;n&&(p.each(_,function(e){o(t,e,n)}),delete e.renderProxy),t.classList.remove(b)}function f(t,e,n){var i=t[v]||(t[v]={}),a=i.resizer=d(u(function(){if(i.resizer)return e(s("resize",n))}));c(t,function(){if(i.resizer){var e=t.parentNode;e&&e!==a.parentNode&&e.insertBefore(a,e.firstChild),a._reset()}})}function g(t){var e=t[v]||{},n=e.resizer;delete e.resizer,h(t),n&&n.parentNode&&n.parentNode.removeChild(n)}function m(t,e){var n=t._style||document.createElement("style");t._style||(t._style=n,e="/* Chart.js */\n"+e,n.setAttribute("type","text/css"),document.getElementsByTagName("head")[0].appendChild(n)),n.appendChild(document.createTextNode(e))}var p=t(45),v="$chartjs",y="chartjs-",b=y+"render-monitor",x=y+"render-animation",_=["animationstart","webkitAnimationStart"],k={touchstart:"mousedown",touchmove:"mousemove",touchend:"mouseup",pointerenter:"mouseenter",pointerdown:"mousedown",pointermove:"mousemove",pointerup:"mouseup",pointerleave:"mouseout",pointerout:"mouseout"},w=!!function(){var t=!1;try{var e=Object.defineProperty({},"passive",{get:function(){t=!0}});window.addEventListener("e",null,e)}catch(t){}return t}()&&{passive:!0};e.exports={_enabled:"undefined"!=typeof window&&"undefined"!=typeof document,initialize:function(){var t="from{opacity:0.99}to{opacity:1}";m(this,"@-webkit-keyframes "+x+"{"+t+"}@keyframes "+x+"{"+t+"}."+b+"{-webkit-animation:"+x+" 0.001s;animation:"+x+" 0.001s;}")},acquireContext:function(t,e){"string"==typeof t?t=document.getElementById(t):t.length&&(t=t[0]),t&&t.canvas&&(t=t.canvas);var n=t&&t.getContext&&t.getContext("2d");return n&&n.canvas===t?(a(t,e),n):null},releaseContext:function(t){var e=t.canvas;if(e[v]){var n=e[v].initial;["height","width"].forEach(function(t){var i=n[t];p.isNullOrUndef(i)?e.removeAttribute(t):e.setAttribute(t,i)}),p.each(n.style||{},function(t,n){e.style[n]=t}),e.width=e.width,delete e[v]}},addEventListener:function(t,e,n){var i=t.canvas;if("resize"!==e){var a=n[v]||(n[v]={});r(i,e,(a.proxies||(a.proxies={}))[t.id+"_"+e]=function(e){n(l(e,t))})}else f(i,n,t)},removeEventListener:function(t,e,n){var i=t.canvas;if("resize"!==e){var a=((n[v]||{}).proxies||{})[t.id+"_"+e];a&&o(i,e,a)}else g(i)}},p.addEvent=r,p.removeEvent=o},{45:45}],48:[function(t,e,n){"use strict";var i=t(45),a=t(46),r=t(47),o=r._enabled?r:a;e.exports=i.extend({initialize:function(){},acquireContext:function(){},releaseContext:function(){},addEventListener:function(){},removeEventListener:function(){}},o)},{45:45,46:46,47:47}],49:[function(t,e,n){"use strict";var i=t(25),a=t(40),r=t(45);i._set("global",{plugins:{filler:{propagate:!0}}}),e.exports=function(){function t(t,e,n){var i,a=t._model||{},r=a.fill;if(void 0===r&&(r=!!a.backgroundColor),!1===r||null===r)return!1;if(!0===r)return"origin";if(i=parseFloat(r,10),isFinite(i)&&Math.floor(i)===i)return"-"!==r[0]&&"+"!==r[0]||(i=e+i),!(i===e||i<0||i>=n)&&i;switch(r){case"bottom":return"start";case"top":return"end";case"zero":return"origin";case"origin":case"start":case"end":return r;default:return!1}}function e(t){var e,n=t.el._model||{},i=t.el._scale||{},a=t.fill,r=null;if(isFinite(a))return null;if("start"===a?r=void 0===n.scaleBottom?i.bottom:n.scaleBottom:"end"===a?r=void 0===n.scaleTop?i.top:n.scaleTop:void 0!==n.scaleZero?r=n.scaleZero:i.getBasePosition?r=i.getBasePosition():i.getBasePixel&&(r=i.getBasePixel()),void 0!==r&&null!==r){if(void 0!==r.x&&void 0!==r.y)return r;if("number"==typeof r&&isFinite(r))return e=i.isHorizontal(),{x:e?r:null,y:e?null:r}}return null}function n(t,e,n){var i,a=t[e].fill,r=[e];if(!n)return a;for(;!1!==a&&-1===r.indexOf(a);){if(!isFinite(a))return a;if(!(i=t[a]))return!1;if(i.visible)return a;r.push(a),a=i.fill}return!1}function o(t){var e=t.fill,n="dataset";return!1===e?null:(isFinite(e)||(n="boundary"),d[n](t))}function s(t){return t&&!t.skip}function l(t,e,n,i,a){var o;if(i&&a){for(t.moveTo(e[0].x,e[0].y),o=1;o<i;++o)r.canvas.lineTo(t,e[o-1],e[o]);for(t.lineTo(n[a-1].x,n[a-1].y),o=a-1;o>0;--o)r.canvas.lineTo(t,n[o],n[o-1],!0)}}function u(t,e,n,i,a,r){var o,u,d,c,h,f,g,m=e.length,p=i.spanGaps,v=[],y=[],b=0,x=0;for(t.beginPath(),o=0,u=m+!!r;o<u;++o)h=n(c=e[d=o%m]._view,d,i),f=s(c),g=s(h),f&&g?(b=v.push(c),x=y.push(h)):b&&x&&(p?(f&&v.push(c),g&&y.push(h)):(l(t,v,y,b,x),b=x=0,v=[],y=[]));l(t,v,y,b,x),t.closePath(),t.fillStyle=a,t.fill()}var d={dataset:function(t){var e=t.fill,n=t.chart,i=n.getDatasetMeta(e),a=i&&n.isDatasetVisible(e)&&i.dataset._children||[],r=a.length||0;return r?function(t,e){return e<r&&a[e]._view||null}:null},boundary:function(t){var e=t.boundary,n=e?e.x:null,i=e?e.y:null;return function(t){return{x:null===n?t.x:n,y:null===i?t.y:i}}}};return{id:"filler",afterDatasetsUpdate:function(i,r){var s,l,u,d,c=(i.data.datasets||[]).length,h=r.propagate,f=[];for(l=0;l<c;++l)d=null,(u=(s=i.getDatasetMeta(l)).dataset)&&u._model&&u instanceof a.Line&&(d={visible:i.isDatasetVisible(l),fill:t(u,l,c),chart:i,el:u}),s.$filler=d,f.push(d);for(l=0;l<c;++l)(d=f[l])&&(d.fill=n(f,l,h),d.boundary=e(d),d.mapper=o(d))},beforeDatasetDraw:function(t,e){var n=e.meta.$filler;if(n){var a=t.ctx,o=n.el,s=o._view,l=o._children||[],d=n.mapper,c=s.backgroundColor||i.global.defaultColor;d&&c&&l.length&&(r.canvas.clipArea(a,t.chartArea),u(a,l,d,s,c,o._loop),r.canvas.unclipArea(a))}}}}},{25:25,40:40,45:45}],50:[function(t,e,n){"use strict";var i=t(25),a=t(26),r=t(45);i._set("global",{legend:{display:!0,position:"top",fullWidth:!0,reverse:!1,weight:1e3,onClick:function(t,e){var n=e.datasetIndex,i=this.chart,a=i.getDatasetMeta(n);a.hidden=null===a.hidden?!i.data.datasets[n].hidden:null,i.update()},onHover:null,labels:{boxWidth:40,padding:10,generateLabels:function(t){var e=t.data;return r.isArray(e.datasets)?e.datasets.map(function(e,n){return{text:e.label,fillStyle:r.isArray(e.backgroundColor)?e.backgroundColor[0]:e.backgroundColor,hidden:!t.isDatasetVisible(n),lineCap:e.borderCapStyle,lineDash:e.borderDash,lineDashOffset:e.borderDashOffset,lineJoin:e.borderJoinStyle,lineWidth:e.borderWidth,strokeStyle:e.borderColor,pointStyle:e.pointStyle,datasetIndex:n}},this):[]}}},legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');for(var n=0;n<t.data.datasets.length;n++)e.push('<li><span style="background-color:'+t.data.datasets[n].backgroundColor+'"></span>'),t.data.datasets[n].label&&e.push(t.data.datasets[n].label),e.push("</li>");return e.push("</ul>"),e.join("")}}),e.exports=function(t){function e(t,e){return t.usePointStyle?e*Math.SQRT2:t.boxWidth}function n(e,n){var i=new t.Legend({ctx:e.ctx,options:n,chart:e});o.configure(e,i,n),o.addBox(e,i),e.legend=i}var o=t.layoutService,s=r.noop;return t.Legend=a.extend({initialize:function(t){r.extend(this,t),this.legendHitBoxes=[],this.doughnutMode=!1},beforeUpdate:s,update:function(t,e,n){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=n,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:s,beforeSetDimensions:s,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:s,beforeBuildLabels:s,buildLabels:function(){var t=this,e=t.options.labels||{},n=r.callback(e.generateLabels,[t.chart],t)||[];e.filter&&(n=n.filter(function(n){return e.filter(n,t.chart.data)})),t.options.reverse&&n.reverse(),t.legendItems=n},afterBuildLabels:s,beforeFit:s,fit:function(){var t=this,n=t.options,a=n.labels,o=n.display,s=t.ctx,l=i.global,u=r.valueOrDefault,d=u(a.fontSize,l.defaultFontSize),c=u(a.fontStyle,l.defaultFontStyle),h=u(a.fontFamily,l.defaultFontFamily),f=r.fontString(d,c,h),g=t.legendHitBoxes=[],m=t.minSize,p=t.isHorizontal();if(p?(m.width=t.maxWidth,m.height=o?10:0):(m.width=o?10:0,m.height=t.maxHeight),o)if(s.font=f,p){var v=t.lineWidths=[0],y=t.legendItems.length?d+a.padding:0;s.textAlign="left",s.textBaseline="top",r.each(t.legendItems,function(n,i){var r=e(a,d)+d/2+s.measureText(n.text).width;v[v.length-1]+r+a.padding>=t.width&&(y+=d+a.padding,v[v.length]=t.left),g[i]={left:0,top:0,width:r,height:d},v[v.length-1]+=r+a.padding}),m.height+=y}else{var b=a.padding,x=t.columnWidths=[],_=a.padding,k=0,w=0,M=d+b;r.each(t.legendItems,function(t,n){var i=e(a,d)+d/2+s.measureText(t.text).width;w+M>m.height&&(_+=k+a.padding,x.push(k),k=0,w=0),k=Math.max(k,i),w+=M,g[n]={left:0,top:0,width:i,height:d}}),_+=k,x.push(k),m.width+=_}t.width=m.width,t.height=m.height},afterFit:s,isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},draw:function(){var t=this,n=t.options,a=n.labels,o=i.global,s=o.elements.line,l=t.width,u=t.lineWidths;if(n.display){var d,c=t.ctx,h=r.valueOrDefault,f=h(a.fontColor,o.defaultFontColor),g=h(a.fontSize,o.defaultFontSize),m=h(a.fontStyle,o.defaultFontStyle),p=h(a.fontFamily,o.defaultFontFamily),v=r.fontString(g,m,p);c.textAlign="left",c.textBaseline="middle",c.lineWidth=.5,c.strokeStyle=f,c.fillStyle=f,c.font=v;var y=e(a,g),b=t.legendHitBoxes,x=function(t,e,i){if(!(isNaN(y)||y<=0)){c.save(),c.fillStyle=h(i.fillStyle,o.defaultColor),c.lineCap=h(i.lineCap,s.borderCapStyle),c.lineDashOffset=h(i.lineDashOffset,s.borderDashOffset),c.lineJoin=h(i.lineJoin,s.borderJoinStyle),c.lineWidth=h(i.lineWidth,s.borderWidth),c.strokeStyle=h(i.strokeStyle,o.defaultColor);var a=0===h(i.lineWidth,s.borderWidth);if(c.setLineDash&&c.setLineDash(h(i.lineDash,s.borderDash)),n.labels&&n.labels.usePointStyle){var l=g*Math.SQRT2/2,u=l/Math.SQRT2,d=t+u,f=e+u;r.canvas.drawPoint(c,i.pointStyle,l,d,f)}else a||c.strokeRect(t,e,y,g),c.fillRect(t,e,y,g);c.restore()}},_=function(t,e,n,i){var a=g/2,r=y+a+t,o=e+a;c.fillText(n.text,r,o),n.hidden&&(c.beginPath(),c.lineWidth=2,c.moveTo(r,o),c.lineTo(r+i,o),c.stroke())},k=t.isHorizontal();d=k?{x:t.left+(l-u[0])/2,y:t.top+a.padding,line:0}:{x:t.left+a.padding,y:t.top+a.padding,line:0};var w=g+a.padding;r.each(t.legendItems,function(e,n){var i=c.measureText(e.text).width,r=y+g/2+i,o=d.x,s=d.y;k?o+r>=l&&(s=d.y+=w,d.line++,o=d.x=t.left+(l-u[d.line])/2):s+w>t.bottom&&(o=d.x=o+t.columnWidths[d.line]+a.padding,s=d.y=t.top+a.padding,d.line++),x(o,s,e),b[n].left=o,b[n].top=s,_(o,s,e,i),k?d.x+=r+a.padding:d.y+=w})}},handleEvent:function(t){var e=this,n=e.options,i="mouseup"===t.type?"click":t.type,a=!1;if("mousemove"===i){if(!n.onHover)return}else{if("click"!==i)return;if(!n.onClick)return}var r=t.x,o=t.y;if(r>=e.left&&r<=e.right&&o>=e.top&&o<=e.bottom)for(var s=e.legendHitBoxes,l=0;l<s.length;++l){var u=s[l];if(r>=u.left&&r<=u.left+u.width&&o>=u.top&&o<=u.top+u.height){if("click"===i){n.onClick.call(e,t.native,e.legendItems[l]),a=!0;break}if("mousemove"===i){n.onHover.call(e,t.native,e.legendItems[l]),a=!0;break}}}return a}}),{id:"legend",beforeInit:function(t){var e=t.options.legend;e&&n(t,e)},beforeUpdate:function(t){var e=t.options.legend,a=t.legend;e?(r.mergeIf(e,i.global.legend),a?(o.configure(t,a,e),a.options=e):n(t,e)):a&&(o.removeBox(t,a),delete t.legend)},afterEvent:function(t,e){var n=t.legend;n&&n.handleEvent(e)}}}},{25:25,26:26,45:45}],51:[function(t,e,n){"use strict";var i=t(25),a=t(26),r=t(45);i._set("global",{title:{display:!1,fontStyle:"bold",fullWidth:!0,lineHeight:1.2,padding:10,position:"top",text:"",weight:2e3}}),e.exports=function(t){function e(e,i){var a=new t.Title({ctx:e.ctx,options:i,chart:e});n.configure(e,a,i),n.addBox(e,a),e.titleBlock=a}var n=t.layoutService,o=r.noop;return t.Title=a.extend({initialize:function(t){var e=this;r.extend(e,t),e.legendHitBoxes=[]},beforeUpdate:o,update:function(t,e,n){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=n,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:o,beforeSetDimensions:o,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:o,beforeBuildLabels:o,buildLabels:o,afterBuildLabels:o,beforeFit:o,fit:function(){var t=this,e=r.valueOrDefault,n=t.options,a=n.display,o=e(n.fontSize,i.global.defaultFontSize),s=t.minSize,l=r.isArray(n.text)?n.text.length:1,u=r.options.toLineHeight(n.lineHeight,o),d=a?l*u+2*n.padding:0;t.isHorizontal()?(s.width=t.maxWidth,s.height=d):(s.width=d,s.height=t.maxHeight),t.width=s.width,t.height=s.height},afterFit:o,isHorizontal:function(){var t=this.options.position;return"top"===t||"bottom"===t},draw:function(){var t=this,e=t.ctx,n=r.valueOrDefault,a=t.options,o=i.global;if(a.display){var s,l,u,d=n(a.fontSize,o.defaultFontSize),c=n(a.fontStyle,o.defaultFontStyle),h=n(a.fontFamily,o.defaultFontFamily),f=r.fontString(d,c,h),g=r.options.toLineHeight(a.lineHeight,d),m=g/2+a.padding,p=0,v=t.top,y=t.left,b=t.bottom,x=t.right;e.fillStyle=n(a.fontColor,o.defaultFontColor),e.font=f,t.isHorizontal()?(l=y+(x-y)/2,u=v+m,s=x-y):(l="left"===a.position?y+m:x-m,u=v+(b-v)/2,s=b-v,p=Math.PI*("left"===a.position?-.5:.5)),e.save(),e.translate(l,u),e.rotate(p),e.textAlign="center",e.textBaseline="middle";var _=a.text;if(r.isArray(_))for(var k=0,w=0;w<_.length;++w)e.fillText(_[w],0,k,s),k+=g;else e.fillText(_,0,0,s);e.restore()}}}),{id:"title",beforeInit:function(t){var n=t.options.title;n&&e(t,n)},beforeUpdate:function(a){var o=a.options.title,s=a.titleBlock;o?(r.mergeIf(o,i.global.title),s?(n.configure(a,s,o),s.options=o):e(a,o)):s&&(t.layoutService.removeBox(a,s),delete a.titleBlock)}}}},{25:25,26:26,45:45}],52:[function(t,e,n){"use strict";e.exports=function(t){var e={position:"bottom"},n=t.Scale.extend({getLabels:function(){var t=this.chart.data;return this.options.labels||(this.isHorizontal()?t.xLabels:t.yLabels)||t.labels},determineDataLimits:function(){var t=this,e=t.getLabels();t.minIndex=0,t.maxIndex=e.length-1;var n;void 0!==t.options.ticks.min&&(n=e.indexOf(t.options.ticks.min),t.minIndex=-1!==n?n:t.minIndex),void 0!==t.options.ticks.max&&(n=e.indexOf(t.options.ticks.max),t.maxIndex=-1!==n?n:t.maxIndex),t.min=e[t.minIndex],t.max=e[t.maxIndex]},buildTicks:function(){var t=this,e=t.getLabels();t.ticks=0===t.minIndex&&t.maxIndex===e.length-1?e:e.slice(t.minIndex,t.maxIndex+1)},getLabelForIndex:function(t,e){var n=this,i=n.chart.data,a=n.isHorizontal();return i.yLabels&&!a?n.getRightValue(i.datasets[e].data[t]):n.ticks[t-n.minIndex]},getPixelForValue:function(t,e){var n,i=this,a=i.options.offset,r=Math.max(i.maxIndex+1-i.minIndex-(a?0:1),1);if(void 0!==t&&null!==t&&(n=i.isHorizontal()?t.x:t.y),void 0!==n||void 0!==t&&isNaN(e)){var o=i.getLabels();t=n||t;var s=o.indexOf(t);e=-1!==s?s:e}if(i.isHorizontal()){var l=i.width/r,u=l*(e-i.minIndex);return a&&(u+=l/2),i.left+Math.round(u)}var d=i.height/r,c=d*(e-i.minIndex);return a&&(c+=d/2),i.top+Math.round(c)},getPixelForTick:function(t){return this.getPixelForValue(this.ticks[t],t+this.minIndex,null)},getValueForPixel:function(t){var e=this,n=e.options.offset,i=Math.max(e._ticks.length-(n?0:1),1),a=e.isHorizontal(),r=(a?e.width:e.height)/i;return t-=a?e.left:e.top,n&&(t-=r/2),(t<=0?0:Math.round(t/r))+e.minIndex},getBasePixel:function(){return this.bottom}});t.scaleService.registerScaleType("category",n,e)}},{}],53:[function(t,e,n){"use strict";var i=t(25),a=t(45),r=t(34);e.exports=function(t){var e={position:"left",ticks:{callback:r.formatters.linear}},n=t.LinearScaleBase.extend({determineDataLimits:function(){function t(t){return o?t.xAxisID===e.id:t.yAxisID===e.id}var e=this,n=e.options,i=e.chart,r=i.data.datasets,o=e.isHorizontal();e.min=null,e.max=null;var s=n.stacked;if(void 0===s&&a.each(r,function(e,n){if(!s){var a=i.getDatasetMeta(n);i.isDatasetVisible(n)&&t(a)&&void 0!==a.stack&&(s=!0)}}),n.stacked||s){var l={};a.each(r,function(r,o){var s=i.getDatasetMeta(o),u=[s.type,void 0===n.stacked&&void 0===s.stack?o:"",s.stack].join(".");void 0===l[u]&&(l[u]={positiveValues:[],negativeValues:[]});var d=l[u].positiveValues,c=l[u].negativeValues;i.isDatasetVisible(o)&&t(s)&&a.each(r.data,function(t,i){var a=+e.getRightValue(t);isNaN(a)||s.data[i].hidden||(d[i]=d[i]||0,c[i]=c[i]||0,n.relativePoints?d[i]=100:a<0?c[i]+=a:d[i]+=a)})}),a.each(l,function(t){var n=t.positiveValues.concat(t.negativeValues),i=a.min(n),r=a.max(n);e.min=null===e.min?i:Math.min(e.min,i),e.max=null===e.max?r:Math.max(e.max,r)})}else a.each(r,function(n,r){var o=i.getDatasetMeta(r);i.isDatasetVisible(r)&&t(o)&&a.each(n.data,function(t,n){var i=+e.getRightValue(t);isNaN(i)||o.data[n].hidden||(null===e.min?e.min=i:i<e.min&&(e.min=i),null===e.max?e.max=i:i>e.max&&(e.max=i))})});e.min=isFinite(e.min)&&!isNaN(e.min)?e.min:0,e.max=isFinite(e.max)&&!isNaN(e.max)?e.max:1,this.handleTickRangeOptions()},getTickLimit:function(){var t,e=this,n=e.options.ticks;if(e.isHorizontal())t=Math.min(n.maxTicksLimit?n.maxTicksLimit:11,Math.ceil(e.width/50));else{var r=a.valueOrDefault(n.fontSize,i.global.defaultFontSize);t=Math.min(n.maxTicksLimit?n.maxTicksLimit:11,Math.ceil(e.height/(2*r)))}return t},handleDirectionalChanges:function(){this.isHorizontal()||this.ticks.reverse()},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForValue:function(t){var e,n=this,i=n.start,a=+n.getRightValue(t),r=n.end-i;return n.isHorizontal()?(e=n.left+n.width/r*(a-i),Math.round(e)):(e=n.bottom-n.height/r*(a-i),Math.round(e))},getValueForPixel:function(t){var e=this,n=e.isHorizontal(),i=n?e.width:e.height,a=(n?t-e.left:e.bottom-t)/i;return e.start+(e.end-e.start)*a},getPixelForTick:function(t){return this.getPixelForValue(this.ticksAsNumbers[t])}});t.scaleService.registerScaleType("linear",n,e)}},{25:25,34:34,45:45}],54:[function(t,e,n){"use strict";var i=t(45),a=t(34);e.exports=function(t){var e=i.noop;t.LinearScaleBase=t.Scale.extend({getRightValue:function(e){return"string"==typeof e?+e:t.Scale.prototype.getRightValue.call(this,e)},handleTickRangeOptions:function(){var t=this,e=t.options.ticks;if(e.beginAtZero){var n=i.sign(t.min),a=i.sign(t.max);n<0&&a<0?t.max=0:n>0&&a>0&&(t.min=0)}var r=void 0!==e.min||void 0!==e.suggestedMin,o=void 0!==e.max||void 0!==e.suggestedMax;void 0!==e.min?t.min=e.min:void 0!==e.suggestedMin&&(null===t.min?t.min=e.suggestedMin:t.min=Math.min(t.min,e.suggestedMin)),void 0!==e.max?t.max=e.max:void 0!==e.suggestedMax&&(null===t.max?t.max=e.suggestedMax:t.max=Math.max(t.max,e.suggestedMax)),r!==o&&t.min>=t.max&&(r?t.max=t.min+1:t.min=t.max-1),t.min===t.max&&(t.max++,e.beginAtZero||t.min--)},getTickLimit:e,handleDirectionalChanges:e,buildTicks:function(){var t=this,e=t.options.ticks,n=t.getTickLimit(),r={maxTicks:n=Math.max(2,n),min:e.min,max:e.max,stepSize:i.valueOrDefault(e.fixedStepSize,e.stepSize)},o=t.ticks=a.generators.linear(r,t);t.handleDirectionalChanges(),t.max=i.max(o),t.min=i.min(o),e.reverse?(o.reverse(),t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max)},convertTicksToLabels:function(){var e=this;e.ticksAsNumbers=e.ticks.slice(),e.zeroLineIndex=e.ticks.indexOf(0),t.Scale.prototype.convertTicksToLabels.call(e)}})}},{34:34,45:45}],55:[function(t,e,n){"use strict";var i=t(45),a=t(34);e.exports=function(t){var e={position:"left",ticks:{callback:a.formatters.logarithmic}},n=t.Scale.extend({determineDataLimits:function(){function t(t){return l?t.xAxisID===e.id:t.yAxisID===e.id}var e=this,n=e.options,a=n.ticks,r=e.chart,o=r.data.datasets,s=i.valueOrDefault,l=e.isHorizontal();e.min=null,e.max=null,e.minNotZero=null;var u=n.stacked;if(void 0===u&&i.each(o,function(e,n){if(!u){var i=r.getDatasetMeta(n);r.isDatasetVisible(n)&&t(i)&&void 0!==i.stack&&(u=!0)}}),n.stacked||u){var d={};i.each(o,function(a,o){var s=r.getDatasetMeta(o),l=[s.type,void 0===n.stacked&&void 0===s.stack?o:"",s.stack].join(".");r.isDatasetVisible(o)&&t(s)&&(void 0===d[l]&&(d[l]=[]),i.each(a.data,function(t,i){var a=d[l],r=+e.getRightValue(t);isNaN(r)||s.data[i].hidden||(a[i]=a[i]||0,n.relativePoints?a[i]=100:a[i]+=r)}))}),i.each(d,function(t){var n=i.min(t),a=i.max(t);e.min=null===e.min?n:Math.min(e.min,n),e.max=null===e.max?a:Math.max(e.max,a)})}else i.each(o,function(n,a){var o=r.getDatasetMeta(a);r.isDatasetVisible(a)&&t(o)&&i.each(n.data,function(t,n){var i=+e.getRightValue(t);isNaN(i)||o.data[n].hidden||(null===e.min?e.min=i:i<e.min&&(e.min=i),null===e.max?e.max=i:i>e.max&&(e.max=i),0!==i&&(null===e.minNotZero||i<e.minNotZero)&&(e.minNotZero=i))})});e.min=s(a.min,e.min),e.max=s(a.max,e.max),e.min===e.max&&(0!==e.min&&null!==e.min?(e.min=Math.pow(10,Math.floor(i.log10(e.min))-1),e.max=Math.pow(10,Math.floor(i.log10(e.max))+1)):(e.min=1,e.max=10))},buildTicks:function(){var t=this,e=t.options.ticks,n={min:e.min,max:e.max},r=t.ticks=a.generators.logarithmic(n,t);t.isHorizontal()||r.reverse(),t.max=i.max(r),t.min=i.min(r),e.reverse?(r.reverse(),t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max)},convertTicksToLabels:function(){this.tickValues=this.ticks.slice(),t.Scale.prototype.convertTicksToLabels.call(this)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForTick:function(t){return this.getPixelForValue(this.tickValues[t])},getPixelForValue:function(t){var e,n,a,r=this,o=r.start,s=+r.getRightValue(t),l=r.options.ticks;return r.isHorizontal()?(a=i.log10(r.end)-i.log10(o),0===s?n=r.left:(e=r.width,n=r.left+e/a*(i.log10(s)-i.log10(o)))):(e=r.height,0!==o||l.reverse?0===r.end&&l.reverse?(a=i.log10(r.start)-i.log10(r.minNotZero),n=s===r.end?r.top:s===r.minNotZero?r.top+.02*e:r.top+.02*e+.98*e/a*(i.log10(s)-i.log10(r.minNotZero))):0===s?n=l.reverse?r.top:r.bottom:(a=i.log10(r.end)-i.log10(o),e=r.height,n=r.bottom-e/a*(i.log10(s)-i.log10(o))):(a=i.log10(r.end)-i.log10(r.minNotZero),n=s===o?r.bottom:s===r.minNotZero?r.bottom-.02*e:r.bottom-.02*e-.98*e/a*(i.log10(s)-i.log10(r.minNotZero)))),n},getValueForPixel:function(t){var e,n,a=this,r=i.log10(a.end)-i.log10(a.start);return a.isHorizontal()?(n=a.width,e=a.start*Math.pow(10,(t-a.left)*r/n)):(n=a.height,e=Math.pow(10,(a.bottom-t)*r/n)/a.start),e}});t.scaleService.registerScaleType("logarithmic",n,e)}},{34:34,45:45}],56:[function(t,e,n){"use strict";var i=t(25),a=t(45),r=t(34);e.exports=function(t){function e(t){var e=t.options;return e.angleLines.display||e.pointLabels.display?t.chart.data.labels.length:0}function n(t){var e=t.options.pointLabels,n=a.valueOrDefault(e.fontSize,p.defaultFontSize),i=a.valueOrDefault(e.fontStyle,p.defaultFontStyle),r=a.valueOrDefault(e.fontFamily,p.defaultFontFamily);return{size:n,style:i,family:r,font:a.fontString(n,i,r)}}function o(t,e,n){return a.isArray(n)?{w:a.longestText(t,t.font,n),h:n.length*e+1.5*(n.length-1)*e}:{w:t.measureText(n).width,h:e}}function s(t,e,n,i,a){return t===i||t===a?{start:e-n/2,end:e+n/2}:t<i||t>a?{start:e-n-5,end:e}:{start:e,end:e+n+5}}function l(t){var i,r,l,u=n(t),d=Math.min(t.height/2,t.width/2),c={r:t.width,l:0,t:t.height,b:0},h={};t.ctx.font=u.font,t._pointLabelSizes=[];var f=e(t);for(i=0;i<f;i++){l=t.getPointPosition(i,d),r=o(t.ctx,u.size,t.pointLabels[i]||""),t._pointLabelSizes[i]=r;var g=t.getIndexAngle(i),m=a.toDegrees(g)%360,p=s(m,l.x,r.w,0,180),v=s(m,l.y,r.h,90,270);p.start<c.l&&(c.l=p.start,h.l=g),p.end>c.r&&(c.r=p.end,h.r=g),v.start<c.t&&(c.t=v.start,h.t=g),v.end>c.b&&(c.b=v.end,h.b=g)}t.setReductions(d,c,h)}function u(t){var e=Math.min(t.height/2,t.width/2);t.drawingArea=Math.round(e),t.setCenterPoint(0,0,0,0)}function d(t){return 0===t||180===t?"center":t<180?"left":"right"}function c(t,e,n,i){if(a.isArray(e))for(var r=n.y,o=1.5*i,s=0;s<e.length;++s)t.fillText(e[s],n.x,r),r+=o;else t.fillText(e,n.x,n.y)}function h(t,e,n){90===t||270===t?n.y-=e.h/2:(t>270||t<90)&&(n.y-=e.h)}function f(t){var i=t.ctx,r=a.valueOrDefault,o=t.options,s=o.angleLines,l=o.pointLabels;i.lineWidth=s.lineWidth,i.strokeStyle=s.color;var u=t.getDistanceFromCenterForValue(o.ticks.reverse?t.min:t.max),f=n(t);i.textBaseline="top";for(var g=e(t)-1;g>=0;g--){if(s.display){var m=t.getPointPosition(g,u);i.beginPath(),i.moveTo(t.xCenter,t.yCenter),i.lineTo(m.x,m.y),i.stroke(),i.closePath()}if(l.display){var v=t.getPointPosition(g,u+5),y=r(l.fontColor,p.defaultFontColor);i.font=f.font,i.fillStyle=y;var b=t.getIndexAngle(g),x=a.toDegrees(b);i.textAlign=d(x),h(x,t._pointLabelSizes[g],v),c(i,t.pointLabels[g]||"",v,f.size)}}}function g(t,n,i,r){var o=t.ctx;if(o.strokeStyle=a.valueAtIndexOrDefault(n.color,r-1),o.lineWidth=a.valueAtIndexOrDefault(n.lineWidth,r-1),t.options.gridLines.circular)o.beginPath(),o.arc(t.xCenter,t.yCenter,i,0,2*Math.PI),o.closePath(),o.stroke();else{var s=e(t);if(0===s)return;o.beginPath();var l=t.getPointPosition(0,i);o.moveTo(l.x,l.y);for(var u=1;u<s;u++)l=t.getPointPosition(u,i),o.lineTo(l.x,l.y);o.closePath(),o.stroke()}}function m(t){return a.isNumber(t)?t:0}var p=i.global,v={display:!0,animate:!0,position:"chartArea",angleLines:{display:!0,color:"rgba(0, 0, 0, 0.1)",lineWidth:1},gridLines:{circular:!1},ticks:{showLabelBackdrop:!0,backdropColor:"rgba(255,255,255,0.75)",backdropPaddingY:2,backdropPaddingX:2,callback:r.formatters.linear},pointLabels:{display:!0,fontSize:10,callback:function(t){return t}}},y=t.LinearScaleBase.extend({setDimensions:function(){var t=this,e=t.options,n=e.ticks;t.width=t.maxWidth,t.height=t.maxHeight,t.xCenter=Math.round(t.width/2),t.yCenter=Math.round(t.height/2);var i=a.min([t.height,t.width]),r=a.valueOrDefault(n.fontSize,p.defaultFontSize);t.drawingArea=e.display?i/2-(r/2+n.backdropPaddingY):i/2},determineDataLimits:function(){var t=this,e=t.chart,n=Number.POSITIVE_INFINITY,i=Number.NEGATIVE_INFINITY;a.each(e.data.datasets,function(r,o){if(e.isDatasetVisible(o)){var s=e.getDatasetMeta(o);a.each(r.data,function(e,a){var r=+t.getRightValue(e);isNaN(r)||s.data[a].hidden||(n=Math.min(r,n),i=Math.max(r,i))})}}),t.min=n===Number.POSITIVE_INFINITY?0:n,t.max=i===Number.NEGATIVE_INFINITY?0:i,t.handleTickRangeOptions()},getTickLimit:function(){var t=this.options.ticks,e=a.valueOrDefault(t.fontSize,p.defaultFontSize);return Math.min(t.maxTicksLimit?t.maxTicksLimit:11,Math.ceil(this.drawingArea/(1.5*e)))},convertTicksToLabels:function(){var e=this;t.LinearScaleBase.prototype.convertTicksToLabels.call(e),e.pointLabels=e.chart.data.labels.map(e.options.pointLabels.callback,e)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},fit:function(){this.options.pointLabels.display?l(this):u(this)},setReductions:function(t,e,n){var i=this,a=e.l/Math.sin(n.l),r=Math.max(e.r-i.width,0)/Math.sin(n.r),o=-e.t/Math.cos(n.t),s=-Math.max(e.b-i.height,0)/Math.cos(n.b);a=m(a),r=m(r),o=m(o),s=m(s),i.drawingArea=Math.min(Math.round(t-(a+r)/2),Math.round(t-(o+s)/2)),i.setCenterPoint(a,r,o,s)},setCenterPoint:function(t,e,n,i){var a=this,r=a.width-e-a.drawingArea,o=t+a.drawingArea,s=n+a.drawingArea,l=a.height-i-a.drawingArea;a.xCenter=Math.round((o+r)/2+a.left),a.yCenter=Math.round((s+l)/2+a.top)},getIndexAngle:function(t){return t*(2*Math.PI/e(this))+(this.chart.options&&this.chart.options.startAngle?this.chart.options.startAngle:0)*Math.PI*2/360},getDistanceFromCenterForValue:function(t){var e=this;if(null===t)return 0;var n=e.drawingArea/(e.max-e.min);return e.options.ticks.reverse?(e.max-t)*n:(t-e.min)*n},getPointPosition:function(t,e){var n=this,i=n.getIndexAngle(t)-Math.PI/2;return{x:Math.round(Math.cos(i)*e)+n.xCenter,y:Math.round(Math.sin(i)*e)+n.yCenter}},getPointPositionForValue:function(t,e){return this.getPointPosition(t,this.getDistanceFromCenterForValue(e))},getBasePosition:function(){var t=this,e=t.min,n=t.max;return t.getPointPositionForValue(0,t.beginAtZero?0:e<0&&n<0?n:e>0&&n>0?e:0)},draw:function(){var t=this,e=t.options,n=e.gridLines,i=e.ticks,r=a.valueOrDefault;if(e.display){var o=t.ctx,s=this.getIndexAngle(0),l=r(i.fontSize,p.defaultFontSize),u=r(i.fontStyle,p.defaultFontStyle),d=r(i.fontFamily,p.defaultFontFamily),c=a.fontString(l,u,d);a.each(t.ticks,function(e,a){if(a>0||i.reverse){var u=t.getDistanceFromCenterForValue(t.ticksAsNumbers[a]);if(n.display&&0!==a&&g(t,n,u,a),i.display){var d=r(i.fontColor,p.defaultFontColor);if(o.font=c,o.save(),o.translate(t.xCenter,t.yCenter),o.rotate(s),i.showLabelBackdrop){var h=o.measureText(e).width;o.fillStyle=i.backdropColor,o.fillRect(-h/2-i.backdropPaddingX,-u-l/2-i.backdropPaddingY,h+2*i.backdropPaddingX,l+2*i.backdropPaddingY)}o.textAlign="center",o.textBaseline="middle",o.fillStyle=d,o.fillText(e,0,-u),o.restore()}}}),(e.angleLines.display||e.pointLabels.display)&&f(t)}}});t.scaleService.registerScaleType("radialLinear",y,v)}},{25:25,34:34,45:45}],57:[function(t,e,n){"use strict";function i(t,e){return t-e}function a(t){var e,n,i,a={},r=[];for(e=0,n=t.length;e<n;++e)a[i=t[e]]||(a[i]=!0,r.push(i));return r}function r(t,e,n,i){if("linear"===i||!t.length)return[{time:e,pos:0},{time:n,pos:1}];var a,r,o,s,l,u=[],d=[e];for(a=0,r=t.length;a<r;++a)(s=t[a])>e&&s<n&&d.push(s);for(d.push(n),a=0,r=d.length;a<r;++a)l=d[a+1],o=d[a-1],s=d[a],void 0!==o&&void 0!==l&&Math.round((l+o)/2)===s||u.push({time:s,pos:a/(r-1)});return u}function o(t,e,n){for(var i,a,r,o=0,s=t.length-1;o>=0&&o<=s;){if(i=o+s>>1,a=t[i-1]||null,r=t[i],!a)return{lo:null,hi:r};if(r[e]<n)o=i+1;else{if(!(a[e]>n))return{lo:a,hi:r};s=i-1}}return{lo:r,hi:null}}function s(t,e,n,i){var a=o(t,e,n),r=a.lo?a.hi?a.lo:t[t.length-2]:t[0],s=a.lo?a.hi?a.hi:t[t.length-1]:t[1],l=s[e]-r[e],u=l?(n-r[e])/l:0,d=(s[i]-r[i])*u;return r[i]+d}function l(t,e){var n=e.parser,i=e.parser||e.format;return"function"==typeof n?n(t):"string"==typeof t&&"string"==typeof i?p(t,i):(t instanceof p||(t=p(t)),t.isValid()?t:"function"==typeof i?i(t):t)}function u(t,e){if(y.isNullOrUndef(t))return null;var n=e.options.time,i=l(e.getRightValue(t),n);return i.isValid()?(n.round&&i.startOf(n.round),i.valueOf()):null}function d(t,e,n,i){var a,r,o,s=e-t,l=_[n],u=l.size,d=l.steps;if(!d)return Math.ceil(s/((i||1)*u));for(a=0,r=d.length;a<r&&(o=d[a],!(Math.ceil(s/(u*o))<=i));++a);return o}function c(t,e,n,i){var a,r,o,s=k.length;for(a=k.indexOf(t);a<s-1;++a)if(r=_[k[a]],o=r.steps?r.steps[r.steps.length-1]:x,r.common&&Math.ceil((n-e)/(o*r.size))<=i)return k[a];return k[s-1]}function h(t){for(var e=k.indexOf(t)+1,n=k.length;e<n;++e)if(_[k[e]].common)return k[e]}function f(t,e,n,i,a,r){var o,s=r.time,l=y.valueOrDefault(s.stepSize,s.unitStepSize),u="week"===n&&s.isoWeekday,c=r.ticks.major.enabled,h=_[n],f=p(t),g=p(e),m=[];for(l||(l=d(t,e,n,a)),u&&(f=f.isoWeekday(u),g=g.isoWeekday(u)),f=f.startOf(u?"day":n),(g=g.startOf(u?"day":n))<e&&g.add(1,n),o=p(f),c&&i&&!u&&!s.round&&(o.startOf(i),o.add(~~((f-o)/(h.size*l))*l,n));o<g;o.add(l,n))m.push(+o);return m.push(+o),m}function g(t,e,n,i,a){var r,o,l=0,u=0;return a.offset&&e.length&&(a.time.min||(r=e.length>1?e[1]:i,o=e[0],l=(s(t,"time",r,"pos")-s(t,"time",o,"pos"))/2),a.time.max||(r=e[e.length-1],o=e.length>1?e[e.length-2]:n,u=(s(t,"time",r,"pos")-s(t,"time",o,"pos"))/2)),{left:l,right:u}}function m(t,e){var n,i,a,r,o=[];for(n=0,i=t.length;n<i;++n)a=t[n],r=!!e&&a===+p(a).startOf(e),o.push({value:a,major:r});return o}var p=t(6);p="function"==typeof p?p:window.moment;var v=t(25),y=t(45),b=Number.MIN_SAFE_INTEGER||-9007199254740991,x=Number.MAX_SAFE_INTEGER||9007199254740991,_={millisecond:{common:!0,size:1,steps:[1,2,5,10,20,50,100,250,500]},second:{common:!0,size:1e3,steps:[1,2,5,10,30]},minute:{common:!0,size:6e4,steps:[1,2,5,10,30]},hour:{common:!0,size:36e5,steps:[1,2,3,6,12]},day:{common:!0,size:864e5,steps:[1,2,5]},week:{common:!1,size:6048e5,steps:[1,2,3,4]},month:{common:!0,size:2628e6,steps:[1,2,3]},quarter:{common:!1,size:7884e6,steps:[1,2,3,4]},year:{common:!0,size:3154e7}},k=Object.keys(_);e.exports=function(t){var e={position:"bottom",distribution:"linear",bounds:"data",time:{parser:!1,format:!1,unit:!1,round:!1,displayFormat:!1,isoWeekday:!1,minUnit:"millisecond",displayFormats:{millisecond:"h:mm:ss.SSS a",second:"h:mm:ss a",minute:"h:mm a",hour:"hA",day:"MMM D",week:"ll",month:"MMM YYYY",quarter:"[Q]Q - YYYY",year:"YYYY"}},ticks:{autoSkip:!1,source:"auto",major:{enabled:!1}}},n=t.Scale.extend({initialize:function(){if(!p)throw new Error("Chart.js - Moment.js could not be found! You must include it before Chart.js to use the time scale. Download at https://momentjs.com");this.mergeTicksOptions(),t.Scale.prototype.initialize.call(this)},update:function(){var e=this,n=e.options;return n.time&&n.time.format&&console.warn("options.time.format is deprecated and replaced by options.time.parser."),t.Scale.prototype.update.apply(e,arguments)},getRightValue:function(e){return e&&void 0!==e.t&&(e=e.t),t.Scale.prototype.getRightValue.call(this,e)},determineDataLimits:function(){var t,e,n,r,o,s,l=this,d=l.chart,c=l.options.time,h=u(c.min,l)||x,f=u(c.max,l)||b,g=[],m=[],v=[];for(t=0,n=d.data.labels.length;t<n;++t)v.push(u(d.data.labels[t],l));for(t=0,n=(d.data.datasets||[]).length;t<n;++t)if(d.isDatasetVisible(t))if(o=d.data.datasets[t].data,y.isObject(o[0]))for(m[t]=[],e=0,r=o.length;e<r;++e)s=u(o[e],l),g.push(s),m[t][e]=s;else g.push.apply(g,v),m[t]=v.slice(0);else m[t]=[];v.length&&(v=a(v).sort(i),h=Math.min(h,v[0]),f=Math.max(f,v[v.length-1])),g.length&&(g=a(g).sort(i),h=Math.min(h,g[0]),f=Math.max(f,g[g.length-1])),h=h===x?+p().startOf("day"):h,f=f===b?+p().endOf("day")+1:f,l.min=Math.min(h,f),l.max=Math.max(h+1,f),l._horizontal=l.isHorizontal(),l._table=[],l._timestamps={data:g,datasets:m,labels:v}},buildTicks:function(){var t,e,n,i=this,a=i.min,o=i.max,s=i.options,l=s.time,d=l.displayFormats,p=i.getLabelCapacity(a),v=l.unit||c(l.minUnit,a,o,p),y=h(v),b=[],x=[];switch(s.ticks.source){case"data":b=i._timestamps.data;break;case"labels":b=i._timestamps.labels;break;case"auto":default:b=f(a,o,v,y,p,s)}for("ticks"===s.bounds&&b.length&&(a=b[0],o=b[b.length-1]),a=u(l.min,i)||a,o=u(l.max,i)||o,t=0,e=b.length;t<e;++t)(n=b[t])>=a&&n<=o&&x.push(n);return i.min=a,i.max=o,i._unit=v,i._majorUnit=y,i._minorFormat=d[v],i._majorFormat=d[y],i._table=r(i._timestamps.data,a,o,s.distribution),i._offsets=g(i._table,x,a,o,s),m(x,y)},getLabelForIndex:function(t,e){var n=this,i=n.chart.data,a=n.options.time,r=i.labels&&t<i.labels.length?i.labels[t]:"",o=i.datasets[e].data[t];return y.isObject(o)&&(r=n.getRightValue(o)),a.tooltipFormat&&(r=l(r,a).format(a.tooltipFormat)),r},tickFormatFunction:function(t,e,n){var i=this,a=i.options,r=t.valueOf(),o=i._majorUnit,s=i._majorFormat,l=t.clone().startOf(i._majorUnit).valueOf(),u=a.ticks.major,d=u.enabled&&o&&s&&r===l,c=t.format(d?s:i._minorFormat),h=d?u:a.ticks.minor,f=y.valueOrDefault(h.callback,h.userCallback);return f?f(c,e,n):c},convertTicksToLabels:function(t){var e,n,i=[];for(e=0,n=t.length;e<n;++e)i.push(this.tickFormatFunction(p(t[e].value),e,t));return i},getPixelForOffset:function(t){var e=this,n=e._horizontal?e.width:e.height,i=e._horizontal?e.left:e.top,a=s(e._table,"time",t,"pos");return i+n*(e._offsets.left+a)/(e._offsets.left+1+e._offsets.right)},getPixelForValue:function(t,e,n){var i=this,a=null;if(void 0!==e&&void 0!==n&&(a=i._timestamps.datasets[n][e]),null===a&&(a=u(t,i)),null!==a)return i.getPixelForOffset(a)},getPixelForTick:function(t){var e=this.getTicks();return t>=0&&t<e.length?this.getPixelForOffset(e[t].value):null},getValueForPixel:function(t){var e=this,n=e._horizontal?e.width:e.height,i=e._horizontal?e.left:e.top,a=(n?(t-i)/n:0)*(e._offsets.left+1+e._offsets.left)-e._offsets.right,r=s(e._table,"pos",a,"time");return p(r)},getLabelWidth:function(t){var e=this,n=e.options.ticks,i=e.ctx.measureText(t).width,a=y.toRadians(n.maxRotation),r=Math.cos(a),o=Math.sin(a);return i*r+y.valueOrDefault(n.fontSize,v.global.defaultFontSize)*o},getLabelCapacity:function(t){var e=this;e._minorFormat=e.options.time.displayFormats.millisecond;var n=e.tickFormatFunction(p(t),0,[]),i=e.getLabelWidth(n),a=e.isHorizontal()?e.width:e.height;return Math.floor(a/i)}});t.scaleService.registerScaleType("time",n,e)}},{25:25,45:45,6:6}]},{},[7])(7)});
assets/js/Chart.min.js CHANGED
@@ -1,10 +1,10 @@
1
- /*!
2
- * Chart.js
3
- * http://chartjs.org/
4
- * Version: 2.7.0
5
- *
6
- * Copyright 2017 Nick Downie
7
- * Released under the MIT license
8
- * https://github.com/chartjs/Chart.js/blob/master/LICENSE.md
9
- */
10
  !function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).Chart=t()}}(function(){return function t(e,n,i){function a(r,l){if(!n[r]){if(!e[r]){var s="function"==typeof require&&require;if(!l&&s)return s(r,!0);if(o)return o(r,!0);var u=new Error("Cannot find module '"+r+"'");throw u.code="MODULE_NOT_FOUND",u}var d=n[r]={exports:{}};e[r][0].call(d.exports,function(t){var n=e[r][1][t];return a(n||t)},d,d.exports,t,e,n,i)}return n[r].exports}for(var o="function"==typeof require&&require,r=0;r<i.length;r++)a(i[r]);return a}({1:[function(t,e,n){},{}],2:[function(t,e,n){function i(t){if(t){var e=/^#([a-fA-F0-9]{3})$/i,n=/^#([a-fA-F0-9]{6})$/i,i=/^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i,a=/^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i,o=/(\w+)/,r=[0,0,0],l=1,s=t.match(e);if(s){s=s[1];for(d=0;d<r.length;d++)r[d]=parseInt(s[d]+s[d],16)}else if(s=t.match(n)){s=s[1];for(d=0;d<r.length;d++)r[d]=parseInt(s.slice(2*d,2*d+2),16)}else if(s=t.match(i)){for(d=0;d<r.length;d++)r[d]=parseInt(s[d+1]);l=parseFloat(s[4])}else if(s=t.match(a)){for(d=0;d<r.length;d++)r[d]=Math.round(2.55*parseFloat(s[d+1]));l=parseFloat(s[4])}else if(s=t.match(o)){if("transparent"==s[1])return[0,0,0,0];if(!(r=c[s[1]]))return}for(var d=0;d<r.length;d++)r[d]=u(r[d],0,255);return l=l||0==l?u(l,0,1):1,r[3]=l,r}}function a(t){if(t){var e=/^hsla?\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/,n=t.match(e);if(n){var i=parseFloat(n[4]);return[u(parseInt(n[1]),0,360),u(parseFloat(n[2]),0,100),u(parseFloat(n[3]),0,100),u(isNaN(i)?1:i,0,1)]}}}function o(t){if(t){var e=/^hwb\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/,n=t.match(e);if(n){var i=parseFloat(n[4]);return[u(parseInt(n[1]),0,360),u(parseFloat(n[2]),0,100),u(parseFloat(n[3]),0,100),u(isNaN(i)?1:i,0,1)]}}}function r(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"rgba("+t[0]+", "+t[1]+", "+t[2]+", "+e+")"}function l(t,e){return"rgba("+Math.round(t[0]/255*100)+"%, "+Math.round(t[1]/255*100)+"%, "+Math.round(t[2]/255*100)+"%, "+(e||t[3]||1)+")"}function s(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"hsla("+t[0]+", "+t[1]+"%, "+t[2]+"%, "+e+")"}function u(t,e,n){return Math.min(Math.max(e,t),n)}function d(t){var e=t.toString(16).toUpperCase();return e.length<2?"0"+e:e}var c=t(6);e.exports={getRgba:i,getHsla:a,getRgb:function(t){var e=i(t);return e&&e.slice(0,3)},getHsl:function(t){var e=a(t);return e&&e.slice(0,3)},getHwb:o,getAlpha:function(t){var e=i(t);return e?e[3]:(e=a(t))?e[3]:(e=o(t))?e[3]:void 0},hexString:function(t){return"#"+d(t[0])+d(t[1])+d(t[2])},rgbString:function(t,e){return e<1||t[3]&&t[3]<1?r(t,e):"rgb("+t[0]+", "+t[1]+", "+t[2]+")"},rgbaString:r,percentString:function(t,e){return e<1||t[3]&&t[3]<1?l(t,e):"rgb("+Math.round(t[0]/255*100)+"%, "+Math.round(t[1]/255*100)+"%, "+Math.round(t[2]/255*100)+"%)"},percentaString:l,hslString:function(t,e){return e<1||t[3]&&t[3]<1?s(t,e):"hsl("+t[0]+", "+t[1]+"%, "+t[2]+"%)"},hslaString:s,hwbString:function(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"hwb("+t[0]+", "+t[1]+"%, "+t[2]+"%"+(void 0!==e&&1!==e?", "+e:"")+")"},keyword:function(t){return h[t.slice(0,3)]}};var h={};for(var f in c)h[c[f]]=f},{6:6}],3:[function(t,e,n){var i=t(5),a=t(2),o=function(t){if(t instanceof o)return t;if(!(this instanceof o))return new o(t);this.valid=!1,this.values={rgb:[0,0,0],hsl:[0,0,0],hsv:[0,0,0],hwb:[0,0,0],cmyk:[0,0,0,0],alpha:1};var e;"string"==typeof t?(e=a.getRgba(t))?this.setValues("rgb",e):(e=a.getHsla(t))?this.setValues("hsl",e):(e=a.getHwb(t))&&this.setValues("hwb",e):"object"==typeof t&&(void 0!==(e=t).r||void 0!==e.red?this.setValues("rgb",e):void 0!==e.l||void 0!==e.lightness?this.setValues("hsl",e):void 0!==e.v||void 0!==e.value?this.setValues("hsv",e):void 0!==e.w||void 0!==e.whiteness?this.setValues("hwb",e):void 0===e.c&&void 0===e.cyan||this.setValues("cmyk",e))};o.prototype={isValid:function(){return this.valid},rgb:function(){return this.setSpace("rgb",arguments)},hsl:function(){return this.setSpace("hsl",arguments)},hsv:function(){return this.setSpace("hsv",arguments)},hwb:function(){return this.setSpace("hwb",arguments)},cmyk:function(){return this.setSpace("cmyk",arguments)},rgbArray:function(){return this.values.rgb},hslArray:function(){return this.values.hsl},hsvArray:function(){return this.values.hsv},hwbArray:function(){var t=this.values;return 1!==t.alpha?t.hwb.concat([t.alpha]):t.hwb},cmykArray:function(){return this.values.cmyk},rgbaArray:function(){var t=this.values;return t.rgb.concat([t.alpha])},hslaArray:function(){var t=this.values;return t.hsl.concat([t.alpha])},alpha:function(t){return void 0===t?this.values.alpha:(this.setValues("alpha",t),this)},red:function(t){return this.setChannel("rgb",0,t)},green:function(t){return this.setChannel("rgb",1,t)},blue:function(t){return this.setChannel("rgb",2,t)},hue:function(t){return t&&(t=(t%=360)<0?360+t:t),this.setChannel("hsl",0,t)},saturation:function(t){return this.setChannel("hsl",1,t)},lightness:function(t){return this.setChannel("hsl",2,t)},saturationv:function(t){return this.setChannel("hsv",1,t)},whiteness:function(t){return this.setChannel("hwb",1,t)},blackness:function(t){return this.setChannel("hwb",2,t)},value:function(t){return this.setChannel("hsv",2,t)},cyan:function(t){return this.setChannel("cmyk",0,t)},magenta:function(t){return this.setChannel("cmyk",1,t)},yellow:function(t){return this.setChannel("cmyk",2,t)},black:function(t){return this.setChannel("cmyk",3,t)},hexString:function(){return a.hexString(this.values.rgb)},rgbString:function(){return a.rgbString(this.values.rgb,this.values.alpha)},rgbaString:function(){return a.rgbaString(this.values.rgb,this.values.alpha)},percentString:function(){return a.percentString(this.values.rgb,this.values.alpha)},hslString:function(){return a.hslString(this.values.hsl,this.values.alpha)},hslaString:function(){return a.hslaString(this.values.hsl,this.values.alpha)},hwbString:function(){return a.hwbString(this.values.hwb,this.values.alpha)},keyword:function(){return a.keyword(this.values.rgb,this.values.alpha)},rgbNumber:function(){var t=this.values.rgb;return t[0]<<16|t[1]<<8|t[2]},luminosity:function(){for(var t=this.values.rgb,e=[],n=0;n<t.length;n++){var i=t[n]/255;e[n]=i<=.03928?i/12.92:Math.pow((i+.055)/1.055,2.4)}return.2126*e[0]+.7152*e[1]+.0722*e[2]},contrast:function(t){var e=this.luminosity(),n=t.luminosity();return e>n?(e+.05)/(n+.05):(n+.05)/(e+.05)},level:function(t){var e=this.contrast(t);return e>=7.1?"AAA":e>=4.5?"AA":""},dark:function(){var t=this.values.rgb;return(299*t[0]+587*t[1]+114*t[2])/1e3<128},light:function(){return!this.dark()},negate:function(){for(var t=[],e=0;e<3;e++)t[e]=255-this.values.rgb[e];return this.setValues("rgb",t),this},lighten:function(t){var e=this.values.hsl;return e[2]+=e[2]*t,this.setValues("hsl",e),this},darken:function(t){var e=this.values.hsl;return e[2]-=e[2]*t,this.setValues("hsl",e),this},saturate:function(t){var e=this.values.hsl;return e[1]+=e[1]*t,this.setValues("hsl",e),this},desaturate:function(t){var e=this.values.hsl;return e[1]-=e[1]*t,this.setValues("hsl",e),this},whiten:function(t){var e=this.values.hwb;return e[1]+=e[1]*t,this.setValues("hwb",e),this},blacken:function(t){var e=this.values.hwb;return e[2]+=e[2]*t,this.setValues("hwb",e),this},greyscale:function(){var t=this.values.rgb,e=.3*t[0]+.59*t[1]+.11*t[2];return this.setValues("rgb",[e,e,e]),this},clearer:function(t){var e=this.values.alpha;return this.setValues("alpha",e-e*t),this},opaquer:function(t){var e=this.values.alpha;return this.setValues("alpha",e+e*t),this},rotate:function(t){var e=this.values.hsl,n=(e[0]+t)%360;return e[0]=n<0?360+n:n,this.setValues("hsl",e),this},mix:function(t,e){var n=this,i=t,a=void 0===e?.5:e,o=2*a-1,r=n.alpha()-i.alpha(),l=((o*r==-1?o:(o+r)/(1+o*r))+1)/2,s=1-l;return this.rgb(l*n.red()+s*i.red(),l*n.green()+s*i.green(),l*n.blue()+s*i.blue()).alpha(n.alpha()*a+i.alpha()*(1-a))},toJSON:function(){return this.rgb()},clone:function(){var t,e,n=new o,i=this.values,a=n.values;for(var r in i)i.hasOwnProperty(r)&&(t=i[r],"[object Array]"===(e={}.toString.call(t))?a[r]=t.slice(0):"[object Number]"===e?a[r]=t:console.error("unexpected color value:",t));return n}},o.prototype.spaces={rgb:["red","green","blue"],hsl:["hue","saturation","lightness"],hsv:["hue","saturation","value"],hwb:["hue","whiteness","blackness"],cmyk:["cyan","magenta","yellow","black"]},o.prototype.maxes={rgb:[255,255,255],hsl:[360,100,100],hsv:[360,100,100],hwb:[360,100,100],cmyk:[100,100,100,100]},o.prototype.getValues=function(t){for(var e=this.values,n={},i=0;i<t.length;i++)n[t.charAt(i)]=e[t][i];return 1!==e.alpha&&(n.a=e.alpha),n},o.prototype.setValues=function(t,e){var n,a=this.values,o=this.spaces,r=this.maxes,l=1;if(this.valid=!0,"alpha"===t)l=e;else if(e.length)a[t]=e.slice(0,t.length),l=e[t.length];else if(void 0!==e[t.charAt(0)]){for(n=0;n<t.length;n++)a[t][n]=e[t.charAt(n)];l=e.a}else if(void 0!==e[o[t][0]]){var s=o[t];for(n=0;n<t.length;n++)a[t][n]=e[s[n]];l=e.alpha}if(a.alpha=Math.max(0,Math.min(1,void 0===l?a.alpha:l)),"alpha"===t)return!1;var u;for(n=0;n<t.length;n++)u=Math.max(0,Math.min(r[t][n],a[t][n])),a[t][n]=Math.round(u);for(var d in o)d!==t&&(a[d]=i[t][d](a[t]));return!0},o.prototype.setSpace=function(t,e){var n=e[0];return void 0===n?this.getValues(t):("number"==typeof n&&(n=Array.prototype.slice.call(e)),this.setValues(t,n),this)},o.prototype.setChannel=function(t,e,n){var i=this.values[t];return void 0===n?i[e]:n===i[e]?this:(i[e]=n,this.setValues(t,i),this)},"undefined"!=typeof window&&(window.Color=o),e.exports=o},{2:2,5:5}],4:[function(t,e,n){function i(t){var e,n,i,a=t[0]/255,o=t[1]/255,r=t[2]/255,l=Math.min(a,o,r),s=Math.max(a,o,r),u=s-l;return s==l?e=0:a==s?e=(o-r)/u:o==s?e=2+(r-a)/u:r==s&&(e=4+(a-o)/u),(e=Math.min(60*e,360))<0&&(e+=360),i=(l+s)/2,n=s==l?0:i<=.5?u/(s+l):u/(2-s-l),[e,100*n,100*i]}function a(t){var e,n,i,a=t[0],o=t[1],r=t[2],l=Math.min(a,o,r),s=Math.max(a,o,r),u=s-l;return n=0==s?0:u/s*1e3/10,s==l?e=0:a==s?e=(o-r)/u:o==s?e=2+(r-a)/u:r==s&&(e=4+(a-o)/u),(e=Math.min(60*e,360))<0&&(e+=360),i=s/255*1e3/10,[e,n,i]}function o(t){var e=t[0],n=t[1],a=t[2];return[i(t)[0],100*(1/255*Math.min(e,Math.min(n,a))),100*(a=1-1/255*Math.max(e,Math.max(n,a)))]}function l(t){var e,n,i,a,o=t[0]/255,r=t[1]/255,l=t[2]/255;return a=Math.min(1-o,1-r,1-l),e=(1-o-a)/(1-a)||0,n=(1-r-a)/(1-a)||0,i=(1-l-a)/(1-a)||0,[100*e,100*n,100*i,100*a]}function s(t){return C[JSON.stringify(t)]}function u(t){var e=t[0]/255,n=t[1]/255,i=t[2]/255;return[100*(.4124*(e=e>.04045?Math.pow((e+.055)/1.055,2.4):e/12.92)+.3576*(n=n>.04045?Math.pow((n+.055)/1.055,2.4):n/12.92)+.1805*(i=i>.04045?Math.pow((i+.055)/1.055,2.4):i/12.92)),100*(.2126*e+.7152*n+.0722*i),100*(.0193*e+.1192*n+.9505*i)]}function d(t){var e,n,i,a=u(t),o=a[0],r=a[1],l=a[2];return o/=95.047,r/=100,l/=108.883,o=o>.008856?Math.pow(o,1/3):7.787*o+16/116,r=r>.008856?Math.pow(r,1/3):7.787*r+16/116,l=l>.008856?Math.pow(l,1/3):7.787*l+16/116,e=116*r-16,n=500*(o-r),i=200*(r-l),[e,n,i]}function c(t){var e,n,i,a,o,r=t[0]/360,l=t[1]/100,s=t[2]/100;if(0==l)return o=255*s,[o,o,o];e=2*s-(n=s<.5?s*(1+l):s+l-s*l),a=[0,0,0];for(var u=0;u<3;u++)(i=r+1/3*-(u-1))<0&&i++,i>1&&i--,o=6*i<1?e+6*(n-e)*i:2*i<1?n:3*i<2?e+(n-e)*(2/3-i)*6:e,a[u]=255*o;return a}function h(t){var e=t[0]/60,n=t[1]/100,i=t[2]/100,a=Math.floor(e)%6,o=e-Math.floor(e),r=255*i*(1-n),l=255*i*(1-n*o),s=255*i*(1-n*(1-o)),i=255*i;switch(a){case 0:return[i,s,r];case 1:return[l,i,r];case 2:return[r,i,s];case 3:return[r,l,i];case 4:return[s,r,i];case 5:return[i,r,l]}}function f(t){var e,n,i,a,o=t[0]/360,l=t[1]/100,s=t[2]/100,u=l+s;switch(u>1&&(l/=u,s/=u),e=Math.floor(6*o),n=1-s,i=6*o-e,0!=(1&e)&&(i=1-i),a=l+i*(n-l),e){default:case 6:case 0:r=n,g=a,b=l;break;case 1:r=a,g=n,b=l;break;case 2:r=l,g=n,b=a;break;case 3:r=l,g=a,b=n;break;case 4:r=a,g=l,b=n;break;case 5:r=n,g=l,b=a}return[255*r,255*g,255*b]}function p(t){var e,n,i,a=t[0]/100,o=t[1]/100,r=t[2]/100,l=t[3]/100;return e=1-Math.min(1,a*(1-l)+l),n=1-Math.min(1,o*(1-l)+l),i=1-Math.min(1,r*(1-l)+l),[255*e,255*n,255*i]}function v(t){var e,n,i,a=t[0]/100,o=t[1]/100,r=t[2]/100;return e=3.2406*a+-1.5372*o+-.4986*r,n=-.9689*a+1.8758*o+.0415*r,i=.0557*a+-.204*o+1.057*r,e=e>.0031308?1.055*Math.pow(e,1/2.4)-.055:e*=12.92,n=n>.0031308?1.055*Math.pow(n,1/2.4)-.055:n*=12.92,i=i>.0031308?1.055*Math.pow(i,1/2.4)-.055:i*=12.92,e=Math.min(Math.max(0,e),1),n=Math.min(Math.max(0,n),1),i=Math.min(Math.max(0,i),1),[255*e,255*n,255*i]}function m(t){var e,n,i,a=t[0],o=t[1],r=t[2];return a/=95.047,o/=100,r/=108.883,a=a>.008856?Math.pow(a,1/3):7.787*a+16/116,o=o>.008856?Math.pow(o,1/3):7.787*o+16/116,r=r>.008856?Math.pow(r,1/3):7.787*r+16/116,e=116*o-16,n=500*(a-o),i=200*(o-r),[e,n,i]}function x(t){var e,n,i,a,o=t[0],r=t[1],l=t[2];return o<=8?a=(n=100*o/903.3)/100*7.787+16/116:(n=100*Math.pow((o+16)/116,3),a=Math.pow(n/100,1/3)),e=e/95.047<=.008856?e=95.047*(r/500+a-16/116)/7.787:95.047*Math.pow(r/500+a,3),i=i/108.883<=.008859?i=108.883*(a-l/200-16/116)/7.787:108.883*Math.pow(a-l/200,3),[e,n,i]}function y(t){var e,n,i,a=t[0],o=t[1],r=t[2];return e=Math.atan2(r,o),(n=360*e/2/Math.PI)<0&&(n+=360),i=Math.sqrt(o*o+r*r),[a,i,n]}function k(t){return v(x(t))}function w(t){var e,n,i,a=t[0],o=t[1];return i=t[2]/360*2*Math.PI,e=o*Math.cos(i),n=o*Math.sin(i),[a,e,n]}function M(t){return S[t]}e.exports={rgb2hsl:i,rgb2hsv:a,rgb2hwb:o,rgb2cmyk:l,rgb2keyword:s,rgb2xyz:u,rgb2lab:d,rgb2lch:function(t){return y(d(t))},hsl2rgb:c,hsl2hsv:function(t){var e,n,i=t[0],a=t[1]/100,o=t[2]/100;return 0===o?[0,0,0]:(o*=2,a*=o<=1?o:2-o,n=(o+a)/2,e=2*a/(o+a),[i,100*e,100*n])},hsl2hwb:function(t){return o(c(t))},hsl2cmyk:function(t){return l(c(t))},hsl2keyword:function(t){return s(c(t))},hsv2rgb:h,hsv2hsl:function(t){var e,n,i=t[0],a=t[1]/100,o=t[2]/100;return n=(2-a)*o,e=a*o,e/=n<=1?n:2-n,e=e||0,n/=2,[i,100*e,100*n]},hsv2hwb:function(t){return o(h(t))},hsv2cmyk:function(t){return l(h(t))},hsv2keyword:function(t){return s(h(t))},hwb2rgb:f,hwb2hsl:function(t){return i(f(t))},hwb2hsv:function(t){return a(f(t))},hwb2cmyk:function(t){return l(f(t))},hwb2keyword:function(t){return s(f(t))},cmyk2rgb:p,cmyk2hsl:function(t){return i(p(t))},cmyk2hsv:function(t){return a(p(t))},cmyk2hwb:function(t){return o(p(t))},cmyk2keyword:function(t){return s(p(t))},keyword2rgb:M,keyword2hsl:function(t){return i(M(t))},keyword2hsv:function(t){return a(M(t))},keyword2hwb:function(t){return o(M(t))},keyword2cmyk:function(t){return l(M(t))},keyword2lab:function(t){return d(M(t))},keyword2xyz:function(t){return u(M(t))},xyz2rgb:v,xyz2lab:m,xyz2lch:function(t){return y(m(t))},lab2xyz:x,lab2rgb:k,lab2lch:y,lch2lab:w,lch2xyz:function(t){return x(w(t))},lch2rgb:function(t){return k(w(t))}};var S={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]},C={};for(var _ in S)C[JSON.stringify(S[_])]=_},{}],5:[function(t,e,n){var i=t(4),a=function(){return new u};for(var o in i){a[o+"Raw"]=function(t){return function(e){return"number"==typeof e&&(e=Array.prototype.slice.call(arguments)),i[t](e)}}(o);var r=/(\w+)2(\w+)/.exec(o),l=r[1],s=r[2];(a[l]=a[l]||{})[s]=a[o]=function(t){return function(e){"number"==typeof e&&(e=Array.prototype.slice.call(arguments));var n=i[t](e);if("string"==typeof n||void 0===n)return n;for(var a=0;a<n.length;a++)n[a]=Math.round(n[a]);return n}}(o)}var u=function(){this.convs={}};u.prototype.routeSpace=function(t,e){var n=e[0];return void 0===n?this.getValues(t):("number"==typeof n&&(n=Array.prototype.slice.call(e)),this.setValues(t,n))},u.prototype.setValues=function(t,e){return this.space=t,this.convs={},this.convs[t]=e,this},u.prototype.getValues=function(t){var e=this.convs[t];if(!e){var n=this.space,i=this.convs[n];e=a[n][t](i),this.convs[t]=e}return e},["rgb","hsl","hsv","cmyk","keyword"].forEach(function(t){u.prototype[t]=function(e){return this.routeSpace(t,arguments)}}),e.exports=a},{4:4}],6:[function(t,e,n){"use strict";e.exports={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]}},{}],7:[function(t,e,n){var i=t(29)();i.helpers=t(45),t(27)(i),i.defaults=t(25),i.Element=t(26),i.elements=t(40),i.Interaction=t(28),i.platform=t(48),t(31)(i),t(22)(i),t(23)(i),t(24)(i),t(30)(i),t(33)(i),t(32)(i),t(35)(i),t(54)(i),t(52)(i),t(53)(i),t(55)(i),t(56)(i),t(57)(i),t(15)(i),t(16)(i),t(17)(i),t(18)(i),t(19)(i),t(20)(i),t(21)(i),t(8)(i),t(9)(i),t(10)(i),t(11)(i),t(12)(i),t(13)(i),t(14)(i);var a=[];a.push(t(49)(i),t(50)(i),t(51)(i)),i.plugins.register(a),i.platform.initialize(),e.exports=i,"undefined"!=typeof window&&(window.Chart=i),i.canvasHelpers=i.helpers.canvas},{10:10,11:11,12:12,13:13,14:14,15:15,16:16,17:17,18:18,19:19,20:20,21:21,22:22,23:23,24:24,25:25,26:26,27:27,28:28,29:29,30:30,31:31,32:32,33:33,35:35,40:40,45:45,48:48,49:49,50:50,51:51,52:52,53:53,54:54,55:55,56:56,57:57,8:8,9:9}],8:[function(t,e,n){"use strict";e.exports=function(t){t.Bar=function(e,n){return n.type="bar",new t(e,n)}}},{}],9:[function(t,e,n){"use strict";e.exports=function(t){t.Bubble=function(e,n){return n.type="bubble",new t(e,n)}}},{}],10:[function(t,e,n){"use strict";e.exports=function(t){t.Doughnut=function(e,n){return n.type="doughnut",new t(e,n)}}},{}],11:[function(t,e,n){"use strict";e.exports=function(t){t.Line=function(e,n){return n.type="line",new t(e,n)}}},{}],12:[function(t,e,n){"use strict";e.exports=function(t){t.PolarArea=function(e,n){return n.type="polarArea",new t(e,n)}}},{}],13:[function(t,e,n){"use strict";e.exports=function(t){t.Radar=function(e,n){return n.type="radar",new t(e,n)}}},{}],14:[function(t,e,n){"use strict";e.exports=function(t){t.Scatter=function(e,n){return n.type="scatter",new t(e,n)}}},{}],15:[function(t,e,n){"use strict";var i=t(25),a=t(40),o=t(45);i._set("bar",{hover:{mode:"label"},scales:{xAxes:[{type:"category",categoryPercentage:.8,barPercentage:.9,offset:!0,gridLines:{offsetGridLines:!0}}],yAxes:[{type:"linear"}]}}),i._set("horizontalBar",{hover:{mode:"index",axis:"y"},scales:{xAxes:[{type:"linear",position:"bottom"}],yAxes:[{position:"left",type:"category",categoryPercentage:.8,barPercentage:.9,offset:!0,gridLines:{offsetGridLines:!0}}]},elements:{rectangle:{borderSkipped:"left"}},tooltips:{callbacks:{title:function(t,e){var n="";return t.length>0&&(t[0].yLabel?n=t[0].yLabel:e.labels.length>0&&t[0].index<e.labels.length&&(n=e.labels[t[0].index])),n},label:function(t,e){return(e.datasets[t.datasetIndex].label||"")+": "+t.xLabel}},mode:"index",axis:"y"}}),e.exports=function(t){t.controllers.bar=t.DatasetController.extend({dataElementType:a.Rectangle,initialize:function(){var e,n=this;t.DatasetController.prototype.initialize.apply(n,arguments),(e=n.getMeta()).stack=n.getDataset().stack,e.bar=!0},update:function(t){var e,n,i=this,a=i.getMeta().data;for(i._ruler=i.getRuler(),e=0,n=a.length;e<n;++e)i.updateElement(a[e],e,t)},updateElement:function(t,e,n){var i=this,a=i.chart,r=i.getMeta(),l=i.getDataset(),s=t.custom||{},u=a.options.elements.rectangle;t._xScale=i.getScaleForId(r.xAxisID),t._yScale=i.getScaleForId(r.yAxisID),t._datasetIndex=i.index,t._index=e,t._model={datasetLabel:l.label,label:a.data.labels[e],borderSkipped:s.borderSkipped?s.borderSkipped:u.borderSkipped,backgroundColor:s.backgroundColor?s.backgroundColor:o.valueAtIndexOrDefault(l.backgroundColor,e,u.backgroundColor),borderColor:s.borderColor?s.borderColor:o.valueAtIndexOrDefault(l.borderColor,e,u.borderColor),borderWidth:s.borderWidth?s.borderWidth:o.valueAtIndexOrDefault(l.borderWidth,e,u.borderWidth)},i.updateElementGeometry(t,e,n),t.pivot()},updateElementGeometry:function(t,e,n){var i=this,a=t._model,o=i.getValueScale(),r=o.getBasePixel(),l=o.isHorizontal(),s=i._ruler||i.getRuler(),u=i.calculateBarValuePixels(i.index,e),d=i.calculateBarIndexPixels(i.index,e,s);a.horizontal=l,a.base=n?r:u.base,a.x=l?n?r:u.head:d.center,a.y=l?d.center:n?r:u.head,a.height=l?d.size:void 0,a.width=l?void 0:d.size},getValueScaleId:function(){return this.getMeta().yAxisID},getIndexScaleId:function(){return this.getMeta().xAxisID},getValueScale:function(){return this.getScaleForId(this.getValueScaleId())},getIndexScale:function(){return this.getScaleForId(this.getIndexScaleId())},getStackCount:function(t){var e,n,i=this,a=i.chart,o=i.getIndexScale().options.stacked,r=void 0===t?a.data.datasets.length:t+1,l=[];for(e=0;e<r;++e)(n=a.getDatasetMeta(e)).bar&&a.isDatasetVisible(e)&&(!1===o||!0===o&&-1===l.indexOf(n.stack)||void 0===o&&(void 0===n.stack||-1===l.indexOf(n.stack)))&&l.push(n.stack);return l.length},getStackIndex:function(t){return this.getStackCount(t)-1},getRuler:function(){var t,e,n=this,i=n.getIndexScale(),a=n.getStackCount(),o=n.index,r=[],l=i.isHorizontal(),s=l?i.left:i.top,u=s+(l?i.width:i.height);for(t=0,e=n.getMeta().data.length;t<e;++t)r.push(i.getPixelForValue(null,t,o));return{pixels:r,start:s,end:u,stackCount:a,scale:i}},calculateBarValuePixels:function(t,e){var n,i,a,o,r,l,s=this,u=s.chart,d=s.getMeta(),c=s.getValueScale(),h=u.data.datasets,f=c.getRightValue(h[t].data[e]),g=c.options.stacked,p=d.stack,v=0;if(g||void 0===g&&void 0!==p)for(n=0;n<t;++n)(i=u.getDatasetMeta(n)).bar&&i.stack===p&&i.controller.getValueScaleId()===c.id&&u.isDatasetVisible(n)&&(a=c.getRightValue(h[n].data[e]),(f<0&&a<0||f>=0&&a>0)&&(v+=a));return o=c.getPixelForValue(v),r=c.getPixelForValue(v+f),l=(r-o)/2,{size:l,base:o,head:r,center:r+l/2}},calculateBarIndexPixels:function(t,e,n){var i,a,r,l,s,u,d=this,c=n.scale.options,h=d.getStackIndex(t),f=n.pixels,g=f[e],p=f.length,v=n.start,m=n.end;return 1===p?(i=g>v?g-v:m-g,a=g<m?m-g:g-v):(e>0&&(i=(g-f[e-1])/2,e===p-1&&(a=i)),e<p-1&&(a=(f[e+1]-g)/2,0===e&&(i=a))),r=i*c.categoryPercentage,l=a*c.categoryPercentage,s=(r+l)/n.stackCount,u=s*c.barPercentage,u=Math.min(o.valueOrDefault(c.barThickness,u),o.valueOrDefault(c.maxBarThickness,1/0)),g-=r,g+=s*h,g+=(s-u)/2,{size:u,base:g,head:g+u,center:g+u/2}},draw:function(){var t=this,e=t.chart,n=t.getValueScale(),i=t.getMeta().data,a=t.getDataset(),r=i.length,l=0;for(o.canvas.clipArea(e.ctx,e.chartArea);l<r;++l)isNaN(n.getRightValue(a.data[l]))||i[l].draw();o.canvas.unclipArea(e.ctx)},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t._index,i=t.custom||{},a=t._model;a.backgroundColor=i.hoverBackgroundColor?i.hoverBackgroundColor:o.valueAtIndexOrDefault(e.hoverBackgroundColor,n,o.getHoverColor(a.backgroundColor)),a.borderColor=i.hoverBorderColor?i.hoverBorderColor:o.valueAtIndexOrDefault(e.hoverBorderColor,n,o.getHoverColor(a.borderColor)),a.borderWidth=i.hoverBorderWidth?i.hoverBorderWidth:o.valueAtIndexOrDefault(e.hoverBorderWidth,n,a.borderWidth)},removeHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t._index,i=t.custom||{},a=t._model,r=this.chart.options.elements.rectangle;a.backgroundColor=i.backgroundColor?i.backgroundColor:o.valueAtIndexOrDefault(e.backgroundColor,n,r.backgroundColor),a.borderColor=i.borderColor?i.borderColor:o.valueAtIndexOrDefault(e.borderColor,n,r.borderColor),a.borderWidth=i.borderWidth?i.borderWidth:o.valueAtIndexOrDefault(e.borderWidth,n,r.borderWidth)}}),t.controllers.horizontalBar=t.controllers.bar.extend({getValueScaleId:function(){return this.getMeta().xAxisID},getIndexScaleId:function(){return this.getMeta().yAxisID}})}},{25:25,40:40,45:45}],16:[function(t,e,n){"use strict";var i=t(25),a=t(40),o=t(45);i._set("bubble",{hover:{mode:"single"},scales:{xAxes:[{type:"linear",position:"bottom",id:"x-axis-0"}],yAxes:[{type:"linear",position:"left",id:"y-axis-0"}]},tooltips:{callbacks:{title:function(){return""},label:function(t,e){var n=e.datasets[t.datasetIndex].label||"",i=e.datasets[t.datasetIndex].data[t.index];return n+": ("+t.xLabel+", "+t.yLabel+", "+i.r+")"}}}}),e.exports=function(t){t.controllers.bubble=t.DatasetController.extend({dataElementType:a.Point,update:function(t){var e=this,n=e.getMeta().data;o.each(n,function(n,i){e.updateElement(n,i,t)})},updateElement:function(t,e,n){var i=this,a=i.getMeta(),o=t.custom||{},r=i.getScaleForId(a.xAxisID),l=i.getScaleForId(a.yAxisID),s=i._resolveElementOptions(t,e),u=i.getDataset().data[e],d=i.index,c=n?r.getPixelForDecimal(.5):r.getPixelForValue("object"==typeof u?u:NaN,e,d),h=n?l.getBasePixel():l.getPixelForValue(u,e,d);t._xScale=r,t._yScale=l,t._options=s,t._datasetIndex=d,t._index=e,t._model={backgroundColor:s.backgroundColor,borderColor:s.borderColor,borderWidth:s.borderWidth,hitRadius:s.hitRadius,pointStyle:s.pointStyle,radius:n?0:s.radius,skip:o.skip||isNaN(c)||isNaN(h),x:c,y:h},t.pivot()},setHoverStyle:function(t){var e=t._model,n=t._options;e.backgroundColor=o.valueOrDefault(n.hoverBackgroundColor,o.getHoverColor(n.backgroundColor)),e.borderColor=o.valueOrDefault(n.hoverBorderColor,o.getHoverColor(n.borderColor)),e.borderWidth=o.valueOrDefault(n.hoverBorderWidth,n.borderWidth),e.radius=n.radius+n.hoverRadius},removeHoverStyle:function(t){var e=t._model,n=t._options;e.backgroundColor=n.backgroundColor,e.borderColor=n.borderColor,e.borderWidth=n.borderWidth,e.radius=n.radius},_resolveElementOptions:function(t,e){var n,i,a,r=this,l=r.chart,s=l.data.datasets[r.index],u=t.custom||{},d=l.options.elements.point,c=o.options.resolve,h=s.data[e],f={},g={chart:l,dataIndex:e,dataset:s,datasetIndex:r.index},p=["backgroundColor","borderColor","borderWidth","hoverBackgroundColor","hoverBorderColor","hoverBorderWidth","hoverRadius","hitRadius","pointStyle"];for(n=0,i=p.length;n<i;++n)f[a=p[n]]=c([u[a],s[a],d[a]],g,e);return f.radius=c([u.radius,h?h.r:void 0,s.radius,d.radius],g,e),f}})}},{25:25,40:40,45:45}],17:[function(t,e,n){"use strict";var i=t(25),a=t(40),o=t(45);i._set("doughnut",{animation:{animateRotate:!0,animateScale:!1},hover:{mode:"single"},legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');var n=t.data,i=n.datasets,a=n.labels;if(i.length)for(var o=0;o<i[0].data.length;++o)e.push('<li><span style="background-color:'+i[0].backgroundColor[o]+'"></span>'),a[o]&&e.push(a[o]),e.push("</li>");return e.push("</ul>"),e.join("")},legend:{labels:{generateLabels:function(t){var e=t.data;return e.labels.length&&e.datasets.length?e.labels.map(function(n,i){var a=t.getDatasetMeta(0),r=e.datasets[0],l=a.data[i],s=l&&l.custom||{},u=o.valueAtIndexOrDefault,d=t.options.elements.arc;return{text:n,fillStyle:s.backgroundColor?s.backgroundColor:u(r.backgroundColor,i,d.backgroundColor),strokeStyle:s.borderColor?s.borderColor:u(r.borderColor,i,d.borderColor),lineWidth:s.borderWidth?s.borderWidth:u(r.borderWidth,i,d.borderWidth),hidden:isNaN(r.data[i])||a.data[i].hidden,index:i}}):[]}},onClick:function(t,e){var n,i,a,o=e.index,r=this.chart;for(n=0,i=(r.data.datasets||[]).length;n<i;++n)(a=r.getDatasetMeta(n)).data[o]&&(a.data[o].hidden=!a.data[o].hidden);r.update()}},cutoutPercentage:50,rotation:-.5*Math.PI,circumference:2*Math.PI,tooltips:{callbacks:{title:function(){return""},label:function(t,e){var n=e.labels[t.index],i=": "+e.datasets[t.datasetIndex].data[t.index];return o.isArray(n)?(n=n.slice())[0]+=i:n+=i,n}}}}),i._set("pie",o.clone(i.doughnut)),i._set("pie",{cutoutPercentage:0}),e.exports=function(t){t.controllers.doughnut=t.controllers.pie=t.DatasetController.extend({dataElementType:a.Arc,linkScales:o.noop,getRingIndex:function(t){for(var e=0,n=0;n<t;++n)this.chart.isDatasetVisible(n)&&++e;return e},update:function(t){var e=this,n=e.chart,i=n.chartArea,a=n.options,r=a.elements.arc,l=i.right-i.left-r.borderWidth,s=i.bottom-i.top-r.borderWidth,u=Math.min(l,s),d={x:0,y:0},c=e.getMeta(),h=a.cutoutPercentage,f=a.circumference;if(f<2*Math.PI){var g=a.rotation%(2*Math.PI),p=(g+=2*Math.PI*(g>=Math.PI?-1:g<-Math.PI?1:0))+f,v={x:Math.cos(g),y:Math.sin(g)},m={x:Math.cos(p),y:Math.sin(p)},b=g<=0&&p>=0||g<=2*Math.PI&&2*Math.PI<=p,x=g<=.5*Math.PI&&.5*Math.PI<=p||g<=2.5*Math.PI&&2.5*Math.PI<=p,y=g<=-Math.PI&&-Math.PI<=p||g<=Math.PI&&Math.PI<=p,k=g<=.5*-Math.PI&&.5*-Math.PI<=p||g<=1.5*Math.PI&&1.5*Math.PI<=p,w=h/100,M={x:y?-1:Math.min(v.x*(v.x<0?1:w),m.x*(m.x<0?1:w)),y:k?-1:Math.min(v.y*(v.y<0?1:w),m.y*(m.y<0?1:w))},S={x:b?1:Math.max(v.x*(v.x>0?1:w),m.x*(m.x>0?1:w)),y:x?1:Math.max(v.y*(v.y>0?1:w),m.y*(m.y>0?1:w))},C={width:.5*(S.x-M.x),height:.5*(S.y-M.y)};u=Math.min(l/C.width,s/C.height),d={x:-.5*(S.x+M.x),y:-.5*(S.y+M.y)}}n.borderWidth=e.getMaxBorderWidth(c.data),n.outerRadius=Math.max((u-n.borderWidth)/2,0),n.innerRadius=Math.max(h?n.outerRadius/100*h:0,0),n.radiusLength=(n.outerRadius-n.innerRadius)/n.getVisibleDatasetCount(),n.offsetX=d.x*n.outerRadius,n.offsetY=d.y*n.outerRadius,c.total=e.calculateTotal(),e.outerRadius=n.outerRadius-n.radiusLength*e.getRingIndex(e.index),e.innerRadius=Math.max(e.outerRadius-n.radiusLength,0),o.each(c.data,function(n,i){e.updateElement(n,i,t)})},updateElement:function(t,e,n){var i=this,a=i.chart,r=a.chartArea,l=a.options,s=l.animation,u=(r.left+r.right)/2,d=(r.top+r.bottom)/2,c=l.rotation,h=l.rotation,f=i.getDataset(),g=n&&s.animateRotate?0:t.hidden?0:i.calculateCircumference(f.data[e])*(l.circumference/(2*Math.PI)),p=n&&s.animateScale?0:i.innerRadius,v=n&&s.animateScale?0:i.outerRadius,m=o.valueAtIndexOrDefault;o.extend(t,{_datasetIndex:i.index,_index:e,_model:{x:u+a.offsetX,y:d+a.offsetY,startAngle:c,endAngle:h,circumference:g,outerRadius:v,innerRadius:p,label:m(f.label,e,a.data.labels[e])}});var b=t._model;this.removeHoverStyle(t),n&&s.animateRotate||(b.startAngle=0===e?l.rotation:i.getMeta().data[e-1]._model.endAngle,b.endAngle=b.startAngle+b.circumference),t.pivot()},removeHoverStyle:function(e){t.DatasetController.prototype.removeHoverStyle.call(this,e,this.chart.options.elements.arc)},calculateTotal:function(){var t,e=this.getDataset(),n=this.getMeta(),i=0;return o.each(n.data,function(n,a){t=e.data[a],isNaN(t)||n.hidden||(i+=Math.abs(t))}),i},calculateCircumference:function(t){var e=this.getMeta().total;return e>0&&!isNaN(t)?2*Math.PI*(t/e):0},getMaxBorderWidth:function(t){for(var e,n,i=0,a=this.index,o=t.length,r=0;r<o;r++)e=t[r]._model?t[r]._model.borderWidth:0,i=(n=t[r]._chart?t[r]._chart.config.data.datasets[a].hoverBorderWidth:0)>(i=e>i?e:i)?n:i;return i}})}},{25:25,40:40,45:45}],18:[function(t,e,n){"use strict";var i=t(25),a=t(40),o=t(45);i._set("line",{showLines:!0,spanGaps:!1,hover:{mode:"label"},scales:{xAxes:[{type:"category",id:"x-axis-0"}],yAxes:[{type:"linear",id:"y-axis-0"}]}}),e.exports=function(t){function e(t,e){return o.valueOrDefault(t.showLine,e.showLines)}t.controllers.line=t.DatasetController.extend({datasetElementType:a.Line,dataElementType:a.Point,update:function(t){var n,i,a,r=this,l=r.getMeta(),s=l.dataset,u=l.data||[],d=r.chart.options,c=d.elements.line,h=r.getScaleForId(l.yAxisID),f=r.getDataset(),g=e(f,d);for(g&&(a=s.custom||{},void 0!==f.tension&&void 0===f.lineTension&&(f.lineTension=f.tension),s._scale=h,s._datasetIndex=r.index,s._children=u,s._model={spanGaps:f.spanGaps?f.spanGaps:d.spanGaps,tension:a.tension?a.tension:o.valueOrDefault(f.lineTension,c.tension),backgroundColor:a.backgroundColor?a.backgroundColor:f.backgroundColor||c.backgroundColor,borderWidth:a.borderWidth?a.borderWidth:f.borderWidth||c.borderWidth,borderColor:a.borderColor?a.borderColor:f.borderColor||c.borderColor,borderCapStyle:a.borderCapStyle?a.borderCapStyle:f.borderCapStyle||c.borderCapStyle,borderDash:a.borderDash?a.borderDash:f.borderDash||c.borderDash,borderDashOffset:a.borderDashOffset?a.borderDashOffset:f.borderDashOffset||c.borderDashOffset,borderJoinStyle:a.borderJoinStyle?a.borderJoinStyle:f.borderJoinStyle||c.borderJoinStyle,fill:a.fill?a.fill:void 0!==f.fill?f.fill:c.fill,steppedLine:a.steppedLine?a.steppedLine:o.valueOrDefault(f.steppedLine,c.stepped),cubicInterpolationMode:a.cubicInterpolationMode?a.cubicInterpolationMode:o.valueOrDefault(f.cubicInterpolationMode,c.cubicInterpolationMode)},s.pivot()),n=0,i=u.length;n<i;++n)r.updateElement(u[n],n,t);for(g&&0!==s._model.tension&&r.updateBezierControlPoints(),n=0,i=u.length;n<i;++n)u[n].pivot()},getPointBackgroundColor:function(t,e){var n=this.chart.options.elements.point.backgroundColor,i=this.getDataset(),a=t.custom||{};return a.backgroundColor?n=a.backgroundColor:i.pointBackgroundColor?n=o.valueAtIndexOrDefault(i.pointBackgroundColor,e,n):i.backgroundColor&&(n=i.backgroundColor),n},getPointBorderColor:function(t,e){var n=this.chart.options.elements.point.borderColor,i=this.getDataset(),a=t.custom||{};return a.borderColor?n=a.borderColor:i.pointBorderColor?n=o.valueAtIndexOrDefault(i.pointBorderColor,e,n):i.borderColor&&(n=i.borderColor),n},getPointBorderWidth:function(t,e){var n=this.chart.options.elements.point.borderWidth,i=this.getDataset(),a=t.custom||{};return isNaN(a.borderWidth)?!isNaN(i.pointBorderWidth)||o.isArray(i.pointBorderWidth)?n=o.valueAtIndexOrDefault(i.pointBorderWidth,e,n):isNaN(i.borderWidth)||(n=i.borderWidth):n=a.borderWidth,n},updateElement:function(t,e,n){var i,a,r=this,l=r.getMeta(),s=t.custom||{},u=r.getDataset(),d=r.index,c=u.data[e],h=r.getScaleForId(l.yAxisID),f=r.getScaleForId(l.xAxisID),g=r.chart.options.elements.point;void 0!==u.radius&&void 0===u.pointRadius&&(u.pointRadius=u.radius),void 0!==u.hitRadius&&void 0===u.pointHitRadius&&(u.pointHitRadius=u.hitRadius),i=f.getPixelForValue("object"==typeof c?c:NaN,e,d),a=n?h.getBasePixel():r.calculatePointY(c,e,d),t._xScale=f,t._yScale=h,t._datasetIndex=d,t._index=e,t._model={x:i,y:a,skip:s.skip||isNaN(i)||isNaN(a),radius:s.radius||o.valueAtIndexOrDefault(u.pointRadius,e,g.radius),pointStyle:s.pointStyle||o.valueAtIndexOrDefault(u.pointStyle,e,g.pointStyle),backgroundColor:r.getPointBackgroundColor(t,e),borderColor:r.getPointBorderColor(t,e),borderWidth:r.getPointBorderWidth(t,e),tension:l.dataset._model?l.dataset._model.tension:0,steppedLine:!!l.dataset._model&&l.dataset._model.steppedLine,hitRadius:s.hitRadius||o.valueAtIndexOrDefault(u.pointHitRadius,e,g.hitRadius)}},calculatePointY:function(t,e,n){var i,a,o,r=this,l=r.chart,s=r.getMeta(),u=r.getScaleForId(s.yAxisID),d=0,c=0;if(u.options.stacked){for(i=0;i<n;i++)if(a=l.data.datasets[i],"line"===(o=l.getDatasetMeta(i)).type&&o.yAxisID===u.id&&l.isDatasetVisible(i)){var h=Number(u.getRightValue(a.data[e]));h<0?c+=h||0:d+=h||0}var f=Number(u.getRightValue(t));return f<0?u.getPixelForValue(c+f):u.getPixelForValue(d+f)}return u.getPixelForValue(t)},updateBezierControlPoints:function(){function t(t,e,n){return Math.max(Math.min(t,n),e)}var e,n,i,a,r=this,l=r.getMeta(),s=r.chart.chartArea,u=l.data||[];if(l.dataset._model.spanGaps&&(u=u.filter(function(t){return!t._model.skip})),"monotone"===l.dataset._model.cubicInterpolationMode)o.splineCurveMonotone(u);else for(e=0,n=u.length;e<n;++e)i=u[e]._model,a=o.splineCurve(o.previousItem(u,e)._model,i,o.nextItem(u,e)._model,l.dataset._model.tension),i.controlPointPreviousX=a.previous.x,i.controlPointPreviousY=a.previous.y,i.controlPointNextX=a.next.x,i.controlPointNextY=a.next.y;if(r.chart.options.elements.line.capBezierPoints)for(e=0,n=u.length;e<n;++e)(i=u[e]._model).controlPointPreviousX=t(i.controlPointPreviousX,s.left,s.right),i.controlPointPreviousY=t(i.controlPointPreviousY,s.top,s.bottom),i.controlPointNextX=t(i.controlPointNextX,s.left,s.right),i.controlPointNextY=t(i.controlPointNextY,s.top,s.bottom)},draw:function(){var t=this,n=t.chart,i=t.getMeta(),a=i.data||[],r=n.chartArea,l=a.length,s=0;for(o.canvas.clipArea(n.ctx,r),e(t.getDataset(),n.options)&&i.dataset.draw(),o.canvas.unclipArea(n.ctx);s<l;++s)a[s].draw(r)},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t._index,i=t.custom||{},a=t._model;a.radius=i.hoverRadius||o.valueAtIndexOrDefault(e.pointHoverRadius,n,this.chart.options.elements.point.hoverRadius),a.backgroundColor=i.hoverBackgroundColor||o.valueAtIndexOrDefault(e.pointHoverBackgroundColor,n,o.getHoverColor(a.backgroundColor)),a.borderColor=i.hoverBorderColor||o.valueAtIndexOrDefault(e.pointHoverBorderColor,n,o.getHoverColor(a.borderColor)),a.borderWidth=i.hoverBorderWidth||o.valueAtIndexOrDefault(e.pointHoverBorderWidth,n,a.borderWidth)},removeHoverStyle:function(t){var e=this,n=e.chart.data.datasets[t._datasetIndex],i=t._index,a=t.custom||{},r=t._model;void 0!==n.radius&&void 0===n.pointRadius&&(n.pointRadius=n.radius),r.radius=a.radius||o.valueAtIndexOrDefault(n.pointRadius,i,e.chart.options.elements.point.radius),r.backgroundColor=e.getPointBackgroundColor(t,i),r.borderColor=e.getPointBorderColor(t,i),r.borderWidth=e.getPointBorderWidth(t,i)}})}},{25:25,40:40,45:45}],19:[function(t,e,n){"use strict";var i=t(25),a=t(40),o=t(45);i._set("polarArea",{scale:{type:"radialLinear",angleLines:{display:!1},gridLines:{circular:!0},pointLabels:{display:!1},ticks:{beginAtZero:!0}},animation:{animateRotate:!0,animateScale:!0},startAngle:-.5*Math.PI,legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');var n=t.data,i=n.datasets,a=n.labels;if(i.length)for(var o=0;o<i[0].data.length;++o)e.push('<li><span style="background-color:'+i[0].backgroundColor[o]+'"></span>'),a[o]&&e.push(a[o]),e.push("</li>");return e.push("</ul>"),e.join("")},legend:{labels:{generateLabels:function(t){var e=t.data;return e.labels.length&&e.datasets.length?e.labels.map(function(n,i){var a=t.getDatasetMeta(0),r=e.datasets[0],l=a.data[i].custom||{},s=o.valueAtIndexOrDefault,u=t.options.elements.arc;return{text:n,fillStyle:l.backgroundColor?l.backgroundColor:s(r.backgroundColor,i,u.backgroundColor),strokeStyle:l.borderColor?l.borderColor:s(r.borderColor,i,u.borderColor),lineWidth:l.borderWidth?l.borderWidth:s(r.borderWidth,i,u.borderWidth),hidden:isNaN(r.data[i])||a.data[i].hidden,index:i}}):[]}},onClick:function(t,e){var n,i,a,o=e.index,r=this.chart;for(n=0,i=(r.data.datasets||[]).length;n<i;++n)(a=r.getDatasetMeta(n)).data[o].hidden=!a.data[o].hidden;r.update()}},tooltips:{callbacks:{title:function(){return""},label:function(t,e){return e.labels[t.index]+": "+t.yLabel}}}}),e.exports=function(t){t.controllers.polarArea=t.DatasetController.extend({dataElementType:a.Arc,linkScales:o.noop,update:function(t){var e=this,n=e.chart,i=n.chartArea,a=e.getMeta(),r=n.options,l=r.elements.arc,s=Math.min(i.right-i.left,i.bottom-i.top);n.outerRadius=Math.max((s-l.borderWidth/2)/2,0),n.innerRadius=Math.max(r.cutoutPercentage?n.outerRadius/100*r.cutoutPercentage:1,0),n.radiusLength=(n.outerRadius-n.innerRadius)/n.getVisibleDatasetCount(),e.outerRadius=n.outerRadius-n.radiusLength*e.index,e.innerRadius=e.outerRadius-n.radiusLength,a.count=e.countVisibleElements(),o.each(a.data,function(n,i){e.updateElement(n,i,t)})},updateElement:function(t,e,n){for(var i=this,a=i.chart,r=i.getDataset(),l=a.options,s=l.animation,u=a.scale,d=a.data.labels,c=i.calculateCircumference(r.data[e]),h=u.xCenter,f=u.yCenter,g=0,p=i.getMeta(),v=0;v<e;++v)isNaN(r.data[v])||p.data[v].hidden||++g;var m=l.startAngle,b=t.hidden?0:u.getDistanceFromCenterForValue(r.data[e]),x=m+c*g,y=x+(t.hidden?0:c),k=s.animateScale?0:u.getDistanceFromCenterForValue(r.data[e]);o.extend(t,{_datasetIndex:i.index,_index:e,_scale:u,_model:{x:h,y:f,innerRadius:0,outerRadius:n?k:b,startAngle:n&&s.animateRotate?m:x,endAngle:n&&s.animateRotate?m:y,label:o.valueAtIndexOrDefault(d,e,d[e])}}),i.removeHoverStyle(t),t.pivot()},removeHoverStyle:function(e){t.DatasetController.prototype.removeHoverStyle.call(this,e,this.chart.options.elements.arc)},countVisibleElements:function(){var t=this.getDataset(),e=this.getMeta(),n=0;return o.each(e.data,function(e,i){isNaN(t.data[i])||e.hidden||n++}),n},calculateCircumference:function(t){var e=this.getMeta().count;return e>0&&!isNaN(t)?2*Math.PI/e:0}})}},{25:25,40:40,45:45}],20:[function(t,e,n){"use strict";var i=t(25),a=t(40),o=t(45);i._set("radar",{scale:{type:"radialLinear"},elements:{line:{tension:0}}}),e.exports=function(t){t.controllers.radar=t.DatasetController.extend({datasetElementType:a.Line,dataElementType:a.Point,linkScales:o.noop,update:function(t){var e=this,n=e.getMeta(),i=n.dataset,a=n.data,r=i.custom||{},l=e.getDataset(),s=e.chart.options.elements.line,u=e.chart.scale;void 0!==l.tension&&void 0===l.lineTension&&(l.lineTension=l.tension),o.extend(n.dataset,{_datasetIndex:e.index,_scale:u,_children:a,_loop:!0,_model:{tension:r.tension?r.tension:o.valueOrDefault(l.lineTension,s.tension),backgroundColor:r.backgroundColor?r.backgroundColor:l.backgroundColor||s.backgroundColor,borderWidth:r.borderWidth?r.borderWidth:l.borderWidth||s.borderWidth,borderColor:r.borderColor?r.borderColor:l.borderColor||s.borderColor,fill:r.fill?r.fill:void 0!==l.fill?l.fill:s.fill,borderCapStyle:r.borderCapStyle?r.borderCapStyle:l.borderCapStyle||s.borderCapStyle,borderDash:r.borderDash?r.borderDash:l.borderDash||s.borderDash,borderDashOffset:r.borderDashOffset?r.borderDashOffset:l.borderDashOffset||s.borderDashOffset,borderJoinStyle:r.borderJoinStyle?r.borderJoinStyle:l.borderJoinStyle||s.borderJoinStyle}}),n.dataset.pivot(),o.each(a,function(n,i){e.updateElement(n,i,t)},e),e.updateBezierControlPoints()},updateElement:function(t,e,n){var i=this,a=t.custom||{},r=i.getDataset(),l=i.chart.scale,s=i.chart.options.elements.point,u=l.getPointPositionForValue(e,r.data[e]);void 0!==r.radius&&void 0===r.pointRadius&&(r.pointRadius=r.radius),void 0!==r.hitRadius&&void 0===r.pointHitRadius&&(r.pointHitRadius=r.hitRadius),o.extend(t,{_datasetIndex:i.index,_index:e,_scale:l,_model:{x:n?l.xCenter:u.x,y:n?l.yCenter:u.y,tension:a.tension?a.tension:o.valueOrDefault(r.lineTension,i.chart.options.elements.line.tension),radius:a.radius?a.radius:o.valueAtIndexOrDefault(r.pointRadius,e,s.radius),backgroundColor:a.backgroundColor?a.backgroundColor:o.valueAtIndexOrDefault(r.pointBackgroundColor,e,s.backgroundColor),borderColor:a.borderColor?a.borderColor:o.valueAtIndexOrDefault(r.pointBorderColor,e,s.borderColor),borderWidth:a.borderWidth?a.borderWidth:o.valueAtIndexOrDefault(r.pointBorderWidth,e,s.borderWidth),pointStyle:a.pointStyle?a.pointStyle:o.valueAtIndexOrDefault(r.pointStyle,e,s.pointStyle),hitRadius:a.hitRadius?a.hitRadius:o.valueAtIndexOrDefault(r.pointHitRadius,e,s.hitRadius)}}),t._model.skip=a.skip?a.skip:isNaN(t._model.x)||isNaN(t._model.y)},updateBezierControlPoints:function(){var t=this.chart.chartArea,e=this.getMeta();o.each(e.data,function(n,i){var a=n._model,r=o.splineCurve(o.previousItem(e.data,i,!0)._model,a,o.nextItem(e.data,i,!0)._model,a.tension);a.controlPointPreviousX=Math.max(Math.min(r.previous.x,t.right),t.left),a.controlPointPreviousY=Math.max(Math.min(r.previous.y,t.bottom),t.top),a.controlPointNextX=Math.max(Math.min(r.next.x,t.right),t.left),a.controlPointNextY=Math.max(Math.min(r.next.y,t.bottom),t.top),n.pivot()})},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t.custom||{},i=t._index,a=t._model;a.radius=n.hoverRadius?n.hoverRadius:o.valueAtIndexOrDefault(e.pointHoverRadius,i,this.chart.options.elements.point.hoverRadius),a.backgroundColor=n.hoverBackgroundColor?n.hoverBackgroundColor:o.valueAtIndexOrDefault(e.pointHoverBackgroundColor,i,o.getHoverColor(a.backgroundColor)),a.borderColor=n.hoverBorderColor?n.hoverBorderColor:o.valueAtIndexOrDefault(e.pointHoverBorderColor,i,o.getHoverColor(a.borderColor)),a.borderWidth=n.hoverBorderWidth?n.hoverBorderWidth:o.valueAtIndexOrDefault(e.pointHoverBorderWidth,i,a.borderWidth)},removeHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t.custom||{},i=t._index,a=t._model,r=this.chart.options.elements.point;a.radius=n.radius?n.radius:o.valueAtIndexOrDefault(e.pointRadius,i,r.radius),a.backgroundColor=n.backgroundColor?n.backgroundColor:o.valueAtIndexOrDefault(e.pointBackgroundColor,i,r.backgroundColor),a.borderColor=n.borderColor?n.borderColor:o.valueAtIndexOrDefault(e.pointBorderColor,i,r.borderColor),a.borderWidth=n.borderWidth?n.borderWidth:o.valueAtIndexOrDefault(e.pointBorderWidth,i,r.borderWidth)}})}},{25:25,40:40,45:45}],21:[function(t,e,n){"use strict";t(25)._set("scatter",{hover:{mode:"single"},scales:{xAxes:[{id:"x-axis-1",type:"linear",position:"bottom"}],yAxes:[{id:"y-axis-1",type:"linear",position:"left"}]},showLines:!1,tooltips:{callbacks:{title:function(){return""},label:function(t){return"("+t.xLabel+", "+t.yLabel+")"}}}}),e.exports=function(t){t.controllers.scatter=t.controllers.line}},{25:25}],22:[function(t,e,n){"use strict";var i=t(25),a=t(26),o=t(45);i._set("global",{animation:{duration:1e3,easing:"easeOutQuart",onProgress:o.noop,onComplete:o.noop}}),e.exports=function(t){t.Animation=a.extend({chart:null,currentStep:0,numSteps:60,easing:"",render:null,onAnimationProgress:null,onAnimationComplete:null}),t.animationService={frameDuration:17,animations:[],dropFrames:0,request:null,addAnimation:function(t,e,n,i){var a,o,r=this.animations;for(e.chart=t,i||(t.animating=!0),a=0,o=r.length;a<o;++a)if(r[a].chart===t)return void(r[a]=e);r.push(e),1===r.length&&this.requestAnimationFrame()},cancelAnimation:function(t){var e=o.findIndex(this.animations,function(e){return e.chart===t});-1!==e&&(this.animations.splice(e,1),t.animating=!1)},requestAnimationFrame:function(){var t=this;null===t.request&&(t.request=o.requestAnimFrame.call(window,function(){t.request=null,t.startDigest()}))},startDigest:function(){var t=this,e=Date.now(),n=0;t.dropFrames>1&&(n=Math.floor(t.dropFrames),t.dropFrames=t.dropFrames%1),t.advance(1+n);var i=Date.now();t.dropFrames+=(i-e)/t.frameDuration,t.animations.length>0&&t.requestAnimationFrame()},advance:function(t){for(var e,n,i=this.animations,a=0;a<i.length;)n=(e=i[a]).chart,e.currentStep=(e.currentStep||0)+t,e.currentStep=Math.min(e.currentStep,e.numSteps),o.callback(e.render,[n,e],n),o.callback(e.onAnimationProgress,[e],n),e.currentStep>=e.numSteps?(o.callback(e.onAnimationComplete,[e],n),n.animating=!1,i.splice(a,1)):++a}},Object.defineProperty(t.Animation.prototype,"animationObject",{get:function(){return this}}),Object.defineProperty(t.Animation.prototype,"chartInstance",{get:function(){return this.chart},set:function(t){this.chart=t}})}},{25:25,26:26,45:45}],23:[function(t,e,n){"use strict";var i=t(25),a=t(45),o=t(28),r=t(48);e.exports=function(t){function e(t){var e=(t=t||{}).data=t.data||{};return e.datasets=e.datasets||[],e.labels=e.labels||[],t.options=a.configMerge(i.global,i[t.type],t.options||{}),t}function n(t){var e=t.options;e.scale?t.scale.options=e.scale:e.scales&&e.scales.xAxes.concat(e.scales.yAxes).forEach(function(e){t.scales[e.id].options=e}),t.tooltip._options=e.tooltips}function l(t){return"top"===t||"bottom"===t}var s=t.plugins;t.types={},t.instances={},t.controllers={},a.extend(t.prototype,{construct:function(n,i){var o=this;i=e(i);var l=r.acquireContext(n,i),s=l&&l.canvas,u=s&&s.height,d=s&&s.width;o.id=a.uid(),o.ctx=l,o.canvas=s,o.config=i,o.width=d,o.height=u,o.aspectRatio=u?d/u:null,o.options=i.options,o._bufferedRender=!1,o.chart=o,o.controller=o,t.instances[o.id]=o,Object.defineProperty(o,"data",{get:function(){return o.config.data},set:function(t){o.config.data=t}}),l&&s?(o.initialize(),o.update()):console.error("Failed to create chart: can't acquire context from the given item")},initialize:function(){var t=this;return s.notify(t,"beforeInit"),a.retinaScale(t,t.options.devicePixelRatio),t.bindEvents(),t.options.responsive&&t.resize(!0),t.ensureScalesHaveIDs(),t.buildScales(),t.initToolTip(),s.notify(t,"afterInit"),t},clear:function(){return a.canvas.clear(this),this},stop:function(){return t.animationService.cancelAnimation(this),this},resize:function(t){var e=this,n=e.options,i=e.canvas,o=n.maintainAspectRatio&&e.aspectRatio||null,r=Math.max(0,Math.floor(a.getMaximumWidth(i))),l=Math.max(0,Math.floor(o?r/o:a.getMaximumHeight(i)));if((e.width!==r||e.height!==l)&&(i.width=e.width=r,i.height=e.height=l,i.style.width=r+"px",i.style.height=l+"px",a.retinaScale(e,n.devicePixelRatio),!t)){var u={width:r,height:l};s.notify(e,"resize",[u]),e.options.onResize&&e.options.onResize(e,u),e.stop(),e.update(e.options.responsiveAnimationDuration)}},ensureScalesHaveIDs:function(){var t=this.options,e=t.scales||{},n=t.scale;a.each(e.xAxes,function(t,e){t.id=t.id||"x-axis-"+e}),a.each(e.yAxes,function(t,e){t.id=t.id||"y-axis-"+e}),n&&(n.id=n.id||"scale")},buildScales:function(){var e=this,n=e.options,i=e.scales={},o=[];n.scales&&(o=o.concat((n.scales.xAxes||[]).map(function(t){return{options:t,dtype:"category",dposition:"bottom"}}),(n.scales.yAxes||[]).map(function(t){return{options:t,dtype:"linear",dposition:"left"}}))),n.scale&&o.push({options:n.scale,dtype:"radialLinear",isDefault:!0,dposition:"chartArea"}),a.each(o,function(n){var o=n.options,r=a.valueOrDefault(o.type,n.dtype),s=t.scaleService.getScaleConstructor(r);if(s){l(o.position)!==l(n.dposition)&&(o.position=n.dposition);var u=new s({id:o.id,options:o,ctx:e.ctx,chart:e});i[u.id]=u,u.mergeTicksOptions(),n.isDefault&&(e.scale=u)}}),t.scaleService.addScalesToLayout(this)},buildOrUpdateControllers:function(){var e=this,n=[],i=[];return a.each(e.data.datasets,function(a,o){var r=e.getDatasetMeta(o),l=a.type||e.config.type;if(r.type&&r.type!==l&&(e.destroyDatasetMeta(o),r=e.getDatasetMeta(o)),r.type=l,n.push(r.type),r.controller)r.controller.updateIndex(o);else{var s=t.controllers[r.type];if(void 0===s)throw new Error('"'+r.type+'" is not a chart type.');r.controller=new s(e,o),i.push(r.controller)}},e),i},resetElements:function(){var t=this;a.each(t.data.datasets,function(e,n){t.getDatasetMeta(n).controller.reset()},t)},reset:function(){this.resetElements(),this.tooltip.initialize()},update:function(t){var e=this;if(t&&"object"==typeof t||(t={duration:t,lazy:arguments[1]}),n(e),!1!==s.notify(e,"beforeUpdate")){e.tooltip._data=e.data;var i=e.buildOrUpdateControllers();a.each(e.data.datasets,function(t,n){e.getDatasetMeta(n).controller.buildOrUpdateElements()},e),e.updateLayout(),a.each(i,function(t){t.reset()}),e.updateDatasets(),s.notify(e,"afterUpdate"),e._bufferedRender?e._bufferedRequest={duration:t.duration,easing:t.easing,lazy:t.lazy}:e.render(t)}},updateLayout:function(){var e=this;!1!==s.notify(e,"beforeLayout")&&(t.layoutService.update(this,this.width,this.height),s.notify(e,"afterScaleUpdate"),s.notify(e,"afterLayout"))},updateDatasets:function(){var t=this;if(!1!==s.notify(t,"beforeDatasetsUpdate")){for(var e=0,n=t.data.datasets.length;e<n;++e)t.updateDataset(e);s.notify(t,"afterDatasetsUpdate")}},updateDataset:function(t){var e=this,n=e.getDatasetMeta(t),i={meta:n,index:t};!1!==s.notify(e,"beforeDatasetUpdate",[i])&&(n.controller.update(),s.notify(e,"afterDatasetUpdate",[i]))},render:function(e){var n=this;e&&"object"==typeof e||(e={duration:e,lazy:arguments[1]});var i=e.duration,o=e.lazy;if(!1!==s.notify(n,"beforeRender")){var r=n.options.animation,l=function(t){s.notify(n,"afterRender"),a.callback(r&&r.onComplete,[t],n)};if(r&&(void 0!==i&&0!==i||void 0===i&&0!==r.duration)){var u=new t.Animation({numSteps:(i||r.duration)/16.66,easing:e.easing||r.easing,render:function(t,e){var n=a.easing.effects[e.easing],i=e.currentStep,o=i/e.numSteps;t.draw(n(o),o,i)},onAnimationProgress:r.onProgress,onAnimationComplete:l});t.animationService.addAnimation(n,u,i,o)}else n.draw(),l(new t.Animation({numSteps:0,chart:n}));return n}},draw:function(t){var e=this;e.clear(),a.isNullOrUndef(t)&&(t=1),e.transition(t),!1!==s.notify(e,"beforeDraw",[t])&&(a.each(e.boxes,function(t){t.draw(e.chartArea)},e),e.scale&&e.scale.draw(),e.drawDatasets(t),e.tooltip.draw(),s.notify(e,"afterDraw",[t]))},transition:function(t){for(var e=this,n=0,i=(e.data.datasets||[]).length;n<i;++n)e.isDatasetVisible(n)&&e.getDatasetMeta(n).controller.transition(t);e.tooltip.transition(t)},drawDatasets:function(t){var e=this;if(!1!==s.notify(e,"beforeDatasetsDraw",[t])){for(var n=(e.data.datasets||[]).length-1;n>=0;--n)e.isDatasetVisible(n)&&e.drawDataset(n,t);s.notify(e,"afterDatasetsDraw",[t])}},drawDataset:function(t,e){var n=this,i=n.getDatasetMeta(t),a={meta:i,index:t,easingValue:e};!1!==s.notify(n,"beforeDatasetDraw",[a])&&(i.controller.draw(e),s.notify(n,"afterDatasetDraw",[a]))},getElementAtEvent:function(t){return o.modes.single(this,t)},getElementsAtEvent:function(t){return o.modes.label(this,t,{intersect:!0})},getElementsAtXAxis:function(t){return o.modes["x-axis"](this,t,{intersect:!0})},getElementsAtEventForMode:function(t,e,n){var i=o.modes[e];return"function"==typeof i?i(this,t,n):[]},getDatasetAtEvent:function(t){return o.modes.dataset(this,t,{intersect:!0})},getDatasetMeta:function(t){var e=this,n=e.data.datasets[t];n._meta||(n._meta={});var i=n._meta[e.id];return i||(i=n._meta[e.id]={type:null,data:[],dataset:null,controller:null,hidden:null,xAxisID:null,yAxisID:null}),i},getVisibleDatasetCount:function(){for(var t=0,e=0,n=this.data.datasets.length;e<n;++e)this.isDatasetVisible(e)&&t++;return t},isDatasetVisible:function(t){var e=this.getDatasetMeta(t);return"boolean"==typeof e.hidden?!e.hidden:!this.data.datasets[t].hidden},generateLegend:function(){return this.options.legendCallback(this)},destroyDatasetMeta:function(t){var e=this.id,n=this.data.datasets[t],i=n._meta&&n._meta[e];i&&(i.controller.destroy(),delete n._meta[e])},destroy:function(){var e,n,i=this,o=i.canvas;for(i.stop(),e=0,n=i.data.datasets.length;e<n;++e)i.destroyDatasetMeta(e);o&&(i.unbindEvents(),a.canvas.clear(i),r.releaseContext(i.ctx),i.canvas=null,i.ctx=null),s.notify(i,"destroy"),delete t.instances[i.id]},toBase64Image:function(){return this.canvas.toDataURL.apply(this.canvas,arguments)},initToolTip:function(){var e=this;e.tooltip=new t.Tooltip({_chart:e,_chartInstance:e,_data:e.data,_options:e.options.tooltips},e)},bindEvents:function(){var t=this,e=t._listeners={},n=function(){t.eventHandler.apply(t,arguments)};a.each(t.options.events,function(i){r.addEventListener(t,i,n),e[i]=n}),t.options.responsive&&(n=function(){t.resize()},r.addEventListener(t,"resize",n),e.resize=n)},unbindEvents:function(){var t=this,e=t._listeners;e&&(delete t._listeners,a.each(e,function(e,n){r.removeEventListener(t,n,e)}))},updateHoverStyle:function(t,e,n){var i,a,o,r=n?"setHoverStyle":"removeHoverStyle";for(a=0,o=t.length;a<o;++a)(i=t[a])&&this.getDatasetMeta(i._datasetIndex).controller[r](i)},eventHandler:function(t){var e=this,n=e.tooltip;if(!1!==s.notify(e,"beforeEvent",[t])){e._bufferedRender=!0,e._bufferedRequest=null;var i=e.handleEvent(t);i|=n&&n.handleEvent(t),s.notify(e,"afterEvent",[t]);var a=e._bufferedRequest;return a?e.render(a):i&&!e.animating&&(e.stop(),e.render(e.options.hover.animationDuration,!0)),e._bufferedRender=!1,e._bufferedRequest=null,e}},handleEvent:function(t){var e=this,n=e.options||{},i=n.hover,o=!1;return e.lastActive=e.lastActive||[],"mouseout"===t.type?e.active=[]:e.active=e.getElementsAtEventForMode(t,i.mode,i),a.callback(n.onHover||n.hover.onHover,[t.native,e.active],e),"mouseup"!==t.type&&"click"!==t.type||n.onClick&&n.onClick.call(e,t.native,e.active),e.lastActive.length&&e.updateHoverStyle(e.lastActive,i.mode,!1),e.active.length&&i.mode&&e.updateHoverStyle(e.active,i.mode,!0),o=!a.arrayEquals(e.active,e.lastActive),e.lastActive=e.active,o}}),t.Controller=t}},{25:25,28:28,45:45,48:48}],24:[function(t,e,n){"use strict";var i=t(45);e.exports=function(t){function e(t,e){t._chartjs?t._chartjs.listeners.push(e):(Object.defineProperty(t,"_chartjs",{configurable:!0,enumerable:!1,value:{listeners:[e]}}),a.forEach(function(e){var n="onData"+e.charAt(0).toUpperCase()+e.slice(1),a=t[e];Object.defineProperty(t,e,{configurable:!0,enumerable:!1,value:function(){var e=Array.prototype.slice.call(arguments),o=a.apply(this,e);return i.each(t._chartjs.listeners,function(t){"function"==typeof t[n]&&t[n].apply(t,e)}),o}})}))}function n(t,e){var n=t._chartjs;if(n){var i=n.listeners,o=i.indexOf(e);-1!==o&&i.splice(o,1),i.length>0||(a.forEach(function(e){delete t[e]}),delete t._chartjs)}}var a=["push","pop","shift","splice","unshift"];t.DatasetController=function(t,e){this.initialize(t,e)},i.extend(t.DatasetController.prototype,{datasetElementType:null,dataElementType:null,initialize:function(t,e){var n=this;n.chart=t,n.index=e,n.linkScales(),n.addElements()},updateIndex:function(t){this.index=t},linkScales:function(){var t=this,e=t.getMeta(),n=t.getDataset();null===e.xAxisID&&(e.xAxisID=n.xAxisID||t.chart.options.scales.xAxes[0].id),null===e.yAxisID&&(e.yAxisID=n.yAxisID||t.chart.options.scales.yAxes[0].id)},getDataset:function(){return this.chart.data.datasets[this.index]},getMeta:function(){return this.chart.getDatasetMeta(this.index)},getScaleForId:function(t){return this.chart.scales[t]},reset:function(){this.update(!0)},destroy:function(){this._data&&n(this._data,this)},createMetaDataset:function(){var t=this,e=t.datasetElementType;return e&&new e({_chart:t.chart,_datasetIndex:t.index})},createMetaData:function(t){var e=this,n=e.dataElementType;return n&&new n({_chart:e.chart,_datasetIndex:e.index,_index:t})},addElements:function(){var t,e,n=this,i=n.getMeta(),a=n.getDataset().data||[],o=i.data;for(t=0,e=a.length;t<e;++t)o[t]=o[t]||n.createMetaData(t);i.dataset=i.dataset||n.createMetaDataset()},addElementAndReset:function(t){var e=this.createMetaData(t);this.getMeta().data.splice(t,0,e),this.updateElement(e,t,!0)},buildOrUpdateElements:function(){var t=this,i=t.getDataset(),a=i.data||(i.data=[]);t._data!==a&&(t._data&&n(t._data,t),e(a,t),t._data=a),t.resyncElements()},update:i.noop,transition:function(t){for(var e=this.getMeta(),n=e.data||[],i=n.length,a=0;a<i;++a)n[a].transition(t);e.dataset&&e.dataset.transition(t)},draw:function(){var t=this.getMeta(),e=t.data||[],n=e.length,i=0;for(t.dataset&&t.dataset.draw();i<n;++i)e[i].draw()},removeHoverStyle:function(t,e){var n=this.chart.data.datasets[t._datasetIndex],a=t._index,o=t.custom||{},r=i.valueAtIndexOrDefault,l=t._model;l.backgroundColor=o.backgroundColor?o.backgroundColor:r(n.backgroundColor,a,e.backgroundColor),l.borderColor=o.borderColor?o.borderColor:r(n.borderColor,a,e.borderColor),l.borderWidth=o.borderWidth?o.borderWidth:r(n.borderWidth,a,e.borderWidth)},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t._index,a=t.custom||{},o=i.valueAtIndexOrDefault,r=i.getHoverColor,l=t._model;l.backgroundColor=a.hoverBackgroundColor?a.hoverBackgroundColor:o(e.hoverBackgroundColor,n,r(l.backgroundColor)),l.borderColor=a.hoverBorderColor?a.hoverBorderColor:o(e.hoverBorderColor,n,r(l.borderColor)),l.borderWidth=a.hoverBorderWidth?a.hoverBorderWidth:o(e.hoverBorderWidth,n,l.borderWidth)},resyncElements:function(){var t=this,e=t.getMeta(),n=t.getDataset().data,i=e.data.length,a=n.length;a<i?e.data.splice(a,i-a):a>i&&t.insertElements(i,a-i)},insertElements:function(t,e){for(var n=0;n<e;++n)this.addElementAndReset(t+n)},onDataPush:function(){this.insertElements(this.getDataset().data.length-1,arguments.length)},onDataPop:function(){this.getMeta().data.pop()},onDataShift:function(){this.getMeta().data.shift()},onDataSplice:function(t,e){this.getMeta().data.splice(t,e),this.insertElements(t,arguments.length-2)},onDataUnshift:function(){this.insertElements(0,arguments.length)}}),t.DatasetController.extend=i.inherits}},{45:45}],25:[function(t,e,n){"use strict";var i=t(45);e.exports={_set:function(t,e){return i.merge(this[t]||(this[t]={}),e)}}},{45:45}],26:[function(t,e,n){"use strict";function i(t,e,n,i){var o,r,l,s,u,d,c,h,f,g=Object.keys(n);for(o=0,r=g.length;o<r;++o)if(l=g[o],d=n[l],e.hasOwnProperty(l)||(e[l]=d),(s=e[l])!==d&&"_"!==l[0]){if(t.hasOwnProperty(l)||(t[l]=s),u=t[l],(c=typeof d)===typeof u)if("string"===c){if((h=a(u)).valid&&(f=a(d)).valid){e[l]=f.mix(h,i).rgbString();continue}}else if("number"===c&&isFinite(u)&&isFinite(d)){e[l]=u+(d-u)*i;continue}e[l]=d}}var a=t(3),o=t(45),r=function(t){o.extend(this,t),this.initialize.apply(this,arguments)};o.extend(r.prototype,{initialize:function(){this.hidden=!1},pivot:function(){var t=this;return t._view||(t._view=o.clone(t._model)),t._start={},t},transition:function(t){var e=this,n=e._model,a=e._start,o=e._view;return n&&1!==t?(o||(o=e._view={}),a||(a=e._start={}),i(a,o,n,t),e):(e._view=n,e._start=null,e)},tooltipPosition:function(){return{x:this._model.x,y:this._model.y}},hasValue:function(){return o.isNumber(this._model.x)&&o.isNumber(this._model.y)}}),r.extend=o.inherits,e.exports=r},{3:3,45:45}],27:[function(t,e,n){"use strict";var i=t(3),a=t(25),o=t(45);e.exports=function(t){function e(t,e,n){var i;return"string"==typeof t?(i=parseInt(t,10),-1!==t.indexOf("%")&&(i=i/100*e.parentNode[n])):i=t,i}function n(t){return void 0!==t&&null!==t&&"none"!==t}function r(t,i,a){var o=document.defaultView,r=t.parentNode,l=o.getComputedStyle(t)[i],s=o.getComputedStyle(r)[i],u=n(l),d=n(s),c=Number.POSITIVE_INFINITY;return u||d?Math.min(u?e(l,t,a):c,d?e(s,r,a):c):"none"}o.extend=function(t){for(var e=1,n=arguments.length;e<n;e++)o.each(arguments[e],function(e,n){t[n]=e});return t},o.configMerge=function(){return o.merge(o.clone(arguments[0]),[].slice.call(arguments,1),{merger:function(e,n,i,a){var r=n[e]||{},l=i[e];"scales"===e?n[e]=o.scaleMerge(r,l):"scale"===e?n[e]=o.merge(r,[t.scaleService.getScaleDefaults(l.type),l]):o._merger(e,n,i,a)}})},o.scaleMerge=function(){return o.merge(o.clone(arguments[0]),[].slice.call(arguments,1),{merger:function(e,n,i,a){if("xAxes"===e||"yAxes"===e){var r,l,s,u=i[e].length;for(n[e]||(n[e]=[]),r=0;r<u;++r)s=i[e][r],l=o.valueOrDefault(s.type,"xAxes"===e?"category":"linear"),r>=n[e].length&&n[e].push({}),!n[e][r].type||s.type&&s.type!==n[e][r].type?o.merge(n[e][r],[t.scaleService.getScaleDefaults(l),s]):o.merge(n[e][r],s)}else o._merger(e,n,i,a)}})},o.where=function(t,e){if(o.isArray(t)&&Array.prototype.filter)return t.filter(e);var n=[];return o.each(t,function(t){e(t)&&n.push(t)}),n},o.findIndex=Array.prototype.findIndex?function(t,e,n){return t.findIndex(e,n)}:function(t,e,n){n=void 0===n?t:n;for(var i=0,a=t.length;i<a;++i)if(e.call(n,t[i],i,t))return i;return-1},o.findNextWhere=function(t,e,n){o.isNullOrUndef(n)&&(n=-1);for(var i=n+1;i<t.length;i++){var a=t[i];if(e(a))return a}},o.findPreviousWhere=function(t,e,n){o.isNullOrUndef(n)&&(n=t.length);for(var i=n-1;i>=0;i--){var a=t[i];if(e(a))return a}},o.inherits=function(t){var e=this,n=t&&t.hasOwnProperty("constructor")?t.constructor:function(){return e.apply(this,arguments)},i=function(){this.constructor=n};return i.prototype=e.prototype,n.prototype=new i,n.extend=o.inherits,t&&o.extend(n.prototype,t),n.__super__=e.prototype,n},o.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},o.almostEquals=function(t,e,n){return Math.abs(t-e)<n},o.almostWhole=function(t,e){var n=Math.round(t);return n-e<t&&n+e>t},o.max=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.max(t,e)},Number.NEGATIVE_INFINITY)},o.min=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.min(t,e)},Number.POSITIVE_INFINITY)},o.sign=Math.sign?function(t){return Math.sign(t)}:function(t){return 0==(t=+t)||isNaN(t)?t:t>0?1:-1},o.log10=Math.log10?function(t){return Math.log10(t)}:function(t){return Math.log(t)/Math.LN10},o.toRadians=function(t){return t*(Math.PI/180)},o.toDegrees=function(t){return t*(180/Math.PI)},o.getAngleFromPoint=function(t,e){var n=e.x-t.x,i=e.y-t.y,a=Math.sqrt(n*n+i*i),o=Math.atan2(i,n);return o<-.5*Math.PI&&(o+=2*Math.PI),{angle:o,distance:a}},o.distanceBetweenPoints=function(t,e){return Math.sqrt(Math.pow(e.x-t.x,2)+Math.pow(e.y-t.y,2))},o.aliasPixel=function(t){return t%2==0?0:.5},o.splineCurve=function(t,e,n,i){var a=t.skip?e:t,o=e,r=n.skip?e:n,l=Math.sqrt(Math.pow(o.x-a.x,2)+Math.pow(o.y-a.y,2)),s=Math.sqrt(Math.pow(r.x-o.x,2)+Math.pow(r.y-o.y,2)),u=l/(l+s),d=s/(l+s),c=i*(u=isNaN(u)?0:u),h=i*(d=isNaN(d)?0:d);return{previous:{x:o.x-c*(r.x-a.x),y:o.y-c*(r.y-a.y)},next:{x:o.x+h*(r.x-a.x),y:o.y+h*(r.y-a.y)}}},o.EPSILON=Number.EPSILON||1e-14,o.splineCurveMonotone=function(t){var e,n,i,a,r=(t||[]).map(function(t){return{model:t._model,deltaK:0,mK:0}}),l=r.length;for(e=0;e<l;++e)if(!(i=r[e]).model.skip){if(n=e>0?r[e-1]:null,(a=e<l-1?r[e+1]:null)&&!a.model.skip){var s=a.model.x-i.model.x;i.deltaK=0!==s?(a.model.y-i.model.y)/s:0}!n||n.model.skip?i.mK=i.deltaK:!a||a.model.skip?i.mK=n.deltaK:this.sign(n.deltaK)!==this.sign(i.deltaK)?i.mK=0:i.mK=(n.deltaK+i.deltaK)/2}var u,d,c,h;for(e=0;e<l-1;++e)i=r[e],a=r[e+1],i.model.skip||a.model.skip||(o.almostEquals(i.deltaK,0,this.EPSILON)?i.mK=a.mK=0:(u=i.mK/i.deltaK,d=a.mK/i.deltaK,(h=Math.pow(u,2)+Math.pow(d,2))<=9||(c=3/Math.sqrt(h),i.mK=u*c*i.deltaK,a.mK=d*c*i.deltaK)));var f;for(e=0;e<l;++e)(i=r[e]).model.skip||(n=e>0?r[e-1]:null,a=e<l-1?r[e+1]:null,n&&!n.model.skip&&(f=(i.model.x-n.model.x)/3,i.model.controlPointPreviousX=i.model.x-f,i.model.controlPointPreviousY=i.model.y-f*i.mK),a&&!a.model.skip&&(f=(a.model.x-i.model.x)/3,i.model.controlPointNextX=i.model.x+f,i.model.controlPointNextY=i.model.y+f*i.mK))},o.nextItem=function(t,e,n){return n?e>=t.length-1?t[0]:t[e+1]:e>=t.length-1?t[t.length-1]:t[e+1]},o.previousItem=function(t,e,n){return n?e<=0?t[t.length-1]:t[e-1]:e<=0?t[0]:t[e-1]},o.niceNum=function(t,e){var n=Math.floor(o.log10(t)),i=t/Math.pow(10,n);return(e?i<1.5?1:i<3?2:i<7?5:10:i<=1?1:i<=2?2:i<=5?5:10)*Math.pow(10,n)},o.requestAnimFrame="undefined"==typeof window?function(t){t()}:window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)},o.getRelativePosition=function(t,e){var n,i,a=t.originalEvent||t,r=t.currentTarget||t.srcElement,l=r.getBoundingClientRect(),s=a.touches;s&&s.length>0?(n=s[0].clientX,i=s[0].clientY):(n=a.clientX,i=a.clientY);var u=parseFloat(o.getStyle(r,"padding-left")),d=parseFloat(o.getStyle(r,"padding-top")),c=parseFloat(o.getStyle(r,"padding-right")),h=parseFloat(o.getStyle(r,"padding-bottom")),f=l.right-l.left-u-c,g=l.bottom-l.top-d-h;return n=Math.round((n-l.left-u)/f*r.width/e.currentDevicePixelRatio),i=Math.round((i-l.top-d)/g*r.height/e.currentDevicePixelRatio),{x:n,y:i}},o.getConstraintWidth=function(t){return r(t,"max-width","clientWidth")},o.getConstraintHeight=function(t){return r(t,"max-height","clientHeight")},o.getMaximumWidth=function(t){var e=t.parentNode;if(!e)return t.clientWidth;var n=parseInt(o.getStyle(e,"padding-left"),10),i=parseInt(o.getStyle(e,"padding-right"),10),a=e.clientWidth-n-i,r=o.getConstraintWidth(t);return isNaN(r)?a:Math.min(a,r)},o.getMaximumHeight=function(t){var e=t.parentNode;if(!e)return t.clientHeight;var n=parseInt(o.getStyle(e,"padding-top"),10),i=parseInt(o.getStyle(e,"padding-bottom"),10),a=e.clientHeight-n-i,r=o.getConstraintHeight(t);return isNaN(r)?a:Math.min(a,r)},o.getStyle=function(t,e){return t.currentStyle?t.currentStyle[e]:document.defaultView.getComputedStyle(t,null).getPropertyValue(e)},o.retinaScale=function(t,e){var n=t.currentDevicePixelRatio=e||window.devicePixelRatio||1;if(1!==n){var i=t.canvas,a=t.height,o=t.width;i.height=a*n,i.width=o*n,t.ctx.scale(n,n),i.style.height=a+"px",i.style.width=o+"px"}},o.fontString=function(t,e,n){return e+" "+t+"px "+n},o.longestText=function(t,e,n,i){var a=(i=i||{}).data=i.data||{},r=i.garbageCollect=i.garbageCollect||[];i.font!==e&&(a=i.data={},r=i.garbageCollect=[],i.font=e),t.font=e;var l=0;o.each(n,function(e){void 0!==e&&null!==e&&!0!==o.isArray(e)?l=o.measureText(t,a,r,l,e):o.isArray(e)&&o.each(e,function(e){void 0===e||null===e||o.isArray(e)||(l=o.measureText(t,a,r,l,e))})});var s=r.length/2;if(s>n.length){for(var u=0;u<s;u++)delete a[r[u]];r.splice(0,s)}return l},o.measureText=function(t,e,n,i,a){var o=e[a];return o||(o=e[a]=t.measureText(a).width,n.push(a)),o>i&&(i=o),i},o.numberOfLabelLines=function(t){var e=1;return o.each(t,function(t){o.isArray(t)&&t.length>e&&(e=t.length)}),e},o.color=i?function(t){return t instanceof CanvasGradient&&(t=a.global.defaultColor),i(t)}:function(t){return console.error("Color.js not found!"),t},o.getHoverColor=function(t){return t instanceof CanvasPattern?t:o.color(t).saturate(.5).darken(.1).rgbString()}}},{25:25,3:3,45:45}],28:[function(t,e,n){"use strict";function i(t,e){return t.native?{x:t.x,y:t.y}:u.getRelativePosition(t,e)}function a(t,e){var n,i,a,o,r;for(i=0,o=t.data.datasets.length;i<o;++i)if(t.isDatasetVisible(i))for(a=0,r=(n=t.getDatasetMeta(i)).data.length;a<r;++a){var l=n.data[a];l._view.skip||e(l)}}function o(t,e){var n=[];return a(t,function(t){t.inRange(e.x,e.y)&&n.push(t)}),n}function r(t,e,n,i){var o=Number.POSITIVE_INFINITY,r=[];return a(t,function(t){if(!n||t.inRange(e.x,e.y)){var a=t.getCenterPoint(),l=i(e,a);l<o?(r=[t],o=l):l===o&&r.push(t)}}),r}function l(t){var e=-1!==t.indexOf("x"),n=-1!==t.indexOf("y");return function(t,i){var a=e?Math.abs(t.x-i.x):0,o=n?Math.abs(t.y-i.y):0;return Math.sqrt(Math.pow(a,2)+Math.pow(o,2))}}function s(t,e,n){var a=i(e,t);n.axis=n.axis||"x";var s=l(n.axis),u=n.intersect?o(t,a):r(t,a,!1,s),d=[];return u.length?(t.data.datasets.forEach(function(e,n){if(t.isDatasetVisible(n)){var i=t.getDatasetMeta(n).data[u[0]._index];i&&!i._view.skip&&d.push(i)}}),d):[]}var u=t(45);e.exports={modes:{single:function(t,e){var n=i(e,t),o=[];return a(t,function(t){if(t.inRange(n.x,n.y))return o.push(t),o}),o.slice(0,1)},label:s,index:s,dataset:function(t,e,n){var a=i(e,t);n.axis=n.axis||"xy";var s=l(n.axis),u=n.intersect?o(t,a):r(t,a,!1,s);return u.length>0&&(u=t.getDatasetMeta(u[0]._datasetIndex).data),u},"x-axis":function(t,e){return s(t,e,{intersect:!1})},point:function(t,e){return o(t,i(e,t))},nearest:function(t,e,n){var a=i(e,t);n.axis=n.axis||"xy";var o=l(n.axis),s=r(t,a,n.intersect,o);return s.length>1&&s.sort(function(t,e){var n=t.getArea()-e.getArea();return 0===n&&(n=t._datasetIndex-e._datasetIndex),n}),s.slice(0,1)},x:function(t,e,n){var o=i(e,t),r=[],l=!1;return a(t,function(t){t.inXRange(o.x)&&r.push(t),t.inRange(o.x,o.y)&&(l=!0)}),n.intersect&&!l&&(r=[]),r},y:function(t,e,n){var o=i(e,t),r=[],l=!1;return a(t,function(t){t.inYRange(o.y)&&r.push(t),t.inRange(o.x,o.y)&&(l=!0)}),n.intersect&&!l&&(r=[]),r}}}},{45:45}],29:[function(t,e,n){"use strict";t(25)._set("global",{responsive:!0,responsiveAnimationDuration:0,maintainAspectRatio:!0,events:["mousemove","mouseout","click","touchstart","touchmove"],hover:{onHover:null,mode:"nearest",intersect:!0,animationDuration:400},onClick:null,defaultColor:"rgba(0,0,0,0.1)",defaultFontColor:"#666",defaultFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",defaultFontSize:12,defaultFontStyle:"normal",showLines:!0,elements:{},layout:{padding:{top:0,right:0,bottom:0,left:0}}}),e.exports=function(){var t=function(t,e){return this.construct(t,e),this};return t.Chart=t,t}},{25:25}],30:[function(t,e,n){"use strict";var i=t(45);e.exports=function(t){function e(t,e){return i.where(t,function(t){return t.position===e})}function n(t,e){t.forEach(function(t,e){return t._tmpIndex_=e,t}),t.sort(function(t,n){var i=e?n:t,a=e?t:n;return i.weight===a.weight?i._tmpIndex_-a._tmpIndex_:i.weight-a.weight}),t.forEach(function(t){delete t._tmpIndex_})}t.layoutService={defaults:{},addBox:function(t,e){t.boxes||(t.boxes=[]),e.fullWidth=e.fullWidth||!1,e.position=e.position||"top",e.weight=e.weight||0,t.boxes.push(e)},removeBox:function(t,e){var n=t.boxes?t.boxes.indexOf(e):-1;-1!==n&&t.boxes.splice(n,1)},configure:function(t,e,n){for(var i,a=["fullWidth","position","weight"],o=a.length,r=0;r<o;++r)i=a[r],n.hasOwnProperty(i)&&(e[i]=n[i])},update:function(t,a,o){function r(t){var e=i.findNextWhere(_,function(e){return e.box===t});if(e)if(t.isHorizontal()){var n={left:Math.max(F,D),right:Math.max(T,I),top:0,bottom:0};t.update(t.fullWidth?x:S,y/2,n)}else t.update(e.minSize.width,C)}function l(t){t.isHorizontal()?(t.left=t.fullWidth?d:F,t.right=t.fullWidth?a-c:F+S,t.top=V,t.bottom=V+t.height,V=t.bottom):(t.left=N,t.right=N+t.width,t.top=O,t.bottom=O+C,N=t.right)}if(t){var s=t.options.layout||{},u=i.options.toPadding(s.padding),d=u.left,c=u.right,h=u.top,f=u.bottom,g=e(t.boxes,"left"),p=e(t.boxes,"right"),v=e(t.boxes,"top"),m=e(t.boxes,"bottom"),b=e(t.boxes,"chartArea");n(g,!0),n(p,!1),n(v,!0),n(m,!1);var x=a-d-c,y=o-h-f,k=y/2,w=(a-x/2)/(g.length+p.length),M=(o-k)/(v.length+m.length),S=x,C=y,_=[];i.each(g.concat(p,v,m),function(t){var e,n=t.isHorizontal();n?(e=t.update(t.fullWidth?x:S,M),C-=e.height):(e=t.update(w,k),S-=e.width),_.push({horizontal:n,minSize:e,box:t})});var D=0,I=0,P=0,A=0;i.each(v.concat(m),function(t){if(t.getPadding){var e=t.getPadding();D=Math.max(D,e.left),I=Math.max(I,e.right)}}),i.each(g.concat(p),function(t){if(t.getPadding){var e=t.getPadding();P=Math.max(P,e.top),A=Math.max(A,e.bottom)}});var F=d,T=c,O=h,R=f;i.each(g.concat(p),r),i.each(g,function(t){F+=t.width}),i.each(p,function(t){T+=t.width}),i.each(v.concat(m),r),i.each(v,function(t){O+=t.height}),i.each(m,function(t){R+=t.height}),i.each(g.concat(p),function(t){var e=i.findNextWhere(_,function(e){return e.box===t}),n={left:0,right:0,top:O,bottom:R};e&&t.update(e.minSize.width,C,n)}),F=d,T=c,O=h,R=f,i.each(g,function(t){F+=t.width}),i.each(p,function(t){T+=t.width}),i.each(v,function(t){O+=t.height}),i.each(m,function(t){R+=t.height});var L=Math.max(D-F,0);F+=L,T+=Math.max(I-T,0);var z=Math.max(P-O,0);O+=z,R+=Math.max(A-R,0);var B=o-O-R,W=a-F-T;W===S&&B===C||(i.each(g,function(t){t.height=B}),i.each(p,function(t){t.height=B}),i.each(v,function(t){t.fullWidth||(t.width=W)}),i.each(m,function(t){t.fullWidth||(t.width=W)}),C=B,S=W);var N=d+L,V=h+z;i.each(g.concat(v),l),N+=S,V+=C,i.each(p,l),i.each(m,l),t.chartArea={left:F,top:O,right:F+S,bottom:O+C},i.each(b,function(e){e.left=t.chartArea.left,e.top=t.chartArea.top,e.right=t.chartArea.right,e.bottom=t.chartArea.bottom,e.update(S,C)})}}}}},{45:45}],31:[function(t,e,n){"use strict";var i=t(25),a=t(26),o=t(45);i._set("global",{plugins:{}}),e.exports=function(t){t.plugins={_plugins:[],_cacheId:0,register:function(t){var e=this._plugins;[].concat(t).forEach(function(t){-1===e.indexOf(t)&&e.push(t)}),this._cacheId++},unregister:function(t){var e=this._plugins;[].concat(t).forEach(function(t){var n=e.indexOf(t);-1!==n&&e.splice(n,1)}),this._cacheId++},clear:function(){this._plugins=[],this._cacheId++},count:function(){return this._plugins.length},getAll:function(){return this._plugins},notify:function(t,e,n){var i,a,o,r,l,s=this.descriptors(t),u=s.length;for(i=0;i<u;++i)if(a=s[i],o=a.plugin,"function"==typeof(l=o[e])&&((r=[t].concat(n||[])).push(a.options),!1===l.apply(o,r)))return!1;return!0},descriptors:function(t){var e=t._plugins||(t._plugins={});if(e.id===this._cacheId)return e.descriptors;var n=[],a=[],r=t&&t.config||{},l=r.options&&r.options.plugins||{};return this._plugins.concat(r.plugins||[]).forEach(function(t){if(-1===n.indexOf(t)){var e=t.id,r=l[e];!1!==r&&(!0===r&&(r=o.clone(i.global.plugins[e])),n.push(t),a.push({plugin:t,options:r||{}}))}}),e.descriptors=a,e.id=this._cacheId,a}},t.pluginService=t.plugins,t.PluginBase=a.extend({})}},{25:25,26:26,45:45}],32:[function(t,e,n){"use strict";function i(t){var e,n,i=[];for(e=0,n=t.length;e<n;++e)i.push(t[e].label);return i}function a(t,e,n){var i=t.getPixelForTick(e);return n&&(i-=0===e?(t.getPixelForTick(1)-i)/2:(i-t.getPixelForTick(e-1))/2),i}var o=t(25),r=t(26),l=t(45),s=t(34);o._set("scale",{display:!0,position:"left",offset:!1,gridLines:{display:!0,color:"rgba(0, 0, 0, 0.1)",lineWidth:1,drawBorder:!0,drawOnChartArea:!0,drawTicks:!0,tickMarkLength:10,zeroLineWidth:1,zeroLineColor:"rgba(0,0,0,0.25)",zeroLineBorderDash:[],zeroLineBorderDashOffset:0,offsetGridLines:!1,borderDash:[],borderDashOffset:0},scaleLabel:{display:!1,labelString:"",lineHeight:1.2,padding:{top:4,bottom:4}},ticks:{beginAtZero:!1,minRotation:0,maxRotation:50,mirror:!1,padding:0,reverse:!1,display:!0,autoSkip:!0,autoSkipPadding:0,labelOffset:0,callback:s.formatters.values,minor:{},major:{}}}),e.exports=function(t){function e(t,e,n){return l.isArray(e)?l.longestText(t,n,e):t.measureText(e).width}function n(t){var e=l.valueOrDefault,n=o.global,i=e(t.fontSize,n.defaultFontSize),a=e(t.fontStyle,n.defaultFontStyle),r=e(t.fontFamily,n.defaultFontFamily);return{size:i,style:a,family:r,font:l.fontString(i,a,r)}}function s(t){return l.options.toLineHeight(l.valueOrDefault(t.lineHeight,1.2),l.valueOrDefault(t.fontSize,o.global.defaultFontSize))}t.Scale=r.extend({getPadding:function(){var t=this;return{left:t.paddingLeft||0,top:t.paddingTop||0,right:t.paddingRight||0,bottom:t.paddingBottom||0}},getTicks:function(){return this._ticks},mergeTicksOptions:function(){var t=this.options.ticks;!1===t.minor&&(t.minor={display:!1}),!1===t.major&&(t.major={display:!1});for(var e in t)"major"!==e&&"minor"!==e&&(void 0===t.minor[e]&&(t.minor[e]=t[e]),void 0===t.major[e]&&(t.major[e]=t[e]))},beforeUpdate:function(){l.callback(this.options.beforeUpdate,[this])},update:function(t,e,n){var i,a,o,r,s,u,d=this;for(d.beforeUpdate(),d.maxWidth=t,d.maxHeight=e,d.margins=l.extend({left:0,right:0,top:0,bottom:0},n),d.longestTextCache=d.longestTextCache||{},d.beforeSetDimensions(),d.setDimensions(),d.afterSetDimensions(),d.beforeDataLimits(),d.determineDataLimits(),d.afterDataLimits(),d.beforeBuildTicks(),s=d.buildTicks()||[],d.afterBuildTicks(),d.beforeTickToLabelConversion(),o=d.convertTicksToLabels(s)||d.ticks,d.afterTickToLabelConversion(),d.ticks=o,i=0,a=o.length;i<a;++i)r=o[i],(u=s[i])?u.label=r:s.push(u={label:r,major:!1});return d._ticks=s,d.beforeCalculateTickRotation(),d.calculateTickRotation(),d.afterCalculateTickRotation(),d.beforeFit(),d.fit(),d.afterFit(),d.afterUpdate(),d.minSize},afterUpdate:function(){l.callback(this.options.afterUpdate,[this])},beforeSetDimensions:function(){l.callback(this.options.beforeSetDimensions,[this])},setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0},afterSetDimensions:function(){l.callback(this.options.afterSetDimensions,[this])},beforeDataLimits:function(){l.callback(this.options.beforeDataLimits,[this])},determineDataLimits:l.noop,afterDataLimits:function(){l.callback(this.options.afterDataLimits,[this])},beforeBuildTicks:function(){l.callback(this.options.beforeBuildTicks,[this])},buildTicks:l.noop,afterBuildTicks:function(){l.callback(this.options.afterBuildTicks,[this])},beforeTickToLabelConversion:function(){l.callback(this.options.beforeTickToLabelConversion,[this])},convertTicksToLabels:function(){var t=this,e=t.options.ticks;t.ticks=t.ticks.map(e.userCallback||e.callback,this)},afterTickToLabelConversion:function(){l.callback(this.options.afterTickToLabelConversion,[this])},beforeCalculateTickRotation:function(){l.callback(this.options.beforeCalculateTickRotation,[this])},calculateTickRotation:function(){var t=this,e=t.ctx,a=t.options.ticks,o=i(t._ticks),r=n(a);e.font=r.font;var s=a.minRotation||0;if(o.length&&t.options.display&&t.isHorizontal())for(var u,d=l.longestText(e,r.font,o,t.longestTextCache),c=d,h=t.getPixelForTick(1)-t.getPixelForTick(0)-6;c>h&&s<a.maxRotation;){var f=l.toRadians(s);if(u=Math.cos(f),Math.sin(f)*d>t.maxHeight){s--;break}s++,c=u*d}t.labelRotation=s},afterCalculateTickRotation:function(){l.callback(this.options.afterCalculateTickRotation,[this])},beforeFit:function(){l.callback(this.options.beforeFit,[this])},fit:function(){var t=this,a=t.minSize={width:0,height:0},o=i(t._ticks),r=t.options,u=r.ticks,d=r.scaleLabel,c=r.gridLines,h=r.display,f=t.isHorizontal(),g=n(u),p=r.gridLines.tickMarkLength;if(a.width=f?t.isFullWidth()?t.maxWidth-t.margins.left-t.margins.right:t.maxWidth:h&&c.drawTicks?p:0,a.height=f?h&&c.drawTicks?p:0:t.maxHeight,d.display&&h){var v=s(d)+l.options.toPadding(d.padding).height;f?a.height+=v:a.width+=v}if(u.display&&h){var m=l.longestText(t.ctx,g.font,o,t.longestTextCache),b=l.numberOfLabelLines(o),x=.5*g.size,y=t.options.ticks.padding;if(f){t.longestLabelWidth=m;var k=l.toRadians(t.labelRotation),w=Math.cos(k),M=Math.sin(k)*m+g.size*b+x*(b-1)+x;a.height=Math.min(t.maxHeight,a.height+M+y),t.ctx.font=g.font;var S=e(t.ctx,o[0],g.font),C=e(t.ctx,o[o.length-1],g.font);0!==t.labelRotation?(t.paddingLeft="bottom"===r.position?w*S+3:w*x+3,t.paddingRight="bottom"===r.position?w*x+3:w*C+3):(t.paddingLeft=S/2+3,t.paddingRight=C/2+3)}else u.mirror?m=0:m+=y+x,a.width=Math.min(t.maxWidth,a.width+m),t.paddingTop=g.size/2,t.paddingBottom=g.size/2}t.handleMargins(),t.width=a.width,t.height=a.height},handleMargins:function(){var t=this;t.margins&&(t.paddingLeft=Math.max(t.paddingLeft-t.margins.left,0),t.paddingTop=Math.max(t.paddingTop-t.margins.top,0),t.paddingRight=Math.max(t.paddingRight-t.margins.right,0),t.paddingBottom=Math.max(t.paddingBottom-t.margins.bottom,0))},afterFit:function(){l.callback(this.options.afterFit,[this])},isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},isFullWidth:function(){return this.options.fullWidth},getRightValue:function(t){if(l.isNullOrUndef(t))return NaN;if("number"==typeof t&&!isFinite(t))return NaN;if(t)if(this.isHorizontal()){if(void 0!==t.x)return this.getRightValue(t.x)}else if(void 0!==t.y)return this.getRightValue(t.y);return t},getLabelForIndex:l.noop,getPixelForValue:l.noop,getValueForPixel:l.noop,getPixelForTick:function(t){var e=this,n=e.options.offset;if(e.isHorizontal()){var i=(e.width-(e.paddingLeft+e.paddingRight))/Math.max(e._ticks.length-(n?0:1),1),a=i*t+e.paddingLeft;n&&(a+=i/2);var o=e.left+Math.round(a);return o+=e.isFullWidth()?e.margins.left:0}var r=e.height-(e.paddingTop+e.paddingBottom);return e.top+t*(r/(e._ticks.length-1))},getPixelForDecimal:function(t){var e=this;if(e.isHorizontal()){var n=(e.width-(e.paddingLeft+e.paddingRight))*t+e.paddingLeft,i=e.left+Math.round(n);return i+=e.isFullWidth()?e.margins.left:0}return e.top+t*e.height},getBasePixel:function(){return this.getPixelForValue(this.getBaseValue())},getBaseValue:function(){var t=this,e=t.min,n=t.max;return t.beginAtZero?0:e<0&&n<0?n:e>0&&n>0?e:0},_autoSkip:function(t){var e,n,i,a,o=this,r=o.isHorizontal(),s=o.options.ticks.minor,u=t.length,d=l.toRadians(o.labelRotation),c=Math.cos(d),h=o.longestLabelWidth*c,f=[];for(s.maxTicksLimit&&(a=s.maxTicksLimit),r&&(e=!1,(h+s.autoSkipPadding)*u>o.width-(o.paddingLeft+o.paddingRight)&&(e=1+Math.floor((h+s.autoSkipPadding)*u/(o.width-(o.paddingLeft+o.paddingRight)))),a&&u>a&&(e=Math.max(e,Math.floor(u/a)))),n=0;n<u;n++)i=t[n],(e>1&&n%e>0||n%e==0&&n+e>=u)&&n!==u-1&&delete i.label,f.push(i);return f},draw:function(t){var e=this,i=e.options;if(i.display){var r=e.ctx,u=o.global,d=i.ticks.minor,c=i.ticks.major||d,h=i.gridLines,f=i.scaleLabel,g=0!==e.labelRotation,p=e.isHorizontal(),v=d.autoSkip?e._autoSkip(e.getTicks()):e.getTicks(),m=l.valueOrDefault(d.fontColor,u.defaultFontColor),b=n(d),x=l.valueOrDefault(c.fontColor,u.defaultFontColor),y=n(c),k=h.drawTicks?h.tickMarkLength:0,w=l.valueOrDefault(f.fontColor,u.defaultFontColor),M=n(f),S=l.options.toPadding(f.padding),C=l.toRadians(e.labelRotation),_=[],D="right"===i.position?e.left:e.right-k,I="right"===i.position?e.left+k:e.right,P="bottom"===i.position?e.top:e.bottom-k,A="bottom"===i.position?e.top+k:e.bottom;if(l.each(v,function(n,o){if(!l.isNullOrUndef(n.label)){var r,s,c,f,m=n.label;o===e.zeroLineIndex&&i.offset===h.offsetGridLines?(r=h.zeroLineWidth,s=h.zeroLineColor,c=h.zeroLineBorderDash,f=h.zeroLineBorderDashOffset):(r=l.valueAtIndexOrDefault(h.lineWidth,o),s=l.valueAtIndexOrDefault(h.color,o),c=l.valueOrDefault(h.borderDash,u.borderDash),f=l.valueOrDefault(h.borderDashOffset,u.borderDashOffset));var b,x,y,w,M,S,F,T,O,R,L="middle",z="middle",B=d.padding;if(p){var W=k+B;"bottom"===i.position?(z=g?"middle":"top",L=g?"right":"center",R=e.top+W):(z=g?"middle":"bottom",L=g?"left":"center",R=e.bottom-W);var N=a(e,o,h.offsetGridLines&&v.length>1);N<e.left&&(s="rgba(0,0,0,0)"),N+=l.aliasPixel(r),O=e.getPixelForTick(o)+d.labelOffset,b=y=M=F=N,x=P,w=A,S=t.top,T=t.bottom}else{var V,E="left"===i.position;d.mirror?(L=E?"left":"right",V=B):(L=E?"right":"left",V=k+B),O=E?e.right-V:e.left+V;var H=a(e,o,h.offsetGridLines&&v.length>1);H<e.top&&(s="rgba(0,0,0,0)"),H+=l.aliasPixel(r),R=e.getPixelForTick(o)+d.labelOffset,b=D,y=I,M=t.left,F=t.right,x=w=S=T=H}_.push({tx1:b,ty1:x,tx2:y,ty2:w,x1:M,y1:S,x2:F,y2:T,labelX:O,labelY:R,glWidth:r,glColor:s,glBorderDash:c,glBorderDashOffset:f,rotation:-1*C,label:m,major:n.major,textBaseline:z,textAlign:L})}}),l.each(_,function(t){if(h.display&&(r.save(),r.lineWidth=t.glWidth,r.strokeStyle=t.glColor,r.setLineDash&&(r.setLineDash(t.glBorderDash),r.lineDashOffset=t.glBorderDashOffset),r.beginPath(),h.drawTicks&&(r.moveTo(t.tx1,t.ty1),r.lineTo(t.tx2,t.ty2)),h.drawOnChartArea&&(r.moveTo(t.x1,t.y1),r.lineTo(t.x2,t.y2)),r.stroke(),r.restore()),d.display){r.save(),r.translate(t.labelX,t.labelY),r.rotate(t.rotation),r.font=t.major?y.font:b.font,r.fillStyle=t.major?x:m,r.textBaseline=t.textBaseline,r.textAlign=t.textAlign;var e=t.label;if(l.isArray(e))for(var n=0,i=0;n<e.length;++n)r.fillText(""+e[n],0,i),i+=1.5*b.size;else r.fillText(e,0,0);r.restore()}}),f.display){var F,T,O=0,R=s(f)/2;if(p)F=e.left+(e.right-e.left)/2,T="bottom"===i.position?e.bottom-R-S.bottom:e.top+R+S.top;else{var L="left"===i.position;F=L?e.left+R+S.top:e.right-R-S.top,T=e.top+(e.bottom-e.top)/2,O=L?-.5*Math.PI:.5*Math.PI}r.save(),r.translate(F,T),r.rotate(O),r.textAlign="center",r.textBaseline="middle",r.fillStyle=w,r.font=M.font,r.fillText(f.labelString,0,0),r.restore()}if(h.drawBorder){r.lineWidth=l.valueAtIndexOrDefault(h.lineWidth,0),r.strokeStyle=l.valueAtIndexOrDefault(h.color,0);var z=e.left,B=e.right,W=e.top,N=e.bottom,V=l.aliasPixel(r.lineWidth);p?(W=N="top"===i.position?e.bottom:e.top,W+=V,N+=V):(z=B="left"===i.position?e.right:e.left,z+=V,B+=V),r.beginPath(),r.moveTo(z,W),r.lineTo(B,N),r.stroke()}}}})}},{25:25,26:26,34:34,45:45}],33:[function(t,e,n){"use strict";var i=t(25),a=t(45);e.exports=function(t){t.scaleService={constructors:{},defaults:{},registerScaleType:function(t,e,n){this.constructors[t]=e,this.defaults[t]=a.clone(n)},getScaleConstructor:function(t){return this.constructors.hasOwnProperty(t)?this.constructors[t]:void 0},getScaleDefaults:function(t){return this.defaults.hasOwnProperty(t)?a.merge({},[i.scale,this.defaults[t]]):{}},updateScaleDefaults:function(t,e){var n=this;n.defaults.hasOwnProperty(t)&&(n.defaults[t]=a.extend(n.defaults[t],e))},addScalesToLayout:function(e){a.each(e.scales,function(n){n.fullWidth=n.options.fullWidth,n.position=n.options.position,n.weight=n.options.weight,t.layoutService.addBox(e,n)})}}}},{25:25,45:45}],34:[function(t,e,n){"use strict";var i=t(45);e.exports={generators:{linear:function(t,e){var n,a=[];if(t.stepSize&&t.stepSize>0)n=t.stepSize;else{var o=i.niceNum(e.max-e.min,!1);n=i.niceNum(o/(t.maxTicks-1),!0)}var r=Math.floor(e.min/n)*n,l=Math.ceil(e.max/n)*n;t.min&&t.max&&t.stepSize&&i.almostWhole((t.max-t.min)/t.stepSize,n/1e3)&&(r=t.min,l=t.max);var s=(l-r)/n;s=i.almostEquals(s,Math.round(s),n/1e3)?Math.round(s):Math.ceil(s),a.push(void 0!==t.min?t.min:r);for(var u=1;u<s;++u)a.push(r+u*n);return a.push(void 0!==t.max?t.max:l),a},logarithmic:function(t,e){var n,a,o=[],r=i.valueOrDefault,l=r(t.min,Math.pow(10,Math.floor(i.log10(e.min)))),s=Math.floor(i.log10(e.max)),u=Math.ceil(e.max/Math.pow(10,s));0===l?(n=Math.floor(i.log10(e.minNotZero)),a=Math.floor(e.minNotZero/Math.pow(10,n)),o.push(l),l=a*Math.pow(10,n)):(n=Math.floor(i.log10(l)),a=Math.floor(l/Math.pow(10,n)));do{o.push(l),10===++a&&(a=1,++n),l=a*Math.pow(10,n)}while(n<s||n===s&&a<u);var d=r(t.max,l);return o.push(d),o}},formatters:{values:function(t){return i.isArray(t)?t:""+t},linear:function(t,e,n){var a=n.length>3?n[2]-n[1]:n[1]-n[0];Math.abs(a)>1&&t!==Math.floor(t)&&(a=t-Math.floor(t));var o=i.log10(Math.abs(a)),r="";if(0!==t){var l=-1*Math.floor(o);l=Math.max(Math.min(l,20),0),r=t.toFixed(l)}else r="0";return r},logarithmic:function(t,e,n){var a=t/Math.pow(10,Math.floor(i.log10(t)));return 0===t?"0":1===a||2===a||5===a||0===e||e===n.length-1?t.toExponential():""}}}},{45:45}],35:[function(t,e,n){"use strict";var i=t(25),a=t(26),o=t(45);i._set("global",{tooltips:{enabled:!0,custom:null,mode:"nearest",position:"average",intersect:!0,backgroundColor:"rgba(0,0,0,0.8)",titleFontStyle:"bold",titleSpacing:2,titleMarginBottom:6,titleFontColor:"#fff",titleAlign:"left",bodySpacing:2,bodyFontColor:"#fff",bodyAlign:"left",footerFontStyle:"bold",footerSpacing:2,footerMarginTop:6,footerFontColor:"#fff",footerAlign:"left",yPadding:6,xPadding:6,caretPadding:2,caretSize:5,cornerRadius:6,multiKeyBackground:"#fff",displayColors:!0,borderColor:"rgba(0,0,0,0)",borderWidth:0,callbacks:{beforeTitle:o.noop,title:function(t,e){var n="",i=e.labels,a=i?i.length:0;if(t.length>0){var o=t[0];o.xLabel?n=o.xLabel:a>0&&o.index<a&&(n=i[o.index])}return n},afterTitle:o.noop,beforeBody:o.noop,beforeLabel:o.noop,label:function(t,e){var n=e.datasets[t.datasetIndex].label||"";return n&&(n+=": "),n+=t.yLabel},labelColor:function(t,e){var n=e.getDatasetMeta(t.datasetIndex).data[t.index]._view;return{borderColor:n.borderColor,backgroundColor:n.backgroundColor}},labelTextColor:function(){return this._options.bodyFontColor},afterLabel:o.noop,afterBody:o.noop,beforeFooter:o.noop,footer:o.noop,afterFooter:o.noop}}}),e.exports=function(t){function e(t,e){var n=o.color(t);return n.alpha(e*n.alpha()).rgbaString()}function n(t,e){return e&&(o.isArray(e)?Array.prototype.push.apply(t,e):t.push(e)),t}function r(t){var e=t._xScale,n=t._yScale||t._scale,i=t._index,a=t._datasetIndex;return{xLabel:e?e.getLabelForIndex(i,a):"",yLabel:n?n.getLabelForIndex(i,a):"",index:i,datasetIndex:a,x:t._model.x,y:t._model.y}}function l(t){var e=i.global,n=o.valueOrDefault;return{xPadding:t.xPadding,yPadding:t.yPadding,xAlign:t.xAlign,yAlign:t.yAlign,bodyFontColor:t.bodyFontColor,_bodyFontFamily:n(t.bodyFontFamily,e.defaultFontFamily),_bodyFontStyle:n(t.bodyFontStyle,e.defaultFontStyle),_bodyAlign:t.bodyAlign,bodyFontSize:n(t.bodyFontSize,e.defaultFontSize),bodySpacing:t.bodySpacing,titleFontColor:t.titleFontColor,_titleFontFamily:n(t.titleFontFamily,e.defaultFontFamily),_titleFontStyle:n(t.titleFontStyle,e.defaultFontStyle),titleFontSize:n(t.titleFontSize,e.defaultFontSize),_titleAlign:t.titleAlign,titleSpacing:t.titleSpacing,titleMarginBottom:t.titleMarginBottom,footerFontColor:t.footerFontColor,_footerFontFamily:n(t.footerFontFamily,e.defaultFontFamily),_footerFontStyle:n(t.footerFontStyle,e.defaultFontStyle),footerFontSize:n(t.footerFontSize,e.defaultFontSize),_footerAlign:t.footerAlign,footerSpacing:t.footerSpacing,footerMarginTop:t.footerMarginTop,caretSize:t.caretSize,cornerRadius:t.cornerRadius,backgroundColor:t.backgroundColor,opacity:0,legendColorBackground:t.multiKeyBackground,displayColors:t.displayColors,borderColor:t.borderColor,borderWidth:t.borderWidth}}function s(t,e){var n=t._chart.ctx,i=2*e.yPadding,a=0,r=e.body,l=r.reduce(function(t,e){return t+e.before.length+e.lines.length+e.after.length},0);l+=e.beforeBody.length+e.afterBody.length;var s=e.title.length,u=e.footer.length,d=e.titleFontSize,c=e.bodyFontSize,h=e.footerFontSize;i+=s*d,i+=s?(s-1)*e.titleSpacing:0,i+=s?e.titleMarginBottom:0,i+=l*c,i+=l?(l-1)*e.bodySpacing:0,i+=u?e.footerMarginTop:0,i+=u*h,i+=u?(u-1)*e.footerSpacing:0;var f=0,g=function(t){a=Math.max(a,n.measureText(t).width+f)};return n.font=o.fontString(d,e._titleFontStyle,e._titleFontFamily),o.each(e.title,g),n.font=o.fontString(c,e._bodyFontStyle,e._bodyFontFamily),o.each(e.beforeBody.concat(e.afterBody),g),f=e.displayColors?c+2:0,o.each(r,function(t){o.each(t.before,g),o.each(t.lines,g),o.each(t.after,g)}),f=0,n.font=o.fontString(h,e._footerFontStyle,e._footerFontFamily),o.each(e.footer,g),a+=2*e.xPadding,{width:a,height:i}}function u(t,e){var n=t._model,i=t._chart,a=t._chart.chartArea,o="center",r="center";n.y<e.height?r="top":n.y>i.height-e.height&&(r="bottom");var l,s,u,d,c,h=(a.left+a.right)/2,f=(a.top+a.bottom)/2;"center"===r?(l=function(t){return t<=h},s=function(t){return t>h}):(l=function(t){return t<=e.width/2},s=function(t){return t>=i.width-e.width/2}),u=function(t){return t+e.width>i.width},d=function(t){return t-e.width<0},c=function(t){return t<=f?"top":"bottom"},l(n.x)?(o="left",u(n.x)&&(o="center",r=c(n.y))):s(n.x)&&(o="right",d(n.x)&&(o="center",r=c(n.y)));var g=t._options;return{xAlign:g.xAlign?g.xAlign:o,yAlign:g.yAlign?g.yAlign:r}}function d(t,e,n){var i=t.x,a=t.y,o=t.caretSize,r=t.caretPadding,l=t.cornerRadius,s=n.xAlign,u=n.yAlign,d=o+r,c=l+r;return"right"===s?i-=e.width:"center"===s&&(i-=e.width/2),"top"===u?a+=d:a-="bottom"===u?e.height+d:e.height/2,"center"===u?"left"===s?i+=d:"right"===s&&(i-=d):"left"===s?i-=c:"right"===s&&(i+=c),{x:i,y:a}}t.Tooltip=a.extend({initialize:function(){this._model=l(this._options)},getTitle:function(){var t=this,e=t._options.callbacks,i=e.beforeTitle.apply(t,arguments),a=e.title.apply(t,arguments),o=e.afterTitle.apply(t,arguments),r=[];return r=n(r,i),r=n(r,a),r=n(r,o)},getBeforeBody:function(){var t=this._options.callbacks.beforeBody.apply(this,arguments);return o.isArray(t)?t:void 0!==t?[t]:[]},getBody:function(t,e){var i=this,a=i._options.callbacks,r=[];return o.each(t,function(t){var o={before:[],lines:[],after:[]};n(o.before,a.beforeLabel.call(i,t,e)),n(o.lines,a.label.call(i,t,e)),n(o.after,a.afterLabel.call(i,t,e)),r.push(o)}),r},getAfterBody:function(){var t=this._options.callbacks.afterBody.apply(this,arguments);return o.isArray(t)?t:void 0!==t?[t]:[]},getFooter:function(){var t=this,e=t._options.callbacks,i=e.beforeFooter.apply(t,arguments),a=e.footer.apply(t,arguments),o=e.afterFooter.apply(t,arguments),r=[];return r=n(r,i),r=n(r,a),r=n(r,o)},update:function(e){var n,i,a=this,c=a._options,h=a._model,f=a._model=l(c),g=a._active,p=a._data,v={xAlign:h.xAlign,yAlign:h.yAlign},m={x:h.x,y:h.y},b={width:h.width,height:h.height},x={x:h.caretX,y:h.caretY};if(g.length){f.opacity=1;var y=[],k=[];x=t.Tooltip.positioners[c.position](g,a._eventPosition);var w=[];for(n=0,i=g.length;n<i;++n)w.push(r(g[n]));c.filter&&(w=w.filter(function(t){return c.filter(t,p)})),c.itemSort&&(w=w.sort(function(t,e){return c.itemSort(t,e,p)})),o.each(w,function(t){y.push(c.callbacks.labelColor.call(a,t,a._chart)),k.push(c.callbacks.labelTextColor.call(a,t,a._chart))}),f.title=a.getTitle(w,p),f.beforeBody=a.getBeforeBody(w,p),f.body=a.getBody(w,p),f.afterBody=a.getAfterBody(w,p),f.footer=a.getFooter(w,p),f.x=Math.round(x.x),f.y=Math.round(x.y),f.caretPadding=c.caretPadding,f.labelColors=y,f.labelTextColors=k,f.dataPoints=w,m=d(f,b=s(this,f),v=u(this,b))}else f.opacity=0;return f.xAlign=v.xAlign,f.yAlign=v.yAlign,f.x=m.x,f.y=m.y,f.width=b.width,f.height=b.height,f.caretX=x.x,f.caretY=x.y,a._model=f,e&&c.custom&&c.custom.call(a,f),a},drawCaret:function(t,e){var n=this._chart.ctx,i=this._view,a=this.getCaretPosition(t,e,i);n.lineTo(a.x1,a.y1),n.lineTo(a.x2,a.y2),n.lineTo(a.x3,a.y3)},getCaretPosition:function(t,e,n){var i,a,o,r,l,s,u=n.caretSize,d=n.cornerRadius,c=n.xAlign,h=n.yAlign,f=t.x,g=t.y,p=e.width,v=e.height;if("center"===h)l=g+v/2,"left"===c?(a=(i=f)-u,o=i,r=l+u,s=l-u):(a=(i=f+p)+u,o=i,r=l-u,s=l+u);else if("left"===c?(i=(a=f+d+u)-u,o=a+u):"right"===c?(i=(a=f+p-d-u)-u,o=a+u):(i=(a=f+p/2)-u,o=a+u),"top"===h)l=(r=g)-u,s=r;else{l=(r=g+v)+u,s=r;var m=o;o=i,i=m}return{x1:i,x2:a,x3:o,y1:r,y2:l,y3:s}},drawTitle:function(t,n,i,a){var r=n.title;if(r.length){i.textAlign=n._titleAlign,i.textBaseline="top";var l=n.titleFontSize,s=n.titleSpacing;i.fillStyle=e(n.titleFontColor,a),i.font=o.fontString(l,n._titleFontStyle,n._titleFontFamily);var u,d;for(u=0,d=r.length;u<d;++u)i.fillText(r[u],t.x,t.y),t.y+=l+s,u+1===r.length&&(t.y+=n.titleMarginBottom-s)}},drawBody:function(t,n,i,a){var r=n.bodyFontSize,l=n.bodySpacing,s=n.body;i.textAlign=n._bodyAlign,i.textBaseline="top",i.font=o.fontString(r,n._bodyFontStyle,n._bodyFontFamily);var u=0,d=function(e){i.fillText(e,t.x+u,t.y),t.y+=r+l};i.fillStyle=e(n.bodyFontColor,a),o.each(n.beforeBody,d);var c=n.displayColors;u=c?r+2:0,o.each(s,function(l,s){var u=e(n.labelTextColors[s],a);i.fillStyle=u,o.each(l.before,d),o.each(l.lines,function(o){c&&(i.fillStyle=e(n.legendColorBackground,a),i.fillRect(t.x,t.y,r,r),i.lineWidth=1,i.strokeStyle=e(n.labelColors[s].borderColor,a),i.strokeRect(t.x,t.y,r,r),i.fillStyle=e(n.labelColors[s].backgroundColor,a),i.fillRect(t.x+1,t.y+1,r-2,r-2),i.fillStyle=u),d(o)}),o.each(l.after,d)}),u=0,o.each(n.afterBody,d),t.y-=l},drawFooter:function(t,n,i,a){var r=n.footer;r.length&&(t.y+=n.footerMarginTop,i.textAlign=n._footerAlign,i.textBaseline="top",i.fillStyle=e(n.footerFontColor,a),i.font=o.fontString(n.footerFontSize,n._footerFontStyle,n._footerFontFamily),o.each(r,function(e){i.fillText(e,t.x,t.y),t.y+=n.footerFontSize+n.footerSpacing}))},drawBackground:function(t,n,i,a,o){i.fillStyle=e(n.backgroundColor,o),i.strokeStyle=e(n.borderColor,o),i.lineWidth=n.borderWidth;var r=n.xAlign,l=n.yAlign,s=t.x,u=t.y,d=a.width,c=a.height,h=n.cornerRadius;i.beginPath(),i.moveTo(s+h,u),"top"===l&&this.drawCaret(t,a),i.lineTo(s+d-h,u),i.quadraticCurveTo(s+d,u,s+d,u+h),"center"===l&&"right"===r&&this.drawCaret(t,a),i.lineTo(s+d,u+c-h),i.quadraticCurveTo(s+d,u+c,s+d-h,u+c),"bottom"===l&&this.drawCaret(t,a),i.lineTo(s+h,u+c),i.quadraticCurveTo(s,u+c,s,u+c-h),"center"===l&&"left"===r&&this.drawCaret(t,a),i.lineTo(s,u+h),i.quadraticCurveTo(s,u,s+h,u),i.closePath(),i.fill(),n.borderWidth>0&&i.stroke()},draw:function(){var t=this._chart.ctx,e=this._view;if(0!==e.opacity){var n={width:e.width,height:e.height},i={x:e.x,y:e.y},a=Math.abs(e.opacity<.001)?0:e.opacity,o=e.title.length||e.beforeBody.length||e.body.length||e.afterBody.length||e.footer.length;this._options.enabled&&o&&(this.drawBackground(i,e,t,n,a),i.x+=e.xPadding,i.y+=e.yPadding,this.drawTitle(i,e,t,a),this.drawBody(i,e,t,a),this.drawFooter(i,e,t,a))}},handleEvent:function(t){var e=this,n=e._options,i=!1;if(e._lastActive=e._lastActive||[],"mouseout"===t.type?e._active=[]:e._active=e._chart.getElementsAtEventForMode(t,n.mode,n),!(i=!o.arrayEquals(e._active,e._lastActive)))return!1;if(e._lastActive=e._active,n.enabled||n.custom){e._eventPosition={x:t.x,y:t.y};var a=e._model;e.update(!0),e.pivot(),i|=a.x!==e._model.x||a.y!==e._model.y}return i}}),t.Tooltip.positioners={average:function(t){if(!t.length)return!1;var e,n,i=0,a=0,o=0;for(e=0,n=t.length;e<n;++e){var r=t[e];if(r&&r.hasValue()){var l=r.tooltipPosition();i+=l.x,a+=l.y,++o}}return{x:Math.round(i/o),y:Math.round(a/o)}},nearest:function(t,e){var n,i,a,r=e.x,l=e.y,s=Number.POSITIVE_INFINITY;for(n=0,i=t.length;n<i;++n){var u=t[n];if(u&&u.hasValue()){var d=u.getCenterPoint(),c=o.distanceBetweenPoints(e,d);c<s&&(s=c,a=u)}}if(a){var h=a.tooltipPosition();r=h.x,l=h.y}return{x:r,y:l}}}}},{25:25,26:26,45:45}],36:[function(t,e,n){"use strict";var i=t(25),a=t(26),o=t(45);i._set("global",{elements:{arc:{backgroundColor:i.global.defaultColor,borderColor:"#fff",borderWidth:2}}}),e.exports=a.extend({inLabelRange:function(t){var e=this._view;return!!e&&Math.pow(t-e.x,2)<Math.pow(e.radius+e.hoverRadius,2)},inRange:function(t,e){var n=this._view;if(n){for(var i=o.getAngleFromPoint(n,{x:t,y:e}),a=i.angle,r=i.distance,l=n.startAngle,s=n.endAngle;s<l;)s+=2*Math.PI;for(;a>s;)a-=2*Math.PI;for(;a<l;)a+=2*Math.PI;var u=a>=l&&a<=s,d=r>=n.innerRadius&&r<=n.outerRadius;return u&&d}return!1},getCenterPoint:function(){var t=this._view,e=(t.startAngle+t.endAngle)/2,n=(t.innerRadius+t.outerRadius)/2;return{x:t.x+Math.cos(e)*n,y:t.y+Math.sin(e)*n}},getArea:function(){var t=this._view;return Math.PI*((t.endAngle-t.startAngle)/(2*Math.PI))*(Math.pow(t.outerRadius,2)-Math.pow(t.innerRadius,2))},tooltipPosition:function(){var t=this._view,e=t.startAngle+(t.endAngle-t.startAngle)/2,n=(t.outerRadius-t.innerRadius)/2+t.innerRadius;return{x:t.x+Math.cos(e)*n,y:t.y+Math.sin(e)*n}},draw:function(){var t=this._chart.ctx,e=this._view,n=e.startAngle,i=e.endAngle;t.beginPath(),t.arc(e.x,e.y,e.outerRadius,n,i),t.arc(e.x,e.y,e.innerRadius,i,n,!0),t.closePath(),t.strokeStyle=e.borderColor,t.lineWidth=e.borderWidth,t.fillStyle=e.backgroundColor,t.fill(),t.lineJoin="bevel",e.borderWidth&&t.stroke()}})},{25:25,26:26,45:45}],37:[function(t,e,n){"use strict";var i=t(25),a=t(26),o=t(45),r=i.global;i._set("global",{elements:{line:{tension:.4,backgroundColor:r.defaultColor,borderWidth:3,borderColor:r.defaultColor,borderCapStyle:"butt",borderDash:[],borderDashOffset:0,borderJoinStyle:"miter",capBezierPoints:!0,fill:!0}}}),e.exports=a.extend({draw:function(){var t,e,n,i,a=this,l=a._view,s=a._chart.ctx,u=l.spanGaps,d=a._children.slice(),c=r.elements.line,h=-1;for(a._loop&&d.length&&d.push(d[0]),s.save(),s.lineCap=l.borderCapStyle||c.borderCapStyle,s.setLineDash&&s.setLineDash(l.borderDash||c.borderDash),s.lineDashOffset=l.borderDashOffset||c.borderDashOffset,s.lineJoin=l.borderJoinStyle||c.borderJoinStyle,s.lineWidth=l.borderWidth||c.borderWidth,s.strokeStyle=l.borderColor||r.defaultColor,s.beginPath(),h=-1,t=0;t<d.length;++t)e=d[t],n=o.previousItem(d,t),i=e._view,0===t?i.skip||(s.moveTo(i.x,i.y),h=t):(n=-1===h?n:d[h],i.skip||(h!==t-1&&!u||-1===h?s.moveTo(i.x,i.y):o.canvas.lineTo(s,n._view,e._view),h=t));s.stroke(),s.restore()}})},{25:25,26:26,45:45}],38:[function(t,e,n){"use strict";function i(t){var e=this._view;return!!e&&Math.pow(t-e.x,2)<Math.pow(e.radius+e.hitRadius,2)}var a=t(25),o=t(26),r=t(45),l=a.global.defaultColor;a._set("global",{elements:{point:{radius:3,pointStyle:"circle",backgroundColor:l,borderColor:l,borderWidth:1,hitRadius:1,hoverRadius:4,hoverBorderWidth:1}}}),e.exports=o.extend({inRange:function(t,e){var n=this._view;return!!n&&Math.pow(t-n.x,2)+Math.pow(e-n.y,2)<Math.pow(n.hitRadius+n.radius,2)},inLabelRange:i,inXRange:i,inYRange:function(t){var e=this._view;return!!e&&Math.pow(t-e.y,2)<Math.pow(e.radius+e.hitRadius,2)},getCenterPoint:function(){var t=this._view;return{x:t.x,y:t.y}},getArea:function(){return Math.PI*Math.pow(this._view.radius,2)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y,padding:t.radius+t.borderWidth}},draw:function(t){var e=this._view,n=this._model,i=this._chart.ctx,o=e.pointStyle,s=e.radius,u=e.x,d=e.y,c=r.color,h=0;e.skip||(i.strokeStyle=e.borderColor||l,i.lineWidth=r.valueOrDefault(e.borderWidth,a.global.elements.point.borderWidth),i.fillStyle=e.backgroundColor||l,void 0!==t&&(n.x<t.left||1.01*t.right<n.x||n.y<t.top||1.01*t.bottom<n.y)&&(n.x<t.left?h=(u-n.x)/(t.left-n.x):1.01*t.right<n.x?h=(n.x-u)/(n.x-t.right):n.y<t.top?h=(d-n.y)/(t.top-n.y):1.01*t.bottom<n.y&&(h=(n.y-d)/(n.y-t.bottom)),h=Math.round(100*h)/100,i.strokeStyle=c(i.strokeStyle).alpha(h).rgbString(),i.fillStyle=c(i.fillStyle).alpha(h).rgbString()),r.canvas.drawPoint(i,o,s,u,d))}})},{25:25,26:26,45:45}],39:[function(t,e,n){"use strict";function i(t){return void 0!==t._view.width}function a(t){var e,n,a,o,r=t._view;if(i(t)){var l=r.width/2;e=r.x-l,n=r.x+l,a=Math.min(r.y,r.base),o=Math.max(r.y,r.base)}else{var s=r.height/2;e=Math.min(r.x,r.base),n=Math.max(r.x,r.base),a=r.y-s,o=r.y+s}return{left:e,top:a,right:n,bottom:o}}var o=t(25),r=t(26);o._set("global",{elements:{rectangle:{backgroundColor:o.global.defaultColor,borderColor:o.global.defaultColor,borderSkipped:"bottom",borderWidth:0}}}),e.exports=r.extend({draw:function(){function t(t){return m[(b+t)%4]}var e,n,i,a,o,r,l,s=this._chart.ctx,u=this._view,d=u.borderWidth;if(u.horizontal?(e=u.base,n=u.x,i=u.y-u.height/2,a=u.y+u.height/2,o=n>e?1:-1,r=1,l=u.borderSkipped||"left"):(e=u.x-u.width/2,n=u.x+u.width/2,i=u.y,o=1,r=(a=u.base)>i?1:-1,l=u.borderSkipped||"bottom"),d){var c=Math.min(Math.abs(e-n),Math.abs(i-a)),h=(d=d>c?c:d)/2,f=e+("left"!==l?h*o:0),g=n+("right"!==l?-h*o:0),p=i+("top"!==l?h*r:0),v=a+("bottom"!==l?-h*r:0);f!==g&&(i=p,a=v),p!==v&&(e=f,n=g)}s.beginPath(),s.fillStyle=u.backgroundColor,s.strokeStyle=u.borderColor,s.lineWidth=d;var m=[[e,a],[e,i],[n,i],[n,a]],b=["bottom","left","top","right"].indexOf(l,0);-1===b&&(b=0);var x=t(0);s.moveTo(x[0],x[1]);for(var y=1;y<4;y++)x=t(y),s.lineTo(x[0],x[1]);s.fill(),d&&s.stroke()},height:function(){var t=this._view;return t.base-t.y},inRange:function(t,e){var n=!1;if(this._view){var i=a(this);n=t>=i.left&&t<=i.right&&e>=i.top&&e<=i.bottom}return n},inLabelRange:function(t,e){var n=this;if(!n._view)return!1;var o=a(n);return i(n)?t>=o.left&&t<=o.right:e>=o.top&&e<=o.bottom},inXRange:function(t){var e=a(this);return t>=e.left&&t<=e.right},inYRange:function(t){var e=a(this);return t>=e.top&&t<=e.bottom},getCenterPoint:function(){var t,e,n=this._view;return i(this)?(t=n.x,e=(n.y+n.base)/2):(t=(n.x+n.base)/2,e=n.y),{x:t,y:e}},getArea:function(){var t=this._view;return t.width*Math.abs(t.y-t.base)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y}}})},{25:25,26:26}],40:[function(t,e,n){"use strict";e.exports={},e.exports.Arc=t(36),e.exports.Line=t(37),e.exports.Point=t(38),e.exports.Rectangle=t(39)},{36:36,37:37,38:38,39:39}],41:[function(t,e,n){"use strict";var i=t(42),n=e.exports={clear:function(t){t.ctx.clearRect(0,0,t.width,t.height)},roundedRect:function(t,e,n,i,a,o){if(o){var r=Math.min(o,i/2),l=Math.min(o,a/2);t.moveTo(e+r,n),t.lineTo(e+i-r,n),t.quadraticCurveTo(e+i,n,e+i,n+l),t.lineTo(e+i,n+a-l),t.quadraticCurveTo(e+i,n+a,e+i-r,n+a),t.lineTo(e+r,n+a),t.quadraticCurveTo(e,n+a,e,n+a-l),t.lineTo(e,n+l),t.quadraticCurveTo(e,n,e+r,n)}else t.rect(e,n,i,a)},drawPoint:function(t,e,n,i,a){var o,r,l,s,u,d;if(!e||"object"!=typeof e||"[object HTMLImageElement]"!==(o=e.toString())&&"[object HTMLCanvasElement]"!==o){if(!(isNaN(n)||n<=0)){switch(e){default:t.beginPath(),t.arc(i,a,n,0,2*Math.PI),t.closePath(),t.fill();break;case"triangle":t.beginPath(),u=(r=3*n/Math.sqrt(3))*Math.sqrt(3)/2,t.moveTo(i-r/2,a+u/3),t.lineTo(i+r/2,a+u/3),t.lineTo(i,a-2*u/3),t.closePath(),t.fill();break;case"rect":d=1/Math.SQRT2*n,t.beginPath(),t.fillRect(i-d,a-d,2*d,2*d),t.strokeRect(i-d,a-d,2*d,2*d);break;case"rectRounded":var c=n/Math.SQRT2,h=i-c,f=a-c,g=Math.SQRT2*n;t.beginPath(),this.roundedRect(t,h,f,g,g,n/2),t.closePath(),t.fill();break;case"rectRot":d=1/Math.SQRT2*n,t.beginPath(),t.moveTo(i-d,a),t.lineTo(i,a+d),t.lineTo(i+d,a),t.lineTo(i,a-d),t.closePath(),t.fill();break;case"cross":t.beginPath(),t.moveTo(i,a+n),t.lineTo(i,a-n),t.moveTo(i-n,a),t.lineTo(i+n,a),t.closePath();break;case"crossRot":t.beginPath(),l=Math.cos(Math.PI/4)*n,s=Math.sin(Math.PI/4)*n,t.moveTo(i-l,a-s),t.lineTo(i+l,a+s),t.moveTo(i-l,a+s),t.lineTo(i+l,a-s),t.closePath();break;case"star":t.beginPath(),t.moveTo(i,a+n),t.lineTo(i,a-n),t.moveTo(i-n,a),t.lineTo(i+n,a),l=Math.cos(Math.PI/4)*n,s=Math.sin(Math.PI/4)*n,t.moveTo(i-l,a-s),t.lineTo(i+l,a+s),t.moveTo(i-l,a+s),t.lineTo(i+l,a-s),t.closePath();break;case"line":t.beginPath(),t.moveTo(i-n,a),t.lineTo(i+n,a),t.closePath();break;case"dash":t.beginPath(),t.moveTo(i,a),t.lineTo(i+n,a),t.closePath()}t.stroke()}}else t.drawImage(e,i-e.width/2,a-e.height/2,e.width,e.height)},clipArea:function(t,e){t.save(),t.beginPath(),t.rect(e.left,e.top,e.right-e.left,e.bottom-e.top),t.clip()},unclipArea:function(t){t.restore()},lineTo:function(t,e,n,i){if(n.steppedLine)return"after"===n.steppedLine&&!i||"after"!==n.steppedLine&&i?t.lineTo(e.x,n.y):t.lineTo(n.x,e.y),void t.lineTo(n.x,n.y);n.tension?t.bezierCurveTo(i?e.controlPointPreviousX:e.controlPointNextX,i?e.controlPointPreviousY:e.controlPointNextY,i?n.controlPointNextX:n.controlPointPreviousX,i?n.controlPointNextY:n.controlPointPreviousY,n.x,n.y):t.lineTo(n.x,n.y)}};i.clear=n.clear,i.drawRoundedRectangle=function(t){t.beginPath(),n.roundedRect.apply(n,arguments),t.closePath()}},{42:42}],42:[function(t,e,n){"use strict";var i={noop:function(){},uid:function(){var t=0;return function(){return t++}}(),isNullOrUndef:function(t){return null===t||void 0===t},isArray:Array.isArray?Array.isArray:function(t){return"[object Array]"===Object.prototype.toString.call(t)},isObject:function(t){return null!==t&&"[object Object]"===Object.prototype.toString.call(t)},valueOrDefault:function(t,e){return void 0===t?e:t},valueAtIndexOrDefault:function(t,e,n){return i.valueOrDefault(i.isArray(t)?t[e]:t,n)},callback:function(t,e,n){if(t&&"function"==typeof t.call)return t.apply(n,e)},each:function(t,e,n,a){var o,r,l;if(i.isArray(t))if(r=t.length,a)for(o=r-1;o>=0;o--)e.call(n,t[o],o);else for(o=0;o<r;o++)e.call(n,t[o],o);else if(i.isObject(t))for(r=(l=Object.keys(t)).length,o=0;o<r;o++)e.call(n,t[l[o]],l[o])},arrayEquals:function(t,e){var n,a,o,r;if(!t||!e||t.length!==e.length)return!1;for(n=0,a=t.length;n<a;++n)if(o=t[n],r=e[n],o instanceof Array&&r instanceof Array){if(!i.arrayEquals(o,r))return!1}else if(o!==r)return!1;return!0},clone:function(t){if(i.isArray(t))return t.map(i.clone);if(i.isObject(t)){for(var e={},n=Object.keys(t),a=n.length,o=0;o<a;++o)e[n[o]]=i.clone(t[n[o]]);return e}return t},_merger:function(t,e,n,a){var o=e[t],r=n[t];i.isObject(o)&&i.isObject(r)?i.merge(o,r,a):e[t]=i.clone(r)},_mergerIf:function(t,e,n){var a=e[t],o=n[t];i.isObject(a)&&i.isObject(o)?i.mergeIf(a,o):e.hasOwnProperty(t)||(e[t]=i.clone(o))},merge:function(t,e,n){var a,o,r,l,s,u=i.isArray(e)?e:[e],d=u.length;if(!i.isObject(t))return t;for(a=(n=n||{}).merger||i._merger,o=0;o<d;++o)if(e=u[o],i.isObject(e))for(s=0,l=(r=Object.keys(e)).length;s<l;++s)a(r[s],t,e,n);return t},mergeIf:function(t,e){return i.merge(t,e,{merger:i._mergerIf})}};e.exports=i,i.callCallback=i.callback,i.indexOf=function(t,e,n){return Array.prototype.indexOf.call(t,e,n)},i.getValueOrDefault=i.valueOrDefault,i.getValueAtIndexOrDefault=i.valueAtIndexOrDefault},{}],43:[function(t,e,n){"use strict";var i=t(42),a={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return-t*(t-2)},easeInOutQuad:function(t){return(t/=.5)<1?.5*t*t:-.5*(--t*(t-2)-1)},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return(t-=1)*t*t+1},easeInOutCubic:function(t){return(t/=.5)<1?.5*t*t*t:.5*((t-=2)*t*t+2)},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return-((t-=1)*t*t*t-1)},easeInOutQuart:function(t){return(t/=.5)<1?.5*t*t*t*t:-.5*((t-=2)*t*t*t-2)},easeInQuint:function(t){return t*t*t*t*t},easeOutQuint:function(t){return(t-=1)*t*t*t*t+1},easeInOutQuint:function(t){return(t/=.5)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)},easeInSine:function(t){return 1-Math.cos(t*(Math.PI/2))},easeOutSine:function(t){return Math.sin(t*(Math.PI/2))},easeInOutSine:function(t){return-.5*(Math.cos(Math.PI*t)-1)},easeInExpo:function(t){return 0===t?0:Math.pow(2,10*(t-1))},easeOutExpo:function(t){return 1===t?1:1-Math.pow(2,-10*t)},easeInOutExpo:function(t){return 0===t?0:1===t?1:(t/=.5)<1?.5*Math.pow(2,10*(t-1)):.5*(2-Math.pow(2,-10*--t))},easeInCirc:function(t){return t>=1?t:-(Math.sqrt(1-t*t)-1)},easeOutCirc:function(t){return Math.sqrt(1-(t-=1)*t)},easeInOutCirc:function(t){return(t/=.5)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:1===t?1:(n||(n=.3),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),-i*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n))},easeOutElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:1===t?1:(n||(n=.3),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),i*Math.pow(2,-10*t)*Math.sin((t-e)*(2*Math.PI)/n)+1)},easeInOutElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:2==(t/=.5)?1:(n||(n=.45),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),t<1?i*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n)*-.5:i*Math.pow(2,-10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n)*.5+1)},easeInBack:function(t){var e=1.70158;return t*t*((e+1)*t-e)},easeOutBack:function(t){var e=1.70158;return(t-=1)*t*((e+1)*t+e)+1},easeInOutBack:function(t){var e=1.70158;return(t/=.5)<1?t*t*((1+(e*=1.525))*t-e)*.5:.5*((t-=2)*t*((1+(e*=1.525))*t+e)+2)},easeInBounce:function(t){return 1-a.easeOutBounce(1-t)},easeOutBounce:function(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375},easeInOutBounce:function(t){return t<.5?.5*a.easeInBounce(2*t):.5*a.easeOutBounce(2*t-1)+.5}};e.exports={effects:a},i.easingEffects=a},{42:42}],44:[function(t,e,n){"use strict";var i=t(42);e.exports={toLineHeight:function(t,e){var n=(""+t).match(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/);if(!n||"normal"===n[1])return 1.2*e;switch(t=+n[2],n[3]){case"px":return t;case"%":t/=100}return e*t},toPadding:function(t){var e,n,a,o;return i.isObject(t)?(e=+t.top||0,n=+t.right||0,a=+t.bottom||0,o=+t.left||0):e=n=a=o=+t||0,{top:e,right:n,bottom:a,left:o,height:e+a,width:o+n}},resolve:function(t,e,n){var a,o,r;for(a=0,o=t.length;a<o;++a)if(void 0!==(r=t[a])&&(void 0!==e&&"function"==typeof r&&(r=r(e)),void 0!==n&&i.isArray(r)&&(r=r[n]),void 0!==r))return r}}},{42:42}],45:[function(t,e,n){"use strict";e.exports=t(42),e.exports.easing=t(43),e.exports.canvas=t(41),e.exports.options=t(44)},{41:41,42:42,43:43,44:44}],46:[function(t,e,n){e.exports={acquireContext:function(t){return t&&t.canvas&&(t=t.canvas),t&&t.getContext("2d")||null}}},{}],47:[function(t,e,n){"use strict";function i(t,e){var n=v.getStyle(t,e),i=n&&n.match(/^(\d+)(\.\d+)?px$/);return i?Number(i[1]):void 0}function a(t,e){var n=t.style,a=t.getAttribute("height"),o=t.getAttribute("width");if(t[m]={initial:{height:a,width:o,style:{display:n.display,height:n.height,width:n.width}}},n.display=n.display||"block",null===o||""===o){var r=i(t,"width");void 0!==r&&(t.width=r)}if(null===a||""===a)if(""===t.style.height)t.height=t.width/(e.options.aspectRatio||2);else{var l=i(t,"height");void 0!==r&&(t.height=l)}return t}function o(t,e,n){t.addEventListener(e,n,M)}function r(t,e,n){t.removeEventListener(e,n,M)}function l(t,e,n,i,a){return{type:t,chart:e,native:a||null,x:void 0!==n?n:null,y:void 0!==i?i:null}}function s(t,e){var n=w[t.type]||t.type,i=v.getRelativePosition(t,e);return l(n,e,i.x,i.y,t)}function u(t,e){var n=!1,i=[];return function(){i=Array.prototype.slice.call(arguments),e=e||this,n||(n=!0,v.requestAnimFrame.call(window,function(){n=!1,t.apply(e,i)}))}}function d(t){var e=document.createElement("div"),n=b+"size-monitor",i="position:absolute;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1;";e.style.cssText=i,e.className=n,e.innerHTML='<div class="'+n+'-expand" style="'+i+'"><div style="position:absolute;width:1000000px;height:1000000px;left:0;top:0"></div></div><div class="'+n+'-shrink" style="'+i+'"><div style="position:absolute;width:200%;height:200%;left:0; top:0"></div></div>';var a=e.childNodes[0],r=e.childNodes[1];e._reset=function(){a.scrollLeft=1e6,a.scrollTop=1e6,r.scrollLeft=1e6,r.scrollTop=1e6};var l=function(){e._reset(),t()};return o(a,"scroll",l.bind(a,"expand")),o(r,"scroll",l.bind(r,"shrink")),e}function c(t,e){var n=(t[m]||(t[m]={})).renderProxy=function(t){t.animationName===y&&e()};v.each(k,function(e){o(t,e,n)}),t.classList.add(x)}function h(t){var e=t[m]||{},n=e.renderProxy;n&&(v.each(k,function(e){r(t,e,n)}),delete e.renderProxy),t.classList.remove(x)}function f(t,e,n){var i=t[m]||(t[m]={}),a=i.resizer=d(u(function(){if(i.resizer)return e(l("resize",n))}));c(t,function(){if(i.resizer){var e=t.parentNode;e&&e!==a.parentNode&&e.insertBefore(a,e.firstChild),a._reset()}})}function g(t){var e=t[m]||{},n=e.resizer;delete e.resizer,h(t),n&&n.parentNode&&n.parentNode.removeChild(n)}function p(t,e){var n=t._style||document.createElement("style");t._style||(t._style=n,e="/* Chart.js */\n"+e,n.setAttribute("type","text/css"),document.getElementsByTagName("head")[0].appendChild(n)),n.appendChild(document.createTextNode(e))}var v=t(45),m="$chartjs",b="chartjs-",x=b+"render-monitor",y=b+"render-animation",k=["animationstart","webkitAnimationStart"],w={touchstart:"mousedown",touchmove:"mousemove",touchend:"mouseup",pointerenter:"mouseenter",pointerdown:"mousedown",pointermove:"mousemove",pointerup:"mouseup",pointerleave:"mouseout",pointerout:"mouseout"},M=!!function(){var t=!1;try{var e=Object.defineProperty({},"passive",{get:function(){t=!0}});window.addEventListener("e",null,e)}catch(t){}return t}()&&{passive:!0};e.exports={_enabled:"undefined"!=typeof window&&"undefined"!=typeof document,initialize:function(){var t="from{opacity:0.99}to{opacity:1}";p(this,"@-webkit-keyframes "+y+"{"+t+"}@keyframes "+y+"{"+t+"}."+x+"{-webkit-animation:"+y+" 0.001s;animation:"+y+" 0.001s;}")},acquireContext:function(t,e){"string"==typeof t?t=document.getElementById(t):t.length&&(t=t[0]),t&&t.canvas&&(t=t.canvas);var n=t&&t.getContext&&t.getContext("2d");return n&&n.canvas===t?(a(t,e),n):null},releaseContext:function(t){var e=t.canvas;if(e[m]){var n=e[m].initial;["height","width"].forEach(function(t){var i=n[t];v.isNullOrUndef(i)?e.removeAttribute(t):e.setAttribute(t,i)}),v.each(n.style||{},function(t,n){e.style[n]=t}),e.width=e.width,delete e[m]}},addEventListener:function(t,e,n){var i=t.canvas;if("resize"!==e){var a=n[m]||(n[m]={});o(i,e,(a.proxies||(a.proxies={}))[t.id+"_"+e]=function(e){n(s(e,t))})}else f(i,n,t)},removeEventListener:function(t,e,n){var i=t.canvas;if("resize"!==e){var a=((n[m]||{}).proxies||{})[t.id+"_"+e];a&&r(i,e,a)}else g(i)}},v.addEvent=o,v.removeEvent=r},{45:45}],48:[function(t,e,n){"use strict";var i=t(45),a=t(46),o=t(47),r=o._enabled?o:a;e.exports=i.extend({initialize:function(){},acquireContext:function(){},releaseContext:function(){},addEventListener:function(){},removeEventListener:function(){}},r)},{45:45,46:46,47:47}],49:[function(t,e,n){"use strict";var i=t(25),a=t(40),o=t(45);i._set("global",{plugins:{filler:{propagate:!0}}}),e.exports=function(){function t(t,e,n){var i,a=t._model||{},o=a.fill;if(void 0===o&&(o=!!a.backgroundColor),!1===o||null===o)return!1;if(!0===o)return"origin";if(i=parseFloat(o,10),isFinite(i)&&Math.floor(i)===i)return"-"!==o[0]&&"+"!==o[0]||(i=e+i),!(i===e||i<0||i>=n)&&i;switch(o){case"bottom":return"start";case"top":return"end";case"zero":return"origin";case"origin":case"start":case"end":return o;default:return!1}}function e(t){var e,n=t.el._model||{},i=t.el._scale||{},a=t.fill,o=null;if(isFinite(a))return null;if("start"===a?o=void 0===n.scaleBottom?i.bottom:n.scaleBottom:"end"===a?o=void 0===n.scaleTop?i.top:n.scaleTop:void 0!==n.scaleZero?o=n.scaleZero:i.getBasePosition?o=i.getBasePosition():i.getBasePixel&&(o=i.getBasePixel()),void 0!==o&&null!==o){if(void 0!==o.x&&void 0!==o.y)return o;if("number"==typeof o&&isFinite(o))return e=i.isHorizontal(),{x:e?o:null,y:e?null:o}}return null}function n(t,e,n){var i,a=t[e].fill,o=[e];if(!n)return a;for(;!1!==a&&-1===o.indexOf(a);){if(!isFinite(a))return a;if(!(i=t[a]))return!1;if(i.visible)return a;o.push(a),a=i.fill}return!1}function r(t){var e=t.fill,n="dataset";return!1===e?null:(isFinite(e)||(n="boundary"),d[n](t))}function l(t){return t&&!t.skip}function s(t,e,n,i,a){var r;if(i&&a){for(t.moveTo(e[0].x,e[0].y),r=1;r<i;++r)o.canvas.lineTo(t,e[r-1],e[r]);for(t.lineTo(n[a-1].x,n[a-1].y),r=a-1;r>0;--r)o.canvas.lineTo(t,n[r],n[r-1],!0)}}function u(t,e,n,i,a,o){var r,u,d,c,h,f,g,p=e.length,v=i.spanGaps,m=[],b=[],x=0,y=0;for(t.beginPath(),r=0,u=p+!!o;r<u;++r)h=n(c=e[d=r%p]._view,d,i),f=l(c),g=l(h),f&&g?(x=m.push(c),y=b.push(h)):x&&y&&(v?(f&&m.push(c),g&&b.push(h)):(s(t,m,b,x,y),x=y=0,m=[],b=[]));s(t,m,b,x,y),t.closePath(),t.fillStyle=a,t.fill()}var d={dataset:function(t){var e=t.fill,n=t.chart,i=n.getDatasetMeta(e),a=i&&n.isDatasetVisible(e)&&i.dataset._children||[],o=a.length||0;return o?function(t,e){return e<o&&a[e]._view||null}:null},boundary:function(t){var e=t.boundary,n=e?e.x:null,i=e?e.y:null;return function(t){return{x:null===n?t.x:n,y:null===i?t.y:i}}}};return{id:"filler",afterDatasetsUpdate:function(i,o){var l,s,u,d,c=(i.data.datasets||[]).length,h=o.propagate,f=[];for(s=0;s<c;++s)d=null,(u=(l=i.getDatasetMeta(s)).dataset)&&u._model&&u instanceof a.Line&&(d={visible:i.isDatasetVisible(s),fill:t(u,s,c),chart:i,el:u}),l.$filler=d,f.push(d);for(s=0;s<c;++s)(d=f[s])&&(d.fill=n(f,s,h),d.boundary=e(d),d.mapper=r(d))},beforeDatasetDraw:function(t,e){var n=e.meta.$filler;if(n){var a=t.ctx,r=n.el,l=r._view,s=r._children||[],d=n.mapper,c=l.backgroundColor||i.global.defaultColor;d&&c&&s.length&&(o.canvas.clipArea(a,t.chartArea),u(a,s,d,l,c,r._loop),o.canvas.unclipArea(a))}}}}},{25:25,40:40,45:45}],50:[function(t,e,n){"use strict";var i=t(25),a=t(26),o=t(45);i._set("global",{legend:{display:!0,position:"top",fullWidth:!0,reverse:!1,weight:1e3,onClick:function(t,e){var n=e.datasetIndex,i=this.chart,a=i.getDatasetMeta(n);a.hidden=null===a.hidden?!i.data.datasets[n].hidden:null,i.update()},onHover:null,labels:{boxWidth:40,padding:10,generateLabels:function(t){var e=t.data;return o.isArray(e.datasets)?e.datasets.map(function(e,n){return{text:e.label,fillStyle:o.isArray(e.backgroundColor)?e.backgroundColor[0]:e.backgroundColor,hidden:!t.isDatasetVisible(n),lineCap:e.borderCapStyle,lineDash:e.borderDash,lineDashOffset:e.borderDashOffset,lineJoin:e.borderJoinStyle,lineWidth:e.borderWidth,strokeStyle:e.borderColor,pointStyle:e.pointStyle,datasetIndex:n}},this):[]}}},legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');for(var n=0;n<t.data.datasets.length;n++)e.push('<li><span style="background-color:'+t.data.datasets[n].backgroundColor+'"></span>'),t.data.datasets[n].label&&e.push(t.data.datasets[n].label),e.push("</li>");return e.push("</ul>"),e.join("")}}),e.exports=function(t){function e(t,e){return t.usePointStyle?e*Math.SQRT2:t.boxWidth}function n(e,n){var i=new t.Legend({ctx:e.ctx,options:n,chart:e});r.configure(e,i,n),r.addBox(e,i),e.legend=i}var r=t.layoutService,l=o.noop;return t.Legend=a.extend({initialize:function(t){o.extend(this,t),this.legendHitBoxes=[],this.doughnutMode=!1},beforeUpdate:l,update:function(t,e,n){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=n,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:l,beforeSetDimensions:l,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:l,beforeBuildLabels:l,buildLabels:function(){var t=this,e=t.options.labels||{},n=o.callback(e.generateLabels,[t.chart],t)||[];e.filter&&(n=n.filter(function(n){return e.filter(n,t.chart.data)})),t.options.reverse&&n.reverse(),t.legendItems=n},afterBuildLabels:l,beforeFit:l,fit:function(){var t=this,n=t.options,a=n.labels,r=n.display,l=t.ctx,s=i.global,u=o.valueOrDefault,d=u(a.fontSize,s.defaultFontSize),c=u(a.fontStyle,s.defaultFontStyle),h=u(a.fontFamily,s.defaultFontFamily),f=o.fontString(d,c,h),g=t.legendHitBoxes=[],p=t.minSize,v=t.isHorizontal();if(v?(p.width=t.maxWidth,p.height=r?10:0):(p.width=r?10:0,p.height=t.maxHeight),r)if(l.font=f,v){var m=t.lineWidths=[0],b=t.legendItems.length?d+a.padding:0;l.textAlign="left",l.textBaseline="top",o.each(t.legendItems,function(n,i){var o=e(a,d)+d/2+l.measureText(n.text).width;m[m.length-1]+o+a.padding>=t.width&&(b+=d+a.padding,m[m.length]=t.left),g[i]={left:0,top:0,width:o,height:d},m[m.length-1]+=o+a.padding}),p.height+=b}else{var x=a.padding,y=t.columnWidths=[],k=a.padding,w=0,M=0,S=d+x;o.each(t.legendItems,function(t,n){var i=e(a,d)+d/2+l.measureText(t.text).width;M+S>p.height&&(k+=w+a.padding,y.push(w),w=0,M=0),w=Math.max(w,i),M+=S,g[n]={left:0,top:0,width:i,height:d}}),k+=w,y.push(w),p.width+=k}t.width=p.width,t.height=p.height},afterFit:l,isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},draw:function(){var t=this,n=t.options,a=n.labels,r=i.global,l=r.elements.line,s=t.width,u=t.lineWidths;if(n.display){var d,c=t.ctx,h=o.valueOrDefault,f=h(a.fontColor,r.defaultFontColor),g=h(a.fontSize,r.defaultFontSize),p=h(a.fontStyle,r.defaultFontStyle),v=h(a.fontFamily,r.defaultFontFamily),m=o.fontString(g,p,v);c.textAlign="left",c.textBaseline="middle",c.lineWidth=.5,c.strokeStyle=f,c.fillStyle=f,c.font=m;var b=e(a,g),x=t.legendHitBoxes,y=function(t,e,i){if(!(isNaN(b)||b<=0)){c.save(),c.fillStyle=h(i.fillStyle,r.defaultColor),c.lineCap=h(i.lineCap,l.borderCapStyle),c.lineDashOffset=h(i.lineDashOffset,l.borderDashOffset),c.lineJoin=h(i.lineJoin,l.borderJoinStyle),c.lineWidth=h(i.lineWidth,l.borderWidth),c.strokeStyle=h(i.strokeStyle,r.defaultColor);var a=0===h(i.lineWidth,l.borderWidth);if(c.setLineDash&&c.setLineDash(h(i.lineDash,l.borderDash)),n.labels&&n.labels.usePointStyle){var s=g*Math.SQRT2/2,u=s/Math.SQRT2,d=t+u,f=e+u;o.canvas.drawPoint(c,i.pointStyle,s,d,f)}else a||c.strokeRect(t,e,b,g),c.fillRect(t,e,b,g);c.restore()}},k=function(t,e,n,i){var a=g/2,o=b+a+t,r=e+a;c.fillText(n.text,o,r),n.hidden&&(c.beginPath(),c.lineWidth=2,c.moveTo(o,r),c.lineTo(o+i,r),c.stroke())},w=t.isHorizontal();d=w?{x:t.left+(s-u[0])/2,y:t.top+a.padding,line:0}:{x:t.left+a.padding,y:t.top+a.padding,line:0};var M=g+a.padding;o.each(t.legendItems,function(e,n){var i=c.measureText(e.text).width,o=b+g/2+i,r=d.x,l=d.y;w?r+o>=s&&(l=d.y+=M,d.line++,r=d.x=t.left+(s-u[d.line])/2):l+M>t.bottom&&(r=d.x=r+t.columnWidths[d.line]+a.padding,l=d.y=t.top+a.padding,d.line++),y(r,l,e),x[n].left=r,x[n].top=l,k(r,l,e,i),w?d.x+=o+a.padding:d.y+=M})}},handleEvent:function(t){var e=this,n=e.options,i="mouseup"===t.type?"click":t.type,a=!1;if("mousemove"===i){if(!n.onHover)return}else{if("click"!==i)return;if(!n.onClick)return}var o=t.x,r=t.y;if(o>=e.left&&o<=e.right&&r>=e.top&&r<=e.bottom)for(var l=e.legendHitBoxes,s=0;s<l.length;++s){var u=l[s];if(o>=u.left&&o<=u.left+u.width&&r>=u.top&&r<=u.top+u.height){if("click"===i){n.onClick.call(e,t.native,e.legendItems[s]),a=!0;break}if("mousemove"===i){n.onHover.call(e,t.native,e.legendItems[s]),a=!0;break}}}return a}}),{id:"legend",beforeInit:function(t){var e=t.options.legend;e&&n(t,e)},beforeUpdate:function(t){var e=t.options.legend,a=t.legend;e?(o.mergeIf(e,i.global.legend),a?(r.configure(t,a,e),a.options=e):n(t,e)):a&&(r.removeBox(t,a),delete t.legend)},afterEvent:function(t,e){var n=t.legend;n&&n.handleEvent(e)}}}},{25:25,26:26,45:45}],51:[function(t,e,n){"use strict";var i=t(25),a=t(26),o=t(45);i._set("global",{title:{display:!1,fontStyle:"bold",fullWidth:!0,lineHeight:1.2,padding:10,position:"top",text:"",weight:2e3}}),e.exports=function(t){function e(e,i){var a=new t.Title({ctx:e.ctx,options:i,chart:e});n.configure(e,a,i),n.addBox(e,a),e.titleBlock=a}var n=t.layoutService,r=o.noop;return t.Title=a.extend({initialize:function(t){var e=this;o.extend(e,t),e.legendHitBoxes=[]},beforeUpdate:r,update:function(t,e,n){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=n,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:r,beforeSetDimensions:r,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:r,beforeBuildLabels:r,buildLabels:r,afterBuildLabels:r,beforeFit:r,fit:function(){var t=this,e=o.valueOrDefault,n=t.options,a=n.display,r=e(n.fontSize,i.global.defaultFontSize),l=t.minSize,s=o.isArray(n.text)?n.text.length:1,u=o.options.toLineHeight(n.lineHeight,r),d=a?s*u+2*n.padding:0;t.isHorizontal()?(l.width=t.maxWidth,l.height=d):(l.width=d,l.height=t.maxHeight),t.width=l.width,t.height=l.height},afterFit:r,isHorizontal:function(){var t=this.options.position;return"top"===t||"bottom"===t},draw:function(){var t=this,e=t.ctx,n=o.valueOrDefault,a=t.options,r=i.global;if(a.display){var l,s,u,d=n(a.fontSize,r.defaultFontSize),c=n(a.fontStyle,r.defaultFontStyle),h=n(a.fontFamily,r.defaultFontFamily),f=o.fontString(d,c,h),g=o.options.toLineHeight(a.lineHeight,d),p=g/2+a.padding,v=0,m=t.top,b=t.left,x=t.bottom,y=t.right;e.fillStyle=n(a.fontColor,r.defaultFontColor),e.font=f,t.isHorizontal()?(s=b+(y-b)/2,u=m+p,l=y-b):(s="left"===a.position?b+p:y-p,u=m+(x-m)/2,l=x-m,v=Math.PI*("left"===a.position?-.5:.5)),e.save(),e.translate(s,u),e.rotate(v),e.textAlign="center",e.textBaseline="middle";var k=a.text;if(o.isArray(k))for(var w=0,M=0;M<k.length;++M)e.fillText(k[M],0,w,l),w+=g;else e.fillText(k,0,0,l);e.restore()}}}),{id:"title",beforeInit:function(t){var n=t.options.title;n&&e(t,n)},beforeUpdate:function(a){var r=a.options.title,l=a.titleBlock;r?(o.mergeIf(r,i.global.title),l?(n.configure(a,l,r),l.options=r):e(a,r)):l&&(t.layoutService.removeBox(a,l),delete a.titleBlock)}}}},{25:25,26:26,45:45}],52:[function(t,e,n){"use strict";e.exports=function(t){var e={position:"bottom"},n=t.Scale.extend({getLabels:function(){var t=this.chart.data;return this.options.labels||(this.isHorizontal()?t.xLabels:t.yLabels)||t.labels},determineDataLimits:function(){var t=this,e=t.getLabels();t.minIndex=0,t.maxIndex=e.length-1;var n;void 0!==t.options.ticks.min&&(n=e.indexOf(t.options.ticks.min),t.minIndex=-1!==n?n:t.minIndex),void 0!==t.options.ticks.max&&(n=e.indexOf(t.options.ticks.max),t.maxIndex=-1!==n?n:t.maxIndex),t.min=e[t.minIndex],t.max=e[t.maxIndex]},buildTicks:function(){var t=this,e=t.getLabels();t.ticks=0===t.minIndex&&t.maxIndex===e.length-1?e:e.slice(t.minIndex,t.maxIndex+1)},getLabelForIndex:function(t,e){var n=this,i=n.chart.data,a=n.isHorizontal();return i.yLabels&&!a?n.getRightValue(i.datasets[e].data[t]):n.ticks[t-n.minIndex]},getPixelForValue:function(t,e){var n,i=this,a=i.options.offset,o=Math.max(i.maxIndex+1-i.minIndex-(a?0:1),1);if(void 0!==t&&null!==t&&(n=i.isHorizontal()?t.x:t.y),void 0!==n||void 0!==t&&isNaN(e)){var r=i.getLabels();t=n||t;var l=r.indexOf(t);e=-1!==l?l:e}if(i.isHorizontal()){var s=i.width/o,u=s*(e-i.minIndex);return a&&(u+=s/2),i.left+Math.round(u)}var d=i.height/o,c=d*(e-i.minIndex);return a&&(c+=d/2),i.top+Math.round(c)},getPixelForTick:function(t){return this.getPixelForValue(this.ticks[t],t+this.minIndex,null)},getValueForPixel:function(t){var e=this,n=e.options.offset,i=Math.max(e._ticks.length-(n?0:1),1),a=e.isHorizontal(),o=(a?e.width:e.height)/i;return t-=a?e.left:e.top,n&&(t-=o/2),(t<=0?0:Math.round(t/o))+e.minIndex},getBasePixel:function(){return this.bottom}});t.scaleService.registerScaleType("category",n,e)}},{}],53:[function(t,e,n){"use strict";var i=t(25),a=t(45),o=t(34);e.exports=function(t){var e={position:"left",ticks:{callback:o.formatters.linear}},n=t.LinearScaleBase.extend({determineDataLimits:function(){function t(t){return r?t.xAxisID===e.id:t.yAxisID===e.id}var e=this,n=e.options,i=e.chart,o=i.data.datasets,r=e.isHorizontal();e.min=null,e.max=null;var l=n.stacked;if(void 0===l&&a.each(o,function(e,n){if(!l){var a=i.getDatasetMeta(n);i.isDatasetVisible(n)&&t(a)&&void 0!==a.stack&&(l=!0)}}),n.stacked||l){var s={};a.each(o,function(o,r){var l=i.getDatasetMeta(r),u=[l.type,void 0===n.stacked&&void 0===l.stack?r:"",l.stack].join(".");void 0===s[u]&&(s[u]={positiveValues:[],negativeValues:[]});var d=s[u].positiveValues,c=s[u].negativeValues;i.isDatasetVisible(r)&&t(l)&&a.each(o.data,function(t,i){var a=+e.getRightValue(t);isNaN(a)||l.data[i].hidden||(d[i]=d[i]||0,c[i]=c[i]||0,n.relativePoints?d[i]=100:a<0?c[i]+=a:d[i]+=a)})}),a.each(s,function(t){var n=t.positiveValues.concat(t.negativeValues),i=a.min(n),o=a.max(n);e.min=null===e.min?i:Math.min(e.min,i),e.max=null===e.max?o:Math.max(e.max,o)})}else a.each(o,function(n,o){var r=i.getDatasetMeta(o);i.isDatasetVisible(o)&&t(r)&&a.each(n.data,function(t,n){var i=+e.getRightValue(t);isNaN(i)||r.data[n].hidden||(null===e.min?e.min=i:i<e.min&&(e.min=i),null===e.max?e.max=i:i>e.max&&(e.max=i))})});e.min=isFinite(e.min)&&!isNaN(e.min)?e.min:0,e.max=isFinite(e.max)&&!isNaN(e.max)?e.max:1,this.handleTickRangeOptions()},getTickLimit:function(){var t,e=this,n=e.options.ticks;if(e.isHorizontal())t=Math.min(n.maxTicksLimit?n.maxTicksLimit:11,Math.ceil(e.width/50));else{var o=a.valueOrDefault(n.fontSize,i.global.defaultFontSize);t=Math.min(n.maxTicksLimit?n.maxTicksLimit:11,Math.ceil(e.height/(2*o)))}return t},handleDirectionalChanges:function(){this.isHorizontal()||this.ticks.reverse()},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForValue:function(t){var e,n=this,i=n.start,a=+n.getRightValue(t),o=n.end-i;return n.isHorizontal()?(e=n.left+n.width/o*(a-i),Math.round(e)):(e=n.bottom-n.height/o*(a-i),Math.round(e))},getValueForPixel:function(t){var e=this,n=e.isHorizontal(),i=n?e.width:e.height,a=(n?t-e.left:e.bottom-t)/i;return e.start+(e.end-e.start)*a},getPixelForTick:function(t){return this.getPixelForValue(this.ticksAsNumbers[t])}});t.scaleService.registerScaleType("linear",n,e)}},{25:25,34:34,45:45}],54:[function(t,e,n){"use strict";var i=t(45),a=t(34);e.exports=function(t){var e=i.noop;t.LinearScaleBase=t.Scale.extend({getRightValue:function(e){return"string"==typeof e?+e:t.Scale.prototype.getRightValue.call(this,e)},handleTickRangeOptions:function(){var t=this,e=t.options.ticks;if(e.beginAtZero){var n=i.sign(t.min),a=i.sign(t.max);n<0&&a<0?t.max=0:n>0&&a>0&&(t.min=0)}var o=void 0!==e.min||void 0!==e.suggestedMin,r=void 0!==e.max||void 0!==e.suggestedMax;void 0!==e.min?t.min=e.min:void 0!==e.suggestedMin&&(null===t.min?t.min=e.suggestedMin:t.min=Math.min(t.min,e.suggestedMin)),void 0!==e.max?t.max=e.max:void 0!==e.suggestedMax&&(null===t.max?t.max=e.suggestedMax:t.max=Math.max(t.max,e.suggestedMax)),o!==r&&t.min>=t.max&&(o?t.max=t.min+1:t.min=t.max-1),t.min===t.max&&(t.max++,e.beginAtZero||t.min--)},getTickLimit:e,handleDirectionalChanges:e,buildTicks:function(){var t=this,e=t.options.ticks,n=t.getTickLimit(),o={maxTicks:n=Math.max(2,n),min:e.min,max:e.max,stepSize:i.valueOrDefault(e.fixedStepSize,e.stepSize)},r=t.ticks=a.generators.linear(o,t);t.handleDirectionalChanges(),t.max=i.max(r),t.min=i.min(r),e.reverse?(r.reverse(),t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max)},convertTicksToLabels:function(){var e=this;e.ticksAsNumbers=e.ticks.slice(),e.zeroLineIndex=e.ticks.indexOf(0),t.Scale.prototype.convertTicksToLabels.call(e)}})}},{34:34,45:45}],55:[function(t,e,n){"use strict";var i=t(45),a=t(34);e.exports=function(t){var e={position:"left",ticks:{callback:a.formatters.logarithmic}},n=t.Scale.extend({determineDataLimits:function(){function t(t){return s?t.xAxisID===e.id:t.yAxisID===e.id}var e=this,n=e.options,a=n.ticks,o=e.chart,r=o.data.datasets,l=i.valueOrDefault,s=e.isHorizontal();e.min=null,e.max=null,e.minNotZero=null;var u=n.stacked;if(void 0===u&&i.each(r,function(e,n){if(!u){var i=o.getDatasetMeta(n);o.isDatasetVisible(n)&&t(i)&&void 0!==i.stack&&(u=!0)}}),n.stacked||u){var d={};i.each(r,function(a,r){var l=o.getDatasetMeta(r),s=[l.type,void 0===n.stacked&&void 0===l.stack?r:"",l.stack].join(".");o.isDatasetVisible(r)&&t(l)&&(void 0===d[s]&&(d[s]=[]),i.each(a.data,function(t,i){var a=d[s],o=+e.getRightValue(t);isNaN(o)||l.data[i].hidden||(a[i]=a[i]||0,n.relativePoints?a[i]=100:a[i]+=o)}))}),i.each(d,function(t){var n=i.min(t),a=i.max(t);e.min=null===e.min?n:Math.min(e.min,n),e.max=null===e.max?a:Math.max(e.max,a)})}else i.each(r,function(n,a){var r=o.getDatasetMeta(a);o.isDatasetVisible(a)&&t(r)&&i.each(n.data,function(t,n){var i=+e.getRightValue(t);isNaN(i)||r.data[n].hidden||(null===e.min?e.min=i:i<e.min&&(e.min=i),null===e.max?e.max=i:i>e.max&&(e.max=i),0!==i&&(null===e.minNotZero||i<e.minNotZero)&&(e.minNotZero=i))})});e.min=l(a.min,e.min),e.max=l(a.max,e.max),e.min===e.max&&(0!==e.min&&null!==e.min?(e.min=Math.pow(10,Math.floor(i.log10(e.min))-1),e.max=Math.pow(10,Math.floor(i.log10(e.max))+1)):(e.min=1,e.max=10))},buildTicks:function(){var t=this,e=t.options.ticks,n={min:e.min,max:e.max},o=t.ticks=a.generators.logarithmic(n,t);t.isHorizontal()||o.reverse(),t.max=i.max(o),t.min=i.min(o),e.reverse?(o.reverse(),t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max)},convertTicksToLabels:function(){this.tickValues=this.ticks.slice(),t.Scale.prototype.convertTicksToLabels.call(this)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForTick:function(t){return this.getPixelForValue(this.tickValues[t])},getPixelForValue:function(t){var e,n,a,o=this,r=o.start,l=+o.getRightValue(t),s=o.options.ticks;return o.isHorizontal()?(a=i.log10(o.end)-i.log10(r),0===l?n=o.left:(e=o.width,n=o.left+e/a*(i.log10(l)-i.log10(r)))):(e=o.height,0!==r||s.reverse?0===o.end&&s.reverse?(a=i.log10(o.start)-i.log10(o.minNotZero),n=l===o.end?o.top:l===o.minNotZero?o.top+.02*e:o.top+.02*e+.98*e/a*(i.log10(l)-i.log10(o.minNotZero))):0===l?n=s.reverse?o.top:o.bottom:(a=i.log10(o.end)-i.log10(r),e=o.height,n=o.bottom-e/a*(i.log10(l)-i.log10(r))):(a=i.log10(o.end)-i.log10(o.minNotZero),n=l===r?o.bottom:l===o.minNotZero?o.bottom-.02*e:o.bottom-.02*e-.98*e/a*(i.log10(l)-i.log10(o.minNotZero)))),n},getValueForPixel:function(t){var e,n,a=this,o=i.log10(a.end)-i.log10(a.start);return a.isHorizontal()?(n=a.width,e=a.start*Math.pow(10,(t-a.left)*o/n)):(n=a.height,e=Math.pow(10,(a.bottom-t)*o/n)/a.start),e}});t.scaleService.registerScaleType("logarithmic",n,e)}},{34:34,45:45}],56:[function(t,e,n){"use strict";var i=t(25),a=t(45),o=t(34);e.exports=function(t){function e(t){var e=t.options;return e.angleLines.display||e.pointLabels.display?t.chart.data.labels.length:0}function n(t){var e=t.options.pointLabels,n=a.valueOrDefault(e.fontSize,v.defaultFontSize),i=a.valueOrDefault(e.fontStyle,v.defaultFontStyle),o=a.valueOrDefault(e.fontFamily,v.defaultFontFamily);return{size:n,style:i,family:o,font:a.fontString(n,i,o)}}function r(t,e,n){return a.isArray(n)?{w:a.longestText(t,t.font,n),h:n.length*e+1.5*(n.length-1)*e}:{w:t.measureText(n).width,h:e}}function l(t,e,n,i,a){return t===i||t===a?{start:e-n/2,end:e+n/2}:t<i||t>a?{start:e-n-5,end:e}:{start:e,end:e+n+5}}function s(t){var i,o,s,u=n(t),d=Math.min(t.height/2,t.width/2),c={r:t.width,l:0,t:t.height,b:0},h={};t.ctx.font=u.font,t._pointLabelSizes=[];var f=e(t);for(i=0;i<f;i++){s=t.getPointPosition(i,d),o=r(t.ctx,u.size,t.pointLabels[i]||""),t._pointLabelSizes[i]=o;var g=t.getIndexAngle(i),p=a.toDegrees(g)%360,v=l(p,s.x,o.w,0,180),m=l(p,s.y,o.h,90,270);v.start<c.l&&(c.l=v.start,h.l=g),v.end>c.r&&(c.r=v.end,h.r=g),m.start<c.t&&(c.t=m.start,h.t=g),m.end>c.b&&(c.b=m.end,h.b=g)}t.setReductions(d,c,h)}function u(t){var e=Math.min(t.height/2,t.width/2);t.drawingArea=Math.round(e),t.setCenterPoint(0,0,0,0)}function d(t){return 0===t||180===t?"center":t<180?"left":"right"}function c(t,e,n,i){if(a.isArray(e))for(var o=n.y,r=1.5*i,l=0;l<e.length;++l)t.fillText(e[l],n.x,o),o+=r;else t.fillText(e,n.x,n.y)}function h(t,e,n){90===t||270===t?n.y-=e.h/2:(t>270||t<90)&&(n.y-=e.h)}function f(t){var i=t.ctx,o=a.valueOrDefault,r=t.options,l=r.angleLines,s=r.pointLabels;i.lineWidth=l.lineWidth,i.strokeStyle=l.color;var u=t.getDistanceFromCenterForValue(r.ticks.reverse?t.min:t.max),f=n(t);i.textBaseline="top";for(var g=e(t)-1;g>=0;g--){if(l.display){var p=t.getPointPosition(g,u);i.beginPath(),i.moveTo(t.xCenter,t.yCenter),i.lineTo(p.x,p.y),i.stroke(),i.closePath()}if(s.display){var m=t.getPointPosition(g,u+5),b=o(s.fontColor,v.defaultFontColor);i.font=f.font,i.fillStyle=b;var x=t.getIndexAngle(g),y=a.toDegrees(x);i.textAlign=d(y),h(y,t._pointLabelSizes[g],m),c(i,t.pointLabels[g]||"",m,f.size)}}}function g(t,n,i,o){var r=t.ctx;if(r.strokeStyle=a.valueAtIndexOrDefault(n.color,o-1),r.lineWidth=a.valueAtIndexOrDefault(n.lineWidth,o-1),t.options.gridLines.circular)r.beginPath(),r.arc(t.xCenter,t.yCenter,i,0,2*Math.PI),r.closePath(),r.stroke();else{var l=e(t);if(0===l)return;r.beginPath();var s=t.getPointPosition(0,i);r.moveTo(s.x,s.y);for(var u=1;u<l;u++)s=t.getPointPosition(u,i),r.lineTo(s.x,s.y);r.closePath(),r.stroke()}}function p(t){return a.isNumber(t)?t:0}var v=i.global,m={display:!0,animate:!0,position:"chartArea",angleLines:{display:!0,color:"rgba(0, 0, 0, 0.1)",lineWidth:1},gridLines:{circular:!1},ticks:{showLabelBackdrop:!0,backdropColor:"rgba(255,255,255,0.75)",backdropPaddingY:2,backdropPaddingX:2,callback:o.formatters.linear},pointLabels:{display:!0,fontSize:10,callback:function(t){return t}}},b=t.LinearScaleBase.extend({setDimensions:function(){var t=this,e=t.options,n=e.ticks;t.width=t.maxWidth,t.height=t.maxHeight,t.xCenter=Math.round(t.width/2),t.yCenter=Math.round(t.height/2);var i=a.min([t.height,t.width]),o=a.valueOrDefault(n.fontSize,v.defaultFontSize);t.drawingArea=e.display?i/2-(o/2+n.backdropPaddingY):i/2},determineDataLimits:function(){var t=this,e=t.chart,n=Number.POSITIVE_INFINITY,i=Number.NEGATIVE_INFINITY;a.each(e.data.datasets,function(o,r){if(e.isDatasetVisible(r)){var l=e.getDatasetMeta(r);a.each(o.data,function(e,a){var o=+t.getRightValue(e);isNaN(o)||l.data[a].hidden||(n=Math.min(o,n),i=Math.max(o,i))})}}),t.min=n===Number.POSITIVE_INFINITY?0:n,t.max=i===Number.NEGATIVE_INFINITY?0:i,t.handleTickRangeOptions()},getTickLimit:function(){var t=this.options.ticks,e=a.valueOrDefault(t.fontSize,v.defaultFontSize);return Math.min(t.maxTicksLimit?t.maxTicksLimit:11,Math.ceil(this.drawingArea/(1.5*e)))},convertTicksToLabels:function(){var e=this;t.LinearScaleBase.prototype.convertTicksToLabels.call(e),e.pointLabels=e.chart.data.labels.map(e.options.pointLabels.callback,e)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},fit:function(){this.options.pointLabels.display?s(this):u(this)},setReductions:function(t,e,n){var i=this,a=e.l/Math.sin(n.l),o=Math.max(e.r-i.width,0)/Math.sin(n.r),r=-e.t/Math.cos(n.t),l=-Math.max(e.b-i.height,0)/Math.cos(n.b);a=p(a),o=p(o),r=p(r),l=p(l),i.drawingArea=Math.min(Math.round(t-(a+o)/2),Math.round(t-(r+l)/2)),i.setCenterPoint(a,o,r,l)},setCenterPoint:function(t,e,n,i){var a=this,o=a.width-e-a.drawingArea,r=t+a.drawingArea,l=n+a.drawingArea,s=a.height-i-a.drawingArea;a.xCenter=Math.round((r+o)/2+a.left),a.yCenter=Math.round((l+s)/2+a.top)},getIndexAngle:function(t){return t*(2*Math.PI/e(this))+(this.chart.options&&this.chart.options.startAngle?this.chart.options.startAngle:0)*Math.PI*2/360},getDistanceFromCenterForValue:function(t){var e=this;if(null===t)return 0;var n=e.drawingArea/(e.max-e.min);return e.options.ticks.reverse?(e.max-t)*n:(t-e.min)*n},getPointPosition:function(t,e){var n=this,i=n.getIndexAngle(t)-Math.PI/2;return{x:Math.round(Math.cos(i)*e)+n.xCenter,y:Math.round(Math.sin(i)*e)+n.yCenter}},getPointPositionForValue:function(t,e){return this.getPointPosition(t,this.getDistanceFromCenterForValue(e))},getBasePosition:function(){var t=this,e=t.min,n=t.max;return t.getPointPositionForValue(0,t.beginAtZero?0:e<0&&n<0?n:e>0&&n>0?e:0)},draw:function(){var t=this,e=t.options,n=e.gridLines,i=e.ticks,o=a.valueOrDefault;if(e.display){var r=t.ctx,l=this.getIndexAngle(0),s=o(i.fontSize,v.defaultFontSize),u=o(i.fontStyle,v.defaultFontStyle),d=o(i.fontFamily,v.defaultFontFamily),c=a.fontString(s,u,d);a.each(t.ticks,function(e,a){if(a>0||i.reverse){var u=t.getDistanceFromCenterForValue(t.ticksAsNumbers[a]);if(n.display&&0!==a&&g(t,n,u,a),i.display){var d=o(i.fontColor,v.defaultFontColor);if(r.font=c,r.save(),r.translate(t.xCenter,t.yCenter),r.rotate(l),i.showLabelBackdrop){var h=r.measureText(e).width;r.fillStyle=i.backdropColor,r.fillRect(-h/2-i.backdropPaddingX,-u-s/2-i.backdropPaddingY,h+2*i.backdropPaddingX,s+2*i.backdropPaddingY)}r.textAlign="center",r.textBaseline="middle",r.fillStyle=d,r.fillText(e,0,-u),r.restore()}}}),(e.angleLines.display||e.pointLabels.display)&&f(t)}}});t.scaleService.registerScaleType("radialLinear",b,m)}},{25:25,34:34,45:45}],57:[function(t,e,n){"use strict";function i(t,e){return t-e}function a(t){var e,n,i,a={},o=[];for(e=0,n=t.length;e<n;++e)a[i=t[e]]||(a[i]=!0,o.push(i));return o}function o(t,e,n,i){if("linear"===i||!t.length)return[{time:e,pos:0},{time:n,pos:1}];var a,o,r,l,s,u=[],d=[e];for(a=0,o=t.length;a<o;++a)(l=t[a])>e&&l<n&&d.push(l);for(d.push(n),a=0,o=d.length;a<o;++a)s=d[a+1],r=d[a-1],l=d[a],void 0!==r&&void 0!==s&&Math.round((s+r)/2)===l||u.push({time:l,pos:a/(o-1)});return u}function r(t,e,n){for(var i,a,o,r=0,l=t.length-1;r>=0&&r<=l;){if(i=r+l>>1,a=t[i-1]||null,o=t[i],!a)return{lo:null,hi:o};if(o[e]<n)r=i+1;else{if(!(a[e]>n))return{lo:a,hi:o};l=i-1}}return{lo:o,hi:null}}function l(t,e,n,i){var a=r(t,e,n),o=a.lo?a.hi?a.lo:t[t.length-2]:t[0],l=a.lo?a.hi?a.hi:t[t.length-1]:t[1],s=l[e]-o[e],u=s?(n-o[e])/s:0,d=(l[i]-o[i])*u;return o[i]+d}function s(t,e){var n=e.parser,i=e.parser||e.format;return"function"==typeof n?n(t):"string"==typeof t&&"string"==typeof i?v(t,i):(t instanceof v||(t=v(t)),t.isValid()?t:"function"==typeof i?i(t):t)}function u(t,e){if(b.isNullOrUndef(t))return null;var n=e.options.time,i=s(e.getRightValue(t),n);return i.isValid()?(n.round&&i.startOf(n.round),i.valueOf()):null}function d(t,e,n,i){var a,o,r,l=e-t,s=k[n],u=s.size,d=s.steps;if(!d)return Math.ceil(l/((i||1)*u));for(a=0,o=d.length;a<o&&(r=d[a],!(Math.ceil(l/(u*r))<=i));++a);return r}function c(t,e,n,i){var a,o,r,l=w.length;for(a=w.indexOf(t);a<l-1;++a)if(o=k[w[a]],r=o.steps?o.steps[o.steps.length-1]:y,o.common&&Math.ceil((n-e)/(r*o.size))<=i)return w[a];return w[l-1]}function h(t){for(var e=w.indexOf(t)+1,n=w.length;e<n;++e)if(k[w[e]].common)return w[e]}function f(t,e,n,i,a,o){var r,l=o.time,s=b.valueOrDefault(l.stepSize,l.unitStepSize),u="week"===n&&l.isoWeekday,c=o.ticks.major.enabled,h=k[n],f=v(t),g=v(e),p=[];for(s||(s=d(t,e,n,a)),u&&(f=f.isoWeekday(u),g=g.isoWeekday(u)),f=f.startOf(u?"day":n),(g=g.startOf(u?"day":n))<e&&g.add(1,n),r=v(f),c&&i&&!u&&!l.round&&(r.startOf(i),r.add(~~((f-r)/(h.size*s))*s,n));r<g;r.add(s,n))p.push(+r);return p.push(+r),p}function g(t,e,n,i,a){var o,r,s=0,u=0;return a.offset&&e.length&&(a.time.min||(o=e.length>1?e[1]:i,r=e[0],s=(l(t,"time",o,"pos")-l(t,"time",r,"pos"))/2),a.time.max||(o=e[e.length-1],r=e.length>1?e[e.length-2]:n,u=(l(t,"time",o,"pos")-l(t,"time",r,"pos"))/2)),{left:s,right:u}}function p(t,e){var n,i,a,o,r=[];for(n=0,i=t.length;n<i;++n)a=t[n],o=!!e&&a===+v(a).startOf(e),r.push({value:a,major:o});return r}var v=t(1);v="function"==typeof v?v:window.moment;var m=t(25),b=t(45),x=Number.MIN_SAFE_INTEGER||-9007199254740991,y=Number.MAX_SAFE_INTEGER||9007199254740991,k={millisecond:{common:!0,size:1,steps:[1,2,5,10,20,50,100,250,500]},second:{common:!0,size:1e3,steps:[1,2,5,10,30]},minute:{common:!0,size:6e4,steps:[1,2,5,10,30]},hour:{common:!0,size:36e5,steps:[1,2,3,6,12]},day:{common:!0,size:864e5,steps:[1,2,5]},week:{common:!1,size:6048e5,steps:[1,2,3,4]},month:{common:!0,size:2628e6,steps:[1,2,3]},quarter:{common:!1,size:7884e6,steps:[1,2,3,4]},year:{common:!0,size:3154e7}},w=Object.keys(k);e.exports=function(t){var e={position:"bottom",distribution:"linear",bounds:"data",time:{parser:!1,format:!1,unit:!1,round:!1,displayFormat:!1,isoWeekday:!1,minUnit:"millisecond",displayFormats:{millisecond:"h:mm:ss.SSS a",second:"h:mm:ss a",minute:"h:mm a",hour:"hA",day:"MMM D",week:"ll",month:"MMM YYYY",quarter:"[Q]Q - YYYY",year:"YYYY"}},ticks:{autoSkip:!1,source:"auto",major:{enabled:!1}}},n=t.Scale.extend({initialize:function(){if(!v)throw new Error("Chart.js - Moment.js could not be found! You must include it before Chart.js to use the time scale. Download at https://momentjs.com");this.mergeTicksOptions(),t.Scale.prototype.initialize.call(this)},update:function(){var e=this,n=e.options;return n.time&&n.time.format&&console.warn("options.time.format is deprecated and replaced by options.time.parser."),t.Scale.prototype.update.apply(e,arguments)},getRightValue:function(e){return e&&void 0!==e.t&&(e=e.t),t.Scale.prototype.getRightValue.call(this,e)},determineDataLimits:function(){var t,e,n,o,r,l,s=this,d=s.chart,c=s.options.time,h=u(c.min,s)||y,f=u(c.max,s)||x,g=[],p=[],m=[];for(t=0,n=d.data.labels.length;t<n;++t)m.push(u(d.data.labels[t],s));for(t=0,n=(d.data.datasets||[]).length;t<n;++t)if(d.isDatasetVisible(t))if(r=d.data.datasets[t].data,b.isObject(r[0]))for(p[t]=[],e=0,o=r.length;e<o;++e)l=u(r[e],s),g.push(l),p[t][e]=l;else g.push.apply(g,m),p[t]=m.slice(0);else p[t]=[];m.length&&(m=a(m).sort(i),h=Math.min(h,m[0]),f=Math.max(f,m[m.length-1])),g.length&&(g=a(g).sort(i),h=Math.min(h,g[0]),f=Math.max(f,g[g.length-1])),h=h===y?+v().startOf("day"):h,f=f===x?+v().endOf("day")+1:f,s.min=Math.min(h,f),s.max=Math.max(h+1,f),s._horizontal=s.isHorizontal(),s._table=[],s._timestamps={data:g,datasets:p,labels:m}},buildTicks:function(){var t,e,n,i=this,a=i.min,r=i.max,l=i.options,s=l.time,d=s.displayFormats,v=i.getLabelCapacity(a),m=s.unit||c(s.minUnit,a,r,v),b=h(m),x=[],y=[];switch(l.ticks.source){case"data":x=i._timestamps.data;break;case"labels":x=i._timestamps.labels;break;case"auto":default:x=f(a,r,m,b,v,l)}for("ticks"===l.bounds&&x.length&&(a=x[0],r=x[x.length-1]),a=u(s.min,i)||a,r=u(s.max,i)||r,t=0,e=x.length;t<e;++t)(n=x[t])>=a&&n<=r&&y.push(n);return i.min=a,i.max=r,i._unit=m,i._majorUnit=b,i._minorFormat=d[m],i._majorFormat=d[b],i._table=o(i._timestamps.data,a,r,l.distribution),i._offsets=g(i._table,y,a,r,l),p(y,b)},getLabelForIndex:function(t,e){var n=this,i=n.chart.data,a=n.options.time,o=i.labels&&t<i.labels.length?i.labels[t]:"",r=i.datasets[e].data[t];return b.isObject(r)&&(o=n.getRightValue(r)),a.tooltipFormat&&(o=s(o,a).format(a.tooltipFormat)),o},tickFormatFunction:function(t,e,n){var i=this,a=i.options,o=t.valueOf(),r=i._majorUnit,l=i._majorFormat,s=t.clone().startOf(i._majorUnit).valueOf(),u=a.ticks.major,d=u.enabled&&r&&l&&o===s,c=t.format(d?l:i._minorFormat),h=d?u:a.ticks.minor,f=b.valueOrDefault(h.callback,h.userCallback);return f?f(c,e,n):c},convertTicksToLabels:function(t){var e,n,i=[];for(e=0,n=t.length;e<n;++e)i.push(this.tickFormatFunction(v(t[e].value),e,t));return i},getPixelForOffset:function(t){var e=this,n=e._horizontal?e.width:e.height,i=e._horizontal?e.left:e.top,a=l(e._table,"time",t,"pos");return i+n*(e._offsets.left+a)/(e._offsets.left+1+e._offsets.right)},getPixelForValue:function(t,e,n){var i=this,a=null;if(void 0!==e&&void 0!==n&&(a=i._timestamps.datasets[n][e]),null===a&&(a=u(t,i)),null!==a)return i.getPixelForOffset(a)},getPixelForTick:function(t){var e=this.getTicks();return t>=0&&t<e.length?this.getPixelForOffset(e[t].value):null},getValueForPixel:function(t){var e=this,n=e._horizontal?e.width:e.height,i=e._horizontal?e.left:e.top,a=(n?(t-i)/n:0)*(e._offsets.left+1+e._offsets.left)-e._offsets.right,o=l(e._table,"pos",a,"time");return v(o)},getLabelWidth:function(t){var e=this,n=e.options.ticks,i=e.ctx.measureText(t).width,a=b.toRadians(n.maxRotation),o=Math.cos(a),r=Math.sin(a);return i*o+b.valueOrDefault(n.fontSize,m.global.defaultFontSize)*r},getLabelCapacity:function(t){var e=this;e._minorFormat=e.options.time.displayFormats.millisecond;var n=e.tickFormatFunction(v(t),0,[]),i=e.getLabelWidth(n),a=e.isHorizontal()?e.width:e.height;return Math.floor(a/i)}});t.scaleService.registerScaleType("time",n,e)}},{1:1,25:25,45:45}]},{},[7])(7)});
1
+ /*!
2
+ * Chart.js
3
+ * http://chartjs.org/
4
+ * Version: 2.7.0
5
+ *
6
+ * Copyright 2017 Nick Downie
7
+ * Released under the MIT license
8
+ * https://github.com/chartjs/Chart.js/blob/master/LICENSE.md
9
+ */
10
  !function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).Chart=t()}}(function(){return function t(e,n,i){function a(r,l){if(!n[r]){if(!e[r]){var s="function"==typeof require&&require;if(!l&&s)return s(r,!0);if(o)return o(r,!0);var u=new Error("Cannot find module '"+r+"'");throw u.code="MODULE_NOT_FOUND",u}var d=n[r]={exports:{}};e[r][0].call(d.exports,function(t){var n=e[r][1][t];return a(n||t)},d,d.exports,t,e,n,i)}return n[r].exports}for(var o="function"==typeof require&&require,r=0;r<i.length;r++)a(i[r]);return a}({1:[function(t,e,n){},{}],2:[function(t,e,n){function i(t){if(t){var e=/^#([a-fA-F0-9]{3})$/i,n=/^#([a-fA-F0-9]{6})$/i,i=/^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i,a=/^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i,o=/(\w+)/,r=[0,0,0],l=1,s=t.match(e);if(s){s=s[1];for(d=0;d<r.length;d++)r[d]=parseInt(s[d]+s[d],16)}else if(s=t.match(n)){s=s[1];for(d=0;d<r.length;d++)r[d]=parseInt(s.slice(2*d,2*d+2),16)}else if(s=t.match(i)){for(d=0;d<r.length;d++)r[d]=parseInt(s[d+1]);l=parseFloat(s[4])}else if(s=t.match(a)){for(d=0;d<r.length;d++)r[d]=Math.round(2.55*parseFloat(s[d+1]));l=parseFloat(s[4])}else if(s=t.match(o)){if("transparent"==s[1])return[0,0,0,0];if(!(r=c[s[1]]))return}for(var d=0;d<r.length;d++)r[d]=u(r[d],0,255);return l=l||0==l?u(l,0,1):1,r[3]=l,r}}function a(t){if(t){var e=/^hsla?\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/,n=t.match(e);if(n){var i=parseFloat(n[4]);return[u(parseInt(n[1]),0,360),u(parseFloat(n[2]),0,100),u(parseFloat(n[3]),0,100),u(isNaN(i)?1:i,0,1)]}}}function o(t){if(t){var e=/^hwb\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/,n=t.match(e);if(n){var i=parseFloat(n[4]);return[u(parseInt(n[1]),0,360),u(parseFloat(n[2]),0,100),u(parseFloat(n[3]),0,100),u(isNaN(i)?1:i,0,1)]}}}function r(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"rgba("+t[0]+", "+t[1]+", "+t[2]+", "+e+")"}function l(t,e){return"rgba("+Math.round(t[0]/255*100)+"%, "+Math.round(t[1]/255*100)+"%, "+Math.round(t[2]/255*100)+"%, "+(e||t[3]||1)+")"}function s(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"hsla("+t[0]+", "+t[1]+"%, "+t[2]+"%, "+e+")"}function u(t,e,n){return Math.min(Math.max(e,t),n)}function d(t){var e=t.toString(16).toUpperCase();return e.length<2?"0"+e:e}var c=t(6);e.exports={getRgba:i,getHsla:a,getRgb:function(t){var e=i(t);return e&&e.slice(0,3)},getHsl:function(t){var e=a(t);return e&&e.slice(0,3)},getHwb:o,getAlpha:function(t){var e=i(t);return e?e[3]:(e=a(t))?e[3]:(e=o(t))?e[3]:void 0},hexString:function(t){return"#"+d(t[0])+d(t[1])+d(t[2])},rgbString:function(t,e){return e<1||t[3]&&t[3]<1?r(t,e):"rgb("+t[0]+", "+t[1]+", "+t[2]+")"},rgbaString:r,percentString:function(t,e){return e<1||t[3]&&t[3]<1?l(t,e):"rgb("+Math.round(t[0]/255*100)+"%, "+Math.round(t[1]/255*100)+"%, "+Math.round(t[2]/255*100)+"%)"},percentaString:l,hslString:function(t,e){return e<1||t[3]&&t[3]<1?s(t,e):"hsl("+t[0]+", "+t[1]+"%, "+t[2]+"%)"},hslaString:s,hwbString:function(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"hwb("+t[0]+", "+t[1]+"%, "+t[2]+"%"+(void 0!==e&&1!==e?", "+e:"")+")"},keyword:function(t){return h[t.slice(0,3)]}};var h={};for(var f in c)h[c[f]]=f},{6:6}],3:[function(t,e,n){var i=t(5),a=t(2),o=function(t){if(t instanceof o)return t;if(!(this instanceof o))return new o(t);this.valid=!1,this.values={rgb:[0,0,0],hsl:[0,0,0],hsv:[0,0,0],hwb:[0,0,0],cmyk:[0,0,0,0],alpha:1};var e;"string"==typeof t?(e=a.getRgba(t))?this.setValues("rgb",e):(e=a.getHsla(t))?this.setValues("hsl",e):(e=a.getHwb(t))&&this.setValues("hwb",e):"object"==typeof t&&(void 0!==(e=t).r||void 0!==e.red?this.setValues("rgb",e):void 0!==e.l||void 0!==e.lightness?this.setValues("hsl",e):void 0!==e.v||void 0!==e.value?this.setValues("hsv",e):void 0!==e.w||void 0!==e.whiteness?this.setValues("hwb",e):void 0===e.c&&void 0===e.cyan||this.setValues("cmyk",e))};o.prototype={isValid:function(){return this.valid},rgb:function(){return this.setSpace("rgb",arguments)},hsl:function(){return this.setSpace("hsl",arguments)},hsv:function(){return this.setSpace("hsv",arguments)},hwb:function(){return this.setSpace("hwb",arguments)},cmyk:function(){return this.setSpace("cmyk",arguments)},rgbArray:function(){return this.values.rgb},hslArray:function(){return this.values.hsl},hsvArray:function(){return this.values.hsv},hwbArray:function(){var t=this.values;return 1!==t.alpha?t.hwb.concat([t.alpha]):t.hwb},cmykArray:function(){return this.values.cmyk},rgbaArray:function(){var t=this.values;return t.rgb.concat([t.alpha])},hslaArray:function(){var t=this.values;return t.hsl.concat([t.alpha])},alpha:function(t){return void 0===t?this.values.alpha:(this.setValues("alpha",t),this)},red:function(t){return this.setChannel("rgb",0,t)},green:function(t){return this.setChannel("rgb",1,t)},blue:function(t){return this.setChannel("rgb",2,t)},hue:function(t){return t&&(t=(t%=360)<0?360+t:t),this.setChannel("hsl",0,t)},saturation:function(t){return this.setChannel("hsl",1,t)},lightness:function(t){return this.setChannel("hsl",2,t)},saturationv:function(t){return this.setChannel("hsv",1,t)},whiteness:function(t){return this.setChannel("hwb",1,t)},blackness:function(t){return this.setChannel("hwb",2,t)},value:function(t){return this.setChannel("hsv",2,t)},cyan:function(t){return this.setChannel("cmyk",0,t)},magenta:function(t){return this.setChannel("cmyk",1,t)},yellow:function(t){return this.setChannel("cmyk",2,t)},black:function(t){return this.setChannel("cmyk",3,t)},hexString:function(){return a.hexString(this.values.rgb)},rgbString:function(){return a.rgbString(this.values.rgb,this.values.alpha)},rgbaString:function(){return a.rgbaString(this.values.rgb,this.values.alpha)},percentString:function(){return a.percentString(this.values.rgb,this.values.alpha)},hslString:function(){return a.hslString(this.values.hsl,this.values.alpha)},hslaString:function(){return a.hslaString(this.values.hsl,this.values.alpha)},hwbString:function(){return a.hwbString(this.values.hwb,this.values.alpha)},keyword:function(){return a.keyword(this.values.rgb,this.values.alpha)},rgbNumber:function(){var t=this.values.rgb;return t[0]<<16|t[1]<<8|t[2]},luminosity:function(){for(var t=this.values.rgb,e=[],n=0;n<t.length;n++){var i=t[n]/255;e[n]=i<=.03928?i/12.92:Math.pow((i+.055)/1.055,2.4)}return.2126*e[0]+.7152*e[1]+.0722*e[2]},contrast:function(t){var e=this.luminosity(),n=t.luminosity();return e>n?(e+.05)/(n+.05):(n+.05)/(e+.05)},level:function(t){var e=this.contrast(t);return e>=7.1?"AAA":e>=4.5?"AA":""},dark:function(){var t=this.values.rgb;return(299*t[0]+587*t[1]+114*t[2])/1e3<128},light:function(){return!this.dark()},negate:function(){for(var t=[],e=0;e<3;e++)t[e]=255-this.values.rgb[e];return this.setValues("rgb",t),this},lighten:function(t){var e=this.values.hsl;return e[2]+=e[2]*t,this.setValues("hsl",e),this},darken:function(t){var e=this.values.hsl;return e[2]-=e[2]*t,this.setValues("hsl",e),this},saturate:function(t){var e=this.values.hsl;return e[1]+=e[1]*t,this.setValues("hsl",e),this},desaturate:function(t){var e=this.values.hsl;return e[1]-=e[1]*t,this.setValues("hsl",e),this},whiten:function(t){var e=this.values.hwb;return e[1]+=e[1]*t,this.setValues("hwb",e),this},blacken:function(t){var e=this.values.hwb;return e[2]+=e[2]*t,this.setValues("hwb",e),this},greyscale:function(){var t=this.values.rgb,e=.3*t[0]+.59*t[1]+.11*t[2];return this.setValues("rgb",[e,e,e]),this},clearer:function(t){var e=this.values.alpha;return this.setValues("alpha",e-e*t),this},opaquer:function(t){var e=this.values.alpha;return this.setValues("alpha",e+e*t),this},rotate:function(t){var e=this.values.hsl,n=(e[0]+t)%360;return e[0]=n<0?360+n:n,this.setValues("hsl",e),this},mix:function(t,e){var n=this,i=t,a=void 0===e?.5:e,o=2*a-1,r=n.alpha()-i.alpha(),l=((o*r==-1?o:(o+r)/(1+o*r))+1)/2,s=1-l;return this.rgb(l*n.red()+s*i.red(),l*n.green()+s*i.green(),l*n.blue()+s*i.blue()).alpha(n.alpha()*a+i.alpha()*(1-a))},toJSON:function(){return this.rgb()},clone:function(){var t,e,n=new o,i=this.values,a=n.values;for(var r in i)i.hasOwnProperty(r)&&(t=i[r],"[object Array]"===(e={}.toString.call(t))?a[r]=t.slice(0):"[object Number]"===e?a[r]=t:console.error("unexpected color value:",t));return n}},o.prototype.spaces={rgb:["red","green","blue"],hsl:["hue","saturation","lightness"],hsv:["hue","saturation","value"],hwb:["hue","whiteness","blackness"],cmyk:["cyan","magenta","yellow","black"]},o.prototype.maxes={rgb:[255,255,255],hsl:[360,100,100],hsv:[360,100,100],hwb:[360,100,100],cmyk:[100,100,100,100]},o.prototype.getValues=function(t){for(var e=this.values,n={},i=0;i<t.length;i++)n[t.charAt(i)]=e[t][i];return 1!==e.alpha&&(n.a=e.alpha),n},o.prototype.setValues=function(t,e){var n,a=this.values,o=this.spaces,r=this.maxes,l=1;if(this.valid=!0,"alpha"===t)l=e;else if(e.length)a[t]=e.slice(0,t.length),l=e[t.length];else if(void 0!==e[t.charAt(0)]){for(n=0;n<t.length;n++)a[t][n]=e[t.charAt(n)];l=e.a}else if(void 0!==e[o[t][0]]){var s=o[t];for(n=0;n<t.length;n++)a[t][n]=e[s[n]];l=e.alpha}if(a.alpha=Math.max(0,Math.min(1,void 0===l?a.alpha:l)),"alpha"===t)return!1;var u;for(n=0;n<t.length;n++)u=Math.max(0,Math.min(r[t][n],a[t][n])),a[t][n]=Math.round(u);for(var d in o)d!==t&&(a[d]=i[t][d](a[t]));return!0},o.prototype.setSpace=function(t,e){var n=e[0];return void 0===n?this.getValues(t):("number"==typeof n&&(n=Array.prototype.slice.call(e)),this.setValues(t,n),this)},o.prototype.setChannel=function(t,e,n){var i=this.values[t];return void 0===n?i[e]:n===i[e]?this:(i[e]=n,this.setValues(t,i),this)},"undefined"!=typeof window&&(window.Color=o),e.exports=o},{2:2,5:5}],4:[function(t,e,n){function i(t){var e,n,i,a=t[0]/255,o=t[1]/255,r=t[2]/255,l=Math.min(a,o,r),s=Math.max(a,o,r),u=s-l;return s==l?e=0:a==s?e=(o-r)/u:o==s?e=2+(r-a)/u:r==s&&(e=4+(a-o)/u),(e=Math.min(60*e,360))<0&&(e+=360),i=(l+s)/2,n=s==l?0:i<=.5?u/(s+l):u/(2-s-l),[e,100*n,100*i]}function a(t){var e,n,i,a=t[0],o=t[1],r=t[2],l=Math.min(a,o,r),s=Math.max(a,o,r),u=s-l;return n=0==s?0:u/s*1e3/10,s==l?e=0:a==s?e=(o-r)/u:o==s?e=2+(r-a)/u:r==s&&(e=4+(a-o)/u),(e=Math.min(60*e,360))<0&&(e+=360),i=s/255*1e3/10,[e,n,i]}function o(t){var e=t[0],n=t[1],a=t[2];return[i(t)[0],100*(1/255*Math.min(e,Math.min(n,a))),100*(a=1-1/255*Math.max(e,Math.max(n,a)))]}function l(t){var e,n,i,a,o=t[0]/255,r=t[1]/255,l=t[2]/255;return a=Math.min(1-o,1-r,1-l),e=(1-o-a)/(1-a)||0,n=(1-r-a)/(1-a)||0,i=(1-l-a)/(1-a)||0,[100*e,100*n,100*i,100*a]}function s(t){return C[JSON.stringify(t)]}function u(t){var e=t[0]/255,n=t[1]/255,i=t[2]/255;return[100*(.4124*(e=e>.04045?Math.pow((e+.055)/1.055,2.4):e/12.92)+.3576*(n=n>.04045?Math.pow((n+.055)/1.055,2.4):n/12.92)+.1805*(i=i>.04045?Math.pow((i+.055)/1.055,2.4):i/12.92)),100*(.2126*e+.7152*n+.0722*i),100*(.0193*e+.1192*n+.9505*i)]}function d(t){var e,n,i,a=u(t),o=a[0],r=a[1],l=a[2];return o/=95.047,r/=100,l/=108.883,o=o>.008856?Math.pow(o,1/3):7.787*o+16/116,r=r>.008856?Math.pow(r,1/3):7.787*r+16/116,l=l>.008856?Math.pow(l,1/3):7.787*l+16/116,e=116*r-16,n=500*(o-r),i=200*(r-l),[e,n,i]}function c(t){var e,n,i,a,o,r=t[0]/360,l=t[1]/100,s=t[2]/100;if(0==l)return o=255*s,[o,o,o];e=2*s-(n=s<.5?s*(1+l):s+l-s*l),a=[0,0,0];for(var u=0;u<3;u++)(i=r+1/3*-(u-1))<0&&i++,i>1&&i--,o=6*i<1?e+6*(n-e)*i:2*i<1?n:3*i<2?e+(n-e)*(2/3-i)*6:e,a[u]=255*o;return a}function h(t){var e=t[0]/60,n=t[1]/100,i=t[2]/100,a=Math.floor(e)%6,o=e-Math.floor(e),r=255*i*(1-n),l=255*i*(1-n*o),s=255*i*(1-n*(1-o)),i=255*i;switch(a){case 0:return[i,s,r];case 1:return[l,i,r];case 2:return[r,i,s];case 3:return[r,l,i];case 4:return[s,r,i];case 5:return[i,r,l]}}function f(t){var e,n,i,a,o=t[0]/360,l=t[1]/100,s=t[2]/100,u=l+s;switch(u>1&&(l/=u,s/=u),e=Math.floor(6*o),n=1-s,i=6*o-e,0!=(1&e)&&(i=1-i),a=l+i*(n-l),e){default:case 6:case 0:r=n,g=a,b=l;break;case 1:r=a,g=n,b=l;break;case 2:r=l,g=n,b=a;break;case 3:r=l,g=a,b=n;break;case 4:r=a,g=l,b=n;break;case 5:r=n,g=l,b=a}return[255*r,255*g,255*b]}function p(t){var e,n,i,a=t[0]/100,o=t[1]/100,r=t[2]/100,l=t[3]/100;return e=1-Math.min(1,a*(1-l)+l),n=1-Math.min(1,o*(1-l)+l),i=1-Math.min(1,r*(1-l)+l),[255*e,255*n,255*i]}function v(t){var e,n,i,a=t[0]/100,o=t[1]/100,r=t[2]/100;return e=3.2406*a+-1.5372*o+-.4986*r,n=-.9689*a+1.8758*o+.0415*r,i=.0557*a+-.204*o+1.057*r,e=e>.0031308?1.055*Math.pow(e,1/2.4)-.055:e*=12.92,n=n>.0031308?1.055*Math.pow(n,1/2.4)-.055:n*=12.92,i=i>.0031308?1.055*Math.pow(i,1/2.4)-.055:i*=12.92,e=Math.min(Math.max(0,e),1),n=Math.min(Math.max(0,n),1),i=Math.min(Math.max(0,i),1),[255*e,255*n,255*i]}function m(t){var e,n,i,a=t[0],o=t[1],r=t[2];return a/=95.047,o/=100,r/=108.883,a=a>.008856?Math.pow(a,1/3):7.787*a+16/116,o=o>.008856?Math.pow(o,1/3):7.787*o+16/116,r=r>.008856?Math.pow(r,1/3):7.787*r+16/116,e=116*o-16,n=500*(a-o),i=200*(o-r),[e,n,i]}function x(t){var e,n,i,a,o=t[0],r=t[1],l=t[2];return o<=8?a=(n=100*o/903.3)/100*7.787+16/116:(n=100*Math.pow((o+16)/116,3),a=Math.pow(n/100,1/3)),e=e/95.047<=.008856?e=95.047*(r/500+a-16/116)/7.787:95.047*Math.pow(r/500+a,3),i=i/108.883<=.008859?i=108.883*(a-l/200-16/116)/7.787:108.883*Math.pow(a-l/200,3),[e,n,i]}function y(t){var e,n,i,a=t[0],o=t[1],r=t[2];return e=Math.atan2(r,o),(n=360*e/2/Math.PI)<0&&(n+=360),i=Math.sqrt(o*o+r*r),[a,i,n]}function k(t){return v(x(t))}function w(t){var e,n,i,a=t[0],o=t[1];return i=t[2]/360*2*Math.PI,e=o*Math.cos(i),n=o*Math.sin(i),[a,e,n]}function M(t){return S[t]}e.exports={rgb2hsl:i,rgb2hsv:a,rgb2hwb:o,rgb2cmyk:l,rgb2keyword:s,rgb2xyz:u,rgb2lab:d,rgb2lch:function(t){return y(d(t))},hsl2rgb:c,hsl2hsv:function(t){var e,n,i=t[0],a=t[1]/100,o=t[2]/100;return 0===o?[0,0,0]:(o*=2,a*=o<=1?o:2-o,n=(o+a)/2,e=2*a/(o+a),[i,100*e,100*n])},hsl2hwb:function(t){return o(c(t))},hsl2cmyk:function(t){return l(c(t))},hsl2keyword:function(t){return s(c(t))},hsv2rgb:h,hsv2hsl:function(t){var e,n,i=t[0],a=t[1]/100,o=t[2]/100;return n=(2-a)*o,e=a*o,e/=n<=1?n:2-n,e=e||0,n/=2,[i,100*e,100*n]},hsv2hwb:function(t){return o(h(t))},hsv2cmyk:function(t){return l(h(t))},hsv2keyword:function(t){return s(h(t))},hwb2rgb:f,hwb2hsl:function(t){return i(f(t))},hwb2hsv:function(t){return a(f(t))},hwb2cmyk:function(t){return l(f(t))},hwb2keyword:function(t){return s(f(t))},cmyk2rgb:p,cmyk2hsl:function(t){return i(p(t))},cmyk2hsv:function(t){return a(p(t))},cmyk2hwb:function(t){return o(p(t))},cmyk2keyword:function(t){return s(p(t))},keyword2rgb:M,keyword2hsl:function(t){return i(M(t))},keyword2hsv:function(t){return a(M(t))},keyword2hwb:function(t){return o(M(t))},keyword2cmyk:function(t){return l(M(t))},keyword2lab:function(t){return d(M(t))},keyword2xyz:function(t){return u(M(t))},xyz2rgb:v,xyz2lab:m,xyz2lch:function(t){return y(m(t))},lab2xyz:x,lab2rgb:k,lab2lch:y,lch2lab:w,lch2xyz:function(t){return x(w(t))},lch2rgb:function(t){return k(w(t))}};var S={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]},C={};for(var _ in S)C[JSON.stringify(S[_])]=_},{}],5:[function(t,e,n){var i=t(4),a=function(){return new u};for(var o in i){a[o+"Raw"]=function(t){return function(e){return"number"==typeof e&&(e=Array.prototype.slice.call(arguments)),i[t](e)}}(o);var r=/(\w+)2(\w+)/.exec(o),l=r[1],s=r[2];(a[l]=a[l]||{})[s]=a[o]=function(t){return function(e){"number"==typeof e&&(e=Array.prototype.slice.call(arguments));var n=i[t](e);if("string"==typeof n||void 0===n)return n;for(var a=0;a<n.length;a++)n[a]=Math.round(n[a]);return n}}(o)}var u=function(){this.convs={}};u.prototype.routeSpace=function(t,e){var n=e[0];return void 0===n?this.getValues(t):("number"==typeof n&&(n=Array.prototype.slice.call(e)),this.setValues(t,n))},u.prototype.setValues=function(t,e){return this.space=t,this.convs={},this.convs[t]=e,this},u.prototype.getValues=function(t){var e=this.convs[t];if(!e){var n=this.space,i=this.convs[n];e=a[n][t](i),this.convs[t]=e}return e},["rgb","hsl","hsv","cmyk","keyword"].forEach(function(t){u.prototype[t]=function(e){return this.routeSpace(t,arguments)}}),e.exports=a},{4:4}],6:[function(t,e,n){"use strict";e.exports={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]}},{}],7:[function(t,e,n){var i=t(29)();i.helpers=t(45),t(27)(i),i.defaults=t(25),i.Element=t(26),i.elements=t(40),i.Interaction=t(28),i.platform=t(48),t(31)(i),t(22)(i),t(23)(i),t(24)(i),t(30)(i),t(33)(i),t(32)(i),t(35)(i),t(54)(i),t(52)(i),t(53)(i),t(55)(i),t(56)(i),t(57)(i),t(15)(i),t(16)(i),t(17)(i),t(18)(i),t(19)(i),t(20)(i),t(21)(i),t(8)(i),t(9)(i),t(10)(i),t(11)(i),t(12)(i),t(13)(i),t(14)(i);var a=[];a.push(t(49)(i),t(50)(i),t(51)(i)),i.plugins.register(a),i.platform.initialize(),e.exports=i,"undefined"!=typeof window&&(window.Chart=i),i.canvasHelpers=i.helpers.canvas},{10:10,11:11,12:12,13:13,14:14,15:15,16:16,17:17,18:18,19:19,20:20,21:21,22:22,23:23,24:24,25:25,26:26,27:27,28:28,29:29,30:30,31:31,32:32,33:33,35:35,40:40,45:45,48:48,49:49,50:50,51:51,52:52,53:53,54:54,55:55,56:56,57:57,8:8,9:9}],8:[function(t,e,n){"use strict";e.exports=function(t){t.Bar=function(e,n){return n.type="bar",new t(e,n)}}},{}],9:[function(t,e,n){"use strict";e.exports=function(t){t.Bubble=function(e,n){return n.type="bubble",new t(e,n)}}},{}],10:[function(t,e,n){"use strict";e.exports=function(t){t.Doughnut=function(e,n){return n.type="doughnut",new t(e,n)}}},{}],11:[function(t,e,n){"use strict";e.exports=function(t){t.Line=function(e,n){return n.type="line",new t(e,n)}}},{}],12:[function(t,e,n){"use strict";e.exports=function(t){t.PolarArea=function(e,n){return n.type="polarArea",new t(e,n)}}},{}],13:[function(t,e,n){"use strict";e.exports=function(t){t.Radar=function(e,n){return n.type="radar",new t(e,n)}}},{}],14:[function(t,e,n){"use strict";e.exports=function(t){t.Scatter=function(e,n){return n.type="scatter",new t(e,n)}}},{}],15:[function(t,e,n){"use strict";var i=t(25),a=t(40),o=t(45);i._set("bar",{hover:{mode:"label"},scales:{xAxes:[{type:"category",categoryPercentage:.8,barPercentage:.9,offset:!0,gridLines:{offsetGridLines:!0}}],yAxes:[{type:"linear"}]}}),i._set("horizontalBar",{hover:{mode:"index",axis:"y"},scales:{xAxes:[{type:"linear",position:"bottom"}],yAxes:[{position:"left",type:"category",categoryPercentage:.8,barPercentage:.9,offset:!0,gridLines:{offsetGridLines:!0}}]},elements:{rectangle:{borderSkipped:"left"}},tooltips:{callbacks:{title:function(t,e){var n="";return t.length>0&&(t[0].yLabel?n=t[0].yLabel:e.labels.length>0&&t[0].index<e.labels.length&&(n=e.labels[t[0].index])),n},label:function(t,e){return(e.datasets[t.datasetIndex].label||"")+": "+t.xLabel}},mode:"index",axis:"y"}}),e.exports=function(t){t.controllers.bar=t.DatasetController.extend({dataElementType:a.Rectangle,initialize:function(){var e,n=this;t.DatasetController.prototype.initialize.apply(n,arguments),(e=n.getMeta()).stack=n.getDataset().stack,e.bar=!0},update:function(t){var e,n,i=this,a=i.getMeta().data;for(i._ruler=i.getRuler(),e=0,n=a.length;e<n;++e)i.updateElement(a[e],e,t)},updateElement:function(t,e,n){var i=this,a=i.chart,r=i.getMeta(),l=i.getDataset(),s=t.custom||{},u=a.options.elements.rectangle;t._xScale=i.getScaleForId(r.xAxisID),t._yScale=i.getScaleForId(r.yAxisID),t._datasetIndex=i.index,t._index=e,t._model={datasetLabel:l.label,label:a.data.labels[e],borderSkipped:s.borderSkipped?s.borderSkipped:u.borderSkipped,backgroundColor:s.backgroundColor?s.backgroundColor:o.valueAtIndexOrDefault(l.backgroundColor,e,u.backgroundColor),borderColor:s.borderColor?s.borderColor:o.valueAtIndexOrDefault(l.borderColor,e,u.borderColor),borderWidth:s.borderWidth?s.borderWidth:o.valueAtIndexOrDefault(l.borderWidth,e,u.borderWidth)},i.updateElementGeometry(t,e,n),t.pivot()},updateElementGeometry:function(t,e,n){var i=this,a=t._model,o=i.getValueScale(),r=o.getBasePixel(),l=o.isHorizontal(),s=i._ruler||i.getRuler(),u=i.calculateBarValuePixels(i.index,e),d=i.calculateBarIndexPixels(i.index,e,s);a.horizontal=l,a.base=n?r:u.base,a.x=l?n?r:u.head:d.center,a.y=l?d.center:n?r:u.head,a.height=l?d.size:void 0,a.width=l?void 0:d.size},getValueScaleId:function(){return this.getMeta().yAxisID},getIndexScaleId:function(){return this.getMeta().xAxisID},getValueScale:function(){return this.getScaleForId(this.getValueScaleId())},getIndexScale:function(){return this.getScaleForId(this.getIndexScaleId())},getStackCount:function(t){var e,n,i=this,a=i.chart,o=i.getIndexScale().options.stacked,r=void 0===t?a.data.datasets.length:t+1,l=[];for(e=0;e<r;++e)(n=a.getDatasetMeta(e)).bar&&a.isDatasetVisible(e)&&(!1===o||!0===o&&-1===l.indexOf(n.stack)||void 0===o&&(void 0===n.stack||-1===l.indexOf(n.stack)))&&l.push(n.stack);return l.length},getStackIndex:function(t){return this.getStackCount(t)-1},getRuler:function(){var t,e,n=this,i=n.getIndexScale(),a=n.getStackCount(),o=n.index,r=[],l=i.isHorizontal(),s=l?i.left:i.top,u=s+(l?i.width:i.height);for(t=0,e=n.getMeta().data.length;t<e;++t)r.push(i.getPixelForValue(null,t,o));return{pixels:r,start:s,end:u,stackCount:a,scale:i}},calculateBarValuePixels:function(t,e){var n,i,a,o,r,l,s=this,u=s.chart,d=s.getMeta(),c=s.getValueScale(),h=u.data.datasets,f=c.getRightValue(h[t].data[e]),g=c.options.stacked,p=d.stack,v=0;if(g||void 0===g&&void 0!==p)for(n=0;n<t;++n)(i=u.getDatasetMeta(n)).bar&&i.stack===p&&i.controller.getValueScaleId()===c.id&&u.isDatasetVisible(n)&&(a=c.getRightValue(h[n].data[e]),(f<0&&a<0||f>=0&&a>0)&&(v+=a));return o=c.getPixelForValue(v),r=c.getPixelForValue(v+f),l=(r-o)/2,{size:l,base:o,head:r,center:r+l/2}},calculateBarIndexPixels:function(t,e,n){var i,a,r,l,s,u,d=this,c=n.scale.options,h=d.getStackIndex(t),f=n.pixels,g=f[e],p=f.length,v=n.start,m=n.end;return 1===p?(i=g>v?g-v:m-g,a=g<m?m-g:g-v):(e>0&&(i=(g-f[e-1])/2,e===p-1&&(a=i)),e<p-1&&(a=(f[e+1]-g)/2,0===e&&(i=a))),r=i*c.categoryPercentage,l=a*c.categoryPercentage,s=(r+l)/n.stackCount,u=s*c.barPercentage,u=Math.min(o.valueOrDefault(c.barThickness,u),o.valueOrDefault(c.maxBarThickness,1/0)),g-=r,g+=s*h,g+=(s-u)/2,{size:u,base:g,head:g+u,center:g+u/2}},draw:function(){var t=this,e=t.chart,n=t.getValueScale(),i=t.getMeta().data,a=t.getDataset(),r=i.length,l=0;for(o.canvas.clipArea(e.ctx,e.chartArea);l<r;++l)isNaN(n.getRightValue(a.data[l]))||i[l].draw();o.canvas.unclipArea(e.ctx)},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t._index,i=t.custom||{},a=t._model;a.backgroundColor=i.hoverBackgroundColor?i.hoverBackgroundColor:o.valueAtIndexOrDefault(e.hoverBackgroundColor,n,o.getHoverColor(a.backgroundColor)),a.borderColor=i.hoverBorderColor?i.hoverBorderColor:o.valueAtIndexOrDefault(e.hoverBorderColor,n,o.getHoverColor(a.borderColor)),a.borderWidth=i.hoverBorderWidth?i.hoverBorderWidth:o.valueAtIndexOrDefault(e.hoverBorderWidth,n,a.borderWidth)},removeHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t._index,i=t.custom||{},a=t._model,r=this.chart.options.elements.rectangle;a.backgroundColor=i.backgroundColor?i.backgroundColor:o.valueAtIndexOrDefault(e.backgroundColor,n,r.backgroundColor),a.borderColor=i.borderColor?i.borderColor:o.valueAtIndexOrDefault(e.borderColor,n,r.borderColor),a.borderWidth=i.borderWidth?i.borderWidth:o.valueAtIndexOrDefault(e.borderWidth,n,r.borderWidth)}}),t.controllers.horizontalBar=t.controllers.bar.extend({getValueScaleId:function(){return this.getMeta().xAxisID},getIndexScaleId:function(){return this.getMeta().yAxisID}})}},{25:25,40:40,45:45}],16:[function(t,e,n){"use strict";var i=t(25),a=t(40),o=t(45);i._set("bubble",{hover:{mode:"single"},scales:{xAxes:[{type:"linear",position:"bottom",id:"x-axis-0"}],yAxes:[{type:"linear",position:"left",id:"y-axis-0"}]},tooltips:{callbacks:{title:function(){return""},label:function(t,e){var n=e.datasets[t.datasetIndex].label||"",i=e.datasets[t.datasetIndex].data[t.index];return n+": ("+t.xLabel+", "+t.yLabel+", "+i.r+")"}}}}),e.exports=function(t){t.controllers.bubble=t.DatasetController.extend({dataElementType:a.Point,update:function(t){var e=this,n=e.getMeta().data;o.each(n,function(n,i){e.updateElement(n,i,t)})},updateElement:function(t,e,n){var i=this,a=i.getMeta(),o=t.custom||{},r=i.getScaleForId(a.xAxisID),l=i.getScaleForId(a.yAxisID),s=i._resolveElementOptions(t,e),u=i.getDataset().data[e],d=i.index,c=n?r.getPixelForDecimal(.5):r.getPixelForValue("object"==typeof u?u:NaN,e,d),h=n?l.getBasePixel():l.getPixelForValue(u,e,d);t._xScale=r,t._yScale=l,t._options=s,t._datasetIndex=d,t._index=e,t._model={backgroundColor:s.backgroundColor,borderColor:s.borderColor,borderWidth:s.borderWidth,hitRadius:s.hitRadius,pointStyle:s.pointStyle,radius:n?0:s.radius,skip:o.skip||isNaN(c)||isNaN(h),x:c,y:h},t.pivot()},setHoverStyle:function(t){var e=t._model,n=t._options;e.backgroundColor=o.valueOrDefault(n.hoverBackgroundColor,o.getHoverColor(n.backgroundColor)),e.borderColor=o.valueOrDefault(n.hoverBorderColor,o.getHoverColor(n.borderColor)),e.borderWidth=o.valueOrDefault(n.hoverBorderWidth,n.borderWidth),e.radius=n.radius+n.hoverRadius},removeHoverStyle:function(t){var e=t._model,n=t._options;e.backgroundColor=n.backgroundColor,e.borderColor=n.borderColor,e.borderWidth=n.borderWidth,e.radius=n.radius},_resolveElementOptions:function(t,e){var n,i,a,r=this,l=r.chart,s=l.data.datasets[r.index],u=t.custom||{},d=l.options.elements.point,c=o.options.resolve,h=s.data[e],f={},g={chart:l,dataIndex:e,dataset:s,datasetIndex:r.index},p=["backgroundColor","borderColor","borderWidth","hoverBackgroundColor","hoverBorderColor","hoverBorderWidth","hoverRadius","hitRadius","pointStyle"];for(n=0,i=p.length;n<i;++n)f[a=p[n]]=c([u[a],s[a],d[a]],g,e);return f.radius=c([u.radius,h?h.r:void 0,s.radius,d.radius],g,e),f}})}},{25:25,40:40,45:45}],17:[function(t,e,n){"use strict";var i=t(25),a=t(40),o=t(45);i._set("doughnut",{animation:{animateRotate:!0,animateScale:!1},hover:{mode:"single"},legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');var n=t.data,i=n.datasets,a=n.labels;if(i.length)for(var o=0;o<i[0].data.length;++o)e.push('<li><span style="background-color:'+i[0].backgroundColor[o]+'"></span>'),a[o]&&e.push(a[o]),e.push("</li>");return e.push("</ul>"),e.join("")},legend:{labels:{generateLabels:function(t){var e=t.data;return e.labels.length&&e.datasets.length?e.labels.map(function(n,i){var a=t.getDatasetMeta(0),r=e.datasets[0],l=a.data[i],s=l&&l.custom||{},u=o.valueAtIndexOrDefault,d=t.options.elements.arc;return{text:n,fillStyle:s.backgroundColor?s.backgroundColor:u(r.backgroundColor,i,d.backgroundColor),strokeStyle:s.borderColor?s.borderColor:u(r.borderColor,i,d.borderColor),lineWidth:s.borderWidth?s.borderWidth:u(r.borderWidth,i,d.borderWidth),hidden:isNaN(r.data[i])||a.data[i].hidden,index:i}}):[]}},onClick:function(t,e){var n,i,a,o=e.index,r=this.chart;for(n=0,i=(r.data.datasets||[]).length;n<i;++n)(a=r.getDatasetMeta(n)).data[o]&&(a.data[o].hidden=!a.data[o].hidden);r.update()}},cutoutPercentage:50,rotation:-.5*Math.PI,circumference:2*Math.PI,tooltips:{callbacks:{title:function(){return""},label:function(t,e){var n=e.labels[t.index],i=": "+e.datasets[t.datasetIndex].data[t.index];return o.isArray(n)?(n=n.slice())[0]+=i:n+=i,n}}}}),i._set("pie",o.clone(i.doughnut)),i._set("pie",{cutoutPercentage:0}),e.exports=function(t){t.controllers.doughnut=t.controllers.pie=t.DatasetController.extend({dataElementType:a.Arc,linkScales:o.noop,getRingIndex:function(t){for(var e=0,n=0;n<t;++n)this.chart.isDatasetVisible(n)&&++e;return e},update:function(t){var e=this,n=e.chart,i=n.chartArea,a=n.options,r=a.elements.arc,l=i.right-i.left-r.borderWidth,s=i.bottom-i.top-r.borderWidth,u=Math.min(l,s),d={x:0,y:0},c=e.getMeta(),h=a.cutoutPercentage,f=a.circumference;if(f<2*Math.PI){var g=a.rotation%(2*Math.PI),p=(g+=2*Math.PI*(g>=Math.PI?-1:g<-Math.PI?1:0))+f,v={x:Math.cos(g),y:Math.sin(g)},m={x:Math.cos(p),y:Math.sin(p)},b=g<=0&&p>=0||g<=2*Math.PI&&2*Math.PI<=p,x=g<=.5*Math.PI&&.5*Math.PI<=p||g<=2.5*Math.PI&&2.5*Math.PI<=p,y=g<=-Math.PI&&-Math.PI<=p||g<=Math.PI&&Math.PI<=p,k=g<=.5*-Math.PI&&.5*-Math.PI<=p||g<=1.5*Math.PI&&1.5*Math.PI<=p,w=h/100,M={x:y?-1:Math.min(v.x*(v.x<0?1:w),m.x*(m.x<0?1:w)),y:k?-1:Math.min(v.y*(v.y<0?1:w),m.y*(m.y<0?1:w))},S={x:b?1:Math.max(v.x*(v.x>0?1:w),m.x*(m.x>0?1:w)),y:x?1:Math.max(v.y*(v.y>0?1:w),m.y*(m.y>0?1:w))},C={width:.5*(S.x-M.x),height:.5*(S.y-M.y)};u=Math.min(l/C.width,s/C.height),d={x:-.5*(S.x+M.x),y:-.5*(S.y+M.y)}}n.borderWidth=e.getMaxBorderWidth(c.data),n.outerRadius=Math.max((u-n.borderWidth)/2,0),n.innerRadius=Math.max(h?n.outerRadius/100*h:0,0),n.radiusLength=(n.outerRadius-n.innerRadius)/n.getVisibleDatasetCount(),n.offsetX=d.x*n.outerRadius,n.offsetY=d.y*n.outerRadius,c.total=e.calculateTotal(),e.outerRadius=n.outerRadius-n.radiusLength*e.getRingIndex(e.index),e.innerRadius=Math.max(e.outerRadius-n.radiusLength,0),o.each(c.data,function(n,i){e.updateElement(n,i,t)})},updateElement:function(t,e,n){var i=this,a=i.chart,r=a.chartArea,l=a.options,s=l.animation,u=(r.left+r.right)/2,d=(r.top+r.bottom)/2,c=l.rotation,h=l.rotation,f=i.getDataset(),g=n&&s.animateRotate?0:t.hidden?0:i.calculateCircumference(f.data[e])*(l.circumference/(2*Math.PI)),p=n&&s.animateScale?0:i.innerRadius,v=n&&s.animateScale?0:i.outerRadius,m=o.valueAtIndexOrDefault;o.extend(t,{_datasetIndex:i.index,_index:e,_model:{x:u+a.offsetX,y:d+a.offsetY,startAngle:c,endAngle:h,circumference:g,outerRadius:v,innerRadius:p,label:m(f.label,e,a.data.labels[e])}});var b=t._model;this.removeHoverStyle(t),n&&s.animateRotate||(b.startAngle=0===e?l.rotation:i.getMeta().data[e-1]._model.endAngle,b.endAngle=b.startAngle+b.circumference),t.pivot()},removeHoverStyle:function(e){t.DatasetController.prototype.removeHoverStyle.call(this,e,this.chart.options.elements.arc)},calculateTotal:function(){var t,e=this.getDataset(),n=this.getMeta(),i=0;return o.each(n.data,function(n,a){t=e.data[a],isNaN(t)||n.hidden||(i+=Math.abs(t))}),i},calculateCircumference:function(t){var e=this.getMeta().total;return e>0&&!isNaN(t)?2*Math.PI*(t/e):0},getMaxBorderWidth:function(t){for(var e,n,i=0,a=this.index,o=t.length,r=0;r<o;r++)e=t[r]._model?t[r]._model.borderWidth:0,i=(n=t[r]._chart?t[r]._chart.config.data.datasets[a].hoverBorderWidth:0)>(i=e>i?e:i)?n:i;return i}})}},{25:25,40:40,45:45}],18:[function(t,e,n){"use strict";var i=t(25),a=t(40),o=t(45);i._set("line",{showLines:!0,spanGaps:!1,hover:{mode:"label"},scales:{xAxes:[{type:"category",id:"x-axis-0"}],yAxes:[{type:"linear",id:"y-axis-0"}]}}),e.exports=function(t){function e(t,e){return o.valueOrDefault(t.showLine,e.showLines)}t.controllers.line=t.DatasetController.extend({datasetElementType:a.Line,dataElementType:a.Point,update:function(t){var n,i,a,r=this,l=r.getMeta(),s=l.dataset,u=l.data||[],d=r.chart.options,c=d.elements.line,h=r.getScaleForId(l.yAxisID),f=r.getDataset(),g=e(f,d);for(g&&(a=s.custom||{},void 0!==f.tension&&void 0===f.lineTension&&(f.lineTension=f.tension),s._scale=h,s._datasetIndex=r.index,s._children=u,s._model={spanGaps:f.spanGaps?f.spanGaps:d.spanGaps,tension:a.tension?a.tension:o.valueOrDefault(f.lineTension,c.tension),backgroundColor:a.backgroundColor?a.backgroundColor:f.backgroundColor||c.backgroundColor,borderWidth:a.borderWidth?a.borderWidth:f.borderWidth||c.borderWidth,borderColor:a.borderColor?a.borderColor:f.borderColor||c.borderColor,borderCapStyle:a.borderCapStyle?a.borderCapStyle:f.borderCapStyle||c.borderCapStyle,borderDash:a.borderDash?a.borderDash:f.borderDash||c.borderDash,borderDashOffset:a.borderDashOffset?a.borderDashOffset:f.borderDashOffset||c.borderDashOffset,borderJoinStyle:a.borderJoinStyle?a.borderJoinStyle:f.borderJoinStyle||c.borderJoinStyle,fill:a.fill?a.fill:void 0!==f.fill?f.fill:c.fill,steppedLine:a.steppedLine?a.steppedLine:o.valueOrDefault(f.steppedLine,c.stepped),cubicInterpolationMode:a.cubicInterpolationMode?a.cubicInterpolationMode:o.valueOrDefault(f.cubicInterpolationMode,c.cubicInterpolationMode)},s.pivot()),n=0,i=u.length;n<i;++n)r.updateElement(u[n],n,t);for(g&&0!==s._model.tension&&r.updateBezierControlPoints(),n=0,i=u.length;n<i;++n)u[n].pivot()},getPointBackgroundColor:function(t,e){var n=this.chart.options.elements.point.backgroundColor,i=this.getDataset(),a=t.custom||{};return a.backgroundColor?n=a.backgroundColor:i.pointBackgroundColor?n=o.valueAtIndexOrDefault(i.pointBackgroundColor,e,n):i.backgroundColor&&(n=i.backgroundColor),n},getPointBorderColor:function(t,e){var n=this.chart.options.elements.point.borderColor,i=this.getDataset(),a=t.custom||{};return a.borderColor?n=a.borderColor:i.pointBorderColor?n=o.valueAtIndexOrDefault(i.pointBorderColor,e,n):i.borderColor&&(n=i.borderColor),n},getPointBorderWidth:function(t,e){var n=this.chart.options.elements.point.borderWidth,i=this.getDataset(),a=t.custom||{};return isNaN(a.borderWidth)?!isNaN(i.pointBorderWidth)||o.isArray(i.pointBorderWidth)?n=o.valueAtIndexOrDefault(i.pointBorderWidth,e,n):isNaN(i.borderWidth)||(n=i.borderWidth):n=a.borderWidth,n},updateElement:function(t,e,n){var i,a,r=this,l=r.getMeta(),s=t.custom||{},u=r.getDataset(),d=r.index,c=u.data[e],h=r.getScaleForId(l.yAxisID),f=r.getScaleForId(l.xAxisID),g=r.chart.options.elements.point;void 0!==u.radius&&void 0===u.pointRadius&&(u.pointRadius=u.radius),void 0!==u.hitRadius&&void 0===u.pointHitRadius&&(u.pointHitRadius=u.hitRadius),i=f.getPixelForValue("object"==typeof c?c:NaN,e,d),a=n?h.getBasePixel():r.calculatePointY(c,e,d),t._xScale=f,t._yScale=h,t._datasetIndex=d,t._index=e,t._model={x:i,y:a,skip:s.skip||isNaN(i)||isNaN(a),radius:s.radius||o.valueAtIndexOrDefault(u.pointRadius,e,g.radius),pointStyle:s.pointStyle||o.valueAtIndexOrDefault(u.pointStyle,e,g.pointStyle),backgroundColor:r.getPointBackgroundColor(t,e),borderColor:r.getPointBorderColor(t,e),borderWidth:r.getPointBorderWidth(t,e),tension:l.dataset._model?l.dataset._model.tension:0,steppedLine:!!l.dataset._model&&l.dataset._model.steppedLine,hitRadius:s.hitRadius||o.valueAtIndexOrDefault(u.pointHitRadius,e,g.hitRadius)}},calculatePointY:function(t,e,n){var i,a,o,r=this,l=r.chart,s=r.getMeta(),u=r.getScaleForId(s.yAxisID),d=0,c=0;if(u.options.stacked){for(i=0;i<n;i++)if(a=l.data.datasets[i],"line"===(o=l.getDatasetMeta(i)).type&&o.yAxisID===u.id&&l.isDatasetVisible(i)){var h=Number(u.getRightValue(a.data[e]));h<0?c+=h||0:d+=h||0}var f=Number(u.getRightValue(t));return f<0?u.getPixelForValue(c+f):u.getPixelForValue(d+f)}return u.getPixelForValue(t)},updateBezierControlPoints:function(){function t(t,e,n){return Math.max(Math.min(t,n),e)}var e,n,i,a,r=this,l=r.getMeta(),s=r.chart.chartArea,u=l.data||[];if(l.dataset._model.spanGaps&&(u=u.filter(function(t){return!t._model.skip})),"monotone"===l.dataset._model.cubicInterpolationMode)o.splineCurveMonotone(u);else for(e=0,n=u.length;e<n;++e)i=u[e]._model,a=o.splineCurve(o.previousItem(u,e)._model,i,o.nextItem(u,e)._model,l.dataset._model.tension),i.controlPointPreviousX=a.previous.x,i.controlPointPreviousY=a.previous.y,i.controlPointNextX=a.next.x,i.controlPointNextY=a.next.y;if(r.chart.options.elements.line.capBezierPoints)for(e=0,n=u.length;e<n;++e)(i=u[e]._model).controlPointPreviousX=t(i.controlPointPreviousX,s.left,s.right),i.controlPointPreviousY=t(i.controlPointPreviousY,s.top,s.bottom),i.controlPointNextX=t(i.controlPointNextX,s.left,s.right),i.controlPointNextY=t(i.controlPointNextY,s.top,s.bottom)},draw:function(){var t=this,n=t.chart,i=t.getMeta(),a=i.data||[],r=n.chartArea,l=a.length,s=0;for(o.canvas.clipArea(n.ctx,r),e(t.getDataset(),n.options)&&i.dataset.draw(),o.canvas.unclipArea(n.ctx);s<l;++s)a[s].draw(r)},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t._index,i=t.custom||{},a=t._model;a.radius=i.hoverRadius||o.valueAtIndexOrDefault(e.pointHoverRadius,n,this.chart.options.elements.point.hoverRadius),a.backgroundColor=i.hoverBackgroundColor||o.valueAtIndexOrDefault(e.pointHoverBackgroundColor,n,o.getHoverColor(a.backgroundColor)),a.borderColor=i.hoverBorderColor||o.valueAtIndexOrDefault(e.pointHoverBorderColor,n,o.getHoverColor(a.borderColor)),a.borderWidth=i.hoverBorderWidth||o.valueAtIndexOrDefault(e.pointHoverBorderWidth,n,a.borderWidth)},removeHoverStyle:function(t){var e=this,n=e.chart.data.datasets[t._datasetIndex],i=t._index,a=t.custom||{},r=t._model;void 0!==n.radius&&void 0===n.pointRadius&&(n.pointRadius=n.radius),r.radius=a.radius||o.valueAtIndexOrDefault(n.pointRadius,i,e.chart.options.elements.point.radius),r.backgroundColor=e.getPointBackgroundColor(t,i),r.borderColor=e.getPointBorderColor(t,i),r.borderWidth=e.getPointBorderWidth(t,i)}})}},{25:25,40:40,45:45}],19:[function(t,e,n){"use strict";var i=t(25),a=t(40),o=t(45);i._set("polarArea",{scale:{type:"radialLinear",angleLines:{display:!1},gridLines:{circular:!0},pointLabels:{display:!1},ticks:{beginAtZero:!0}},animation:{animateRotate:!0,animateScale:!0},startAngle:-.5*Math.PI,legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');var n=t.data,i=n.datasets,a=n.labels;if(i.length)for(var o=0;o<i[0].data.length;++o)e.push('<li><span style="background-color:'+i[0].backgroundColor[o]+'"></span>'),a[o]&&e.push(a[o]),e.push("</li>");return e.push("</ul>"),e.join("")},legend:{labels:{generateLabels:function(t){var e=t.data;return e.labels.length&&e.datasets.length?e.labels.map(function(n,i){var a=t.getDatasetMeta(0),r=e.datasets[0],l=a.data[i].custom||{},s=o.valueAtIndexOrDefault,u=t.options.elements.arc;return{text:n,fillStyle:l.backgroundColor?l.backgroundColor:s(r.backgroundColor,i,u.backgroundColor),strokeStyle:l.borderColor?l.borderColor:s(r.borderColor,i,u.borderColor),lineWidth:l.borderWidth?l.borderWidth:s(r.borderWidth,i,u.borderWidth),hidden:isNaN(r.data[i])||a.data[i].hidden,index:i}}):[]}},onClick:function(t,e){var n,i,a,o=e.index,r=this.chart;for(n=0,i=(r.data.datasets||[]).length;n<i;++n)(a=r.getDatasetMeta(n)).data[o].hidden=!a.data[o].hidden;r.update()}},tooltips:{callbacks:{title:function(){return""},label:function(t,e){return e.labels[t.index]+": "+t.yLabel}}}}),e.exports=function(t){t.controllers.polarArea=t.DatasetController.extend({dataElementType:a.Arc,linkScales:o.noop,update:function(t){var e=this,n=e.chart,i=n.chartArea,a=e.getMeta(),r=n.options,l=r.elements.arc,s=Math.min(i.right-i.left,i.bottom-i.top);n.outerRadius=Math.max((s-l.borderWidth/2)/2,0),n.innerRadius=Math.max(r.cutoutPercentage?n.outerRadius/100*r.cutoutPercentage:1,0),n.radiusLength=(n.outerRadius-n.innerRadius)/n.getVisibleDatasetCount(),e.outerRadius=n.outerRadius-n.radiusLength*e.index,e.innerRadius=e.outerRadius-n.radiusLength,a.count=e.countVisibleElements(),o.each(a.data,function(n,i){e.updateElement(n,i,t)})},updateElement:function(t,e,n){for(var i=this,a=i.chart,r=i.getDataset(),l=a.options,s=l.animation,u=a.scale,d=a.data.labels,c=i.calculateCircumference(r.data[e]),h=u.xCenter,f=u.yCenter,g=0,p=i.getMeta(),v=0;v<e;++v)isNaN(r.data[v])||p.data[v].hidden||++g;var m=l.startAngle,b=t.hidden?0:u.getDistanceFromCenterForValue(r.data[e]),x=m+c*g,y=x+(t.hidden?0:c),k=s.animateScale?0:u.getDistanceFromCenterForValue(r.data[e]);o.extend(t,{_datasetIndex:i.index,_index:e,_scale:u,_model:{x:h,y:f,innerRadius:0,outerRadius:n?k:b,startAngle:n&&s.animateRotate?m:x,endAngle:n&&s.animateRotate?m:y,label:o.valueAtIndexOrDefault(d,e,d[e])}}),i.removeHoverStyle(t),t.pivot()},removeHoverStyle:function(e){t.DatasetController.prototype.removeHoverStyle.call(this,e,this.chart.options.elements.arc)},countVisibleElements:function(){var t=this.getDataset(),e=this.getMeta(),n=0;return o.each(e.data,function(e,i){isNaN(t.data[i])||e.hidden||n++}),n},calculateCircumference:function(t){var e=this.getMeta().count;return e>0&&!isNaN(t)?2*Math.PI/e:0}})}},{25:25,40:40,45:45}],20:[function(t,e,n){"use strict";var i=t(25),a=t(40),o=t(45);i._set("radar",{scale:{type:"radialLinear"},elements:{line:{tension:0}}}),e.exports=function(t){t.controllers.radar=t.DatasetController.extend({datasetElementType:a.Line,dataElementType:a.Point,linkScales:o.noop,update:function(t){var e=this,n=e.getMeta(),i=n.dataset,a=n.data,r=i.custom||{},l=e.getDataset(),s=e.chart.options.elements.line,u=e.chart.scale;void 0!==l.tension&&void 0===l.lineTension&&(l.lineTension=l.tension),o.extend(n.dataset,{_datasetIndex:e.index,_scale:u,_children:a,_loop:!0,_model:{tension:r.tension?r.tension:o.valueOrDefault(l.lineTension,s.tension),backgroundColor:r.backgroundColor?r.backgroundColor:l.backgroundColor||s.backgroundColor,borderWidth:r.borderWidth?r.borderWidth:l.borderWidth||s.borderWidth,borderColor:r.borderColor?r.borderColor:l.borderColor||s.borderColor,fill:r.fill?r.fill:void 0!==l.fill?l.fill:s.fill,borderCapStyle:r.borderCapStyle?r.borderCapStyle:l.borderCapStyle||s.borderCapStyle,borderDash:r.borderDash?r.borderDash:l.borderDash||s.borderDash,borderDashOffset:r.borderDashOffset?r.borderDashOffset:l.borderDashOffset||s.borderDashOffset,borderJoinStyle:r.borderJoinStyle?r.borderJoinStyle:l.borderJoinStyle||s.borderJoinStyle}}),n.dataset.pivot(),o.each(a,function(n,i){e.updateElement(n,i,t)},e),e.updateBezierControlPoints()},updateElement:function(t,e,n){var i=this,a=t.custom||{},r=i.getDataset(),l=i.chart.scale,s=i.chart.options.elements.point,u=l.getPointPositionForValue(e,r.data[e]);void 0!==r.radius&&void 0===r.pointRadius&&(r.pointRadius=r.radius),void 0!==r.hitRadius&&void 0===r.pointHitRadius&&(r.pointHitRadius=r.hitRadius),o.extend(t,{_datasetIndex:i.index,_index:e,_scale:l,_model:{x:n?l.xCenter:u.x,y:n?l.yCenter:u.y,tension:a.tension?a.tension:o.valueOrDefault(r.lineTension,i.chart.options.elements.line.tension),radius:a.radius?a.radius:o.valueAtIndexOrDefault(r.pointRadius,e,s.radius),backgroundColor:a.backgroundColor?a.backgroundColor:o.valueAtIndexOrDefault(r.pointBackgroundColor,e,s.backgroundColor),borderColor:a.borderColor?a.borderColor:o.valueAtIndexOrDefault(r.pointBorderColor,e,s.borderColor),borderWidth:a.borderWidth?a.borderWidth:o.valueAtIndexOrDefault(r.pointBorderWidth,e,s.borderWidth),pointStyle:a.pointStyle?a.pointStyle:o.valueAtIndexOrDefault(r.pointStyle,e,s.pointStyle),hitRadius:a.hitRadius?a.hitRadius:o.valueAtIndexOrDefault(r.pointHitRadius,e,s.hitRadius)}}),t._model.skip=a.skip?a.skip:isNaN(t._model.x)||isNaN(t._model.y)},updateBezierControlPoints:function(){var t=this.chart.chartArea,e=this.getMeta();o.each(e.data,function(n,i){var a=n._model,r=o.splineCurve(o.previousItem(e.data,i,!0)._model,a,o.nextItem(e.data,i,!0)._model,a.tension);a.controlPointPreviousX=Math.max(Math.min(r.previous.x,t.right),t.left),a.controlPointPreviousY=Math.max(Math.min(r.previous.y,t.bottom),t.top),a.controlPointNextX=Math.max(Math.min(r.next.x,t.right),t.left),a.controlPointNextY=Math.max(Math.min(r.next.y,t.bottom),t.top),n.pivot()})},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t.custom||{},i=t._index,a=t._model;a.radius=n.hoverRadius?n.hoverRadius:o.valueAtIndexOrDefault(e.pointHoverRadius,i,this.chart.options.elements.point.hoverRadius),a.backgroundColor=n.hoverBackgroundColor?n.hoverBackgroundColor:o.valueAtIndexOrDefault(e.pointHoverBackgroundColor,i,o.getHoverColor(a.backgroundColor)),a.borderColor=n.hoverBorderColor?n.hoverBorderColor:o.valueAtIndexOrDefault(e.pointHoverBorderColor,i,o.getHoverColor(a.borderColor)),a.borderWidth=n.hoverBorderWidth?n.hoverBorderWidth:o.valueAtIndexOrDefault(e.pointHoverBorderWidth,i,a.borderWidth)},removeHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t.custom||{},i=t._index,a=t._model,r=this.chart.options.elements.point;a.radius=n.radius?n.radius:o.valueAtIndexOrDefault(e.pointRadius,i,r.radius),a.backgroundColor=n.backgroundColor?n.backgroundColor:o.valueAtIndexOrDefault(e.pointBackgroundColor,i,r.backgroundColor),a.borderColor=n.borderColor?n.borderColor:o.valueAtIndexOrDefault(e.pointBorderColor,i,r.borderColor),a.borderWidth=n.borderWidth?n.borderWidth:o.valueAtIndexOrDefault(e.pointBorderWidth,i,r.borderWidth)}})}},{25:25,40:40,45:45}],21:[function(t,e,n){"use strict";t(25)._set("scatter",{hover:{mode:"single"},scales:{xAxes:[{id:"x-axis-1",type:"linear",position:"bottom"}],yAxes:[{id:"y-axis-1",type:"linear",position:"left"}]},showLines:!1,tooltips:{callbacks:{title:function(){return""},label:function(t){return"("+t.xLabel+", "+t.yLabel+")"}}}}),e.exports=function(t){t.controllers.scatter=t.controllers.line}},{25:25}],22:[function(t,e,n){"use strict";var i=t(25),a=t(26),o=t(45);i._set("global",{animation:{duration:1e3,easing:"easeOutQuart",onProgress:o.noop,onComplete:o.noop}}),e.exports=function(t){t.Animation=a.extend({chart:null,currentStep:0,numSteps:60,easing:"",render:null,onAnimationProgress:null,onAnimationComplete:null}),t.animationService={frameDuration:17,animations:[],dropFrames:0,request:null,addAnimation:function(t,e,n,i){var a,o,r=this.animations;for(e.chart=t,i||(t.animating=!0),a=0,o=r.length;a<o;++a)if(r[a].chart===t)return void(r[a]=e);r.push(e),1===r.length&&this.requestAnimationFrame()},cancelAnimation:function(t){var e=o.findIndex(this.animations,function(e){return e.chart===t});-1!==e&&(this.animations.splice(e,1),t.animating=!1)},requestAnimationFrame:function(){var t=this;null===t.request&&(t.request=o.requestAnimFrame.call(window,function(){t.request=null,t.startDigest()}))},startDigest:function(){var t=this,e=Date.now(),n=0;t.dropFrames>1&&(n=Math.floor(t.dropFrames),t.dropFrames=t.dropFrames%1),t.advance(1+n);var i=Date.now();t.dropFrames+=(i-e)/t.frameDuration,t.animations.length>0&&t.requestAnimationFrame()},advance:function(t){for(var e,n,i=this.animations,a=0;a<i.length;)n=(e=i[a]).chart,e.currentStep=(e.currentStep||0)+t,e.currentStep=Math.min(e.currentStep,e.numSteps),o.callback(e.render,[n,e],n),o.callback(e.onAnimationProgress,[e],n),e.currentStep>=e.numSteps?(o.callback(e.onAnimationComplete,[e],n),n.animating=!1,i.splice(a,1)):++a}},Object.defineProperty(t.Animation.prototype,"animationObject",{get:function(){return this}}),Object.defineProperty(t.Animation.prototype,"chartInstance",{get:function(){return this.chart},set:function(t){this.chart=t}})}},{25:25,26:26,45:45}],23:[function(t,e,n){"use strict";var i=t(25),a=t(45),o=t(28),r=t(48);e.exports=function(t){function e(t){var e=(t=t||{}).data=t.data||{};return e.datasets=e.datasets||[],e.labels=e.labels||[],t.options=a.configMerge(i.global,i[t.type],t.options||{}),t}function n(t){var e=t.options;e.scale?t.scale.options=e.scale:e.scales&&e.scales.xAxes.concat(e.scales.yAxes).forEach(function(e){t.scales[e.id].options=e}),t.tooltip._options=e.tooltips}function l(t){return"top"===t||"bottom"===t}var s=t.plugins;t.types={},t.instances={},t.controllers={},a.extend(t.prototype,{construct:function(n,i){var o=this;i=e(i);var l=r.acquireContext(n,i),s=l&&l.canvas,u=s&&s.height,d=s&&s.width;o.id=a.uid(),o.ctx=l,o.canvas=s,o.config=i,o.width=d,o.height=u,o.aspectRatio=u?d/u:null,o.options=i.options,o._bufferedRender=!1,o.chart=o,o.controller=o,t.instances[o.id]=o,Object.defineProperty(o,"data",{get:function(){return o.config.data},set:function(t){o.config.data=t}}),l&&s?(o.initialize(),o.update()):console.error("Failed to create chart: can't acquire context from the given item")},initialize:function(){var t=this;return s.notify(t,"beforeInit"),a.retinaScale(t,t.options.devicePixelRatio),t.bindEvents(),t.options.responsive&&t.resize(!0),t.ensureScalesHaveIDs(),t.buildScales(),t.initToolTip(),s.notify(t,"afterInit"),t},clear:function(){return a.canvas.clear(this),this},stop:function(){return t.animationService.cancelAnimation(this),this},resize:function(t){var e=this,n=e.options,i=e.canvas,o=n.maintainAspectRatio&&e.aspectRatio||null,r=Math.max(0,Math.floor(a.getMaximumWidth(i))),l=Math.max(0,Math.floor(o?r/o:a.getMaximumHeight(i)));if((e.width!==r||e.height!==l)&&(i.width=e.width=r,i.height=e.height=l,i.style.width=r+"px",i.style.height=l+"px",a.retinaScale(e,n.devicePixelRatio),!t)){var u={width:r,height:l};s.notify(e,"resize",[u]),e.options.onResize&&e.options.onResize(e,u),e.stop(),e.update(e.options.responsiveAnimationDuration)}},ensureScalesHaveIDs:function(){var t=this.options,e=t.scales||{},n=t.scale;a.each(e.xAxes,function(t,e){t.id=t.id||"x-axis-"+e}),a.each(e.yAxes,function(t,e){t.id=t.id||"y-axis-"+e}),n&&(n.id=n.id||"scale")},buildScales:function(){var e=this,n=e.options,i=e.scales={},o=[];n.scales&&(o=o.concat((n.scales.xAxes||[]).map(function(t){return{options:t,dtype:"category",dposition:"bottom"}}),(n.scales.yAxes||[]).map(function(t){return{options:t,dtype:"linear",dposition:"left"}}))),n.scale&&o.push({options:n.scale,dtype:"radialLinear",isDefault:!0,dposition:"chartArea"}),a.each(o,function(n){var o=n.options,r=a.valueOrDefault(o.type,n.dtype),s=t.scaleService.getScaleConstructor(r);if(s){l(o.position)!==l(n.dposition)&&(o.position=n.dposition);var u=new s({id:o.id,options:o,ctx:e.ctx,chart:e});i[u.id]=u,u.mergeTicksOptions(),n.isDefault&&(e.scale=u)}}),t.scaleService.addScalesToLayout(this)},buildOrUpdateControllers:function(){var e=this,n=[],i=[];return a.each(e.data.datasets,function(a,o){var r=e.getDatasetMeta(o),l=a.type||e.config.type;if(r.type&&r.type!==l&&(e.destroyDatasetMeta(o),r=e.getDatasetMeta(o)),r.type=l,n.push(r.type),r.controller)r.controller.updateIndex(o);else{var s=t.controllers[r.type];if(void 0===s)throw new Error('"'+r.type+'" is not a chart type.');r.controller=new s(e,o),i.push(r.controller)}},e),i},resetElements:function(){var t=this;a.each(t.data.datasets,function(e,n){t.getDatasetMeta(n).controller.reset()},t)},reset:function(){this.resetElements(),this.tooltip.initialize()},update:function(t){var e=this;if(t&&"object"==typeof t||(t={duration:t,lazy:arguments[1]}),n(e),!1!==s.notify(e,"beforeUpdate")){e.tooltip._data=e.data;var i=e.buildOrUpdateControllers();a.each(e.data.datasets,function(t,n){e.getDatasetMeta(n).controller.buildOrUpdateElements()},e),e.updateLayout(),a.each(i,function(t){t.reset()}),e.updateDatasets(),s.notify(e,"afterUpdate"),e._bufferedRender?e._bufferedRequest={duration:t.duration,easing:t.easing,lazy:t.lazy}:e.render(t)}},updateLayout:function(){var e=this;!1!==s.notify(e,"beforeLayout")&&(t.layoutService.update(this,this.width,this.height),s.notify(e,"afterScaleUpdate"),s.notify(e,"afterLayout"))},updateDatasets:function(){var t=this;if(!1!==s.notify(t,"beforeDatasetsUpdate")){for(var e=0,n=t.data.datasets.length;e<n;++e)t.updateDataset(e);s.notify(t,"afterDatasetsUpdate")}},updateDataset:function(t){var e=this,n=e.getDatasetMeta(t),i={meta:n,index:t};!1!==s.notify(e,"beforeDatasetUpdate",[i])&&(n.controller.update(),s.notify(e,"afterDatasetUpdate",[i]))},render:function(e){var n=this;e&&"object"==typeof e||(e={duration:e,lazy:arguments[1]});var i=e.duration,o=e.lazy;if(!1!==s.notify(n,"beforeRender")){var r=n.options.animation,l=function(t){s.notify(n,"afterRender"),a.callback(r&&r.onComplete,[t],n)};if(r&&(void 0!==i&&0!==i||void 0===i&&0!==r.duration)){var u=new t.Animation({numSteps:(i||r.duration)/16.66,easing:e.easing||r.easing,render:function(t,e){var n=a.easing.effects[e.easing],i=e.currentStep,o=i/e.numSteps;t.draw(n(o),o,i)},onAnimationProgress:r.onProgress,onAnimationComplete:l});t.animationService.addAnimation(n,u,i,o)}else n.draw(),l(new t.Animation({numSteps:0,chart:n}));return n}},draw:function(t){var e=this;e.clear(),a.isNullOrUndef(t)&&(t=1),e.transition(t),!1!==s.notify(e,"beforeDraw",[t])&&(a.each(e.boxes,function(t){t.draw(e.chartArea)},e),e.scale&&e.scale.draw(),e.drawDatasets(t),e.tooltip.draw(),s.notify(e,"afterDraw",[t]))},transition:function(t){for(var e=this,n=0,i=(e.data.datasets||[]).length;n<i;++n)e.isDatasetVisible(n)&&e.getDatasetMeta(n).controller.transition(t);e.tooltip.transition(t)},drawDatasets:function(t){var e=this;if(!1!==s.notify(e,"beforeDatasetsDraw",[t])){for(var n=(e.data.datasets||[]).length-1;n>=0;--n)e.isDatasetVisible(n)&&e.drawDataset(n,t);s.notify(e,"afterDatasetsDraw",[t])}},drawDataset:function(t,e){var n=this,i=n.getDatasetMeta(t),a={meta:i,index:t,easingValue:e};!1!==s.notify(n,"beforeDatasetDraw",[a])&&(i.controller.draw(e),s.notify(n,"afterDatasetDraw",[a]))},getElementAtEvent:function(t){return o.modes.single(this,t)},getElementsAtEvent:function(t){return o.modes.label(this,t,{intersect:!0})},getElementsAtXAxis:function(t){return o.modes["x-axis"](this,t,{intersect:!0})},getElementsAtEventForMode:function(t,e,n){var i=o.modes[e];return"function"==typeof i?i(this,t,n):[]},getDatasetAtEvent:function(t){return o.modes.dataset(this,t,{intersect:!0})},getDatasetMeta:function(t){var e=this,n=e.data.datasets[t];n._meta||(n._meta={});var i=n._meta[e.id];return i||(i=n._meta[e.id]={type:null,data:[],dataset:null,controller:null,hidden:null,xAxisID:null,yAxisID:null}),i},getVisibleDatasetCount:function(){for(var t=0,e=0,n=this.data.datasets.length;e<n;++e)this.isDatasetVisible(e)&&t++;return t},isDatasetVisible:function(t){var e=this.getDatasetMeta(t);return"boolean"==typeof e.hidden?!e.hidden:!this.data.datasets[t].hidden},generateLegend:function(){return this.options.legendCallback(this)},destroyDatasetMeta:function(t){var e=this.id,n=this.data.datasets[t],i=n._meta&&n._meta[e];i&&(i.controller.destroy(),delete n._meta[e])},destroy:function(){var e,n,i=this,o=i.canvas;for(i.stop(),e=0,n=i.data.datasets.length;e<n;++e)i.destroyDatasetMeta(e);o&&(i.unbindEvents(),a.canvas.clear(i),r.releaseContext(i.ctx),i.canvas=null,i.ctx=null),s.notify(i,"destroy"),delete t.instances[i.id]},toBase64Image:function(){return this.canvas.toDataURL.apply(this.canvas,arguments)},initToolTip:function(){var e=this;e.tooltip=new t.Tooltip({_chart:e,_chartInstance:e,_data:e.data,_options:e.options.tooltips},e)},bindEvents:function(){var t=this,e=t._listeners={},n=function(){t.eventHandler.apply(t,arguments)};a.each(t.options.events,function(i){r.addEventListener(t,i,n),e[i]=n}),t.options.responsive&&(n=function(){t.resize()},r.addEventListener(t,"resize",n),e.resize=n)},unbindEvents:function(){var t=this,e=t._listeners;e&&(delete t._listeners,a.each(e,function(e,n){r.removeEventListener(t,n,e)}))},updateHoverStyle:function(t,e,n){var i,a,o,r=n?"setHoverStyle":"removeHoverStyle";for(a=0,o=t.length;a<o;++a)(i=t[a])&&this.getDatasetMeta(i._datasetIndex).controller[r](i)},eventHandler:function(t){var e=this,n=e.tooltip;if(!1!==s.notify(e,"beforeEvent",[t])){e._bufferedRender=!0,e._bufferedRequest=null;var i=e.handleEvent(t);i|=n&&n.handleEvent(t),s.notify(e,"afterEvent",[t]);var a=e._bufferedRequest;return a?e.render(a):i&&!e.animating&&(e.stop(),e.render(e.options.hover.animationDuration,!0)),e._bufferedRender=!1,e._bufferedRequest=null,e}},handleEvent:function(t){var e=this,n=e.options||{},i=n.hover,o=!1;return e.lastActive=e.lastActive||[],"mouseout"===t.type?e.active=[]:e.active=e.getElementsAtEventForMode(t,i.mode,i),a.callback(n.onHover||n.hover.onHover,[t.native,e.active],e),"mouseup"!==t.type&&"click"!==t.type||n.onClick&&n.onClick.call(e,t.native,e.active),e.lastActive.length&&e.updateHoverStyle(e.lastActive,i.mode,!1),e.active.length&&i.mode&&e.updateHoverStyle(e.active,i.mode,!0),o=!a.arrayEquals(e.active,e.lastActive),e.lastActive=e.active,o}}),t.Controller=t}},{25:25,28:28,45:45,48:48}],24:[function(t,e,n){"use strict";var i=t(45);e.exports=function(t){function e(t,e){t._chartjs?t._chartjs.listeners.push(e):(Object.defineProperty(t,"_chartjs",{configurable:!0,enumerable:!1,value:{listeners:[e]}}),a.forEach(function(e){var n="onData"+e.charAt(0).toUpperCase()+e.slice(1),a=t[e];Object.defineProperty(t,e,{configurable:!0,enumerable:!1,value:function(){var e=Array.prototype.slice.call(arguments),o=a.apply(this,e);return i.each(t._chartjs.listeners,function(t){"function"==typeof t[n]&&t[n].apply(t,e)}),o}})}))}function n(t,e){var n=t._chartjs;if(n){var i=n.listeners,o=i.indexOf(e);-1!==o&&i.splice(o,1),i.length>0||(a.forEach(function(e){delete t[e]}),delete t._chartjs)}}var a=["push","pop","shift","splice","unshift"];t.DatasetController=function(t,e){this.initialize(t,e)},i.extend(t.DatasetController.prototype,{datasetElementType:null,dataElementType:null,initialize:function(t,e){var n=this;n.chart=t,n.index=e,n.linkScales(),n.addElements()},updateIndex:function(t){this.index=t},linkScales:function(){var t=this,e=t.getMeta(),n=t.getDataset();null===e.xAxisID&&(e.xAxisID=n.xAxisID||t.chart.options.scales.xAxes[0].id),null===e.yAxisID&&(e.yAxisID=n.yAxisID||t.chart.options.scales.yAxes[0].id)},getDataset:function(){return this.chart.data.datasets[this.index]},getMeta:function(){return this.chart.getDatasetMeta(this.index)},getScaleForId:function(t){return this.chart.scales[t]},reset:function(){this.update(!0)},destroy:function(){this._data&&n(this._data,this)},createMetaDataset:function(){var t=this,e=t.datasetElementType;return e&&new e({_chart:t.chart,_datasetIndex:t.index})},createMetaData:function(t){var e=this,n=e.dataElementType;return n&&new n({_chart:e.chart,_datasetIndex:e.index,_index:t})},addElements:function(){var t,e,n=this,i=n.getMeta(),a=n.getDataset().data||[],o=i.data;for(t=0,e=a.length;t<e;++t)o[t]=o[t]||n.createMetaData(t);i.dataset=i.dataset||n.createMetaDataset()},addElementAndReset:function(t){var e=this.createMetaData(t);this.getMeta().data.splice(t,0,e),this.updateElement(e,t,!0)},buildOrUpdateElements:function(){var t=this,i=t.getDataset(),a=i.data||(i.data=[]);t._data!==a&&(t._data&&n(t._data,t),e(a,t),t._data=a),t.resyncElements()},update:i.noop,transition:function(t){for(var e=this.getMeta(),n=e.data||[],i=n.length,a=0;a<i;++a)n[a].transition(t);e.dataset&&e.dataset.transition(t)},draw:function(){var t=this.getMeta(),e=t.data||[],n=e.length,i=0;for(t.dataset&&t.dataset.draw();i<n;++i)e[i].draw()},removeHoverStyle:function(t,e){var n=this.chart.data.datasets[t._datasetIndex],a=t._index,o=t.custom||{},r=i.valueAtIndexOrDefault,l=t._model;l.backgroundColor=o.backgroundColor?o.backgroundColor:r(n.backgroundColor,a,e.backgroundColor),l.borderColor=o.borderColor?o.borderColor:r(n.borderColor,a,e.borderColor),l.borderWidth=o.borderWidth?o.borderWidth:r(n.borderWidth,a,e.borderWidth)},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t._index,a=t.custom||{},o=i.valueAtIndexOrDefault,r=i.getHoverColor,l=t._model;l.backgroundColor=a.hoverBackgroundColor?a.hoverBackgroundColor:o(e.hoverBackgroundColor,n,r(l.backgroundColor)),l.borderColor=a.hoverBorderColor?a.hoverBorderColor:o(e.hoverBorderColor,n,r(l.borderColor)),l.borderWidth=a.hoverBorderWidth?a.hoverBorderWidth:o(e.hoverBorderWidth,n,l.borderWidth)},resyncElements:function(){var t=this,e=t.getMeta(),n=t.getDataset().data,i=e.data.length,a=n.length;a<i?e.data.splice(a,i-a):a>i&&t.insertElements(i,a-i)},insertElements:function(t,e){for(var n=0;n<e;++n)this.addElementAndReset(t+n)},onDataPush:function(){this.insertElements(this.getDataset().data.length-1,arguments.length)},onDataPop:function(){this.getMeta().data.pop()},onDataShift:function(){this.getMeta().data.shift()},onDataSplice:function(t,e){this.getMeta().data.splice(t,e),this.insertElements(t,arguments.length-2)},onDataUnshift:function(){this.insertElements(0,arguments.length)}}),t.DatasetController.extend=i.inherits}},{45:45}],25:[function(t,e,n){"use strict";var i=t(45);e.exports={_set:function(t,e){return i.merge(this[t]||(this[t]={}),e)}}},{45:45}],26:[function(t,e,n){"use strict";function i(t,e,n,i){var o,r,l,s,u,d,c,h,f,g=Object.keys(n);for(o=0,r=g.length;o<r;++o)if(l=g[o],d=n[l],e.hasOwnProperty(l)||(e[l]=d),(s=e[l])!==d&&"_"!==l[0]){if(t.hasOwnProperty(l)||(t[l]=s),u=t[l],(c=typeof d)===typeof u)if("string"===c){if((h=a(u)).valid&&(f=a(d)).valid){e[l]=f.mix(h,i).rgbString();continue}}else if("number"===c&&isFinite(u)&&isFinite(d)){e[l]=u+(d-u)*i;continue}e[l]=d}}var a=t(3),o=t(45),r=function(t){o.extend(this,t),this.initialize.apply(this,arguments)};o.extend(r.prototype,{initialize:function(){this.hidden=!1},pivot:function(){var t=this;return t._view||(t._view=o.clone(t._model)),t._start={},t},transition:function(t){var e=this,n=e._model,a=e._start,o=e._view;return n&&1!==t?(o||(o=e._view={}),a||(a=e._start={}),i(a,o,n,t),e):(e._view=n,e._start=null,e)},tooltipPosition:function(){return{x:this._model.x,y:this._model.y}},hasValue:function(){return o.isNumber(this._model.x)&&o.isNumber(this._model.y)}}),r.extend=o.inherits,e.exports=r},{3:3,45:45}],27:[function(t,e,n){"use strict";var i=t(3),a=t(25),o=t(45);e.exports=function(t){function e(t,e,n){var i;return"string"==typeof t?(i=parseInt(t,10),-1!==t.indexOf("%")&&(i=i/100*e.parentNode[n])):i=t,i}function n(t){return void 0!==t&&null!==t&&"none"!==t}function r(t,i,a){var o=document.defaultView,r=t.parentNode,l=o.getComputedStyle(t)[i],s=o.getComputedStyle(r)[i],u=n(l),d=n(s),c=Number.POSITIVE_INFINITY;return u||d?Math.min(u?e(l,t,a):c,d?e(s,r,a):c):"none"}o.extend=function(t){for(var e=1,n=arguments.length;e<n;e++)o.each(arguments[e],function(e,n){t[n]=e});return t},o.configMerge=function(){return o.merge(o.clone(arguments[0]),[].slice.call(arguments,1),{merger:function(e,n,i,a){var r=n[e]||{},l=i[e];"scales"===e?n[e]=o.scaleMerge(r,l):"scale"===e?n[e]=o.merge(r,[t.scaleService.getScaleDefaults(l.type),l]):o._merger(e,n,i,a)}})},o.scaleMerge=function(){return o.merge(o.clone(arguments[0]),[].slice.call(arguments,1),{merger:function(e,n,i,a){if("xAxes"===e||"yAxes"===e){var r,l,s,u=i[e].length;for(n[e]||(n[e]=[]),r=0;r<u;++r)s=i[e][r],l=o.valueOrDefault(s.type,"xAxes"===e?"category":"linear"),r>=n[e].length&&n[e].push({}),!n[e][r].type||s.type&&s.type!==n[e][r].type?o.merge(n[e][r],[t.scaleService.getScaleDefaults(l),s]):o.merge(n[e][r],s)}else o._merger(e,n,i,a)}})},o.where=function(t,e){if(o.isArray(t)&&Array.prototype.filter)return t.filter(e);var n=[];return o.each(t,function(t){e(t)&&n.push(t)}),n},o.findIndex=Array.prototype.findIndex?function(t,e,n){return t.findIndex(e,n)}:function(t,e,n){n=void 0===n?t:n;for(var i=0,a=t.length;i<a;++i)if(e.call(n,t[i],i,t))return i;return-1},o.findNextWhere=function(t,e,n){o.isNullOrUndef(n)&&(n=-1);for(var i=n+1;i<t.length;i++){var a=t[i];if(e(a))return a}},o.findPreviousWhere=function(t,e,n){o.isNullOrUndef(n)&&(n=t.length);for(var i=n-1;i>=0;i--){var a=t[i];if(e(a))return a}},o.inherits=function(t){var e=this,n=t&&t.hasOwnProperty("constructor")?t.constructor:function(){return e.apply(this,arguments)},i=function(){this.constructor=n};return i.prototype=e.prototype,n.prototype=new i,n.extend=o.inherits,t&&o.extend(n.prototype,t),n.__super__=e.prototype,n},o.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},o.almostEquals=function(t,e,n){return Math.abs(t-e)<n},o.almostWhole=function(t,e){var n=Math.round(t);return n-e<t&&n+e>t},o.max=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.max(t,e)},Number.NEGATIVE_INFINITY)},o.min=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.min(t,e)},Number.POSITIVE_INFINITY)},o.sign=Math.sign?function(t){return Math.sign(t)}:function(t){return 0==(t=+t)||isNaN(t)?t:t>0?1:-1},o.log10=Math.log10?function(t){return Math.log10(t)}:function(t){return Math.log(t)/Math.LN10},o.toRadians=function(t){return t*(Math.PI/180)},o.toDegrees=function(t){return t*(180/Math.PI)},o.getAngleFromPoint=function(t,e){var n=e.x-t.x,i=e.y-t.y,a=Math.sqrt(n*n+i*i),o=Math.atan2(i,n);return o<-.5*Math.PI&&(o+=2*Math.PI),{angle:o,distance:a}},o.distanceBetweenPoints=function(t,e){return Math.sqrt(Math.pow(e.x-t.x,2)+Math.pow(e.y-t.y,2))},o.aliasPixel=function(t){return t%2==0?0:.5},o.splineCurve=function(t,e,n,i){var a=t.skip?e:t,o=e,r=n.skip?e:n,l=Math.sqrt(Math.pow(o.x-a.x,2)+Math.pow(o.y-a.y,2)),s=Math.sqrt(Math.pow(r.x-o.x,2)+Math.pow(r.y-o.y,2)),u=l/(l+s),d=s/(l+s),c=i*(u=isNaN(u)?0:u),h=i*(d=isNaN(d)?0:d);return{previous:{x:o.x-c*(r.x-a.x),y:o.y-c*(r.y-a.y)},next:{x:o.x+h*(r.x-a.x),y:o.y+h*(r.y-a.y)}}},o.EPSILON=Number.EPSILON||1e-14,o.splineCurveMonotone=function(t){var e,n,i,a,r=(t||[]).map(function(t){return{model:t._model,deltaK:0,mK:0}}),l=r.length;for(e=0;e<l;++e)if(!(i=r[e]).model.skip){if(n=e>0?r[e-1]:null,(a=e<l-1?r[e+1]:null)&&!a.model.skip){var s=a.model.x-i.model.x;i.deltaK=0!==s?(a.model.y-i.model.y)/s:0}!n||n.model.skip?i.mK=i.deltaK:!a||a.model.skip?i.mK=n.deltaK:this.sign(n.deltaK)!==this.sign(i.deltaK)?i.mK=0:i.mK=(n.deltaK+i.deltaK)/2}var u,d,c,h;for(e=0;e<l-1;++e)i=r[e],a=r[e+1],i.model.skip||a.model.skip||(o.almostEquals(i.deltaK,0,this.EPSILON)?i.mK=a.mK=0:(u=i.mK/i.deltaK,d=a.mK/i.deltaK,(h=Math.pow(u,2)+Math.pow(d,2))<=9||(c=3/Math.sqrt(h),i.mK=u*c*i.deltaK,a.mK=d*c*i.deltaK)));var f;for(e=0;e<l;++e)(i=r[e]).model.skip||(n=e>0?r[e-1]:null,a=e<l-1?r[e+1]:null,n&&!n.model.skip&&(f=(i.model.x-n.model.x)/3,i.model.controlPointPreviousX=i.model.x-f,i.model.controlPointPreviousY=i.model.y-f*i.mK),a&&!a.model.skip&&(f=(a.model.x-i.model.x)/3,i.model.controlPointNextX=i.model.x+f,i.model.controlPointNextY=i.model.y+f*i.mK))},o.nextItem=function(t,e,n){return n?e>=t.length-1?t[0]:t[e+1]:e>=t.length-1?t[t.length-1]:t[e+1]},o.previousItem=function(t,e,n){return n?e<=0?t[t.length-1]:t[e-1]:e<=0?t[0]:t[e-1]},o.niceNum=function(t,e){var n=Math.floor(o.log10(t)),i=t/Math.pow(10,n);return(e?i<1.5?1:i<3?2:i<7?5:10:i<=1?1:i<=2?2:i<=5?5:10)*Math.pow(10,n)},o.requestAnimFrame="undefined"==typeof window?function(t){t()}:window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)},o.getRelativePosition=function(t,e){var n,i,a=t.originalEvent||t,r=t.currentTarget||t.srcElement,l=r.getBoundingClientRect(),s=a.touches;s&&s.length>0?(n=s[0].clientX,i=s[0].clientY):(n=a.clientX,i=a.clientY);var u=parseFloat(o.getStyle(r,"padding-left")),d=parseFloat(o.getStyle(r,"padding-top")),c=parseFloat(o.getStyle(r,"padding-right")),h=parseFloat(o.getStyle(r,"padding-bottom")),f=l.right-l.left-u-c,g=l.bottom-l.top-d-h;return n=Math.round((n-l.left-u)/f*r.width/e.currentDevicePixelRatio),i=Math.round((i-l.top-d)/g*r.height/e.currentDevicePixelRatio),{x:n,y:i}},o.getConstraintWidth=function(t){return r(t,"max-width","clientWidth")},o.getConstraintHeight=function(t){return r(t,"max-height","clientHeight")},o.getMaximumWidth=function(t){var e=t.parentNode;if(!e)return t.clientWidth;var n=parseInt(o.getStyle(e,"padding-left"),10),i=parseInt(o.getStyle(e,"padding-right"),10),a=e.clientWidth-n-i,r=o.getConstraintWidth(t);return isNaN(r)?a:Math.min(a,r)},o.getMaximumHeight=function(t){var e=t.parentNode;if(!e)return t.clientHeight;var n=parseInt(o.getStyle(e,"padding-top"),10),i=parseInt(o.getStyle(e,"padding-bottom"),10),a=e.clientHeight-n-i,r=o.getConstraintHeight(t);return isNaN(r)?a:Math.min(a,r)},o.getStyle=function(t,e){return t.currentStyle?t.currentStyle[e]:document.defaultView.getComputedStyle(t,null).getPropertyValue(e)},o.retinaScale=function(t,e){var n=t.currentDevicePixelRatio=e||window.devicePixelRatio||1;if(1!==n){var i=t.canvas,a=t.height,o=t.width;i.height=a*n,i.width=o*n,t.ctx.scale(n,n),i.style.height=a+"px",i.style.width=o+"px"}},o.fontString=function(t,e,n){return e+" "+t+"px "+n},o.longestText=function(t,e,n,i){var a=(i=i||{}).data=i.data||{},r=i.garbageCollect=i.garbageCollect||[];i.font!==e&&(a=i.data={},r=i.garbageCollect=[],i.font=e),t.font=e;var l=0;o.each(n,function(e){void 0!==e&&null!==e&&!0!==o.isArray(e)?l=o.measureText(t,a,r,l,e):o.isArray(e)&&o.each(e,function(e){void 0===e||null===e||o.isArray(e)||(l=o.measureText(t,a,r,l,e))})});var s=r.length/2;if(s>n.length){for(var u=0;u<s;u++)delete a[r[u]];r.splice(0,s)}return l},o.measureText=function(t,e,n,i,a){var o=e[a];return o||(o=e[a]=t.measureText(a).width,n.push(a)),o>i&&(i=o),i},o.numberOfLabelLines=function(t){var e=1;return o.each(t,function(t){o.isArray(t)&&t.length>e&&(e=t.length)}),e},o.color=i?function(t){return t instanceof CanvasGradient&&(t=a.global.defaultColor),i(t)}:function(t){return console.error("Color.js not found!"),t},o.getHoverColor=function(t){return t instanceof CanvasPattern?t:o.color(t).saturate(.5).darken(.1).rgbString()}}},{25:25,3:3,45:45}],28:[function(t,e,n){"use strict";function i(t,e){return t.native?{x:t.x,y:t.y}:u.getRelativePosition(t,e)}function a(t,e){var n,i,a,o,r;for(i=0,o=t.data.datasets.length;i<o;++i)if(t.isDatasetVisible(i))for(a=0,r=(n=t.getDatasetMeta(i)).data.length;a<r;++a){var l=n.data[a];l._view.skip||e(l)}}function o(t,e){var n=[];return a(t,function(t){t.inRange(e.x,e.y)&&n.push(t)}),n}function r(t,e,n,i){var o=Number.POSITIVE_INFINITY,r=[];return a(t,function(t){if(!n||t.inRange(e.x,e.y)){var a=t.getCenterPoint(),l=i(e,a);l<o?(r=[t],o=l):l===o&&r.push(t)}}),r}function l(t){var e=-1!==t.indexOf("x"),n=-1!==t.indexOf("y");return function(t,i){var a=e?Math.abs(t.x-i.x):0,o=n?Math.abs(t.y-i.y):0;return Math.sqrt(Math.pow(a,2)+Math.pow(o,2))}}function s(t,e,n){var a=i(e,t);n.axis=n.axis||"x";var s=l(n.axis),u=n.intersect?o(t,a):r(t,a,!1,s),d=[];return u.length?(t.data.datasets.forEach(function(e,n){if(t.isDatasetVisible(n)){var i=t.getDatasetMeta(n).data[u[0]._index];i&&!i._view.skip&&d.push(i)}}),d):[]}var u=t(45);e.exports={modes:{single:function(t,e){var n=i(e,t),o=[];return a(t,function(t){if(t.inRange(n.x,n.y))return o.push(t),o}),o.slice(0,1)},label:s,index:s,dataset:function(t,e,n){var a=i(e,t);n.axis=n.axis||"xy";var s=l(n.axis),u=n.intersect?o(t,a):r(t,a,!1,s);return u.length>0&&(u=t.getDatasetMeta(u[0]._datasetIndex).data),u},"x-axis":function(t,e){return s(t,e,{intersect:!1})},point:function(t,e){return o(t,i(e,t))},nearest:function(t,e,n){var a=i(e,t);n.axis=n.axis||"xy";var o=l(n.axis),s=r(t,a,n.intersect,o);return s.length>1&&s.sort(function(t,e){var n=t.getArea()-e.getArea();return 0===n&&(n=t._datasetIndex-e._datasetIndex),n}),s.slice(0,1)},x:function(t,e,n){var o=i(e,t),r=[],l=!1;return a(t,function(t){t.inXRange(o.x)&&r.push(t),t.inRange(o.x,o.y)&&(l=!0)}),n.intersect&&!l&&(r=[]),r},y:function(t,e,n){var o=i(e,t),r=[],l=!1;return a(t,function(t){t.inYRange(o.y)&&r.push(t),t.inRange(o.x,o.y)&&(l=!0)}),n.intersect&&!l&&(r=[]),r}}}},{45:45}],29:[function(t,e,n){"use strict";t(25)._set("global",{responsive:!0,responsiveAnimationDuration:0,maintainAspectRatio:!0,events:["mousemove","mouseout","click","touchstart","touchmove"],hover:{onHover:null,mode:"nearest",intersect:!0,animationDuration:400},onClick:null,defaultColor:"rgba(0,0,0,0.1)",defaultFontColor:"#666",defaultFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",defaultFontSize:12,defaultFontStyle:"normal",showLines:!0,elements:{},layout:{padding:{top:0,right:0,bottom:0,left:0}}}),e.exports=function(){var t=function(t,e){return this.construct(t,e),this};return t.Chart=t,t}},{25:25}],30:[function(t,e,n){"use strict";var i=t(45);e.exports=function(t){function e(t,e){return i.where(t,function(t){return t.position===e})}function n(t,e){t.forEach(function(t,e){return t._tmpIndex_=e,t}),t.sort(function(t,n){var i=e?n:t,a=e?t:n;return i.weight===a.weight?i._tmpIndex_-a._tmpIndex_:i.weight-a.weight}),t.forEach(function(t){delete t._tmpIndex_})}t.layoutService={defaults:{},addBox:function(t,e){t.boxes||(t.boxes=[]),e.fullWidth=e.fullWidth||!1,e.position=e.position||"top",e.weight=e.weight||0,t.boxes.push(e)},removeBox:function(t,e){var n=t.boxes?t.boxes.indexOf(e):-1;-1!==n&&t.boxes.splice(n,1)},configure:function(t,e,n){for(var i,a=["fullWidth","position","weight"],o=a.length,r=0;r<o;++r)i=a[r],n.hasOwnProperty(i)&&(e[i]=n[i])},update:function(t,a,o){function r(t){var e=i.findNextWhere(_,function(e){return e.box===t});if(e)if(t.isHorizontal()){var n={left:Math.max(F,D),right:Math.max(T,I),top:0,bottom:0};t.update(t.fullWidth?x:S,y/2,n)}else t.update(e.minSize.width,C)}function l(t){t.isHorizontal()?(t.left=t.fullWidth?d:F,t.right=t.fullWidth?a-c:F+S,t.top=V,t.bottom=V+t.height,V=t.bottom):(t.left=N,t.right=N+t.width,t.top=O,t.bottom=O+C,N=t.right)}if(t){var s=t.options.layout||{},u=i.options.toPadding(s.padding),d=u.left,c=u.right,h=u.top,f=u.bottom,g=e(t.boxes,"left"),p=e(t.boxes,"right"),v=e(t.boxes,"top"),m=e(t.boxes,"bottom"),b=e(t.boxes,"chartArea");n(g,!0),n(p,!1),n(v,!0),n(m,!1);var x=a-d-c,y=o-h-f,k=y/2,w=(a-x/2)/(g.length+p.length),M=(o-k)/(v.length+m.length),S=x,C=y,_=[];i.each(g.concat(p,v,m),function(t){var e,n=t.isHorizontal();n?(e=t.update(t.fullWidth?x:S,M),C-=e.height):(e=t.update(w,k),S-=e.width),_.push({horizontal:n,minSize:e,box:t})});var D=0,I=0,P=0,A=0;i.each(v.concat(m),function(t){if(t.getPadding){var e=t.getPadding();D=Math.max(D,e.left),I=Math.max(I,e.right)}}),i.each(g.concat(p),function(t){if(t.getPadding){var e=t.getPadding();P=Math.max(P,e.top),A=Math.max(A,e.bottom)}});var F=d,T=c,O=h,R=f;i.each(g.concat(p),r),i.each(g,function(t){F+=t.width}),i.each(p,function(t){T+=t.width}),i.each(v.concat(m),r),i.each(v,function(t){O+=t.height}),i.each(m,function(t){R+=t.height}),i.each(g.concat(p),function(t){var e=i.findNextWhere(_,function(e){return e.box===t}),n={left:0,right:0,top:O,bottom:R};e&&t.update(e.minSize.width,C,n)}),F=d,T=c,O=h,R=f,i.each(g,function(t){F+=t.width}),i.each(p,function(t){T+=t.width}),i.each(v,function(t){O+=t.height}),i.each(m,function(t){R+=t.height});var L=Math.max(D-F,0);F+=L,T+=Math.max(I-T,0);var z=Math.max(P-O,0);O+=z,R+=Math.max(A-R,0);var B=o-O-R,W=a-F-T;W===S&&B===C||(i.each(g,function(t){t.height=B}),i.each(p,function(t){t.height=B}),i.each(v,function(t){t.fullWidth||(t.width=W)}),i.each(m,function(t){t.fullWidth||(t.width=W)}),C=B,S=W);var N=d+L,V=h+z;i.each(g.concat(v),l),N+=S,V+=C,i.each(p,l),i.each(m,l),t.chartArea={left:F,top:O,right:F+S,bottom:O+C},i.each(b,function(e){e.left=t.chartArea.left,e.top=t.chartArea.top,e.right=t.chartArea.right,e.bottom=t.chartArea.bottom,e.update(S,C)})}}}}},{45:45}],31:[function(t,e,n){"use strict";var i=t(25),a=t(26),o=t(45);i._set("global",{plugins:{}}),e.exports=function(t){t.plugins={_plugins:[],_cacheId:0,register:function(t){var e=this._plugins;[].concat(t).forEach(function(t){-1===e.indexOf(t)&&e.push(t)}),this._cacheId++},unregister:function(t){var e=this._plugins;[].concat(t).forEach(function(t){var n=e.indexOf(t);-1!==n&&e.splice(n,1)}),this._cacheId++},clear:function(){this._plugins=[],this._cacheId++},count:function(){return this._plugins.length},getAll:function(){return this._plugins},notify:function(t,e,n){var i,a,o,r,l,s=this.descriptors(t),u=s.length;for(i=0;i<u;++i)if(a=s[i],o=a.plugin,"function"==typeof(l=o[e])&&((r=[t].concat(n||[])).push(a.options),!1===l.apply(o,r)))return!1;return!0},descriptors:function(t){var e=t._plugins||(t._plugins={});if(e.id===this._cacheId)return e.descriptors;var n=[],a=[],r=t&&t.config||{},l=r.options&&r.options.plugins||{};return this._plugins.concat(r.plugins||[]).forEach(function(t){if(-1===n.indexOf(t)){var e=t.id,r=l[e];!1!==r&&(!0===r&&(r=o.clone(i.global.plugins[e])),n.push(t),a.push({plugin:t,options:r||{}}))}}),e.descriptors=a,e.id=this._cacheId,a}},t.pluginService=t.plugins,t.PluginBase=a.extend({})}},{25:25,26:26,45:45}],32:[function(t,e,n){"use strict";function i(t){var e,n,i=[];for(e=0,n=t.length;e<n;++e)i.push(t[e].label);return i}function a(t,e,n){var i=t.getPixelForTick(e);return n&&(i-=0===e?(t.getPixelForTick(1)-i)/2:(i-t.getPixelForTick(e-1))/2),i}var o=t(25),r=t(26),l=t(45),s=t(34);o._set("scale",{display:!0,position:"left",offset:!1,gridLines:{display:!0,color:"rgba(0, 0, 0, 0.1)",lineWidth:1,drawBorder:!0,drawOnChartArea:!0,drawTicks:!0,tickMarkLength:10,zeroLineWidth:1,zeroLineColor:"rgba(0,0,0,0.25)",zeroLineBorderDash:[],zeroLineBorderDashOffset:0,offsetGridLines:!1,borderDash:[],borderDashOffset:0},scaleLabel:{display:!1,labelString:"",lineHeight:1.2,padding:{top:4,bottom:4}},ticks:{beginAtZero:!1,minRotation:0,maxRotation:50,mirror:!1,padding:0,reverse:!1,display:!0,autoSkip:!0,autoSkipPadding:0,labelOffset:0,callback:s.formatters.values,minor:{},major:{}}}),e.exports=function(t){function e(t,e,n){return l.isArray(e)?l.longestText(t,n,e):t.measureText(e).width}function n(t){var e=l.valueOrDefault,n=o.global,i=e(t.fontSize,n.defaultFontSize),a=e(t.fontStyle,n.defaultFontStyle),r=e(t.fontFamily,n.defaultFontFamily);return{size:i,style:a,family:r,font:l.fontString(i,a,r)}}function s(t){return l.options.toLineHeight(l.valueOrDefault(t.lineHeight,1.2),l.valueOrDefault(t.fontSize,o.global.defaultFontSize))}t.Scale=r.extend({getPadding:function(){var t=this;return{left:t.paddingLeft||0,top:t.paddingTop||0,right:t.paddingRight||0,bottom:t.paddingBottom||0}},getTicks:function(){return this._ticks},mergeTicksOptions:function(){var t=this.options.ticks;!1===t.minor&&(t.minor={display:!1}),!1===t.major&&(t.major={display:!1});for(var e in t)"major"!==e&&"minor"!==e&&(void 0===t.minor[e]&&(t.minor[e]=t[e]),void 0===t.major[e]&&(t.major[e]=t[e]))},beforeUpdate:function(){l.callback(this.options.beforeUpdate,[this])},update:function(t,e,n){var i,a,o,r,s,u,d=this;for(d.beforeUpdate(),d.maxWidth=t,d.maxHeight=e,d.margins=l.extend({left:0,right:0,top:0,bottom:0},n),d.longestTextCache=d.longestTextCache||{},d.beforeSetDimensions(),d.setDimensions(),d.afterSetDimensions(),d.beforeDataLimits(),d.determineDataLimits(),d.afterDataLimits(),d.beforeBuildTicks(),s=d.buildTicks()||[],d.afterBuildTicks(),d.beforeTickToLabelConversion(),o=d.convertTicksToLabels(s)||d.ticks,d.afterTickToLabelConversion(),d.ticks=o,i=0,a=o.length;i<a;++i)r=o[i],(u=s[i])?u.label=r:s.push(u={label:r,major:!1});return d._ticks=s,d.beforeCalculateTickRotation(),d.calculateTickRotation(),d.afterCalculateTickRotation(),d.beforeFit(),d.fit(),d.afterFit(),d.afterUpdate(),d.minSize},afterUpdate:function(){l.callback(this.options.afterUpdate,[this])},beforeSetDimensions:function(){l.callback(this.options.beforeSetDimensions,[this])},setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0},afterSetDimensions:function(){l.callback(this.options.afterSetDimensions,[this])},beforeDataLimits:function(){l.callback(this.options.beforeDataLimits,[this])},determineDataLimits:l.noop,afterDataLimits:function(){l.callback(this.options.afterDataLimits,[this])},beforeBuildTicks:function(){l.callback(this.options.beforeBuildTicks,[this])},buildTicks:l.noop,afterBuildTicks:function(){l.callback(this.options.afterBuildTicks,[this])},beforeTickToLabelConversion:function(){l.callback(this.options.beforeTickToLabelConversion,[this])},convertTicksToLabels:function(){var t=this,e=t.options.ticks;t.ticks=t.ticks.map(e.userCallback||e.callback,this)},afterTickToLabelConversion:function(){l.callback(this.options.afterTickToLabelConversion,[this])},beforeCalculateTickRotation:function(){l.callback(this.options.beforeCalculateTickRotation,[this])},calculateTickRotation:function(){var t=this,e=t.ctx,a=t.options.ticks,o=i(t._ticks),r=n(a);e.font=r.font;var s=a.minRotation||0;if(o.length&&t.options.display&&t.isHorizontal())for(var u,d=l.longestText(e,r.font,o,t.longestTextCache),c=d,h=t.getPixelForTick(1)-t.getPixelForTick(0)-6;c>h&&s<a.maxRotation;){var f=l.toRadians(s);if(u=Math.cos(f),Math.sin(f)*d>t.maxHeight){s--;break}s++,c=u*d}t.labelRotation=s},afterCalculateTickRotation:function(){l.callback(this.options.afterCalculateTickRotation,[this])},beforeFit:function(){l.callback(this.options.beforeFit,[this])},fit:function(){var t=this,a=t.minSize={width:0,height:0},o=i(t._ticks),r=t.options,u=r.ticks,d=r.scaleLabel,c=r.gridLines,h=r.display,f=t.isHorizontal(),g=n(u),p=r.gridLines.tickMarkLength;if(a.width=f?t.isFullWidth()?t.maxWidth-t.margins.left-t.margins.right:t.maxWidth:h&&c.drawTicks?p:0,a.height=f?h&&c.drawTicks?p:0:t.maxHeight,d.display&&h){var v=s(d)+l.options.toPadding(d.padding).height;f?a.height+=v:a.width+=v}if(u.display&&h){var m=l.longestText(t.ctx,g.font,o,t.longestTextCache),b=l.numberOfLabelLines(o),x=.5*g.size,y=t.options.ticks.padding;if(f){t.longestLabelWidth=m;var k=l.toRadians(t.labelRotation),w=Math.cos(k),M=Math.sin(k)*m+g.size*b+x*(b-1)+x;a.height=Math.min(t.maxHeight,a.height+M+y),t.ctx.font=g.font;var S=e(t.ctx,o[0],g.font),C=e(t.ctx,o[o.length-1],g.font);0!==t.labelRotation?(t.paddingLeft="bottom"===r.position?w*S+3:w*x+3,t.paddingRight="bottom"===r.position?w*x+3:w*C+3):(t.paddingLeft=S/2+3,t.paddingRight=C/2+3)}else u.mirror?m=0:m+=y+x,a.width=Math.min(t.maxWidth,a.width+m),t.paddingTop=g.size/2,t.paddingBottom=g.size/2}t.handleMargins(),t.width=a.width,t.height=a.height},handleMargins:function(){var t=this;t.margins&&(t.paddingLeft=Math.max(t.paddingLeft-t.margins.left,0),t.paddingTop=Math.max(t.paddingTop-t.margins.top,0),t.paddingRight=Math.max(t.paddingRight-t.margins.right,0),t.paddingBottom=Math.max(t.paddingBottom-t.margins.bottom,0))},afterFit:function(){l.callback(this.options.afterFit,[this])},isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},isFullWidth:function(){return this.options.fullWidth},getRightValue:function(t){if(l.isNullOrUndef(t))return NaN;if("number"==typeof t&&!isFinite(t))return NaN;if(t)if(this.isHorizontal()){if(void 0!==t.x)return this.getRightValue(t.x)}else if(void 0!==t.y)return this.getRightValue(t.y);return t},getLabelForIndex:l.noop,getPixelForValue:l.noop,getValueForPixel:l.noop,getPixelForTick:function(t){var e=this,n=e.options.offset;if(e.isHorizontal()){var i=(e.width-(e.paddingLeft+e.paddingRight))/Math.max(e._ticks.length-(n?0:1),1),a=i*t+e.paddingLeft;n&&(a+=i/2);var o=e.left+Math.round(a);return o+=e.isFullWidth()?e.margins.left:0}var r=e.height-(e.paddingTop+e.paddingBottom);return e.top+t*(r/(e._ticks.length-1))},getPixelForDecimal:function(t){var e=this;if(e.isHorizontal()){var n=(e.width-(e.paddingLeft+e.paddingRight))*t+e.paddingLeft,i=e.left+Math.round(n);return i+=e.isFullWidth()?e.margins.left:0}return e.top+t*e.height},getBasePixel:function(){return this.getPixelForValue(this.getBaseValue())},getBaseValue:function(){var t=this,e=t.min,n=t.max;return t.beginAtZero?0:e<0&&n<0?n:e>0&&n>0?e:0},_autoSkip:function(t){var e,n,i,a,o=this,r=o.isHorizontal(),s=o.options.ticks.minor,u=t.length,d=l.toRadians(o.labelRotation),c=Math.cos(d),h=o.longestLabelWidth*c,f=[];for(s.maxTicksLimit&&(a=s.maxTicksLimit),r&&(e=!1,(h+s.autoSkipPadding)*u>o.width-(o.paddingLeft+o.paddingRight)&&(e=1+Math.floor((h+s.autoSkipPadding)*u/(o.width-(o.paddingLeft+o.paddingRight)))),a&&u>a&&(e=Math.max(e,Math.floor(u/a)))),n=0;n<u;n++)i=t[n],(e>1&&n%e>0||n%e==0&&n+e>=u)&&n!==u-1&&delete i.label,f.push(i);return f},draw:function(t){var e=this,i=e.options;if(i.display){var r=e.ctx,u=o.global,d=i.ticks.minor,c=i.ticks.major||d,h=i.gridLines,f=i.scaleLabel,g=0!==e.labelRotation,p=e.isHorizontal(),v=d.autoSkip?e._autoSkip(e.getTicks()):e.getTicks(),m=l.valueOrDefault(d.fontColor,u.defaultFontColor),b=n(d),x=l.valueOrDefault(c.fontColor,u.defaultFontColor),y=n(c),k=h.drawTicks?h.tickMarkLength:0,w=l.valueOrDefault(f.fontColor,u.defaultFontColor),M=n(f),S=l.options.toPadding(f.padding),C=l.toRadians(e.labelRotation),_=[],D="right"===i.position?e.left:e.right-k,I="right"===i.position?e.left+k:e.right,P="bottom"===i.position?e.top:e.bottom-k,A="bottom"===i.position?e.top+k:e.bottom;if(l.each(v,function(n,o){if(!l.isNullOrUndef(n.label)){var r,s,c,f,m=n.label;o===e.zeroLineIndex&&i.offset===h.offsetGridLines?(r=h.zeroLineWidth,s=h.zeroLineColor,c=h.zeroLineBorderDash,f=h.zeroLineBorderDashOffset):(r=l.valueAtIndexOrDefault(h.lineWidth,o),s=l.valueAtIndexOrDefault(h.color,o),c=l.valueOrDefault(h.borderDash,u.borderDash),f=l.valueOrDefault(h.borderDashOffset,u.borderDashOffset));var b,x,y,w,M,S,F,T,O,R,L="middle",z="middle",B=d.padding;if(p){var W=k+B;"bottom"===i.position?(z=g?"middle":"top",L=g?"right":"center",R=e.top+W):(z=g?"middle":"bottom",L=g?"left":"center",R=e.bottom-W);var N=a(e,o,h.offsetGridLines&&v.length>1);N<e.left&&(s="rgba(0,0,0,0)"),N+=l.aliasPixel(r),O=e.getPixelForTick(o)+d.labelOffset,b=y=M=F=N,x=P,w=A,S=t.top,T=t.bottom}else{var V,E="left"===i.position;d.mirror?(L=E?"left":"right",V=B):(L=E?"right":"left",V=k+B),O=E?e.right-V:e.left+V;var H=a(e,o,h.offsetGridLines&&v.length>1);H<e.top&&(s="rgba(0,0,0,0)"),H+=l.aliasPixel(r),R=e.getPixelForTick(o)+d.labelOffset,b=D,y=I,M=t.left,F=t.right,x=w=S=T=H}_.push({tx1:b,ty1:x,tx2:y,ty2:w,x1:M,y1:S,x2:F,y2:T,labelX:O,labelY:R,glWidth:r,glColor:s,glBorderDash:c,glBorderDashOffset:f,rotation:-1*C,label:m,major:n.major,textBaseline:z,textAlign:L})}}),l.each(_,function(t){if(h.display&&(r.save(),r.lineWidth=t.glWidth,r.strokeStyle=t.glColor,r.setLineDash&&(r.setLineDash(t.glBorderDash),r.lineDashOffset=t.glBorderDashOffset),r.beginPath(),h.drawTicks&&(r.moveTo(t.tx1,t.ty1),r.lineTo(t.tx2,t.ty2)),h.drawOnChartArea&&(r.moveTo(t.x1,t.y1),r.lineTo(t.x2,t.y2)),r.stroke(),r.restore()),d.display){r.save(),r.translate(t.labelX,t.labelY),r.rotate(t.rotation),r.font=t.major?y.font:b.font,r.fillStyle=t.major?x:m,r.textBaseline=t.textBaseline,r.textAlign=t.textAlign;var e=t.label;if(l.isArray(e))for(var n=0,i=0;n<e.length;++n)r.fillText(""+e[n],0,i),i+=1.5*b.size;else r.fillText(e,0,0);r.restore()}}),f.display){var F,T,O=0,R=s(f)/2;if(p)F=e.left+(e.right-e.left)/2,T="bottom"===i.position?e.bottom-R-S.bottom:e.top+R+S.top;else{var L="left"===i.position;F=L?e.left+R+S.top:e.right-R-S.top,T=e.top+(e.bottom-e.top)/2,O=L?-.5*Math.PI:.5*Math.PI}r.save(),r.translate(F,T),r.rotate(O),r.textAlign="center",r.textBaseline="middle",r.fillStyle=w,r.font=M.font,r.fillText(f.labelString,0,0),r.restore()}if(h.drawBorder){r.lineWidth=l.valueAtIndexOrDefault(h.lineWidth,0),r.strokeStyle=l.valueAtIndexOrDefault(h.color,0);var z=e.left,B=e.right,W=e.top,N=e.bottom,V=l.aliasPixel(r.lineWidth);p?(W=N="top"===i.position?e.bottom:e.top,W+=V,N+=V):(z=B="left"===i.position?e.right:e.left,z+=V,B+=V),r.beginPath(),r.moveTo(z,W),r.lineTo(B,N),r.stroke()}}}})}},{25:25,26:26,34:34,45:45}],33:[function(t,e,n){"use strict";var i=t(25),a=t(45);e.exports=function(t){t.scaleService={constructors:{},defaults:{},registerScaleType:function(t,e,n){this.constructors[t]=e,this.defaults[t]=a.clone(n)},getScaleConstructor:function(t){return this.constructors.hasOwnProperty(t)?this.constructors[t]:void 0},getScaleDefaults:function(t){return this.defaults.hasOwnProperty(t)?a.merge({},[i.scale,this.defaults[t]]):{}},updateScaleDefaults:function(t,e){var n=this;n.defaults.hasOwnProperty(t)&&(n.defaults[t]=a.extend(n.defaults[t],e))},addScalesToLayout:function(e){a.each(e.scales,function(n){n.fullWidth=n.options.fullWidth,n.position=n.options.position,n.weight=n.options.weight,t.layoutService.addBox(e,n)})}}}},{25:25,45:45}],34:[function(t,e,n){"use strict";var i=t(45);e.exports={generators:{linear:function(t,e){var n,a=[];if(t.stepSize&&t.stepSize>0)n=t.stepSize;else{var o=i.niceNum(e.max-e.min,!1);n=i.niceNum(o/(t.maxTicks-1),!0)}var r=Math.floor(e.min/n)*n,l=Math.ceil(e.max/n)*n;t.min&&t.max&&t.stepSize&&i.almostWhole((t.max-t.min)/t.stepSize,n/1e3)&&(r=t.min,l=t.max);var s=(l-r)/n;s=i.almostEquals(s,Math.round(s),n/1e3)?Math.round(s):Math.ceil(s),a.push(void 0!==t.min?t.min:r);for(var u=1;u<s;++u)a.push(r+u*n);return a.push(void 0!==t.max?t.max:l),a},logarithmic:function(t,e){var n,a,o=[],r=i.valueOrDefault,l=r(t.min,Math.pow(10,Math.floor(i.log10(e.min)))),s=Math.floor(i.log10(e.max)),u=Math.ceil(e.max/Math.pow(10,s));0===l?(n=Math.floor(i.log10(e.minNotZero)),a=Math.floor(e.minNotZero/Math.pow(10,n)),o.push(l),l=a*Math.pow(10,n)):(n=Math.floor(i.log10(l)),a=Math.floor(l/Math.pow(10,n)));do{o.push(l),10===++a&&(a=1,++n),l=a*Math.pow(10,n)}while(n<s||n===s&&a<u);var d=r(t.max,l);return o.push(d),o}},formatters:{values:function(t){return i.isArray(t)?t:""+t},linear:function(t,e,n){var a=n.length>3?n[2]-n[1]:n[1]-n[0];Math.abs(a)>1&&t!==Math.floor(t)&&(a=t-Math.floor(t));var o=i.log10(Math.abs(a)),r="";if(0!==t){var l=-1*Math.floor(o);l=Math.max(Math.min(l,20),0),r=t.toFixed(l)}else r="0";return r},logarithmic:function(t,e,n){var a=t/Math.pow(10,Math.floor(i.log10(t)));return 0===t?"0":1===a||2===a||5===a||0===e||e===n.length-1?t.toExponential():""}}}},{45:45}],35:[function(t,e,n){"use strict";var i=t(25),a=t(26),o=t(45);i._set("global",{tooltips:{enabled:!0,custom:null,mode:"nearest",position:"average",intersect:!0,backgroundColor:"rgba(0,0,0,0.8)",titleFontStyle:"bold",titleSpacing:2,titleMarginBottom:6,titleFontColor:"#fff",titleAlign:"left",bodySpacing:2,bodyFontColor:"#fff",bodyAlign:"left",footerFontStyle:"bold",footerSpacing:2,footerMarginTop:6,footerFontColor:"#fff",footerAlign:"left",yPadding:6,xPadding:6,caretPadding:2,caretSize:5,cornerRadius:6,multiKeyBackground:"#fff",displayColors:!0,borderColor:"rgba(0,0,0,0)",borderWidth:0,callbacks:{beforeTitle:o.noop,title:function(t,e){var n="",i=e.labels,a=i?i.length:0;if(t.length>0){var o=t[0];o.xLabel?n=o.xLabel:a>0&&o.index<a&&(n=i[o.index])}return n},afterTitle:o.noop,beforeBody:o.noop,beforeLabel:o.noop,label:function(t,e){var n=e.datasets[t.datasetIndex].label||"";return n&&(n+=": "),n+=t.yLabel},labelColor:function(t,e){var n=e.getDatasetMeta(t.datasetIndex).data[t.index]._view;return{borderColor:n.borderColor,backgroundColor:n.backgroundColor}},labelTextColor:function(){return this._options.bodyFontColor},afterLabel:o.noop,afterBody:o.noop,beforeFooter:o.noop,footer:o.noop,afterFooter:o.noop}}}),e.exports=function(t){function e(t,e){var n=o.color(t);return n.alpha(e*n.alpha()).rgbaString()}function n(t,e){return e&&(o.isArray(e)?Array.prototype.push.apply(t,e):t.push(e)),t}function r(t){var e=t._xScale,n=t._yScale||t._scale,i=t._index,a=t._datasetIndex;return{xLabel:e?e.getLabelForIndex(i,a):"",yLabel:n?n.getLabelForIndex(i,a):"",index:i,datasetIndex:a,x:t._model.x,y:t._model.y}}function l(t){var e=i.global,n=o.valueOrDefault;return{xPadding:t.xPadding,yPadding:t.yPadding,xAlign:t.xAlign,yAlign:t.yAlign,bodyFontColor:t.bodyFontColor,_bodyFontFamily:n(t.bodyFontFamily,e.defaultFontFamily),_bodyFontStyle:n(t.bodyFontStyle,e.defaultFontStyle),_bodyAlign:t.bodyAlign,bodyFontSize:n(t.bodyFontSize,e.defaultFontSize),bodySpacing:t.bodySpacing,titleFontColor:t.titleFontColor,_titleFontFamily:n(t.titleFontFamily,e.defaultFontFamily),_titleFontStyle:n(t.titleFontStyle,e.defaultFontStyle),titleFontSize:n(t.titleFontSize,e.defaultFontSize),_titleAlign:t.titleAlign,titleSpacing:t.titleSpacing,titleMarginBottom:t.titleMarginBottom,footerFontColor:t.footerFontColor,_footerFontFamily:n(t.footerFontFamily,e.defaultFontFamily),_footerFontStyle:n(t.footerFontStyle,e.defaultFontStyle),footerFontSize:n(t.footerFontSize,e.defaultFontSize),_footerAlign:t.footerAlign,footerSpacing:t.footerSpacing,footerMarginTop:t.footerMarginTop,caretSize:t.caretSize,cornerRadius:t.cornerRadius,backgroundColor:t.backgroundColor,opacity:0,legendColorBackground:t.multiKeyBackground,displayColors:t.displayColors,borderColor:t.borderColor,borderWidth:t.borderWidth}}function s(t,e){var n=t._chart.ctx,i=2*e.yPadding,a=0,r=e.body,l=r.reduce(function(t,e){return t+e.before.length+e.lines.length+e.after.length},0);l+=e.beforeBody.length+e.afterBody.length;var s=e.title.length,u=e.footer.length,d=e.titleFontSize,c=e.bodyFontSize,h=e.footerFontSize;i+=s*d,i+=s?(s-1)*e.titleSpacing:0,i+=s?e.titleMarginBottom:0,i+=l*c,i+=l?(l-1)*e.bodySpacing:0,i+=u?e.footerMarginTop:0,i+=u*h,i+=u?(u-1)*e.footerSpacing:0;var f=0,g=function(t){a=Math.max(a,n.measureText(t).width+f)};return n.font=o.fontString(d,e._titleFontStyle,e._titleFontFamily),o.each(e.title,g),n.font=o.fontString(c,e._bodyFontStyle,e._bodyFontFamily),o.each(e.beforeBody.concat(e.afterBody),g),f=e.displayColors?c+2:0,o.each(r,function(t){o.each(t.before,g),o.each(t.lines,g),o.each(t.after,g)}),f=0,n.font=o.fontString(h,e._footerFontStyle,e._footerFontFamily),o.each(e.footer,g),a+=2*e.xPadding,{width:a,height:i}}function u(t,e){var n=t._model,i=t._chart,a=t._chart.chartArea,o="center",r="center";n.y<e.height?r="top":n.y>i.height-e.height&&(r="bottom");var l,s,u,d,c,h=(a.left+a.right)/2,f=(a.top+a.bottom)/2;"center"===r?(l=function(t){return t<=h},s=function(t){return t>h}):(l=function(t){return t<=e.width/2},s=function(t){return t>=i.width-e.width/2}),u=function(t){return t+e.width>i.width},d=function(t){return t-e.width<0},c=function(t){return t<=f?"top":"bottom"},l(n.x)?(o="left",u(n.x)&&(o="center",r=c(n.y))):s(n.x)&&(o="right",d(n.x)&&(o="center",r=c(n.y)));var g=t._options;return{xAlign:g.xAlign?g.xAlign:o,yAlign:g.yAlign?g.yAlign:r}}function d(t,e,n){var i=t.x,a=t.y,o=t.caretSize,r=t.caretPadding,l=t.cornerRadius,s=n.xAlign,u=n.yAlign,d=o+r,c=l+r;return"right"===s?i-=e.width:"center"===s&&(i-=e.width/2),"top"===u?a+=d:a-="bottom"===u?e.height+d:e.height/2,"center"===u?"left"===s?i+=d:"right"===s&&(i-=d):"left"===s?i-=c:"right"===s&&(i+=c),{x:i,y:a}}t.Tooltip=a.extend({initialize:function(){this._model=l(this._options)},getTitle:function(){var t=this,e=t._options.callbacks,i=e.beforeTitle.apply(t,arguments),a=e.title.apply(t,arguments),o=e.afterTitle.apply(t,arguments),r=[];return r=n(r,i),r=n(r,a),r=n(r,o)},getBeforeBody:function(){var t=this._options.callbacks.beforeBody.apply(this,arguments);return o.isArray(t)?t:void 0!==t?[t]:[]},getBody:function(t,e){var i=this,a=i._options.callbacks,r=[];return o.each(t,function(t){var o={before:[],lines:[],after:[]};n(o.before,a.beforeLabel.call(i,t,e)),n(o.lines,a.label.call(i,t,e)),n(o.after,a.afterLabel.call(i,t,e)),r.push(o)}),r},getAfterBody:function(){var t=this._options.callbacks.afterBody.apply(this,arguments);return o.isArray(t)?t:void 0!==t?[t]:[]},getFooter:function(){var t=this,e=t._options.callbacks,i=e.beforeFooter.apply(t,arguments),a=e.footer.apply(t,arguments),o=e.afterFooter.apply(t,arguments),r=[];return r=n(r,i),r=n(r,a),r=n(r,o)},update:function(e){var n,i,a=this,c=a._options,h=a._model,f=a._model=l(c),g=a._active,p=a._data,v={xAlign:h.xAlign,yAlign:h.yAlign},m={x:h.x,y:h.y},b={width:h.width,height:h.height},x={x:h.caretX,y:h.caretY};if(g.length){f.opacity=1;var y=[],k=[];x=t.Tooltip.positioners[c.position](g,a._eventPosition);var w=[];for(n=0,i=g.length;n<i;++n)w.push(r(g[n]));c.filter&&(w=w.filter(function(t){return c.filter(t,p)})),c.itemSort&&(w=w.sort(function(t,e){return c.itemSort(t,e,p)})),o.each(w,function(t){y.push(c.callbacks.labelColor.call(a,t,a._chart)),k.push(c.callbacks.labelTextColor.call(a,t,a._chart))}),f.title=a.getTitle(w,p),f.beforeBody=a.getBeforeBody(w,p),f.body=a.getBody(w,p),f.afterBody=a.getAfterBody(w,p),f.footer=a.getFooter(w,p),f.x=Math.round(x.x),f.y=Math.round(x.y),f.caretPadding=c.caretPadding,f.labelColors=y,f.labelTextColors=k,f.dataPoints=w,m=d(f,b=s(this,f),v=u(this,b))}else f.opacity=0;return f.xAlign=v.xAlign,f.yAlign=v.yAlign,f.x=m.x,f.y=m.y,f.width=b.width,f.height=b.height,f.caretX=x.x,f.caretY=x.y,a._model=f,e&&c.custom&&c.custom.call(a,f),a},drawCaret:function(t,e){var n=this._chart.ctx,i=this._view,a=this.getCaretPosition(t,e,i);n.lineTo(a.x1,a.y1),n.lineTo(a.x2,a.y2),n.lineTo(a.x3,a.y3)},getCaretPosition:function(t,e,n){var i,a,o,r,l,s,u=n.caretSize,d=n.cornerRadius,c=n.xAlign,h=n.yAlign,f=t.x,g=t.y,p=e.width,v=e.height;if("center"===h)l=g+v/2,"left"===c?(a=(i=f)-u,o=i,r=l+u,s=l-u):(a=(i=f+p)+u,o=i,r=l-u,s=l+u);else if("left"===c?(i=(a=f+d+u)-u,o=a+u):"right"===c?(i=(a=f+p-d-u)-u,o=a+u):(i=(a=f+p/2)-u,o=a+u),"top"===h)l=(r=g)-u,s=r;else{l=(r=g+v)+u,s=r;var m=o;o=i,i=m}return{x1:i,x2:a,x3:o,y1:r,y2:l,y3:s}},drawTitle:function(t,n,i,a){var r=n.title;if(r.length){i.textAlign=n._titleAlign,i.textBaseline="top";var l=n.titleFontSize,s=n.titleSpacing;i.fillStyle=e(n.titleFontColor,a),i.font=o.fontString(l,n._titleFontStyle,n._titleFontFamily);var u,d;for(u=0,d=r.length;u<d;++u)i.fillText(r[u],t.x,t.y),t.y+=l+s,u+1===r.length&&(t.y+=n.titleMarginBottom-s)}},drawBody:function(t,n,i,a){var r=n.bodyFontSize,l=n.bodySpacing,s=n.body;i.textAlign=n._bodyAlign,i.textBaseline="top",i.font=o.fontString(r,n._bodyFontStyle,n._bodyFontFamily);var u=0,d=function(e){i.fillText(e,t.x+u,t.y),t.y+=r+l};i.fillStyle=e(n.bodyFontColor,a),o.each(n.beforeBody,d);var c=n.displayColors;u=c?r+2:0,o.each(s,function(l,s){var u=e(n.labelTextColors[s],a);i.fillStyle=u,o.each(l.before,d),o.each(l.lines,function(o){c&&(i.fillStyle=e(n.legendColorBackground,a),i.fillRect(t.x,t.y,r,r),i.lineWidth=1,i.strokeStyle=e(n.labelColors[s].borderColor,a),i.strokeRect(t.x,t.y,r,r),i.fillStyle=e(n.labelColors[s].backgroundColor,a),i.fillRect(t.x+1,t.y+1,r-2,r-2),i.fillStyle=u),d(o)}),o.each(l.after,d)}),u=0,o.each(n.afterBody,d),t.y-=l},drawFooter:function(t,n,i,a){var r=n.footer;r.length&&(t.y+=n.footerMarginTop,i.textAlign=n._footerAlign,i.textBaseline="top",i.fillStyle=e(n.footerFontColor,a),i.font=o.fontString(n.footerFontSize,n._footerFontStyle,n._footerFontFamily),o.each(r,function(e){i.fillText(e,t.x,t.y),t.y+=n.footerFontSize+n.footerSpacing}))},drawBackground:function(t,n,i,a,o){i.fillStyle=e(n.backgroundColor,o),i.strokeStyle=e(n.borderColor,o),i.lineWidth=n.borderWidth;var r=n.xAlign,l=n.yAlign,s=t.x,u=t.y,d=a.width,c=a.height,h=n.cornerRadius;i.beginPath(),i.moveTo(s+h,u),"top"===l&&this.drawCaret(t,a),i.lineTo(s+d-h,u),i.quadraticCurveTo(s+d,u,s+d,u+h),"center"===l&&"right"===r&&this.drawCaret(t,a),i.lineTo(s+d,u+c-h),i.quadraticCurveTo(s+d,u+c,s+d-h,u+c),"bottom"===l&&this.drawCaret(t,a),i.lineTo(s+h,u+c),i.quadraticCurveTo(s,u+c,s,u+c-h),"center"===l&&"left"===r&&this.drawCaret(t,a),i.lineTo(s,u+h),i.quadraticCurveTo(s,u,s+h,u),i.closePath(),i.fill(),n.borderWidth>0&&i.stroke()},draw:function(){var t=this._chart.ctx,e=this._view;if(0!==e.opacity){var n={width:e.width,height:e.height},i={x:e.x,y:e.y},a=Math.abs(e.opacity<.001)?0:e.opacity,o=e.title.length||e.beforeBody.length||e.body.length||e.afterBody.length||e.footer.length;this._options.enabled&&o&&(this.drawBackground(i,e,t,n,a),i.x+=e.xPadding,i.y+=e.yPadding,this.drawTitle(i,e,t,a),this.drawBody(i,e,t,a),this.drawFooter(i,e,t,a))}},handleEvent:function(t){var e=this,n=e._options,i=!1;if(e._lastActive=e._lastActive||[],"mouseout"===t.type?e._active=[]:e._active=e._chart.getElementsAtEventForMode(t,n.mode,n),!(i=!o.arrayEquals(e._active,e._lastActive)))return!1;if(e._lastActive=e._active,n.enabled||n.custom){e._eventPosition={x:t.x,y:t.y};var a=e._model;e.update(!0),e.pivot(),i|=a.x!==e._model.x||a.y!==e._model.y}return i}}),t.Tooltip.positioners={average:function(t){if(!t.length)return!1;var e,n,i=0,a=0,o=0;for(e=0,n=t.length;e<n;++e){var r=t[e];if(r&&r.hasValue()){var l=r.tooltipPosition();i+=l.x,a+=l.y,++o}}return{x:Math.round(i/o),y:Math.round(a/o)}},nearest:function(t,e){var n,i,a,r=e.x,l=e.y,s=Number.POSITIVE_INFINITY;for(n=0,i=t.length;n<i;++n){var u=t[n];if(u&&u.hasValue()){var d=u.getCenterPoint(),c=o.distanceBetweenPoints(e,d);c<s&&(s=c,a=u)}}if(a){var h=a.tooltipPosition();r=h.x,l=h.y}return{x:r,y:l}}}}},{25:25,26:26,45:45}],36:[function(t,e,n){"use strict";var i=t(25),a=t(26),o=t(45);i._set("global",{elements:{arc:{backgroundColor:i.global.defaultColor,borderColor:"#fff",borderWidth:2}}}),e.exports=a.extend({inLabelRange:function(t){var e=this._view;return!!e&&Math.pow(t-e.x,2)<Math.pow(e.radius+e.hoverRadius,2)},inRange:function(t,e){var n=this._view;if(n){for(var i=o.getAngleFromPoint(n,{x:t,y:e}),a=i.angle,r=i.distance,l=n.startAngle,s=n.endAngle;s<l;)s+=2*Math.PI;for(;a>s;)a-=2*Math.PI;for(;a<l;)a+=2*Math.PI;var u=a>=l&&a<=s,d=r>=n.innerRadius&&r<=n.outerRadius;return u&&d}return!1},getCenterPoint:function(){var t=this._view,e=(t.startAngle+t.endAngle)/2,n=(t.innerRadius+t.outerRadius)/2;return{x:t.x+Math.cos(e)*n,y:t.y+Math.sin(e)*n}},getArea:function(){var t=this._view;return Math.PI*((t.endAngle-t.startAngle)/(2*Math.PI))*(Math.pow(t.outerRadius,2)-Math.pow(t.innerRadius,2))},tooltipPosition:function(){var t=this._view,e=t.startAngle+(t.endAngle-t.startAngle)/2,n=(t.outerRadius-t.innerRadius)/2+t.innerRadius;return{x:t.x+Math.cos(e)*n,y:t.y+Math.sin(e)*n}},draw:function(){var t=this._chart.ctx,e=this._view,n=e.startAngle,i=e.endAngle;t.beginPath(),t.arc(e.x,e.y,e.outerRadius,n,i),t.arc(e.x,e.y,e.innerRadius,i,n,!0),t.closePath(),t.strokeStyle=e.borderColor,t.lineWidth=e.borderWidth,t.fillStyle=e.backgroundColor,t.fill(),t.lineJoin="bevel",e.borderWidth&&t.stroke()}})},{25:25,26:26,45:45}],37:[function(t,e,n){"use strict";var i=t(25),a=t(26),o=t(45),r=i.global;i._set("global",{elements:{line:{tension:.4,backgroundColor:r.defaultColor,borderWidth:3,borderColor:r.defaultColor,borderCapStyle:"butt",borderDash:[],borderDashOffset:0,borderJoinStyle:"miter",capBezierPoints:!0,fill:!0}}}),e.exports=a.extend({draw:function(){var t,e,n,i,a=this,l=a._view,s=a._chart.ctx,u=l.spanGaps,d=a._children.slice(),c=r.elements.line,h=-1;for(a._loop&&d.length&&d.push(d[0]),s.save(),s.lineCap=l.borderCapStyle||c.borderCapStyle,s.setLineDash&&s.setLineDash(l.borderDash||c.borderDash),s.lineDashOffset=l.borderDashOffset||c.borderDashOffset,s.lineJoin=l.borderJoinStyle||c.borderJoinStyle,s.lineWidth=l.borderWidth||c.borderWidth,s.strokeStyle=l.borderColor||r.defaultColor,s.beginPath(),h=-1,t=0;t<d.length;++t)e=d[t],n=o.previousItem(d,t),i=e._view,0===t?i.skip||(s.moveTo(i.x,i.y),h=t):(n=-1===h?n:d[h],i.skip||(h!==t-1&&!u||-1===h?s.moveTo(i.x,i.y):o.canvas.lineTo(s,n._view,e._view),h=t));s.stroke(),s.restore()}})},{25:25,26:26,45:45}],38:[function(t,e,n){"use strict";function i(t){var e=this._view;return!!e&&Math.pow(t-e.x,2)<Math.pow(e.radius+e.hitRadius,2)}var a=t(25),o=t(26),r=t(45),l=a.global.defaultColor;a._set("global",{elements:{point:{radius:3,pointStyle:"circle",backgroundColor:l,borderColor:l,borderWidth:1,hitRadius:1,hoverRadius:4,hoverBorderWidth:1}}}),e.exports=o.extend({inRange:function(t,e){var n=this._view;return!!n&&Math.pow(t-n.x,2)+Math.pow(e-n.y,2)<Math.pow(n.hitRadius+n.radius,2)},inLabelRange:i,inXRange:i,inYRange:function(t){var e=this._view;return!!e&&Math.pow(t-e.y,2)<Math.pow(e.radius+e.hitRadius,2)},getCenterPoint:function(){var t=this._view;return{x:t.x,y:t.y}},getArea:function(){return Math.PI*Math.pow(this._view.radius,2)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y,padding:t.radius+t.borderWidth}},draw:function(t){var e=this._view,n=this._model,i=this._chart.ctx,o=e.pointStyle,s=e.radius,u=e.x,d=e.y,c=r.color,h=0;e.skip||(i.strokeStyle=e.borderColor||l,i.lineWidth=r.valueOrDefault(e.borderWidth,a.global.elements.point.borderWidth),i.fillStyle=e.backgroundColor||l,void 0!==t&&(n.x<t.left||1.01*t.right<n.x||n.y<t.top||1.01*t.bottom<n.y)&&(n.x<t.left?h=(u-n.x)/(t.left-n.x):1.01*t.right<n.x?h=(n.x-u)/(n.x-t.right):n.y<t.top?h=(d-n.y)/(t.top-n.y):1.01*t.bottom<n.y&&(h=(n.y-d)/(n.y-t.bottom)),h=Math.round(100*h)/100,i.strokeStyle=c(i.strokeStyle).alpha(h).rgbString(),i.fillStyle=c(i.fillStyle).alpha(h).rgbString()),r.canvas.drawPoint(i,o,s,u,d))}})},{25:25,26:26,45:45}],39:[function(t,e,n){"use strict";function i(t){return void 0!==t._view.width}function a(t){var e,n,a,o,r=t._view;if(i(t)){var l=r.width/2;e=r.x-l,n=r.x+l,a=Math.min(r.y,r.base),o=Math.max(r.y,r.base)}else{var s=r.height/2;e=Math.min(r.x,r.base),n=Math.max(r.x,r.base),a=r.y-s,o=r.y+s}return{left:e,top:a,right:n,bottom:o}}var o=t(25),r=t(26);o._set("global",{elements:{rectangle:{backgroundColor:o.global.defaultColor,borderColor:o.global.defaultColor,borderSkipped:"bottom",borderWidth:0}}}),e.exports=r.extend({draw:function(){function t(t){return m[(b+t)%4]}var e,n,i,a,o,r,l,s=this._chart.ctx,u=this._view,d=u.borderWidth;if(u.horizontal?(e=u.base,n=u.x,i=u.y-u.height/2,a=u.y+u.height/2,o=n>e?1:-1,r=1,l=u.borderSkipped||"left"):(e=u.x-u.width/2,n=u.x+u.width/2,i=u.y,o=1,r=(a=u.base)>i?1:-1,l=u.borderSkipped||"bottom"),d){var c=Math.min(Math.abs(e-n),Math.abs(i-a)),h=(d=d>c?c:d)/2,f=e+("left"!==l?h*o:0),g=n+("right"!==l?-h*o:0),p=i+("top"!==l?h*r:0),v=a+("bottom"!==l?-h*r:0);f!==g&&(i=p,a=v),p!==v&&(e=f,n=g)}s.beginPath(),s.fillStyle=u.backgroundColor,s.strokeStyle=u.borderColor,s.lineWidth=d;var m=[[e,a],[e,i],[n,i],[n,a]],b=["bottom","left","top","right"].indexOf(l,0);-1===b&&(b=0);var x=t(0);s.moveTo(x[0],x[1]);for(var y=1;y<4;y++)x=t(y),s.lineTo(x[0],x[1]);s.fill(),d&&s.stroke()},height:function(){var t=this._view;return t.base-t.y},inRange:function(t,e){var n=!1;if(this._view){var i=a(this);n=t>=i.left&&t<=i.right&&e>=i.top&&e<=i.bottom}return n},inLabelRange:function(t,e){var n=this;if(!n._view)return!1;var o=a(n);return i(n)?t>=o.left&&t<=o.right:e>=o.top&&e<=o.bottom},inXRange:function(t){var e=a(this);return t>=e.left&&t<=e.right},inYRange:function(t){var e=a(this);return t>=e.top&&t<=e.bottom},getCenterPoint:function(){var t,e,n=this._view;return i(this)?(t=n.x,e=(n.y+n.base)/2):(t=(n.x+n.base)/2,e=n.y),{x:t,y:e}},getArea:function(){var t=this._view;return t.width*Math.abs(t.y-t.base)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y}}})},{25:25,26:26}],40:[function(t,e,n){"use strict";e.exports={},e.exports.Arc=t(36),e.exports.Line=t(37),e.exports.Point=t(38),e.exports.Rectangle=t(39)},{36:36,37:37,38:38,39:39}],41:[function(t,e,n){"use strict";var i=t(42),n=e.exports={clear:function(t){t.ctx.clearRect(0,0,t.width,t.height)},roundedRect:function(t,e,n,i,a,o){if(o){var r=Math.min(o,i/2),l=Math.min(o,a/2);t.moveTo(e+r,n),t.lineTo(e+i-r,n),t.quadraticCurveTo(e+i,n,e+i,n+l),t.lineTo(e+i,n+a-l),t.quadraticCurveTo(e+i,n+a,e+i-r,n+a),t.lineTo(e+r,n+a),t.quadraticCurveTo(e,n+a,e,n+a-l),t.lineTo(e,n+l),t.quadraticCurveTo(e,n,e+r,n)}else t.rect(e,n,i,a)},drawPoint:function(t,e,n,i,a){var o,r,l,s,u,d;if(!e||"object"!=typeof e||"[object HTMLImageElement]"!==(o=e.toString())&&"[object HTMLCanvasElement]"!==o){if(!(isNaN(n)||n<=0)){switch(e){default:t.beginPath(),t.arc(i,a,n,0,2*Math.PI),t.closePath(),t.fill();break;case"triangle":t.beginPath(),u=(r=3*n/Math.sqrt(3))*Math.sqrt(3)/2,t.moveTo(i-r/2,a+u/3),t.lineTo(i+r/2,a+u/3),t.lineTo(i,a-2*u/3),t.closePath(),t.fill();break;case"rect":d=1/Math.SQRT2*n,t.beginPath(),t.fillRect(i-d,a-d,2*d,2*d),t.strokeRect(i-d,a-d,2*d,2*d);break;case"rectRounded":var c=n/Math.SQRT2,h=i-c,f=a-c,g=Math.SQRT2*n;t.beginPath(),this.roundedRect(t,h,f,g,g,n/2),t.closePath(),t.fill();break;case"rectRot":d=1/Math.SQRT2*n,t.beginPath(),t.moveTo(i-d,a),t.lineTo(i,a+d),t.lineTo(i+d,a),t.lineTo(i,a-d),t.closePath(),t.fill();break;case"cross":t.beginPath(),t.moveTo(i,a+n),t.lineTo(i,a-n),t.moveTo(i-n,a),t.lineTo(i+n,a),t.closePath();break;case"crossRot":t.beginPath(),l=Math.cos(Math.PI/4)*n,s=Math.sin(Math.PI/4)*n,t.moveTo(i-l,a-s),t.lineTo(i+l,a+s),t.moveTo(i-l,a+s),t.lineTo(i+l,a-s),t.closePath();break;case"star":t.beginPath(),t.moveTo(i,a+n),t.lineTo(i,a-n),t.moveTo(i-n,a),t.lineTo(i+n,a),l=Math.cos(Math.PI/4)*n,s=Math.sin(Math.PI/4)*n,t.moveTo(i-l,a-s),t.lineTo(i+l,a+s),t.moveTo(i-l,a+s),t.lineTo(i+l,a-s),t.closePath();break;case"line":t.beginPath(),t.moveTo(i-n,a),t.lineTo(i+n,a),t.closePath();break;case"dash":t.beginPath(),t.moveTo(i,a),t.lineTo(i+n,a),t.closePath()}t.stroke()}}else t.drawImage(e,i-e.width/2,a-e.height/2,e.width,e.height)},clipArea:function(t,e){t.save(),t.beginPath(),t.rect(e.left,e.top,e.right-e.left,e.bottom-e.top),t.clip()},unclipArea:function(t){t.restore()},lineTo:function(t,e,n,i){if(n.steppedLine)return"after"===n.steppedLine&&!i||"after"!==n.steppedLine&&i?t.lineTo(e.x,n.y):t.lineTo(n.x,e.y),void t.lineTo(n.x,n.y);n.tension?t.bezierCurveTo(i?e.controlPointPreviousX:e.controlPointNextX,i?e.controlPointPreviousY:e.controlPointNextY,i?n.controlPointNextX:n.controlPointPreviousX,i?n.controlPointNextY:n.controlPointPreviousY,n.x,n.y):t.lineTo(n.x,n.y)}};i.clear=n.clear,i.drawRoundedRectangle=function(t){t.beginPath(),n.roundedRect.apply(n,arguments),t.closePath()}},{42:42}],42:[function(t,e,n){"use strict";var i={noop:function(){},uid:function(){var t=0;return function(){return t++}}(),isNullOrUndef:function(t){return null===t||void 0===t},isArray:Array.isArray?Array.isArray:function(t){return"[object Array]"===Object.prototype.toString.call(t)},isObject:function(t){return null!==t&&"[object Object]"===Object.prototype.toString.call(t)},valueOrDefault:function(t,e){return void 0===t?e:t},valueAtIndexOrDefault:function(t,e,n){return i.valueOrDefault(i.isArray(t)?t[e]:t,n)},callback:function(t,e,n){if(t&&"function"==typeof t.call)return t.apply(n,e)},each:function(t,e,n,a){var o,r,l;if(i.isArray(t))if(r=t.length,a)for(o=r-1;o>=0;o--)e.call(n,t[o],o);else for(o=0;o<r;o++)e.call(n,t[o],o);else if(i.isObject(t))for(r=(l=Object.keys(t)).length,o=0;o<r;o++)e.call(n,t[l[o]],l[o])},arrayEquals:function(t,e){var n,a,o,r;if(!t||!e||t.length!==e.length)return!1;for(n=0,a=t.length;n<a;++n)if(o=t[n],r=e[n],o instanceof Array&&r instanceof Array){if(!i.arrayEquals(o,r))return!1}else if(o!==r)return!1;return!0},clone:function(t){if(i.isArray(t))return t.map(i.clone);if(i.isObject(t)){for(var e={},n=Object.keys(t),a=n.length,o=0;o<a;++o)e[n[o]]=i.clone(t[n[o]]);return e}return t},_merger:function(t,e,n,a){var o=e[t],r=n[t];i.isObject(o)&&i.isObject(r)?i.merge(o,r,a):e[t]=i.clone(r)},_mergerIf:function(t,e,n){var a=e[t],o=n[t];i.isObject(a)&&i.isObject(o)?i.mergeIf(a,o):e.hasOwnProperty(t)||(e[t]=i.clone(o))},merge:function(t,e,n){var a,o,r,l,s,u=i.isArray(e)?e:[e],d=u.length;if(!i.isObject(t))return t;for(a=(n=n||{}).merger||i._merger,o=0;o<d;++o)if(e=u[o],i.isObject(e))for(s=0,l=(r=Object.keys(e)).length;s<l;++s)a(r[s],t,e,n);return t},mergeIf:function(t,e){return i.merge(t,e,{merger:i._mergerIf})}};e.exports=i,i.callCallback=i.callback,i.indexOf=function(t,e,n){return Array.prototype.indexOf.call(t,e,n)},i.getValueOrDefault=i.valueOrDefault,i.getValueAtIndexOrDefault=i.valueAtIndexOrDefault},{}],43:[function(t,e,n){"use strict";var i=t(42),a={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return-t*(t-2)},easeInOutQuad:function(t){return(t/=.5)<1?.5*t*t:-.5*(--t*(t-2)-1)},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return(t-=1)*t*t+1},easeInOutCubic:function(t){return(t/=.5)<1?.5*t*t*t:.5*((t-=2)*t*t+2)},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return-((t-=1)*t*t*t-1)},easeInOutQuart:function(t){return(t/=.5)<1?.5*t*t*t*t:-.5*((t-=2)*t*t*t-2)},easeInQuint:function(t){return t*t*t*t*t},easeOutQuint:function(t){return(t-=1)*t*t*t*t+1},easeInOutQuint:function(t){return(t/=.5)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)},easeInSine:function(t){return 1-Math.cos(t*(Math.PI/2))},easeOutSine:function(t){return Math.sin(t*(Math.PI/2))},easeInOutSine:function(t){return-.5*(Math.cos(Math.PI*t)-1)},easeInExpo:function(t){return 0===t?0:Math.pow(2,10*(t-1))},easeOutExpo:function(t){return 1===t?1:1-Math.pow(2,-10*t)},easeInOutExpo:function(t){return 0===t?0:1===t?1:(t/=.5)<1?.5*Math.pow(2,10*(t-1)):.5*(2-Math.pow(2,-10*--t))},easeInCirc:function(t){return t>=1?t:-(Math.sqrt(1-t*t)-1)},easeOutCirc:function(t){return Math.sqrt(1-(t-=1)*t)},easeInOutCirc:function(t){return(t/=.5)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:1===t?1:(n||(n=.3),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),-i*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n))},easeOutElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:1===t?1:(n||(n=.3),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),i*Math.pow(2,-10*t)*Math.sin((t-e)*(2*Math.PI)/n)+1)},easeInOutElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:2==(t/=.5)?1:(n||(n=.45),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),t<1?i*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n)*-.5:i*Math.pow(2,-10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n)*.5+1)},easeInBack:function(t){var e=1.70158;return t*t*((e+1)*t-e)},easeOutBack:function(t){var e=1.70158;return(t-=1)*t*((e+1)*t+e)+1},easeInOutBack:function(t){var e=1.70158;return(t/=.5)<1?t*t*((1+(e*=1.525))*t-e)*.5:.5*((t-=2)*t*((1+(e*=1.525))*t+e)+2)},easeInBounce:function(t){return 1-a.easeOutBounce(1-t)},easeOutBounce:function(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375},easeInOutBounce:function(t){return t<.5?.5*a.easeInBounce(2*t):.5*a.easeOutBounce(2*t-1)+.5}};e.exports={effects:a},i.easingEffects=a},{42:42}],44:[function(t,e,n){"use strict";var i=t(42);e.exports={toLineHeight:function(t,e){var n=(""+t).match(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/);if(!n||"normal"===n[1])return 1.2*e;switch(t=+n[2],n[3]){case"px":return t;case"%":t/=100}return e*t},toPadding:function(t){var e,n,a,o;return i.isObject(t)?(e=+t.top||0,n=+t.right||0,a=+t.bottom||0,o=+t.left||0):e=n=a=o=+t||0,{top:e,right:n,bottom:a,left:o,height:e+a,width:o+n}},resolve:function(t,e,n){var a,o,r;for(a=0,o=t.length;a<o;++a)if(void 0!==(r=t[a])&&(void 0!==e&&"function"==typeof r&&(r=r(e)),void 0!==n&&i.isArray(r)&&(r=r[n]),void 0!==r))return r}}},{42:42}],45:[function(t,e,n){"use strict";e.exports=t(42),e.exports.easing=t(43),e.exports.canvas=t(41),e.exports.options=t(44)},{41:41,42:42,43:43,44:44}],46:[function(t,e,n){e.exports={acquireContext:function(t){return t&&t.canvas&&(t=t.canvas),t&&t.getContext("2d")||null}}},{}],47:[function(t,e,n){"use strict";function i(t,e){var n=v.getStyle(t,e),i=n&&n.match(/^(\d+)(\.\d+)?px$/);return i?Number(i[1]):void 0}function a(t,e){var n=t.style,a=t.getAttribute("height"),o=t.getAttribute("width");if(t[m]={initial:{height:a,width:o,style:{display:n.display,height:n.height,width:n.width}}},n.display=n.display||"block",null===o||""===o){var r=i(t,"width");void 0!==r&&(t.width=r)}if(null===a||""===a)if(""===t.style.height)t.height=t.width/(e.options.aspectRatio||2);else{var l=i(t,"height");void 0!==r&&(t.height=l)}return t}function o(t,e,n){t.addEventListener(e,n,M)}function r(t,e,n){t.removeEventListener(e,n,M)}function l(t,e,n,i,a){return{type:t,chart:e,native:a||null,x:void 0!==n?n:null,y:void 0!==i?i:null}}function s(t,e){var n=w[t.type]||t.type,i=v.getRelativePosition(t,e);return l(n,e,i.x,i.y,t)}function u(t,e){var n=!1,i=[];return function(){i=Array.prototype.slice.call(arguments),e=e||this,n||(n=!0,v.requestAnimFrame.call(window,function(){n=!1,t.apply(e,i)}))}}function d(t){var e=document.createElement("div"),n=b+"size-monitor",i="position:absolute;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1;";e.style.cssText=i,e.className=n,e.innerHTML='<div class="'+n+'-expand" style="'+i+'"><div style="position:absolute;width:1000000px;height:1000000px;left:0;top:0"></div></div><div class="'+n+'-shrink" style="'+i+'"><div style="position:absolute;width:200%;height:200%;left:0; top:0"></div></div>';var a=e.childNodes[0],r=e.childNodes[1];e._reset=function(){a.scrollLeft=1e6,a.scrollTop=1e6,r.scrollLeft=1e6,r.scrollTop=1e6};var l=function(){e._reset(),t()};return o(a,"scroll",l.bind(a,"expand")),o(r,"scroll",l.bind(r,"shrink")),e}function c(t,e){var n=(t[m]||(t[m]={})).renderProxy=function(t){t.animationName===y&&e()};v.each(k,function(e){o(t,e,n)}),t.classList.add(x)}function h(t){var e=t[m]||{},n=e.renderProxy;n&&(v.each(k,function(e){r(t,e,n)}),delete e.renderProxy),t.classList.remove(x)}function f(t,e,n){var i=t[m]||(t[m]={}),a=i.resizer=d(u(function(){if(i.resizer)return e(l("resize",n))}));c(t,function(){if(i.resizer){var e=t.parentNode;e&&e!==a.parentNode&&e.insertBefore(a,e.firstChild),a._reset()}})}function g(t){var e=t[m]||{},n=e.resizer;delete e.resizer,h(t),n&&n.parentNode&&n.parentNode.removeChild(n)}function p(t,e){var n=t._style||document.createElement("style");t._style||(t._style=n,e="/* Chart.js */\n"+e,n.setAttribute("type","text/css"),document.getElementsByTagName("head")[0].appendChild(n)),n.appendChild(document.createTextNode(e))}var v=t(45),m="$chartjs",b="chartjs-",x=b+"render-monitor",y=b+"render-animation",k=["animationstart","webkitAnimationStart"],w={touchstart:"mousedown",touchmove:"mousemove",touchend:"mouseup",pointerenter:"mouseenter",pointerdown:"mousedown",pointermove:"mousemove",pointerup:"mouseup",pointerleave:"mouseout",pointerout:"mouseout"},M=!!function(){var t=!1;try{var e=Object.defineProperty({},"passive",{get:function(){t=!0}});window.addEventListener("e",null,e)}catch(t){}return t}()&&{passive:!0};e.exports={_enabled:"undefined"!=typeof window&&"undefined"!=typeof document,initialize:function(){var t="from{opacity:0.99}to{opacity:1}";p(this,"@-webkit-keyframes "+y+"{"+t+"}@keyframes "+y+"{"+t+"}."+x+"{-webkit-animation:"+y+" 0.001s;animation:"+y+" 0.001s;}")},acquireContext:function(t,e){"string"==typeof t?t=document.getElementById(t):t.length&&(t=t[0]),t&&t.canvas&&(t=t.canvas);var n=t&&t.getContext&&t.getContext("2d");return n&&n.canvas===t?(a(t,e),n):null},releaseContext:function(t){var e=t.canvas;if(e[m]){var n=e[m].initial;["height","width"].forEach(function(t){var i=n[t];v.isNullOrUndef(i)?e.removeAttribute(t):e.setAttribute(t,i)}),v.each(n.style||{},function(t,n){e.style[n]=t}),e.width=e.width,delete e[m]}},addEventListener:function(t,e,n){var i=t.canvas;if("resize"!==e){var a=n[m]||(n[m]={});o(i,e,(a.proxies||(a.proxies={}))[t.id+"_"+e]=function(e){n(s(e,t))})}else f(i,n,t)},removeEventListener:function(t,e,n){var i=t.canvas;if("resize"!==e){var a=((n[m]||{}).proxies||{})[t.id+"_"+e];a&&r(i,e,a)}else g(i)}},v.addEvent=o,v.removeEvent=r},{45:45}],48:[function(t,e,n){"use strict";var i=t(45),a=t(46),o=t(47),r=o._enabled?o:a;e.exports=i.extend({initialize:function(){},acquireContext:function(){},releaseContext:function(){},addEventListener:function(){},removeEventListener:function(){}},r)},{45:45,46:46,47:47}],49:[function(t,e,n){"use strict";var i=t(25),a=t(40),o=t(45);i._set("global",{plugins:{filler:{propagate:!0}}}),e.exports=function(){function t(t,e,n){var i,a=t._model||{},o=a.fill;if(void 0===o&&(o=!!a.backgroundColor),!1===o||null===o)return!1;if(!0===o)return"origin";if(i=parseFloat(o,10),isFinite(i)&&Math.floor(i)===i)return"-"!==o[0]&&"+"!==o[0]||(i=e+i),!(i===e||i<0||i>=n)&&i;switch(o){case"bottom":return"start";case"top":return"end";case"zero":return"origin";case"origin":case"start":case"end":return o;default:return!1}}function e(t){var e,n=t.el._model||{},i=t.el._scale||{},a=t.fill,o=null;if(isFinite(a))return null;if("start"===a?o=void 0===n.scaleBottom?i.bottom:n.scaleBottom:"end"===a?o=void 0===n.scaleTop?i.top:n.scaleTop:void 0!==n.scaleZero?o=n.scaleZero:i.getBasePosition?o=i.getBasePosition():i.getBasePixel&&(o=i.getBasePixel()),void 0!==o&&null!==o){if(void 0!==o.x&&void 0!==o.y)return o;if("number"==typeof o&&isFinite(o))return e=i.isHorizontal(),{x:e?o:null,y:e?null:o}}return null}function n(t,e,n){var i,a=t[e].fill,o=[e];if(!n)return a;for(;!1!==a&&-1===o.indexOf(a);){if(!isFinite(a))return a;if(!(i=t[a]))return!1;if(i.visible)return a;o.push(a),a=i.fill}return!1}function r(t){var e=t.fill,n="dataset";return!1===e?null:(isFinite(e)||(n="boundary"),d[n](t))}function l(t){return t&&!t.skip}function s(t,e,n,i,a){var r;if(i&&a){for(t.moveTo(e[0].x,e[0].y),r=1;r<i;++r)o.canvas.lineTo(t,e[r-1],e[r]);for(t.lineTo(n[a-1].x,n[a-1].y),r=a-1;r>0;--r)o.canvas.lineTo(t,n[r],n[r-1],!0)}}function u(t,e,n,i,a,o){var r,u,d,c,h,f,g,p=e.length,v=i.spanGaps,m=[],b=[],x=0,y=0;for(t.beginPath(),r=0,u=p+!!o;r<u;++r)h=n(c=e[d=r%p]._view,d,i),f=l(c),g=l(h),f&&g?(x=m.push(c),y=b.push(h)):x&&y&&(v?(f&&m.push(c),g&&b.push(h)):(s(t,m,b,x,y),x=y=0,m=[],b=[]));s(t,m,b,x,y),t.closePath(),t.fillStyle=a,t.fill()}var d={dataset:function(t){var e=t.fill,n=t.chart,i=n.getDatasetMeta(e),a=i&&n.isDatasetVisible(e)&&i.dataset._children||[],o=a.length||0;return o?function(t,e){return e<o&&a[e]._view||null}:null},boundary:function(t){var e=t.boundary,n=e?e.x:null,i=e?e.y:null;return function(t){return{x:null===n?t.x:n,y:null===i?t.y:i}}}};return{id:"filler",afterDatasetsUpdate:function(i,o){var l,s,u,d,c=(i.data.datasets||[]).length,h=o.propagate,f=[];for(s=0;s<c;++s)d=null,(u=(l=i.getDatasetMeta(s)).dataset)&&u._model&&u instanceof a.Line&&(d={visible:i.isDatasetVisible(s),fill:t(u,s,c),chart:i,el:u}),l.$filler=d,f.push(d);for(s=0;s<c;++s)(d=f[s])&&(d.fill=n(f,s,h),d.boundary=e(d),d.mapper=r(d))},beforeDatasetDraw:function(t,e){var n=e.meta.$filler;if(n){var a=t.ctx,r=n.el,l=r._view,s=r._children||[],d=n.mapper,c=l.backgroundColor||i.global.defaultColor;d&&c&&s.length&&(o.canvas.clipArea(a,t.chartArea),u(a,s,d,l,c,r._loop),o.canvas.unclipArea(a))}}}}},{25:25,40:40,45:45}],50:[function(t,e,n){"use strict";var i=t(25),a=t(26),o=t(45);i._set("global",{legend:{display:!0,position:"top",fullWidth:!0,reverse:!1,weight:1e3,onClick:function(t,e){var n=e.datasetIndex,i=this.chart,a=i.getDatasetMeta(n);a.hidden=null===a.hidden?!i.data.datasets[n].hidden:null,i.update()},onHover:null,labels:{boxWidth:40,padding:10,generateLabels:function(t){var e=t.data;return o.isArray(e.datasets)?e.datasets.map(function(e,n){return{text:e.label,fillStyle:o.isArray(e.backgroundColor)?e.backgroundColor[0]:e.backgroundColor,hidden:!t.isDatasetVisible(n),lineCap:e.borderCapStyle,lineDash:e.borderDash,lineDashOffset:e.borderDashOffset,lineJoin:e.borderJoinStyle,lineWidth:e.borderWidth,strokeStyle:e.borderColor,pointStyle:e.pointStyle,datasetIndex:n}},this):[]}}},legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');for(var n=0;n<t.data.datasets.length;n++)e.push('<li><span style="background-color:'+t.data.datasets[n].backgroundColor+'"></span>'),t.data.datasets[n].label&&e.push(t.data.datasets[n].label),e.push("</li>");return e.push("</ul>"),e.join("")}}),e.exports=function(t){function e(t,e){return t.usePointStyle?e*Math.SQRT2:t.boxWidth}function n(e,n){var i=new t.Legend({ctx:e.ctx,options:n,chart:e});r.configure(e,i,n),r.addBox(e,i),e.legend=i}var r=t.layoutService,l=o.noop;return t.Legend=a.extend({initialize:function(t){o.extend(this,t),this.legendHitBoxes=[],this.doughnutMode=!1},beforeUpdate:l,update:function(t,e,n){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=n,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:l,beforeSetDimensions:l,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:l,beforeBuildLabels:l,buildLabels:function(){var t=this,e=t.options.labels||{},n=o.callback(e.generateLabels,[t.chart],t)||[];e.filter&&(n=n.filter(function(n){return e.filter(n,t.chart.data)})),t.options.reverse&&n.reverse(),t.legendItems=n},afterBuildLabels:l,beforeFit:l,fit:function(){var t=this,n=t.options,a=n.labels,r=n.display,l=t.ctx,s=i.global,u=o.valueOrDefault,d=u(a.fontSize,s.defaultFontSize),c=u(a.fontStyle,s.defaultFontStyle),h=u(a.fontFamily,s.defaultFontFamily),f=o.fontString(d,c,h),g=t.legendHitBoxes=[],p=t.minSize,v=t.isHorizontal();if(v?(p.width=t.maxWidth,p.height=r?10:0):(p.width=r?10:0,p.height=t.maxHeight),r)if(l.font=f,v){var m=t.lineWidths=[0],b=t.legendItems.length?d+a.padding:0;l.textAlign="left",l.textBaseline="top",o.each(t.legendItems,function(n,i){var o=e(a,d)+d/2+l.measureText(n.text).width;m[m.length-1]+o+a.padding>=t.width&&(b+=d+a.padding,m[m.length]=t.left),g[i]={left:0,top:0,width:o,height:d},m[m.length-1]+=o+a.padding}),p.height+=b}else{var x=a.padding,y=t.columnWidths=[],k=a.padding,w=0,M=0,S=d+x;o.each(t.legendItems,function(t,n){var i=e(a,d)+d/2+l.measureText(t.text).width;M+S>p.height&&(k+=w+a.padding,y.push(w),w=0,M=0),w=Math.max(w,i),M+=S,g[n]={left:0,top:0,width:i,height:d}}),k+=w,y.push(w),p.width+=k}t.width=p.width,t.height=p.height},afterFit:l,isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},draw:function(){var t=this,n=t.options,a=n.labels,r=i.global,l=r.elements.line,s=t.width,u=t.lineWidths;if(n.display){var d,c=t.ctx,h=o.valueOrDefault,f=h(a.fontColor,r.defaultFontColor),g=h(a.fontSize,r.defaultFontSize),p=h(a.fontStyle,r.defaultFontStyle),v=h(a.fontFamily,r.defaultFontFamily),m=o.fontString(g,p,v);c.textAlign="left",c.textBaseline="middle",c.lineWidth=.5,c.strokeStyle=f,c.fillStyle=f,c.font=m;var b=e(a,g),x=t.legendHitBoxes,y=function(t,e,i){if(!(isNaN(b)||b<=0)){c.save(),c.fillStyle=h(i.fillStyle,r.defaultColor),c.lineCap=h(i.lineCap,l.borderCapStyle),c.lineDashOffset=h(i.lineDashOffset,l.borderDashOffset),c.lineJoin=h(i.lineJoin,l.borderJoinStyle),c.lineWidth=h(i.lineWidth,l.borderWidth),c.strokeStyle=h(i.strokeStyle,r.defaultColor);var a=0===h(i.lineWidth,l.borderWidth);if(c.setLineDash&&c.setLineDash(h(i.lineDash,l.borderDash)),n.labels&&n.labels.usePointStyle){var s=g*Math.SQRT2/2,u=s/Math.SQRT2,d=t+u,f=e+u;o.canvas.drawPoint(c,i.pointStyle,s,d,f)}else a||c.strokeRect(t,e,b,g),c.fillRect(t,e,b,g);c.restore()}},k=function(t,e,n,i){var a=g/2,o=b+a+t,r=e+a;c.fillText(n.text,o,r),n.hidden&&(c.beginPath(),c.lineWidth=2,c.moveTo(o,r),c.lineTo(o+i,r),c.stroke())},w=t.isHorizontal();d=w?{x:t.left+(s-u[0])/2,y:t.top+a.padding,line:0}:{x:t.left+a.padding,y:t.top+a.padding,line:0};var M=g+a.padding;o.each(t.legendItems,function(e,n){var i=c.measureText(e.text).width,o=b+g/2+i,r=d.x,l=d.y;w?r+o>=s&&(l=d.y+=M,d.line++,r=d.x=t.left+(s-u[d.line])/2):l+M>t.bottom&&(r=d.x=r+t.columnWidths[d.line]+a.padding,l=d.y=t.top+a.padding,d.line++),y(r,l,e),x[n].left=r,x[n].top=l,k(r,l,e,i),w?d.x+=o+a.padding:d.y+=M})}},handleEvent:function(t){var e=this,n=e.options,i="mouseup"===t.type?"click":t.type,a=!1;if("mousemove"===i){if(!n.onHover)return}else{if("click"!==i)return;if(!n.onClick)return}var o=t.x,r=t.y;if(o>=e.left&&o<=e.right&&r>=e.top&&r<=e.bottom)for(var l=e.legendHitBoxes,s=0;s<l.length;++s){var u=l[s];if(o>=u.left&&o<=u.left+u.width&&r>=u.top&&r<=u.top+u.height){if("click"===i){n.onClick.call(e,t.native,e.legendItems[s]),a=!0;break}if("mousemove"===i){n.onHover.call(e,t.native,e.legendItems[s]),a=!0;break}}}return a}}),{id:"legend",beforeInit:function(t){var e=t.options.legend;e&&n(t,e)},beforeUpdate:function(t){var e=t.options.legend,a=t.legend;e?(o.mergeIf(e,i.global.legend),a?(r.configure(t,a,e),a.options=e):n(t,e)):a&&(r.removeBox(t,a),delete t.legend)},afterEvent:function(t,e){var n=t.legend;n&&n.handleEvent(e)}}}},{25:25,26:26,45:45}],51:[function(t,e,n){"use strict";var i=t(25),a=t(26),o=t(45);i._set("global",{title:{display:!1,fontStyle:"bold",fullWidth:!0,lineHeight:1.2,padding:10,position:"top",text:"",weight:2e3}}),e.exports=function(t){function e(e,i){var a=new t.Title({ctx:e.ctx,options:i,chart:e});n.configure(e,a,i),n.addBox(e,a),e.titleBlock=a}var n=t.layoutService,r=o.noop;return t.Title=a.extend({initialize:function(t){var e=this;o.extend(e,t),e.legendHitBoxes=[]},beforeUpdate:r,update:function(t,e,n){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=n,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:r,beforeSetDimensions:r,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:r,beforeBuildLabels:r,buildLabels:r,afterBuildLabels:r,beforeFit:r,fit:function(){var t=this,e=o.valueOrDefault,n=t.options,a=n.display,r=e(n.fontSize,i.global.defaultFontSize),l=t.minSize,s=o.isArray(n.text)?n.text.length:1,u=o.options.toLineHeight(n.lineHeight,r),d=a?s*u+2*n.padding:0;t.isHorizontal()?(l.width=t.maxWidth,l.height=d):(l.width=d,l.height=t.maxHeight),t.width=l.width,t.height=l.height},afterFit:r,isHorizontal:function(){var t=this.options.position;return"top"===t||"bottom"===t},draw:function(){var t=this,e=t.ctx,n=o.valueOrDefault,a=t.options,r=i.global;if(a.display){var l,s,u,d=n(a.fontSize,r.defaultFontSize),c=n(a.fontStyle,r.defaultFontStyle),h=n(a.fontFamily,r.defaultFontFamily),f=o.fontString(d,c,h),g=o.options.toLineHeight(a.lineHeight,d),p=g/2+a.padding,v=0,m=t.top,b=t.left,x=t.bottom,y=t.right;e.fillStyle=n(a.fontColor,r.defaultFontColor),e.font=f,t.isHorizontal()?(s=b+(y-b)/2,u=m+p,l=y-b):(s="left"===a.position?b+p:y-p,u=m+(x-m)/2,l=x-m,v=Math.PI*("left"===a.position?-.5:.5)),e.save(),e.translate(s,u),e.rotate(v),e.textAlign="center",e.textBaseline="middle";var k=a.text;if(o.isArray(k))for(var w=0,M=0;M<k.length;++M)e.fillText(k[M],0,w,l),w+=g;else e.fillText(k,0,0,l);e.restore()}}}),{id:"title",beforeInit:function(t){var n=t.options.title;n&&e(t,n)},beforeUpdate:function(a){var r=a.options.title,l=a.titleBlock;r?(o.mergeIf(r,i.global.title),l?(n.configure(a,l,r),l.options=r):e(a,r)):l&&(t.layoutService.removeBox(a,l),delete a.titleBlock)}}}},{25:25,26:26,45:45}],52:[function(t,e,n){"use strict";e.exports=function(t){var e={position:"bottom"},n=t.Scale.extend({getLabels:function(){var t=this.chart.data;return this.options.labels||(this.isHorizontal()?t.xLabels:t.yLabels)||t.labels},determineDataLimits:function(){var t=this,e=t.getLabels();t.minIndex=0,t.maxIndex=e.length-1;var n;void 0!==t.options.ticks.min&&(n=e.indexOf(t.options.ticks.min),t.minIndex=-1!==n?n:t.minIndex),void 0!==t.options.ticks.max&&(n=e.indexOf(t.options.ticks.max),t.maxIndex=-1!==n?n:t.maxIndex),t.min=e[t.minIndex],t.max=e[t.maxIndex]},buildTicks:function(){var t=this,e=t.getLabels();t.ticks=0===t.minIndex&&t.maxIndex===e.length-1?e:e.slice(t.minIndex,t.maxIndex+1)},getLabelForIndex:function(t,e){var n=this,i=n.chart.data,a=n.isHorizontal();return i.yLabels&&!a?n.getRightValue(i.datasets[e].data[t]):n.ticks[t-n.minIndex]},getPixelForValue:function(t,e){var n,i=this,a=i.options.offset,o=Math.max(i.maxIndex+1-i.minIndex-(a?0:1),1);if(void 0!==t&&null!==t&&(n=i.isHorizontal()?t.x:t.y),void 0!==n||void 0!==t&&isNaN(e)){var r=i.getLabels();t=n||t;var l=r.indexOf(t);e=-1!==l?l:e}if(i.isHorizontal()){var s=i.width/o,u=s*(e-i.minIndex);return a&&(u+=s/2),i.left+Math.round(u)}var d=i.height/o,c=d*(e-i.minIndex);return a&&(c+=d/2),i.top+Math.round(c)},getPixelForTick:function(t){return this.getPixelForValue(this.ticks[t],t+this.minIndex,null)},getValueForPixel:function(t){var e=this,n=e.options.offset,i=Math.max(e._ticks.length-(n?0:1),1),a=e.isHorizontal(),o=(a?e.width:e.height)/i;return t-=a?e.left:e.top,n&&(t-=o/2),(t<=0?0:Math.round(t/o))+e.minIndex},getBasePixel:function(){return this.bottom}});t.scaleService.registerScaleType("category",n,e)}},{}],53:[function(t,e,n){"use strict";var i=t(25),a=t(45),o=t(34);e.exports=function(t){var e={position:"left",ticks:{callback:o.formatters.linear}},n=t.LinearScaleBase.extend({determineDataLimits:function(){function t(t){return r?t.xAxisID===e.id:t.yAxisID===e.id}var e=this,n=e.options,i=e.chart,o=i.data.datasets,r=e.isHorizontal();e.min=null,e.max=null;var l=n.stacked;if(void 0===l&&a.each(o,function(e,n){if(!l){var a=i.getDatasetMeta(n);i.isDatasetVisible(n)&&t(a)&&void 0!==a.stack&&(l=!0)}}),n.stacked||l){var s={};a.each(o,function(o,r){var l=i.getDatasetMeta(r),u=[l.type,void 0===n.stacked&&void 0===l.stack?r:"",l.stack].join(".");void 0===s[u]&&(s[u]={positiveValues:[],negativeValues:[]});var d=s[u].positiveValues,c=s[u].negativeValues;i.isDatasetVisible(r)&&t(l)&&a.each(o.data,function(t,i){var a=+e.getRightValue(t);isNaN(a)||l.data[i].hidden||(d[i]=d[i]||0,c[i]=c[i]||0,n.relativePoints?d[i]=100:a<0?c[i]+=a:d[i]+=a)})}),a.each(s,function(t){var n=t.positiveValues.concat(t.negativeValues),i=a.min(n),o=a.max(n);e.min=null===e.min?i:Math.min(e.min,i),e.max=null===e.max?o:Math.max(e.max,o)})}else a.each(o,function(n,o){var r=i.getDatasetMeta(o);i.isDatasetVisible(o)&&t(r)&&a.each(n.data,function(t,n){var i=+e.getRightValue(t);isNaN(i)||r.data[n].hidden||(null===e.min?e.min=i:i<e.min&&(e.min=i),null===e.max?e.max=i:i>e.max&&(e.max=i))})});e.min=isFinite(e.min)&&!isNaN(e.min)?e.min:0,e.max=isFinite(e.max)&&!isNaN(e.max)?e.max:1,this.handleTickRangeOptions()},getTickLimit:function(){var t,e=this,n=e.options.ticks;if(e.isHorizontal())t=Math.min(n.maxTicksLimit?n.maxTicksLimit:11,Math.ceil(e.width/50));else{var o=a.valueOrDefault(n.fontSize,i.global.defaultFontSize);t=Math.min(n.maxTicksLimit?n.maxTicksLimit:11,Math.ceil(e.height/(2*o)))}return t},handleDirectionalChanges:function(){this.isHorizontal()||this.ticks.reverse()},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForValue:function(t){var e,n=this,i=n.start,a=+n.getRightValue(t),o=n.end-i;return n.isHorizontal()?(e=n.left+n.width/o*(a-i),Math.round(e)):(e=n.bottom-n.height/o*(a-i),Math.round(e))},getValueForPixel:function(t){var e=this,n=e.isHorizontal(),i=n?e.width:e.height,a=(n?t-e.left:e.bottom-t)/i;return e.start+(e.end-e.start)*a},getPixelForTick:function(t){return this.getPixelForValue(this.ticksAsNumbers[t])}});t.scaleService.registerScaleType("linear",n,e)}},{25:25,34:34,45:45}],54:[function(t,e,n){"use strict";var i=t(45),a=t(34);e.exports=function(t){var e=i.noop;t.LinearScaleBase=t.Scale.extend({getRightValue:function(e){return"string"==typeof e?+e:t.Scale.prototype.getRightValue.call(this,e)},handleTickRangeOptions:function(){var t=this,e=t.options.ticks;if(e.beginAtZero){var n=i.sign(t.min),a=i.sign(t.max);n<0&&a<0?t.max=0:n>0&&a>0&&(t.min=0)}var o=void 0!==e.min||void 0!==e.suggestedMin,r=void 0!==e.max||void 0!==e.suggestedMax;void 0!==e.min?t.min=e.min:void 0!==e.suggestedMin&&(null===t.min?t.min=e.suggestedMin:t.min=Math.min(t.min,e.suggestedMin)),void 0!==e.max?t.max=e.max:void 0!==e.suggestedMax&&(null===t.max?t.max=e.suggestedMax:t.max=Math.max(t.max,e.suggestedMax)),o!==r&&t.min>=t.max&&(o?t.max=t.min+1:t.min=t.max-1),t.min===t.max&&(t.max++,e.beginAtZero||t.min--)},getTickLimit:e,handleDirectionalChanges:e,buildTicks:function(){var t=this,e=t.options.ticks,n=t.getTickLimit(),o={maxTicks:n=Math.max(2,n),min:e.min,max:e.max,stepSize:i.valueOrDefault(e.fixedStepSize,e.stepSize)},r=t.ticks=a.generators.linear(o,t);t.handleDirectionalChanges(),t.max=i.max(r),t.min=i.min(r),e.reverse?(r.reverse(),t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max)},convertTicksToLabels:function(){var e=this;e.ticksAsNumbers=e.ticks.slice(),e.zeroLineIndex=e.ticks.indexOf(0),t.Scale.prototype.convertTicksToLabels.call(e)}})}},{34:34,45:45}],55:[function(t,e,n){"use strict";var i=t(45),a=t(34);e.exports=function(t){var e={position:"left",ticks:{callback:a.formatters.logarithmic}},n=t.Scale.extend({determineDataLimits:function(){function t(t){return s?t.xAxisID===e.id:t.yAxisID===e.id}var e=this,n=e.options,a=n.ticks,o=e.chart,r=o.data.datasets,l=i.valueOrDefault,s=e.isHorizontal();e.min=null,e.max=null,e.minNotZero=null;var u=n.stacked;if(void 0===u&&i.each(r,function(e,n){if(!u){var i=o.getDatasetMeta(n);o.isDatasetVisible(n)&&t(i)&&void 0!==i.stack&&(u=!0)}}),n.stacked||u){var d={};i.each(r,function(a,r){var l=o.getDatasetMeta(r),s=[l.type,void 0===n.stacked&&void 0===l.stack?r:"",l.stack].join(".");o.isDatasetVisible(r)&&t(l)&&(void 0===d[s]&&(d[s]=[]),i.each(a.data,function(t,i){var a=d[s],o=+e.getRightValue(t);isNaN(o)||l.data[i].hidden||(a[i]=a[i]||0,n.relativePoints?a[i]=100:a[i]+=o)}))}),i.each(d,function(t){var n=i.min(t),a=i.max(t);e.min=null===e.min?n:Math.min(e.min,n),e.max=null===e.max?a:Math.max(e.max,a)})}else i.each(r,function(n,a){var r=o.getDatasetMeta(a);o.isDatasetVisible(a)&&t(r)&&i.each(n.data,function(t,n){var i=+e.getRightValue(t);isNaN(i)||r.data[n].hidden||(null===e.min?e.min=i:i<e.min&&(e.min=i),null===e.max?e.max=i:i>e.max&&(e.max=i),0!==i&&(null===e.minNotZero||i<e.minNotZero)&&(e.minNotZero=i))})});e.min=l(a.min,e.min),e.max=l(a.max,e.max),e.min===e.max&&(0!==e.min&&null!==e.min?(e.min=Math.pow(10,Math.floor(i.log10(e.min))-1),e.max=Math.pow(10,Math.floor(i.log10(e.max))+1)):(e.min=1,e.max=10))},buildTicks:function(){var t=this,e=t.options.ticks,n={min:e.min,max:e.max},o=t.ticks=a.generators.logarithmic(n,t);t.isHorizontal()||o.reverse(),t.max=i.max(o),t.min=i.min(o),e.reverse?(o.reverse(),t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max)},convertTicksToLabels:function(){this.tickValues=this.ticks.slice(),t.Scale.prototype.convertTicksToLabels.call(this)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForTick:function(t){return this.getPixelForValue(this.tickValues[t])},getPixelForValue:function(t){var e,n,a,o=this,r=o.start,l=+o.getRightValue(t),s=o.options.ticks;return o.isHorizontal()?(a=i.log10(o.end)-i.log10(r),0===l?n=o.left:(e=o.width,n=o.left+e/a*(i.log10(l)-i.log10(r)))):(e=o.height,0!==r||s.reverse?0===o.end&&s.reverse?(a=i.log10(o.start)-i.log10(o.minNotZero),n=l===o.end?o.top:l===o.minNotZero?o.top+.02*e:o.top+.02*e+.98*e/a*(i.log10(l)-i.log10(o.minNotZero))):0===l?n=s.reverse?o.top:o.bottom:(a=i.log10(o.end)-i.log10(r),e=o.height,n=o.bottom-e/a*(i.log10(l)-i.log10(r))):(a=i.log10(o.end)-i.log10(o.minNotZero),n=l===r?o.bottom:l===o.minNotZero?o.bottom-.02*e:o.bottom-.02*e-.98*e/a*(i.log10(l)-i.log10(o.minNotZero)))),n},getValueForPixel:function(t){var e,n,a=this,o=i.log10(a.end)-i.log10(a.start);return a.isHorizontal()?(n=a.width,e=a.start*Math.pow(10,(t-a.left)*o/n)):(n=a.height,e=Math.pow(10,(a.bottom-t)*o/n)/a.start),e}});t.scaleService.registerScaleType("logarithmic",n,e)}},{34:34,45:45}],56:[function(t,e,n){"use strict";var i=t(25),a=t(45),o=t(34);e.exports=function(t){function e(t){var e=t.options;return e.angleLines.display||e.pointLabels.display?t.chart.data.labels.length:0}function n(t){var e=t.options.pointLabels,n=a.valueOrDefault(e.fontSize,v.defaultFontSize),i=a.valueOrDefault(e.fontStyle,v.defaultFontStyle),o=a.valueOrDefault(e.fontFamily,v.defaultFontFamily);return{size:n,style:i,family:o,font:a.fontString(n,i,o)}}function r(t,e,n){return a.isArray(n)?{w:a.longestText(t,t.font,n),h:n.length*e+1.5*(n.length-1)*e}:{w:t.measureText(n).width,h:e}}function l(t,e,n,i,a){return t===i||t===a?{start:e-n/2,end:e+n/2}:t<i||t>a?{start:e-n-5,end:e}:{start:e,end:e+n+5}}function s(t){var i,o,s,u=n(t),d=Math.min(t.height/2,t.width/2),c={r:t.width,l:0,t:t.height,b:0},h={};t.ctx.font=u.font,t._pointLabelSizes=[];var f=e(t);for(i=0;i<f;i++){s=t.getPointPosition(i,d),o=r(t.ctx,u.size,t.pointLabels[i]||""),t._pointLabelSizes[i]=o;var g=t.getIndexAngle(i),p=a.toDegrees(g)%360,v=l(p,s.x,o.w,0,180),m=l(p,s.y,o.h,90,270);v.start<c.l&&(c.l=v.start,h.l=g),v.end>c.r&&(c.r=v.end,h.r=g),m.start<c.t&&(c.t=m.start,h.t=g),m.end>c.b&&(c.b=m.end,h.b=g)}t.setReductions(d,c,h)}function u(t){var e=Math.min(t.height/2,t.width/2);t.drawingArea=Math.round(e),t.setCenterPoint(0,0,0,0)}function d(t){return 0===t||180===t?"center":t<180?"left":"right"}function c(t,e,n,i){if(a.isArray(e))for(var o=n.y,r=1.5*i,l=0;l<e.length;++l)t.fillText(e[l],n.x,o),o+=r;else t.fillText(e,n.x,n.y)}function h(t,e,n){90===t||270===t?n.y-=e.h/2:(t>270||t<90)&&(n.y-=e.h)}function f(t){var i=t.ctx,o=a.valueOrDefault,r=t.options,l=r.angleLines,s=r.pointLabels;i.lineWidth=l.lineWidth,i.strokeStyle=l.color;var u=t.getDistanceFromCenterForValue(r.ticks.reverse?t.min:t.max),f=n(t);i.textBaseline="top";for(var g=e(t)-1;g>=0;g--){if(l.display){var p=t.getPointPosition(g,u);i.beginPath(),i.moveTo(t.xCenter,t.yCenter),i.lineTo(p.x,p.y),i.stroke(),i.closePath()}if(s.display){var m=t.getPointPosition(g,u+5),b=o(s.fontColor,v.defaultFontColor);i.font=f.font,i.fillStyle=b;var x=t.getIndexAngle(g),y=a.toDegrees(x);i.textAlign=d(y),h(y,t._pointLabelSizes[g],m),c(i,t.pointLabels[g]||"",m,f.size)}}}function g(t,n,i,o){var r=t.ctx;if(r.strokeStyle=a.valueAtIndexOrDefault(n.color,o-1),r.lineWidth=a.valueAtIndexOrDefault(n.lineWidth,o-1),t.options.gridLines.circular)r.beginPath(),r.arc(t.xCenter,t.yCenter,i,0,2*Math.PI),r.closePath(),r.stroke();else{var l=e(t);if(0===l)return;r.beginPath();var s=t.getPointPosition(0,i);r.moveTo(s.x,s.y);for(var u=1;u<l;u++)s=t.getPointPosition(u,i),r.lineTo(s.x,s.y);r.closePath(),r.stroke()}}function p(t){return a.isNumber(t)?t:0}var v=i.global,m={display:!0,animate:!0,position:"chartArea",angleLines:{display:!0,color:"rgba(0, 0, 0, 0.1)",lineWidth:1},gridLines:{circular:!1},ticks:{showLabelBackdrop:!0,backdropColor:"rgba(255,255,255,0.75)",backdropPaddingY:2,backdropPaddingX:2,callback:o.formatters.linear},pointLabels:{display:!0,fontSize:10,callback:function(t){return t}}},b=t.LinearScaleBase.extend({setDimensions:function(){var t=this,e=t.options,n=e.ticks;t.width=t.maxWidth,t.height=t.maxHeight,t.xCenter=Math.round(t.width/2),t.yCenter=Math.round(t.height/2);var i=a.min([t.height,t.width]),o=a.valueOrDefault(n.fontSize,v.defaultFontSize);t.drawingArea=e.display?i/2-(o/2+n.backdropPaddingY):i/2},determineDataLimits:function(){var t=this,e=t.chart,n=Number.POSITIVE_INFINITY,i=Number.NEGATIVE_INFINITY;a.each(e.data.datasets,function(o,r){if(e.isDatasetVisible(r)){var l=e.getDatasetMeta(r);a.each(o.data,function(e,a){var o=+t.getRightValue(e);isNaN(o)||l.data[a].hidden||(n=Math.min(o,n),i=Math.max(o,i))})}}),t.min=n===Number.POSITIVE_INFINITY?0:n,t.max=i===Number.NEGATIVE_INFINITY?0:i,t.handleTickRangeOptions()},getTickLimit:function(){var t=this.options.ticks,e=a.valueOrDefault(t.fontSize,v.defaultFontSize);return Math.min(t.maxTicksLimit?t.maxTicksLimit:11,Math.ceil(this.drawingArea/(1.5*e)))},convertTicksToLabels:function(){var e=this;t.LinearScaleBase.prototype.convertTicksToLabels.call(e),e.pointLabels=e.chart.data.labels.map(e.options.pointLabels.callback,e)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},fit:function(){this.options.pointLabels.display?s(this):u(this)},setReductions:function(t,e,n){var i=this,a=e.l/Math.sin(n.l),o=Math.max(e.r-i.width,0)/Math.sin(n.r),r=-e.t/Math.cos(n.t),l=-Math.max(e.b-i.height,0)/Math.cos(n.b);a=p(a),o=p(o),r=p(r),l=p(l),i.drawingArea=Math.min(Math.round(t-(a+o)/2),Math.round(t-(r+l)/2)),i.setCenterPoint(a,o,r,l)},setCenterPoint:function(t,e,n,i){var a=this,o=a.width-e-a.drawingArea,r=t+a.drawingArea,l=n+a.drawingArea,s=a.height-i-a.drawingArea;a.xCenter=Math.round((r+o)/2+a.left),a.yCenter=Math.round((l+s)/2+a.top)},getIndexAngle:function(t){return t*(2*Math.PI/e(this))+(this.chart.options&&this.chart.options.startAngle?this.chart.options.startAngle:0)*Math.PI*2/360},getDistanceFromCenterForValue:function(t){var e=this;if(null===t)return 0;var n=e.drawingArea/(e.max-e.min);return e.options.ticks.reverse?(e.max-t)*n:(t-e.min)*n},getPointPosition:function(t,e){var n=this,i=n.getIndexAngle(t)-Math.PI/2;return{x:Math.round(Math.cos(i)*e)+n.xCenter,y:Math.round(Math.sin(i)*e)+n.yCenter}},getPointPositionForValue:function(t,e){return this.getPointPosition(t,this.getDistanceFromCenterForValue(e))},getBasePosition:function(){var t=this,e=t.min,n=t.max;return t.getPointPositionForValue(0,t.beginAtZero?0:e<0&&n<0?n:e>0&&n>0?e:0)},draw:function(){var t=this,e=t.options,n=e.gridLines,i=e.ticks,o=a.valueOrDefault;if(e.display){var r=t.ctx,l=this.getIndexAngle(0),s=o(i.fontSize,v.defaultFontSize),u=o(i.fontStyle,v.defaultFontStyle),d=o(i.fontFamily,v.defaultFontFamily),c=a.fontString(s,u,d);a.each(t.ticks,function(e,a){if(a>0||i.reverse){var u=t.getDistanceFromCenterForValue(t.ticksAsNumbers[a]);if(n.display&&0!==a&&g(t,n,u,a),i.display){var d=o(i.fontColor,v.defaultFontColor);if(r.font=c,r.save(),r.translate(t.xCenter,t.yCenter),r.rotate(l),i.showLabelBackdrop){var h=r.measureText(e).width;r.fillStyle=i.backdropColor,r.fillRect(-h/2-i.backdropPaddingX,-u-s/2-i.backdropPaddingY,h+2*i.backdropPaddingX,s+2*i.backdropPaddingY)}r.textAlign="center",r.textBaseline="middle",r.fillStyle=d,r.fillText(e,0,-u),r.restore()}}}),(e.angleLines.display||e.pointLabels.display)&&f(t)}}});t.scaleService.registerScaleType("radialLinear",b,m)}},{25:25,34:34,45:45}],57:[function(t,e,n){"use strict";function i(t,e){return t-e}function a(t){var e,n,i,a={},o=[];for(e=0,n=t.length;e<n;++e)a[i=t[e]]||(a[i]=!0,o.push(i));return o}function o(t,e,n,i){if("linear"===i||!t.length)return[{time:e,pos:0},{time:n,pos:1}];var a,o,r,l,s,u=[],d=[e];for(a=0,o=t.length;a<o;++a)(l=t[a])>e&&l<n&&d.push(l);for(d.push(n),a=0,o=d.length;a<o;++a)s=d[a+1],r=d[a-1],l=d[a],void 0!==r&&void 0!==s&&Math.round((s+r)/2)===l||u.push({time:l,pos:a/(o-1)});return u}function r(t,e,n){for(var i,a,o,r=0,l=t.length-1;r>=0&&r<=l;){if(i=r+l>>1,a=t[i-1]||null,o=t[i],!a)return{lo:null,hi:o};if(o[e]<n)r=i+1;else{if(!(a[e]>n))return{lo:a,hi:o};l=i-1}}return{lo:o,hi:null}}function l(t,e,n,i){var a=r(t,e,n),o=a.lo?a.hi?a.lo:t[t.length-2]:t[0],l=a.lo?a.hi?a.hi:t[t.length-1]:t[1],s=l[e]-o[e],u=s?(n-o[e])/s:0,d=(l[i]-o[i])*u;return o[i]+d}function s(t,e){var n=e.parser,i=e.parser||e.format;return"function"==typeof n?n(t):"string"==typeof t&&"string"==typeof i?v(t,i):(t instanceof v||(t=v(t)),t.isValid()?t:"function"==typeof i?i(t):t)}function u(t,e){if(b.isNullOrUndef(t))return null;var n=e.options.time,i=s(e.getRightValue(t),n);return i.isValid()?(n.round&&i.startOf(n.round),i.valueOf()):null}function d(t,e,n,i){var a,o,r,l=e-t,s=k[n],u=s.size,d=s.steps;if(!d)return Math.ceil(l/((i||1)*u));for(a=0,o=d.length;a<o&&(r=d[a],!(Math.ceil(l/(u*r))<=i));++a);return r}function c(t,e,n,i){var a,o,r,l=w.length;for(a=w.indexOf(t);a<l-1;++a)if(o=k[w[a]],r=o.steps?o.steps[o.steps.length-1]:y,o.common&&Math.ceil((n-e)/(r*o.size))<=i)return w[a];return w[l-1]}function h(t){for(var e=w.indexOf(t)+1,n=w.length;e<n;++e)if(k[w[e]].common)return w[e]}function f(t,e,n,i,a,o){var r,l=o.time,s=b.valueOrDefault(l.stepSize,l.unitStepSize),u="week"===n&&l.isoWeekday,c=o.ticks.major.enabled,h=k[n],f=v(t),g=v(e),p=[];for(s||(s=d(t,e,n,a)),u&&(f=f.isoWeekday(u),g=g.isoWeekday(u)),f=f.startOf(u?"day":n),(g=g.startOf(u?"day":n))<e&&g.add(1,n),r=v(f),c&&i&&!u&&!l.round&&(r.startOf(i),r.add(~~((f-r)/(h.size*s))*s,n));r<g;r.add(s,n))p.push(+r);return p.push(+r),p}function g(t,e,n,i,a){var o,r,s=0,u=0;return a.offset&&e.length&&(a.time.min||(o=e.length>1?e[1]:i,r=e[0],s=(l(t,"time",o,"pos")-l(t,"time",r,"pos"))/2),a.time.max||(o=e[e.length-1],r=e.length>1?e[e.length-2]:n,u=(l(t,"time",o,"pos")-l(t,"time",r,"pos"))/2)),{left:s,right:u}}function p(t,e){var n,i,a,o,r=[];for(n=0,i=t.length;n<i;++n)a=t[n],o=!!e&&a===+v(a).startOf(e),r.push({value:a,major:o});return r}var v=t(1);v="function"==typeof v?v:window.moment;var m=t(25),b=t(45),x=Number.MIN_SAFE_INTEGER||-9007199254740991,y=Number.MAX_SAFE_INTEGER||9007199254740991,k={millisecond:{common:!0,size:1,steps:[1,2,5,10,20,50,100,250,500]},second:{common:!0,size:1e3,steps:[1,2,5,10,30]},minute:{common:!0,size:6e4,steps:[1,2,5,10,30]},hour:{common:!0,size:36e5,steps:[1,2,3,6,12]},day:{common:!0,size:864e5,steps:[1,2,5]},week:{common:!1,size:6048e5,steps:[1,2,3,4]},month:{common:!0,size:2628e6,steps:[1,2,3]},quarter:{common:!1,size:7884e6,steps:[1,2,3,4]},year:{common:!0,size:3154e7}},w=Object.keys(k);e.exports=function(t){var e={position:"bottom",distribution:"linear",bounds:"data",time:{parser:!1,format:!1,unit:!1,round:!1,displayFormat:!1,isoWeekday:!1,minUnit:"millisecond",displayFormats:{millisecond:"h:mm:ss.SSS a",second:"h:mm:ss a",minute:"h:mm a",hour:"hA",day:"MMM D",week:"ll",month:"MMM YYYY",quarter:"[Q]Q - YYYY",year:"YYYY"}},ticks:{autoSkip:!1,source:"auto",major:{enabled:!1}}},n=t.Scale.extend({initialize:function(){if(!v)throw new Error("Chart.js - Moment.js could not be found! You must include it before Chart.js to use the time scale. Download at https://momentjs.com");this.mergeTicksOptions(),t.Scale.prototype.initialize.call(this)},update:function(){var e=this,n=e.options;return n.time&&n.time.format&&console.warn("options.time.format is deprecated and replaced by options.time.parser."),t.Scale.prototype.update.apply(e,arguments)},getRightValue:function(e){return e&&void 0!==e.t&&(e=e.t),t.Scale.prototype.getRightValue.call(this,e)},determineDataLimits:function(){var t,e,n,o,r,l,s=this,d=s.chart,c=s.options.time,h=u(c.min,s)||y,f=u(c.max,s)||x,g=[],p=[],m=[];for(t=0,n=d.data.labels.length;t<n;++t)m.push(u(d.data.labels[t],s));for(t=0,n=(d.data.datasets||[]).length;t<n;++t)if(d.isDatasetVisible(t))if(r=d.data.datasets[t].data,b.isObject(r[0]))for(p[t]=[],e=0,o=r.length;e<o;++e)l=u(r[e],s),g.push(l),p[t][e]=l;else g.push.apply(g,m),p[t]=m.slice(0);else p[t]=[];m.length&&(m=a(m).sort(i),h=Math.min(h,m[0]),f=Math.max(f,m[m.length-1])),g.length&&(g=a(g).sort(i),h=Math.min(h,g[0]),f=Math.max(f,g[g.length-1])),h=h===y?+v().startOf("day"):h,f=f===x?+v().endOf("day")+1:f,s.min=Math.min(h,f),s.max=Math.max(h+1,f),s._horizontal=s.isHorizontal(),s._table=[],s._timestamps={data:g,datasets:p,labels:m}},buildTicks:function(){var t,e,n,i=this,a=i.min,r=i.max,l=i.options,s=l.time,d=s.displayFormats,v=i.getLabelCapacity(a),m=s.unit||c(s.minUnit,a,r,v),b=h(m),x=[],y=[];switch(l.ticks.source){case"data":x=i._timestamps.data;break;case"labels":x=i._timestamps.labels;break;case"auto":default:x=f(a,r,m,b,v,l)}for("ticks"===l.bounds&&x.length&&(a=x[0],r=x[x.length-1]),a=u(s.min,i)||a,r=u(s.max,i)||r,t=0,e=x.length;t<e;++t)(n=x[t])>=a&&n<=r&&y.push(n);return i.min=a,i.max=r,i._unit=m,i._majorUnit=b,i._minorFormat=d[m],i._majorFormat=d[b],i._table=o(i._timestamps.data,a,r,l.distribution),i._offsets=g(i._table,y,a,r,l),p(y,b)},getLabelForIndex:function(t,e){var n=this,i=n.chart.data,a=n.options.time,o=i.labels&&t<i.labels.length?i.labels[t]:"",r=i.datasets[e].data[t];return b.isObject(r)&&(o=n.getRightValue(r)),a.tooltipFormat&&(o=s(o,a).format(a.tooltipFormat)),o},tickFormatFunction:function(t,e,n){var i=this,a=i.options,o=t.valueOf(),r=i._majorUnit,l=i._majorFormat,s=t.clone().startOf(i._majorUnit).valueOf(),u=a.ticks.major,d=u.enabled&&r&&l&&o===s,c=t.format(d?l:i._minorFormat),h=d?u:a.ticks.minor,f=b.valueOrDefault(h.callback,h.userCallback);return f?f(c,e,n):c},convertTicksToLabels:function(t){var e,n,i=[];for(e=0,n=t.length;e<n;++e)i.push(this.tickFormatFunction(v(t[e].value),e,t));return i},getPixelForOffset:function(t){var e=this,n=e._horizontal?e.width:e.height,i=e._horizontal?e.left:e.top,a=l(e._table,"time",t,"pos");return i+n*(e._offsets.left+a)/(e._offsets.left+1+e._offsets.right)},getPixelForValue:function(t,e,n){var i=this,a=null;if(void 0!==e&&void 0!==n&&(a=i._timestamps.datasets[n][e]),null===a&&(a=u(t,i)),null!==a)return i.getPixelForOffset(a)},getPixelForTick:function(t){var e=this.getTicks();return t>=0&&t<e.length?this.getPixelForOffset(e[t].value):null},getValueForPixel:function(t){var e=this,n=e._horizontal?e.width:e.height,i=e._horizontal?e.left:e.top,a=(n?(t-i)/n:0)*(e._offsets.left+1+e._offsets.left)-e._offsets.right,o=l(e._table,"pos",a,"time");return v(o)},getLabelWidth:function(t){var e=this,n=e.options.ticks,i=e.ctx.measureText(t).width,a=b.toRadians(n.maxRotation),o=Math.cos(a),r=Math.sin(a);return i*o+b.valueOrDefault(n.fontSize,m.global.defaultFontSize)*r},getLabelCapacity:function(t){var e=this;e._minorFormat=e.options.time.displayFormats.millisecond;var n=e.tickFormatFunction(v(t),0,[]),i=e.getLabelWidth(n),a=e.isHorizontal()?e.width:e.height;return Math.floor(a/i)}});t.scaleService.registerScaleType("time",n,e)}},{1:1,25:25,45:45}]},{},[7])(7)});
assets/js/admin.js ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(document).ready(function () {
2
+ // Check setting page
3
+ if (jQuery('.wp-statistics-settings').length) {
4
+
5
+ var current_tab = getParameterValue('tab');
6
+ if (current_tab) {
7
+ enableTab(current_tab);
8
+ }
9
+
10
+ jQuery('.wp-statistics-settings ul.tabs li').click(function () {
11
+ var tab_id = jQuery(this).attr('data-tab');
12
+ enableTab(tab_id);
13
+ });
14
+ }
15
+
16
+ /**
17
+ * Get Parameter value
18
+ * @param name
19
+ * @returns {*}
20
+ */
21
+ function getParameterValue(name) {
22
+ var results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(window.location.href);
23
+ if (results) {
24
+ return results[1];
25
+ }
26
+ }
27
+
28
+ /**
29
+ * Enable Tab
30
+ * @param tab_id
31
+ */
32
+ function enableTab(tab_id) {
33
+ jQuery('.wp-statistics-settings ul.tabs li').removeClass('current');
34
+ jQuery('.wp-statistics-settings .tab-content').removeClass('current');
35
+
36
+ jQuery("[data-tab=" + tab_id + "]").addClass('current');
37
+ jQuery("#" + tab_id).addClass('current');
38
+
39
+ if (jQuery('#wp-statistics-settings-form').length) {
40
+ var click_url = jQuery(location).attr('href') + '&tab=' + tab_id;
41
+ jQuery('#wp-statistics-settings-form').attr('action', click_url).submit();
42
+ }
43
+ }
44
+ });
composer.json CHANGED
@@ -1,6 +1,11 @@
1
  {
2
- "require": {
3
- "geoip2/geoip2": "2.*",
4
- "s1lentium/iptools": "*"
5
- }
 
 
 
 
 
6
  }
1
  {
2
+ "require": {
3
+ "geoip2/geoip2": "2.*",
4
+ "s1lentium/iptools": "*",
5
+ "donatj/phpuseragentparser": "*",
6
+ "garetjax/phpbrowscap": "*"
7
+ },
8
+ "config": {
9
+ "vendor-dir": "includes/vendor"
10
+ }
11
  }
composer.lock CHANGED
@@ -4,7 +4,7 @@
4
  "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
5
  "This file is @generated automatically"
6
  ],
7
- "content-hash": "b02574b3168e88e8f4d17f9f12d910a4",
8
  "packages": [
9
  {
10
  "name": "composer/ca-bundle",
@@ -65,18 +65,112 @@
65
  ],
66
  "time": "2017-09-11T07:24:36+00:00"
67
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  {
69
  "name": "geoip2/geoip2",
70
- "version": "v2.6.0",
71
  "source": {
72
  "type": "git",
73
  "url": "https://github.com/maxmind/GeoIP2-php.git",
74
- "reference": "9f6f1edf9901fed5cd692dd260333bf52091acd3"
75
  },
76
  "dist": {
77
  "type": "zip",
78
- "url": "https://api.github.com/repos/maxmind/GeoIP2-php/zipball/9f6f1edf9901fed5cd692dd260333bf52091acd3",
79
- "reference": "9f6f1edf9901fed5cd692dd260333bf52091acd3",
80
  "shasum": ""
81
  },
82
  "require": {
@@ -116,33 +210,34 @@
116
  "geolocation",
117
  "maxmind"
118
  ],
119
- "time": "2017-07-10T17:59:43+00:00"
120
  },
121
  {
122
  "name": "maxmind-db/reader",
123
- "version": "v1.1.3",
124
  "source": {
125
  "type": "git",
126
  "url": "https://github.com/maxmind/MaxMind-DB-Reader-php.git",
127
- "reference": "7eeccf61b078bb23bb07b1a151a7e5db52871e65"
128
  },
129
  "dist": {
130
  "type": "zip",
131
- "url": "https://api.github.com/repos/maxmind/MaxMind-DB-Reader-php/zipball/7eeccf61b078bb23bb07b1a151a7e5db52871e65",
132
- "reference": "7eeccf61b078bb23bb07b1a151a7e5db52871e65",
133
  "shasum": ""
134
  },
135
  "require": {
136
- "php": ">=5.3.1"
137
  },
138
  "require-dev": {
139
- "phpunit/phpunit": "4.2.*",
 
140
  "satooshi/php-coveralls": "1.0.*",
141
- "squizlabs/php_codesniffer": "2.*"
142
  },
143
  "suggest": {
144
- "ext-bcmath": "bcmath or gmp is requred for decoding larger integers with the pure PHP decoder",
145
- "ext-gmp": "bcmath or gmp is requred for decoding larger integers with the pure PHP decoder",
146
  "ext-maxminddb": "A C-based database decoder that provides significantly faster lookups"
147
  },
148
  "type": "library",
@@ -171,7 +266,7 @@
171
  "geolocation",
172
  "maxmind"
173
  ],
174
- "time": "2017-01-19T23:49:38+00:00"
175
  },
176
  {
177
  "name": "maxmind/web-service-common",
4
  "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
5
  "This file is @generated automatically"
6
  ],
7
+ "content-hash": "d0dfa74fe673b70917290c46512c2ef4",
8
  "packages": [
9
  {
10
  "name": "composer/ca-bundle",
65
  ],
66
  "time": "2017-09-11T07:24:36+00:00"
67
  },
68
+ {
69
+ "name": "donatj/phpuseragentparser",
70
+ "version": "v0.9.0",
71
+ "source": {
72
+ "type": "git",
73
+ "url": "https://github.com/donatj/PhpUserAgent.git",
74
+ "reference": "ea79de6a18e52285e62cd75cf1cebe276ecaf503"
75
+ },
76
+ "dist": {
77
+ "type": "zip",
78
+ "url": "https://api.github.com/repos/donatj/PhpUserAgent/zipball/ea79de6a18e52285e62cd75cf1cebe276ecaf503",
79
+ "reference": "ea79de6a18e52285e62cd75cf1cebe276ecaf503",
80
+ "shasum": ""
81
+ },
82
+ "require": {
83
+ "php": ">=5.3.0"
84
+ },
85
+ "require-dev": {
86
+ "camspiers/json-pretty": "0.1.*",
87
+ "donatj/drop": "*",
88
+ "phpunit/phpunit": "~4.8"
89
+ },
90
+ "type": "library",
91
+ "autoload": {
92
+ "files": [
93
+ "Source/UserAgentParser.php"
94
+ ]
95
+ },
96
+ "notification-url": "https://packagist.org/downloads/",
97
+ "license": [
98
+ "MIT"
99
+ ],
100
+ "authors": [
101
+ {
102
+ "name": "Jesse G. Donat",
103
+ "email": "donatj@gmail.com",
104
+ "homepage": "http://donatstudios.com",
105
+ "role": "Developer"
106
+ }
107
+ ],
108
+ "description": "Simple, streamlined PHP user-agent parser",
109
+ "homepage": "http://donatstudios.com/PHP-Parser-HTTP_USER_AGENT",
110
+ "keywords": [
111
+ "browser",
112
+ "browser detection",
113
+ "parser",
114
+ "user agent",
115
+ "useragent"
116
+ ],
117
+ "time": "2017-10-23T16:52:52+00:00"
118
+ },
119
+ {
120
+ "name": "garetjax/phpbrowscap",
121
+ "version": "2.0",
122
+ "source": {
123
+ "type": "git",
124
+ "url": "https://github.com/GaretJax/phpbrowscap.git",
125
+ "reference": "ed661716d0d9158bac6ab3b074b18b70f8d18bef"
126
+ },
127
+ "dist": {
128
+ "type": "zip",
129
+ "url": "https://api.github.com/repos/GaretJax/phpbrowscap/zipball/ed661716d0d9158bac6ab3b074b18b70f8d18bef",
130
+ "reference": "ed661716d0d9158bac6ab3b074b18b70f8d18bef",
131
+ "shasum": ""
132
+ },
133
+ "require": {
134
+ "php": ">=5.3.0"
135
+ },
136
+ "type": "library",
137
+ "autoload": {
138
+ "psr-0": {
139
+ "phpbrowscap": "src/"
140
+ }
141
+ },
142
+ "notification-url": "https://packagist.org/downloads/",
143
+ "license": [
144
+ "MIT License"
145
+ ],
146
+ "authors": [
147
+ {
148
+ "name": "Jonathan Stoppani",
149
+ "email": "jonathan.stoppani@gmail.com"
150
+ }
151
+ ],
152
+ "description": "Standalone replacement for php's native get_browser() function",
153
+ "homepage": "http://github.com/GaretJax/phpbrowscap",
154
+ "keywords": [
155
+ "browser",
156
+ "capabilities",
157
+ "get_browser",
158
+ "user agent"
159
+ ],
160
+ "time": "2014-02-04T09:18:51+00:00"
161
+ },
162
  {
163
  "name": "geoip2/geoip2",
164
+ "version": "v2.7.0",
165
  "source": {
166
  "type": "git",
167
  "url": "https://github.com/maxmind/GeoIP2-php.git",
168
+ "reference": "ca9f9a244474d97eac1ef542aaced7cc944bafbe"
169
  },
170
  "dist": {
171
  "type": "zip",
172
+ "url": "https://api.github.com/repos/maxmind/GeoIP2-php/zipball/ca9f9a244474d97eac1ef542aaced7cc944bafbe",
173
+ "reference": "ca9f9a244474d97eac1ef542aaced7cc944bafbe",
174
  "shasum": ""
175
  },
176
  "require": {
210
  "geolocation",
211
  "maxmind"
212
  ],
213
+ "time": "2017-10-27T19:20:22+00:00"
214
  },
215
  {
216
  "name": "maxmind-db/reader",
217
+ "version": "v1.2.0",
218
  "source": {
219
  "type": "git",
220
  "url": "https://github.com/maxmind/MaxMind-DB-Reader-php.git",
221
+ "reference": "1647820dfbcb552222fb5feb3a8387e2636394c9"
222
  },
223
  "dist": {
224
  "type": "zip",
225
+ "url": "https://api.github.com/repos/maxmind/MaxMind-DB-Reader-php/zipball/1647820dfbcb552222fb5feb3a8387e2636394c9",
226
+ "reference": "1647820dfbcb552222fb5feb3a8387e2636394c9",
227
  "shasum": ""
228
  },
229
  "require": {
230
+ "php": ">=5.4"
231
  },
232
  "require-dev": {
233
+ "friendsofphp/php-cs-fixer": "2.*",
234
+ "phpunit/phpunit": "4.*",
235
  "satooshi/php-coveralls": "1.0.*",
236
+ "squizlabs/php_codesniffer": "3.*"
237
  },
238
  "suggest": {
239
+ "ext-bcmath": "bcmath or gmp is required for decoding larger integers with the pure PHP decoder",
240
+ "ext-gmp": "bcmath or gmp is required for decoding larger integers with the pure PHP decoder",
241
  "ext-maxminddb": "A C-based database decoder that provides significantly faster lookups"
242
  },
243
  "type": "library",
266
  "geolocation",
267
  "maxmind"
268
  ],
269
+ "time": "2017-10-27T19:15:33+00:00"
270
  },
271
  {
272
  "name": "maxmind/web-service-common",
dashboard.php DELETED
@@ -1,233 +0,0 @@
1
- <?php
2
- add_action( 'wp_dashboard_setup', 'wp_statistics_dashboard_widget_load' );
3
- add_action( 'admin_footer', 'wp_statistics_dashboard_inline_javascript' );
4
-
5
- function wp_statistics_dashboard_widget_load() {
6
- GLOBAL $WP_Statistics;
7
-
8
- $WP_Statistics->load_user_options();
9
-
10
- // We need to fudge the display settings for first time users so not all of the widgets are displayed, we only want to do this on
11
- // the first time they visit the dashboard though so check to see if we've been here before.
12
- if ( ! $WP_Statistics->get_user_option( 'dashboard_set' ) ) {
13
- $WP_Statistics->update_user_option( 'dashboard_set', WP_STATISTICS_VERSION );
14
-
15
- $hidden_widgets = get_user_meta( $WP_Statistics->user_id, 'metaboxhidden_dashboard', true );
16
- if ( ! is_array( $hidden_widgets ) ) {
17
- $hidden_widgets = array();
18
- }
19
-
20
- $default_hidden = array(
21
- 'wp-statistics-browsers-widget',
22
- 'wp-statistics-countries-widget',
23
- 'wp-statistics-hitsmap-widget',
24
- 'wp-statistics-hits-widget',
25
- 'wp-statistics-pages-widget',
26
- 'wp-statistics-recent-widget',
27
- 'wp-statistics-referring-widget',
28
- 'wp-statistics-search-widget',
29
- 'wp-statistics-summary-widget',
30
- 'wp-statistics-words-widget',
31
- 'wp-statistics-top-visitors-widget'
32
- );
33
-
34
- foreach ( $default_hidden as $widget ) {
35
- if ( ! in_array( $widget, $hidden_widgets ) ) {
36
- $hidden_widgets[] = $widget;
37
- }
38
- }
39
-
40
- update_user_meta( $WP_Statistics->user_id, 'metaboxhidden_dashboard', $hidden_widgets );
41
- } else if ( $WP_Statistics->get_user_option( 'dashboard_set' ) != WP_STATISTICS_VERSION ) {
42
- // We also have to fudge things when we add new widgets to the code base.
43
- if ( version_compare( $WP_Statistics->get_user_option( 'dashboard_set' ), '8.7', '<' ) ) {
44
-
45
- $WP_Statistics->update_user_option( 'dashboard_set', WP_STATISTICS_VERSION );
46
-
47
- $hidden_widgets = get_user_meta( $WP_Statistics->user_id, 'metaboxhidden_dashboard', true );
48
- if ( ! is_array( $hidden_widgets ) ) {
49
- $hidden_widgets = array();
50
- }
51
-
52
- $default_hidden = array( 'wp-statistics-top-visitors-widget' );
53
-
54
- foreach ( $default_hidden as $widget ) {
55
- if ( ! in_array( $widget, $hidden_widgets ) ) {
56
- $hidden_widgets[] = $widget;
57
- }
58
- }
59
-
60
- update_user_meta( $WP_Statistics->user_id, 'metaboxhidden_dashboard', $hidden_widgets );
61
- }
62
- }
63
-
64
- // If the user does not have at least read access to the status plugin, just return without adding the widgets.
65
- if ( ! current_user_can( wp_statistics_validate_capability( $WP_Statistics->get_option( 'read_capability', 'manage_option' ) ) ) ) {
66
- return;
67
- }
68
-
69
- // If the admin has disabled the widgets, don't display them.
70
- if ( ! $WP_Statistics->get_option( 'disable_dashboard' ) ) {
71
- wp_add_dashboard_widget( 'wp-statistics-quickstats-widget', __( 'Quick Stats', 'wp-statistics' ), 'wp_statistics_generate_dashboard_postbox_contents', $control_callback = null, array( 'widget' => 'quickstats' ) );
72
- if ( $WP_Statistics->get_option( 'visitors' ) ) {
73
- wp_add_dashboard_widget( 'wp-statistics-browsers-widget', __( 'Top 10 Browsers', 'wp-statistics' ), 'wp_statistics_generate_dashboard_postbox_contents', $control_callback = null, array( 'widget' => 'browsers' ) );
74
- }
75
- if ( $WP_Statistics->get_option( 'geoip' ) && $WP_Statistics->get_option( 'visitors' ) ) {
76
- wp_add_dashboard_widget( 'wp-statistics-countries-widget', __( 'Top 10 Countries', 'wp-statistics' ), 'wp_statistics_generate_dashboard_postbox_contents', $control_callback = null, array( 'widget' => 'countries' ) );
77
- }
78
- if ( $WP_Statistics->get_option( 'visitors' ) ) {
79
- wp_add_dashboard_widget( 'wp-statistics-hitsmap-widget', __( 'Today\'s Visitors Map', 'wp-statistics' ), 'wp_statistics_generate_dashboard_postbox_contents', $control_callback = null, array( 'widget' => 'hitsmap' ) );
80
- }
81
- if ( $WP_Statistics->get_option( 'visits' ) ) {
82
- wp_add_dashboard_widget( 'wp-statistics-hits-widget', __( 'Hit Statistics', 'wp-statistics' ), 'wp_statistics_generate_dashboard_postbox_contents', $control_callback = null, array( 'widget' => 'hits' ) );
83
- }
84
- if ( $WP_Statistics->get_option( 'pages' ) ) {
85
- wp_add_dashboard_widget( 'wp-statistics-pages-widget', __( 'Top 10 Pages', 'wp-statistics' ), 'wp_statistics_generate_dashboard_postbox_contents', $control_callback = null, array( 'widget' => 'pages' ) );
86
- }
87
- if ( $WP_Statistics->get_option( 'visitors' ) ) {
88
- wp_add_dashboard_widget( 'wp-statistics-recent-widget', __( 'Recent Visitors', 'wp-statistics' ), 'wp_statistics_generate_dashboard_postbox_contents', $control_callback = null, array( 'widget' => 'recent' ) );
89
- }
90
- if ( $WP_Statistics->get_option( 'visitors' ) ) {
91
- wp_add_dashboard_widget( 'wp-statistics-referring-widget', __( 'Top Referring Sites', 'wp-statistics' ), 'wp_statistics_generate_dashboard_postbox_contents', $control_callback = null, array( 'widget' => 'referring' ) );
92
- }
93
- if ( $WP_Statistics->get_option( 'visitors' ) ) {
94
- wp_add_dashboard_widget( 'wp-statistics-search-widget', __( 'Search Engine Referrals', 'wp-statistics' ), 'wp_statistics_generate_dashboard_postbox_contents', $control_callback = null, array( 'widget' => 'search' ) );
95
- }
96
- wp_add_dashboard_widget( 'wp-statistics-summary-widget', __( 'Summary', 'wp-statistics' ), 'wp_statistics_generate_dashboard_postbox_contents', $control_callback = null, array( 'widget' => 'summary' ) );
97
- if ( $WP_Statistics->get_option( 'visitors' ) ) {
98
- wp_add_dashboard_widget( 'wp-statistics-words-widget', __( 'Latest Search Words', 'wp-statistics' ), 'wp_statistics_generate_dashboard_postbox_contents', $control_callback = null, array( 'widget' => 'words' ) );
99
- }
100
- if ( $WP_Statistics->get_option( 'visitors' ) ) {
101
- wp_add_dashboard_widget( 'wp-statistics-top-visitors-widget', __( 'Top 10 Visitors Today', 'wp-statistics' ), 'wp_statistics_generate_dashboard_postbox_contents', $control_callback = null, array( 'widget' => 'top.visitors' ) );
102
- }
103
- }
104
- }
105
-
106
- function wp_statistics_load_widget_css_and_scripts() {
107
- GLOBAL $WP_Statistics;
108
-
109
- // Load the css we use for the statistics pages.
110
- wp_enqueue_style( 'wpstatistics-log-css', plugin_dir_url( __FILE__ ) . 'assets/css/log.css', true, '1.1' );
111
- wp_enqueue_style( 'wpstatistics-admin-css', plugin_dir_url( __FILE__ ) . 'assets/css/admin.css', true, '1.0' );
112
-
113
- // Don't forget the right to left support.
114
- if ( is_rtl() ) {
115
- wp_enqueue_style( 'rtl-css', plugin_dir_url( __FILE__ ) . 'assets/css/rtl.css', true, '1.1' );
116
- }
117
-
118
- // Load the map code.
119
- wp_enqueue_style( 'jqvmap-css', plugin_dir_url( __FILE__ ) . 'assets/jqvmap/jqvmap.css', true, '1.5.1' );
120
- wp_enqueue_script( 'jquery-vmap', plugin_dir_url( __FILE__ ) . 'assets/jqvmap/jquery.vmap.js', true, '1.5.1' );
121
- wp_enqueue_script( 'jquery-vmap-world', plugin_dir_url( __FILE__ ) . 'assets/jqvmap/maps/jquery.vmap.world.js', true, '1.5.1' );
122
-
123
- // Load chart library
124
- if ( !isset( $_GET['post'] ) ) {
125
- wp_enqueue_script( 'wp-statistics-chart-js', WP_STATISTICS_PLUGIN_DIR . 'assets/js/Chart.bundle.min.js', false, '2.7.0' );
126
- }
127
-
128
- $screen = get_current_screen();
129
-
130
- // Load our custom widgets handling javascript.
131
- if ( 'post' == $screen->id || 'page' == $screen->id ) {
132
- wp_enqueue_script( 'wp_statistics_editor', plugin_dir_url( __FILE__ ) . 'assets/js/editor.js' );
133
- } else {
134
- wp_enqueue_script( 'wp_statistics_dashboard', plugin_dir_url( __FILE__ ) . 'assets/js/dashboard.js' );
135
- }
136
- }
137
-
138
- function wp_statistics_generate_dashboard_postbox_contents( $post, $args ) {
139
- $loading_img = '<div style="width: 100%; text-align: center;"><img src=" ' . plugins_url( 'wp-statistics/assets/images/' ) . 'ajax-loading.gif" alt="' . __( 'Loading...', 'wp-statistics' ) . '"></div>';
140
- $widget = $args['args']['widget'];
141
- $container_id = 'wp-statistics-' . str_replace( '.', '-', $widget ) . '-div';
142
-
143
- echo '<div id="' . $container_id . '">' . $loading_img . '</div>';
144
- wp_statistics_generate_widget_load_javascript( $widget, $container_id );
145
- }
146
-
147
-
148
- function wp_statistics_dashboard_inline_javascript() {
149
- $screen = get_current_screen();
150
-
151
- if ( 'dashboard' != $screen->id ) {
152
- return;
153
- }
154
-
155
- wp_statistics_load_widget_css_and_scripts();
156
-
157
- $loading_img = '<div style="width: 100%; text-align: center;"><img src=" ' . plugins_url( 'wp-statistics/assets/images/' ) . 'ajax-loading.gif" alt="' . __( 'Reloading...', 'wp-statistics' ) . '"></div>';
158
-
159
- $new_buttons = '</button><button class="handlediv button-link wps-refresh" type="button" id="{{refreshid}}">' . wp_statistics_icons( 'dashicons-update' ) . '<span class="screen-reader-text">' . __( 'Reload', 'wp-statistics' ) . '</span></button><button class="handlediv button-link wps-more" type="button" id="{{moreid}}">' . wp_statistics_icons( 'dashicons-migrate' ) . '<span class="screen-reader-text">' . __( 'More Details', 'wp-statistics' ) . '</span></button>';
160
- $new_button = '</button><button class="handlediv button-link wps-refresh" type="button" id="{{refreshid}}">' . wp_statistics_icons( 'dashicons-update' ) . '<span class="screen-reader-text">' . __( 'Reload', 'wp-statistics' ) . '</span></button>';
161
-
162
- $admin_url = get_admin_url() . "admin.php?page=";
163
-
164
- $page_urls = array();
165
-
166
- $page_urls['wp-statistics-browsers-widget_more_button'] = $admin_url . WP_STATISTICS_BROWSERS_PAGE;
167
- $page_urls['wp-statistics-countries-widget_more_button'] = $admin_url . WP_STATISTICS_COUNTRIES_PAGE;
168
- $page_urls['wp-statistics-exclusions-widget_more_button'] = $admin_url . WP_STATISTICS_EXCLUSIONS_PAGE;
169
- $page_urls['wp-statistics-hits-widget_more_button'] = $admin_url . WP_STATISTICS_HITS_PAGE;
170
- $page_urls['wp-statistics-online-widget_more_button'] = $admin_url . WP_STATISTICS_ONLINE_PAGE;
171
- $page_urls['wp-statistics-pages-widget_more_button'] = $admin_url . WP_STATISTICS_PAGES_PAGE;
172
- $page_urls['wp-statistics-referring-widget_more_button'] = $admin_url . WP_STATISTICS_REFERRERS_PAGE;
173
- $page_urls['wp-statistics-search-widget_more_button'] = $admin_url . WP_STATISTICS_SEARCHES_PAGE;
174
- $page_urls['wp-statistics-words-widget_more_button'] = $admin_url . WP_STATISTICS_WORDS_PAGE;
175
- $page_urls['wp-statistics-top-visitors-widget_more_button'] = $admin_url . WP_STATISTICS_TOP_VISITORS_PAGE;
176
- $page_urls['wp-statistics-recent-widget_more_button'] = $admin_url . WP_STATISTICS_VISITORS_PAGE;
177
- $page_urls['wp-statistics-quickstats-widget_more_button'] = $admin_url . WP_STATISTICS_OVERVIEW_PAGE;
178
-
179
- ?>
180
- <script type="text/javascript">
181
- var wp_statistics_destinations = <?php echo json_encode( $page_urls ); ?>;
182
- var wp_statistics_loading_image = '<?php echo $loading_img; ?>';
183
-
184
- function wp_statistics_wait_for_postboxes() {
185
-
186
- if (!jQuery('#show-settings-link').is(':visible')) {
187
- setTimeout(wp_statistics_wait_for_postboxes, 500);
188
- }
189
-
190
- jQuery('.wps-refresh').unbind('click').on('click', wp_statistics_refresh_widget);
191
- jQuery('.wps-more').unbind('click').on('click', wp_statistics_goto_more);
192
-
193
- jQuery('.hide-postbox-tog').on('click', wp_statistics_refresh_on_toggle_widget);
194
- }
195
-
196
- jQuery(document).ready(function () {
197
-
198
- // Add the "more" and "refresh" buttons.
199
- jQuery('.postbox').each(function () {
200
- var temp = jQuery(this);
201
- var temp_id = temp.attr('id');
202
-
203
- if (temp_id.substr(0, 14) != 'wp-statistics-') {
204
- return;
205
- }
206
-
207
- var temp_html = temp.html();
208
-
209
- if (temp_id == 'wp-statistics-summary-widget') {
210
- new_text = '<?php echo $new_button;?>';
211
- new_text = new_text.replace('{{refreshid}}', temp_id + '_refresh_button');
212
-
213
- temp_html = temp_html.replace('</button>', new_text);
214
- } else {
215
- new_text = '<?php echo $new_buttons;?>';
216
- new_text = new_text.replace('{{refreshid}}', temp_id + '_refresh_button');
217
- new_text = new_text.replace('{{moreid}}', temp_id + '_more_button');
218
-
219
- temp_html = temp_html.replace('</button>', new_text);
220
- }
221
-
222
- temp.html(temp_html);
223
- });
224
-
225
- // We have use a timeout here because we don't now what order this code will run in comparison to the postbox code.
226
- // Any timeout value should work as the timeout won't run until the rest of the javascript as run through once.
227
- setTimeout(wp_statistics_wait_for_postboxes, 100);
228
- });
229
- </script>
230
- <?php
231
- }
232
-
233
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
editor.php DELETED
@@ -1,152 +0,0 @@
1
- <?php
2
- /*
3
- Adds a box to the main column on the Post and Page edit screens.
4
- */
5
- function wp_statistics_add_editor_meta_box() {
6
- GLOBAL $WP_Statistics;
7
-
8
- $WP_Statistics->load_user_options();
9
-
10
- // We need to fudge the display settings for first time users so not all of the widgets are displayed, we only want to do this on
11
- // the first time they visit the dashboard though so check to see if we've been here before.
12
- if ( ! $WP_Statistics->get_user_option( 'editor_set' ) ) {
13
- $WP_Statistics->update_user_option( 'editor_set', WP_STATISTICS_VERSION );
14
-
15
- $hidden_widgets = get_user_meta( $WP_Statistics->user_id, 'metaboxhidden_post', true );
16
- if ( ! is_array( $hidden_widgets ) ) {
17
- $hidden_widgets = array();
18
- }
19
-
20
- if ( ! in_array( 'wp_statistics_editor_meta_box', $hidden_widgets ) ) {
21
- $hidden_widgets[] = 'wp_statistics_editor_meta_box';
22
- }
23
-
24
- update_user_meta( $WP_Statistics->user_id, 'metaboxhidden_post', $hidden_widgets );
25
-
26
- $hidden_widgets = get_user_meta( $WP_Statistics->user_id, 'metaboxhidden_page', true );
27
- if ( ! is_array( $hidden_widgets ) ) {
28
- $hidden_widgets = array();
29
- }
30
-
31
- if ( ! in_array( 'wp_statistics_editor_meta_box', $hidden_widgets ) ) {
32
- $hidden_widgets[] = 'wp_statistics_editor_meta_box';
33
- }
34
-
35
- update_user_meta( $WP_Statistics->user_id, 'metaboxhidden_page', $hidden_widgets );
36
- }
37
-
38
- // If the user does not have at least read access to the status plugin, just return without adding the widgets.
39
- if ( ! current_user_can( wp_statistics_validate_capability( $WP_Statistics->get_option( 'read_capability', 'manage_option' ) ) ) ) {
40
- return;
41
- }
42
-
43
- // If the admin has disabled the widgets don't display them.
44
- if ( $WP_Statistics->get_option( 'disable_editor' ) ) {
45
- return;
46
- }
47
-
48
- $screens = array( 'post', 'page' );
49
-
50
- foreach ( $screens as $screen ) {
51
-
52
- add_meta_box(
53
- 'wp_statistics_editor_meta_box',
54
- __( 'Hit Statistics', 'wp-statistics' ),
55
- 'wp_statistics_editor_meta_box',
56
- $screen,
57
- 'normal',
58
- 'high'
59
- );
60
- }
61
- }
62
-
63
- add_action( 'add_meta_boxes', 'wp_statistics_add_editor_meta_box' );
64
-
65
- function wp_statistics_editor_meta_box( $post ) {
66
- // If the post isn't published yet, don't output the stats as they take too much memory and CPU to compute for no reason.
67
- if ( $post->post_status != 'publish' && $post->post_status != 'private' ) {
68
- _e( 'This post is not yet published.', 'wp-statistics' );
69
-
70
- return;
71
- }
72
-
73
- add_action( 'admin_footer', 'wp_statistics_editor_inline_javascript' );
74
-
75
- wp_statistics_generate_editor_postbox_contents( $post->ID, array( 'args' => array( 'widget' => 'page' ) ) );
76
- }
77
-
78
- function wp_statistics_generate_editor_postbox_contents( $post, $args ) {
79
- $loading_img = '<div style="width: 100%; text-align: center;"><img src=" ' . plugins_url( 'wp-statistics/assets/images/' ) . 'ajax-loading.gif" alt="' . __( 'Loading...', 'wp-statistics' ) . '"></div>';
80
- $widget = $args['args']['widget'];
81
- $container_id = 'wp-statistics-' . str_replace( '.', '-', $widget ) . '-div';
82
-
83
- echo '<div id="' . $container_id . '">' . $loading_img . '</div>';
84
- echo '<script type="text/javascript">var wp_statistics_current_id = \'' . $post . '\';</script>';
85
- wp_statistics_generate_widget_load_javascript( $widget, $container_id );
86
- }
87
-
88
- function wp_statistics_editor_inline_javascript() {
89
- $screen = get_current_screen();
90
-
91
- if ( 'post' != $screen->id && 'page' != $screen->id ) {
92
- return;
93
- }
94
-
95
- wp_statistics_load_widget_css_and_scripts();
96
-
97
- $loading_img = '<div style="width: 100%; text-align: center;"><img src=" ' . plugins_url( 'wp-statistics/assets/images/' ) . 'ajax-loading.gif" alt="' . __( 'Reloading...', 'wp-statistics' ) . '"></div>';
98
-
99
- $new_buttons = '</button><button class="handlediv button-link wps-refresh" type="button" id="{{refreshid}}">' . wp_statistics_icons( 'dashicons-update' ) . '<span class="screen-reader-text">' . __( 'Reload', 'wp-statistics' ) . '</span></button><button class="handlediv button-link wps-more" type="button" id="{{moreid}}">' . wp_statistics_icons( 'dashicons-migrate' ) . '<span class="screen-reader-text">' . __( 'More Details', 'wp-statistics' ) . '</span></button>';
100
- $new_button = '</button><button class="handlediv button-link wps-refresh" type="button" id="{{refreshid}}">' . wp_statistics_icons( 'dashicons-update' ) . '<span class="screen-reader-text">' . __( 'Reload', 'wp-statistics' ) . '</span></button>';
101
-
102
- $admin_url = get_admin_url() . "/admin.php?page=";
103
-
104
- $page_urls = array();
105
-
106
- $page_urls['wp_statistics_editor_meta_box_more_button'] = $admin_url . WP_STATISTICS_PAGES_PAGE . '&page-id=';
107
-
108
- ?>
109
- <script type="text/javascript">
110
- var wp_statistics_destinations = <?php echo json_encode( $page_urls ); ?>;
111
- var wp_statistics_loading_image = '<?php echo $loading_img; ?>';
112
-
113
- function wp_statistics_wait_for_postboxes() {
114
-
115
- if (!jQuery('#show-settings-link').is(':visible')) {
116
- setTimeout(wp_statistics_wait_for_postboxes, 500);
117
- }
118
-
119
- jQuery('.wps-refresh').unbind('click').on('click', wp_statistics_refresh_widget);
120
- jQuery('.wps-more').unbind('click').on('click', wp_statistics_goto_more);
121
-
122
- jQuery('.hide-postbox-tog').on('click', wp_statistics_refresh_on_toggle_widget);
123
- }
124
-
125
- jQuery(document).ready(function () {
126
-
127
- // Add the "more" and "refresh" buttons.
128
- jQuery('.postbox').each(function () {
129
- var temp = jQuery(this);
130
- var temp_id = temp.attr('id');
131
-
132
- if (temp_id == 'wp_statistics_editor_meta_box') {
133
-
134
- var temp_html = temp.html();
135
-
136
- new_text = '<?php echo $new_buttons;?>';
137
- new_text = new_text.replace('{{refreshid}}', temp_id + '_refresh_button');
138
- new_text = new_text.replace('{{moreid}}', temp_id + '_more_button');
139
-
140
- temp_html = temp_html.replace('</button>', new_text);
141
-
142
- temp.html(temp_html);
143
- }
144
- });
145
-
146
- // We have use a timeout here because we don't now what order this code will run in comparison to the postbox code.
147
- // Any timeout value should work as the timeout won't run until the rest of the javascript as run through once.
148
- setTimeout(wp_statistics_wait_for_postboxes, 100);
149
- });
150
- </script>
151
- <?php
152
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/classes/class-wp-statistics-ajax.php ADDED
@@ -0,0 +1,398 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace {
4
+ /**
5
+ * Class WP_Statistics_Ajax
6
+ */
7
+ class WP_Statistics_Ajax {
8
+
9
+ /**
10
+ * WP_Statistics_Ajax constructor.
11
+ */
12
+ function __construct() {
13
+ add_action(
14
+ 'wp_ajax_wp_statistics_close_donation_nag',
15
+ 'WP_Statistics_Ajax::close_donation_nag_action_callback'
16
+ );
17
+ add_action('wp_ajax_wp_statistics_delete_agents', 'WP_Statistics_Ajax::delete_agents_action_callback');
18
+ add_action(
19
+ 'wp_ajax_wp_statistics_delete_platforms',
20
+ 'WP_Statistics_Ajax::delete_platforms_action_callback'
21
+ );
22
+ add_action('wp_ajax_wp_statistics_empty_table', 'WP_Statistics_Ajax::empty_table_action_callback');
23
+ add_action('wp_ajax_wp_statistics_purge_data', 'WP_Statistics_Ajax::purge_data_action_callback');
24
+ add_action(
25
+ 'wp_ajax_wp_statistics_purge_visitor_hits',
26
+ 'WP_Statistics_Ajax::purge_visitor_hits_action_callback'
27
+ );
28
+ add_action('wp_ajax_wp_statistics_get_widget_contents', 'WP_Statistics_Ajax::get_widget_contents_callback');
29
+ }
30
+
31
+ /**
32
+ * Setup an AJAX action to close the donation nag banner on the overview page.
33
+ */
34
+ static function close_donation_nag_action_callback() {
35
+ GLOBAL $WP_Statistics; // this is how you get access to the database
36
+
37
+ $manage_cap = wp_statistics_validate_capability(
38
+ $WP_Statistics->get_option('manage_capability', 'manage_options')
39
+ );
40
+
41
+ if ( current_user_can($manage_cap) ) {
42
+ $WP_Statistics->update_option('disable_donation_nag', true);
43
+ }
44
+
45
+ wp_die(); // this is required to terminate immediately and return a proper response
46
+ }
47
+
48
+ /**
49
+ * Setup an AJAX action to delete an agent in the optimization page.
50
+ */
51
+ static function delete_agents_action_callback() {
52
+ GLOBAL $WP_Statistics, $wpdb; // this is how you get access to the database
53
+
54
+ $manage_cap = wp_statistics_validate_capability(
55
+ $WP_Statistics->get_option('manage_capability', 'manage_options')
56
+ );
57
+
58
+ if ( current_user_can($manage_cap) ) {
59
+ $agent = $_POST['agent-name'];
60
+
61
+ if ( $agent ) {
62
+
63
+ $result = $wpdb->query(
64
+ $wpdb->prepare("DELETE FROM {$wpdb->prefix}statistics_visitor WHERE `agent` = %s", $agent)
65
+ );
66
+
67
+ if ( $result ) {
68
+ echo sprintf(
69
+ __('%s agent data deleted successfully.', 'wp-statistics'),
70
+ '<code>' . $agent . '</code>'
71
+ );
72
+ } else {
73
+ _e('No agent data found to remove!', 'wp-statistics');
74
+ }
75
+
76
+ } else {
77
+ _e('Please select the desired items.', 'wp-statistics');
78
+ }
79
+ } else {
80
+ _e('Access denied!', 'wp-statistics');
81
+ }
82
+
83
+ wp_die(); // this is required to terminate immediately and return a proper response
84
+ }
85
+
86
+ /**
87
+ * Setup an AJAX action to delete a platform in the optimization page.
88
+ */
89
+ static function delete_platforms_action_callback() {
90
+ GLOBAL $WP_Statistics, $wpdb; // this is how you get access to the database
91
+
92
+ $manage_cap = wp_statistics_validate_capability(
93
+ $WP_Statistics->get_option('manage_capability', 'manage_options')
94
+ );
95
+
96
+ if ( current_user_can($manage_cap) ) {
97
+ $platform = $_POST['platform-name'];
98
+
99
+ if ( $platform ) {
100
+
101
+ $result = $wpdb->query(
102
+ $wpdb->prepare("DELETE FROM {$wpdb->prefix}statistics_visitor WHERE `platform` = %s", $platform)
103
+ );
104
+
105
+ if ( $result ) {
106
+ echo sprintf(
107
+ __('%s platform data deleted successfully.', 'wp-statistics'),
108
+ '<code>' . htmlentities($platform, ENT_QUOTES) . '</code>'
109
+ );
110
+ } else {
111
+ _e('No platform data found to remove!', 'wp-statistics');
112
+ }
113
+ } else {
114
+ _e('Please select the desired items.', 'wp-statistics');
115
+ }
116
+ } else {
117
+ _e('Access denied!', 'wp-statistics');
118
+ }
119
+
120
+ wp_die(); // this is required to terminate immediately and return a proper response
121
+ }
122
+
123
+ /**
124
+ * Setup an AJAX action to empty a table in the optimization page.
125
+ */
126
+ static function empty_table_action_callback() {
127
+ GLOBAL $WP_Statistics, $wpdb; // this is how you get access to the database
128
+
129
+ $manage_cap = wp_statistics_validate_capability(
130
+ $WP_Statistics->get_option('manage_capability', 'manage_options')
131
+ );
132
+
133
+ if ( current_user_can($manage_cap) ) {
134
+ $table_name = $_POST['table-name'];
135
+
136
+ if ( $table_name ) {
137
+
138
+ switch ( $table_name ) {
139
+ case 'useronline':
140
+ echo wp_statitiscs_empty_table($wpdb->prefix . 'statistics_useronline');
141
+ break;
142
+ case 'visit':
143
+ echo wp_statitiscs_empty_table($wpdb->prefix . 'statistics_visit');
144
+ break;
145
+ case 'visitors':
146
+ echo wp_statitiscs_empty_table($wpdb->prefix . 'statistics_visitor');
147
+ break;
148
+ case 'exclusions':
149
+ echo wp_statitiscs_empty_table($wpdb->prefix . 'statistics_exclusions');
150
+ break;
151
+ case 'pages':
152
+ echo wp_statitiscs_empty_table($wpdb->prefix . 'statistics_pages');
153
+ break;
154
+ case 'search':
155
+ echo wp_statitiscs_empty_table($wpdb->prefix . 'statistics_search');
156
+ break;
157
+ case 'all':
158
+ $result_string = wp_statitiscs_empty_table($wpdb->prefix . 'statistics_useronline');
159
+ $result_string .= '<br>' . wp_statitiscs_empty_table($wpdb->prefix . 'statistics_visit');
160
+ $result_string .= '<br>' . wp_statitiscs_empty_table($wpdb->prefix . 'statistics_visitor');
161
+ $result_string .= '<br>' .
162
+ wp_statitiscs_empty_table($wpdb->prefix . 'statistics_exclusions');
163
+ $result_string .= '<br>' . wp_statitiscs_empty_table($wpdb->prefix . 'statistics_pages');
164
+ $result_string .= '<br>' . wp_statitiscs_empty_table($wpdb->prefix . 'statistics_search');
165
+
166
+ echo $result_string;
167
+
168
+ break;
169
+ default:
170
+ _e('Please select the desired items.', 'wp-statistics');
171
+ }
172
+
173
+ $WP_Statistics->Primary_Values();
174
+
175
+ } else {
176
+ _e('Please select the desired items.', 'wp-statistics');
177
+ }
178
+ } else {
179
+ _e('Access denied!', 'wp-statistics');
180
+ }
181
+
182
+ wp_die(); // this is required to terminate immediately and return a proper response
183
+ }
184
+
185
+ /**
186
+ * Setup an AJAX action to purge old data in the optimization page.
187
+ */
188
+ static function purge_data_action_callback() {
189
+ GLOBAL $WP_Statistics; // this is how you get access to the database
190
+
191
+ require( WP_Statistics::$reg['plugin-dir'] . 'includes/functions/purge.php' );
192
+
193
+ $manage_cap = wp_statistics_validate_capability(
194
+ $WP_Statistics->get_option('manage_capability', 'manage_options')
195
+ );
196
+
197
+ if ( current_user_can($manage_cap) ) {
198
+ $purge_days = 0;
199
+
200
+ if ( array_key_exists('purge-days', $_POST) ) {
201
+ // Get the number of days to purge data before.
202
+ $purge_days = intval($_POST['purge-days']);
203
+ }
204
+
205
+ echo wp_statistics_purge_data($purge_days);
206
+ } else {
207
+ _e('Access denied!', 'wp-statistics');
208
+ }
209
+
210
+ wp_die(); // this is required to terminate immediately and return a proper response
211
+ }
212
+
213
+ /**
214
+ * Setup an AJAX action to purge visitors with more than a defined number of hits.
215
+ */
216
+ static function purge_visitor_hits_action_callback() {
217
+ GLOBAL $WP_Statistics; // this is how you get access to the database
218
+
219
+ require( WP_Statistics::$reg['plugin-dir'] . 'includes/functions/purge-hits.php' );
220
+
221
+ $manage_cap = wp_statistics_validate_capability(
222
+ $WP_Statistics->get_option('manage_capability', 'manage_options')
223
+ );
224
+
225
+ if ( current_user_can($manage_cap) ) {
226
+ $purge_hits = 10;
227
+
228
+ if ( array_key_exists('purge-hits', $_POST) ) {
229
+ // Get the number of days to purge data before.
230
+ $purge_hits = intval($_POST['purge-hits']);
231
+ }
232
+
233
+ if ( $purge_hits < 10 ) {
234
+ _e('Number of hits must be greater than or equal to 10!', 'wp-statistics');
235
+ } else {
236
+ echo wp_statistics_purge_visitor_hits($purge_hits);
237
+ }
238
+ } else {
239
+ _e('Access denied!', 'wp-statistics');
240
+ }
241
+
242
+ wp_die(); // this is required to terminate immediately and return a proper response
243
+ }
244
+
245
+ /**
246
+ * Setup an AJAX action to purge visitors with more than a defined number of hits.
247
+ */
248
+ static function get_widget_contents_callback() {
249
+ GLOBAL $WP_Statistics; // this is how you get access to the database
250
+
251
+ $widgets = array(
252
+ 'about',
253
+ 'browsers',
254
+ 'map',
255
+ 'countries',
256
+ 'hits',
257
+ 'hitsmap',
258
+ 'page',
259
+ 'pages',
260
+ 'quickstats',
261
+ 'recent',
262
+ 'referring',
263
+ 'search',
264
+ 'summary',
265
+ 'top.visitors',
266
+ 'words',
267
+ 'searched.phrases',
268
+ );
269
+
270
+ if ( array_key_exists('format', $_POST) and $_POST['format'] == 'dashboard' ) {
271
+ $size = 220;
272
+ $days = 10;
273
+ } else {
274
+ $size = 110;
275
+ $days = 20;
276
+ }
277
+
278
+ $view_cap = wp_statistics_validate_capability(
279
+ $WP_Statistics->get_option('read_capability', 'manage_options')
280
+ );
281
+
282
+ if ( current_user_can($view_cap) ) {
283
+ $widget = '';
284
+
285
+ if ( array_key_exists('widget', $_POST) ) {
286
+ // Get the widget we're going to display.
287
+
288
+ if ( in_array($_POST['widget'], $widgets) ) {
289
+ $widget = $_POST['widget'];
290
+ }
291
+ }
292
+
293
+ if ( 'map' == $widget || 'hitsmap' == $widget ) {
294
+ $widget = 'jqv.map';
295
+ }
296
+
297
+ if ( '' == $widget ) {
298
+ _e('No matching widget found!', 'wp-statistics');
299
+ wp_die();
300
+ }
301
+
302
+ $ISOCountryCode = $WP_Statistics->get_country_codes();
303
+ $search_engines = wp_statistics_searchengine_list();
304
+
305
+ require( WP_Statistics::$reg['plugin-dir'] . 'includes/log/widgets/' . $widget . '.php' );
306
+
307
+ switch ( $widget ) {
308
+ case 'summary':
309
+ wp_statistics_generate_summary_postbox_content($search_engines);
310
+
311
+ break;
312
+ case 'quickstats':
313
+ wp_statistics_generate_quickstats_postbox_content($search_engines);
314
+
315
+ break;
316
+
317
+ case 'browsers':
318
+ wp_statistics_generate_browsers_postbox_content();
319
+
320
+ break;
321
+ case 'referring':
322
+ wp_statistics_generate_referring_postbox_content();
323
+
324
+ break;
325
+ case 'searched.phrases':
326
+ wp_statistics_generate_searched_phrases_postbox_content();
327
+
328
+ break;
329
+ case 'countries':
330
+ wp_statistics_generate_countries_postbox_content($ISOCountryCode);
331
+
332
+ break;
333
+ case 'jqv.map':
334
+ wp_statistics_generate_map_postbox_content($ISOCountryCode);
335
+
336
+ break;
337
+ case 'hits':
338
+ wp_statistics_generate_hits_postbox_content($size, $days);
339
+
340
+ break;
341
+ case 'search':
342
+ wp_statistics_generate_search_postbox_content($search_engines, $size, $days);
343
+
344
+ break;
345
+ case 'words':
346
+ wp_statistics_generate_words_postbox_content($ISOCountryCode);
347
+
348
+ break;
349
+ case 'page':
350
+ _e('This feature temporarily disabled.', 'wp-statistics');
351
+
352
+ if ( array_key_exists('page-id', $_POST) ) {
353
+ $pageid = (int) $_POST['page-id'];
354
+ echo '&nbsp;';
355
+ echo sprintf(
356
+ __('<a href="%s">Click here</a> to see page stats.', 'wp-statistics'),
357
+ 'admin.php?page=wps_pages_page&page-id=' . $pageid
358
+ );
359
+
360
+ // This feature temporarily disabled because there is conflicts.
361
+ //wp_statistics_generate_page_postbox_content( null, $pageid );
362
+ }
363
+
364
+ break;
365
+ case 'pages':
366
+ list( $total, $uris ) = wp_statistics_get_top_pages();
367
+ wp_statistics_generate_pages_postbox_content($total, $uris);
368
+
369
+ break;
370
+ case 'recent':
371
+ wp_statistics_generate_recent_postbox_content($ISOCountryCode);
372
+
373
+ break;
374
+ case 'top.visitors':
375
+ $format = null;
376
+
377
+ if ( array_key_exists('format', $_POST) ) {
378
+ $format = 'compact';
379
+ }
380
+
381
+ wp_statistics_generate_top_visitors_postbox_content($ISOCountryCode, 'today', 10, $format);
382
+
383
+ break;
384
+ case 'about':
385
+ wp_statistics_generate_about_postbox_content($ISOCountryCode);
386
+
387
+ break;
388
+ default:
389
+ _e('ERROR: Widget not found!', 'wp-statistics');
390
+ }
391
+ } else {
392
+ _e('Access denied!', 'wp-statistics');
393
+ }
394
+
395
+ wp_die(); // this is required to terminate immediately and return a proper response
396
+ }
397
+ }
398
+ }
includes/classes/class-wp-statistics-bootstrap.php ADDED
@@ -0,0 +1,1482 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace {
4
+ /**
5
+ * Class WP_Statistics_Bootstrap
6
+ */
7
+ class WP_Statistics_Bootstrap {
8
+
9
+ /**
10
+ * WP_Statistics_Bootstrap constructor.
11
+ */
12
+ function __construct($WP_Statistics) {
13
+ // Display the admin notices if we should.
14
+ if ( isset( $pagenow ) && array_key_exists('page', $_GET) ) {
15
+ if ( $pagenow == "admin.php" && substr($_GET['page'], 0, 14) == 'wp-statistics/' ) {
16
+ add_action('admin_notices', 'WP_Statistics_Bootstrap::not_enable');
17
+ }
18
+ }
19
+
20
+ // Add the honey trap code in the footer.
21
+ add_action('wp_footer', 'WP_Statistics_Bootstrap::footer_action');
22
+
23
+
24
+ // If we've been told to exclude the feeds from the statistics add a detection hook when WordPress generates the RSS feed.
25
+ if ( $WP_Statistics->get_option('exclude_feeds') ) {
26
+ add_filter('the_title_rss', 'WP_Statistics_Bootstrap::check_feed_title');
27
+ }
28
+
29
+ // We can wait until the very end of the page to process the statistics,
30
+ // that way the page loads and displays quickly.
31
+ add_action('shutdown', 'WP_Statistics_Bootstrap::shutdown_action');
32
+
33
+ add_filter(
34
+ 'plugin_action_links_' . plugin_basename(WP_Statistics::$reg['main-file']),
35
+ 'WP_Statistics_Bootstrap::settings_links',
36
+ 10,
37
+ 2
38
+ );
39
+
40
+ add_filter('plugin_row_meta', 'WP_Statistics_Bootstrap::add_meta_links', 10, 2);
41
+
42
+ add_action('load-edit.php', 'WP_Statistics_Bootstrap::load_edit_init');
43
+
44
+ if ( $WP_Statistics->get_option('pages') && ! $WP_Statistics->get_option('disable_column') ) {
45
+ add_action('post_submitbox_misc_actions', 'WP_Statistics_Bootstrap::post_init');
46
+ }
47
+
48
+ add_action('admin_menu', 'WP_Statistics_Bootstrap::menu');
49
+
50
+ if ( is_multisite() ) {
51
+ add_action('network_admin_menu', 'WP_Statistics_Bootstrap::networkmenu');
52
+ }
53
+
54
+ if ( $WP_Statistics->get_option('menu_bar') ) {
55
+ add_action('admin_bar_menu', 'WP_Statistics_Bootstrap::menubar', 20);
56
+ }
57
+
58
+ add_action('admin_enqueue_scripts', 'WP_Statistics_Bootstrap::enqueue_scripts');
59
+ }
60
+
61
+ /**
62
+ * This function outputs error messages in the admin interface
63
+ * if the primary components of WP Statistics are enabled.
64
+ */
65
+ static function not_enable() {
66
+ global $WP_Statistics;
67
+
68
+ // If the user had told us to be quite, do so.
69
+ if ( ! $WP_Statistics->get_option('hide_notices') ) {
70
+
71
+ // Check to make sure the current user can manage WP Statistics,
72
+ // if not there's no point displaying the warnings.
73
+ $manage_cap = wp_statistics_validate_capability(
74
+ $WP_Statistics->get_option(
75
+ 'manage_capability',
76
+ 'manage_options'
77
+ )
78
+ );
79
+ if ( ! current_user_can($manage_cap) ) {
80
+ return;
81
+ }
82
+
83
+ $get_bloginfo_url = get_admin_url() . "admin.php?page=" . WP_Statistics::$page['settings'];
84
+
85
+ $itemstoenable = array();
86
+ if ( ! $WP_Statistics->get_option('useronline') ) {
87
+ $itemstoenable[] = __('online user tracking', 'wp-statistics');
88
+ }
89
+ if ( ! $WP_Statistics->get_option('visits') ) {
90
+ $itemstoenable[] = __('hit tracking', 'wp-statistics');
91
+ }
92
+ if ( ! $WP_Statistics->get_option('visitors') ) {
93
+ $itemstoenable[] = __('visitor tracking', 'wp-statistics');
94
+ }
95
+ if ( ! $WP_Statistics->get_option('geoip') && wp_statistics_geoip_supported() ) {
96
+ $itemstoenable[] = __('geoip collection', 'wp-statistics');
97
+ }
98
+
99
+ if ( count($itemstoenable) > 0 ) {
100
+ echo '<div class="update-nag">' . sprintf(
101
+ __(
102
+ 'The following features are disabled, please go to %ssettings page%s and enable them: %s',
103
+ 'wp-statistics'
104
+ ),
105
+ '<a href="' . $get_bloginfo_url . '">',
106
+ '</a>',
107
+ implode(__(',', 'wp-statistics'), $itemstoenable)
108
+ ) . '</div>';
109
+ }
110
+
111
+ $get_bloginfo_url = get_admin_url() .
112
+ "admin.php?page=" .
113
+ WP_Statistics::$page['optimization'] .
114
+ "&tab=database";
115
+
116
+ $dbupdatestodo = array();
117
+
118
+ if ( ! $WP_Statistics->get_option('search_converted') ) {
119
+ $dbupdatestodo[] = __('search table', 'wp-statistics');
120
+ }
121
+
122
+ // Check to see if there are any database changes the user hasn't done yet.
123
+ $dbupdates = $WP_Statistics->get_option('pending_db_updates', false);
124
+
125
+ // The database updates are stored in an array so loop thorugh it and output some notices.
126
+ if ( is_array($dbupdates) ) {
127
+ $dbstrings = array(
128
+ 'date_ip_agent' => __('countries database index', 'wp-statistics'),
129
+ 'unique_date' => __('visit database index', 'wp-statistics'),
130
+ );
131
+
132
+ foreach ( $dbupdates as $key => $update ) {
133
+ if ( $update == true ) {
134
+ $dbupdatestodo[] = $dbstrings[ $key ];
135
+ }
136
+ }
137
+
138
+ if ( count($dbupdatestodo) > 0 ) {
139
+ echo '<div class="update-nag">' . sprintf(
140
+ __(
141
+ 'Database updates are required, please go to %soptimization page%s and update the following: %s',
142
+ 'wp-statistics'
143
+ ),
144
+ '<a href="' . $get_bloginfo_url . '">',
145
+ '</a>',
146
+ implode(__(',', 'wp-statistics'), $dbupdatestodo)
147
+ ) . '</div>';
148
+ }
149
+
150
+ }
151
+ }
152
+ }
153
+
154
+
155
+ /**
156
+ * Footer Action
157
+ */
158
+ static function footer_action() {
159
+ global $WP_Statistics;
160
+ if ( $WP_Statistics->get_option('use_honeypot') && $WP_Statistics->get_option('honeypot_postid') > 0 ) {
161
+ $post_url = get_permalink($WP_Statistics->get_option('honeypot_postid'));
162
+ echo '<a href="' . $post_url . '" style="display: none;">&nbsp;</a>';
163
+ }
164
+ }
165
+
166
+ /**
167
+ * Check Feed Title
168
+ *
169
+ * @param string $title Title
170
+ *
171
+ * @return string Title
172
+ */
173
+ static function check_feed_title( $title ) {
174
+ global $WP_Statistics;
175
+ $WP_Statistics->feed_detected();
176
+
177
+ return $title;
178
+ }
179
+
180
+
181
+ /**
182
+ * Shutdown Action
183
+ */
184
+ static function shutdown_action() {
185
+ global $WP_Statistics;
186
+
187
+ // If something has gone horribly wrong and $WP_Statistics isn't an object, bail out.
188
+ // This seems to happen sometimes with WP Cron calls.
189
+ if ( ! is_object($WP_Statistics) ) {
190
+ return;
191
+ }
192
+
193
+ // Create a new hit class, if we're GeoIP enabled, use WP_Statistics_GEO_IP_Hits().
194
+ if ( class_exists('WP_Statistics_GEO_IP_Hits') ) {
195
+ $h = new WP_Statistics_GEO_IP_Hits();
196
+ } else {
197
+ $h = new WP_Statistics_Hits();
198
+ }
199
+
200
+ // Call the online users tracking code.
201
+ if ( $WP_Statistics->get_option('useronline') ) {
202
+ $h->Check_online();
203
+ }
204
+
205
+ // Call the visitor tracking code.
206
+ if ( $WP_Statistics->get_option('visitors') ) {
207
+ $h->Visitors();
208
+ }
209
+
210
+ // Call the visit tracking code.
211
+ if ( $WP_Statistics->get_option('visits') ) {
212
+ $h->Visits();
213
+ }
214
+
215
+ // Call the page tracking code.
216
+ if ( $WP_Statistics->get_option('pages') ) {
217
+ $h->Pages();
218
+ }
219
+
220
+ // Check to see if the GeoIP database needs to be downloaded and do so if required.
221
+ if ( $WP_Statistics->get_option('update_geoip') ) {
222
+ WP_Statistics_Updates::download_geoip();
223
+ }
224
+
225
+ // Check to see if the browscap database needs to be downloaded and do so if required.
226
+ if ( $WP_Statistics->get_option('update_browscap') ) {
227
+ WP_Statistics_Updates::download_browscap();
228
+ }
229
+
230
+ // Check to see if the referrerspam database needs to be downloaded and do so if required.
231
+ if ( $WP_Statistics->get_option('update_referrerspam') ) {
232
+ WP_Statistics_Updates::download_referrerspam();
233
+ }
234
+
235
+ if ( $WP_Statistics->get_option('send_upgrade_email') ) {
236
+ $WP_Statistics->update_option('send_upgrade_email', false);
237
+
238
+ $blogname = get_bloginfo('name');
239
+ $blogemail = get_bloginfo('admin_email');
240
+
241
+ $headers[] = "From: $blogname <$blogemail>";
242
+ $headers[] = "MIME-Version: 1.0";
243
+ $headers[] = "Content-type: text/html; charset=utf-8";
244
+
245
+ if ( $WP_Statistics->get_option('email_list') == '' ) {
246
+ $WP_Statistics->update_option('email_list', $blogemail);
247
+ }
248
+
249
+ wp_mail(
250
+ $WP_Statistics->get_option('email_list'),
251
+ sprintf(__('WP Statistics %s installed on', 'wp-statistics'), WP_Statistics::$reg['version']) .
252
+ ' ' .
253
+ $blogname,
254
+ "Installation/upgrade complete!",
255
+ $headers
256
+ );
257
+ }
258
+ }
259
+
260
+
261
+ /**
262
+ * Add a settings link to the plugin list.
263
+ *
264
+ * @param string $links Links
265
+ * @param string $file Not Used!
266
+ *
267
+ * @return string Links
268
+ */
269
+ static function settings_links( $links, $file ) {
270
+ global $WP_Statistics;
271
+
272
+ $manage_cap = wp_statistics_validate_capability(
273
+ $WP_Statistics->get_option('manage_capability', 'manage_options')
274
+ );
275
+
276
+ if ( current_user_can($manage_cap) ) {
277
+ array_unshift(
278
+ $links,
279
+ '<a href="' . admin_url('admin.php?page=' . WP_Statistics::$page['settings']) . '">' . __(
280
+ 'Settings',
281
+ 'wp-statistics'
282
+ ) . '</a>'
283
+ );
284
+ }
285
+
286
+ return $links;
287
+ }
288
+
289
+
290
+ /**
291
+ * Add a WordPress plugin page and rating links to the meta information to the plugin list.
292
+ *
293
+ * @param string $links Links
294
+ * @param string $file File
295
+ *
296
+ * @return array Links
297
+ */
298
+ static function add_meta_links( $links, $file ) {
299
+ if ( $file == plugin_basename(WP_Statistics::$reg['main-file']) ) {
300
+ $plugin_url = 'http://wordpress.org/plugins/wp-statistics/';
301
+
302
+ $links[] = '<a href="' . $plugin_url . '" target="_blank" title="' . __(
303
+ 'Click here to visit the plugin on WordPress.org',
304
+ 'wp-statistics'
305
+ ) . '">' . __('Visit WordPress.org page', 'wp-statistics') . '</a>';
306
+
307
+ $rate_url = 'https://wordpress.org/support/plugin/wp-statistics/reviews/?rate=5#new-post';
308
+ $links[] = '<a href="' . $rate_url . '" target="_blank" title="' . __(
309
+ 'Click here to rate and review this plugin on WordPress.org',
310
+ 'wp-statistics'
311
+ ) . '">' . __('Rate this plugin', 'wp-statistics') . '</a>';
312
+ }
313
+
314
+ return $links;
315
+ }
316
+
317
+ /**
318
+ * Add a custom column to post/pages for hit statistics.
319
+ *
320
+ * @param array $columns Columns
321
+ *
322
+ * @return array Columns
323
+ */
324
+ static function add_column( $columns ) {
325
+ $columns['wp-statistics'] = __('Hits', 'wp-statistics');
326
+
327
+ return $columns;
328
+ }
329
+
330
+ /**
331
+ * Render the custom column on the post/pages lists.
332
+ *
333
+ * @param string $column_name Column Name
334
+ * @param string $post_id Post ID
335
+ */
336
+ static function render_column( $column_name, $post_id ) {
337
+ if ( $column_name == 'wp-statistics' ) {
338
+ echo "<a href='" .
339
+ get_admin_url() .
340
+ "admin.php?page=" .
341
+ WP_Statistics::$page['pages'] .
342
+ "&page-id={$post_id}'>" .
343
+ wp_statistics_pages('total', "", $post_id) .
344
+ "</a>";
345
+ }
346
+ }
347
+
348
+ /**
349
+ * Call the add/render functions at the appropriate times.
350
+ */
351
+ static function load_edit_init() {
352
+ GLOBAL $WP_Statistics;
353
+
354
+ $read_cap = wp_statistics_validate_capability(
355
+ $WP_Statistics->get_option('read_capability', 'manage_options')
356
+ );
357
+
358
+ if ( current_user_can($read_cap) && $WP_Statistics->get_option('pages') && ! $WP_Statistics->get_option(
359
+ 'disable_column'
360
+ )
361
+ ) {
362
+ $post_types = (array) get_post_types(array( 'show_ui' => true ), 'object');
363
+
364
+ foreach ( $post_types as $type ) {
365
+ add_action('manage_' . $type->name . '_posts_columns', 'wp_statistics_add_column', 10, 2);
366
+ add_action('manage_' . $type->name . '_posts_custom_column', 'wp_statistics_render_column', 10, 2);
367
+ }
368
+ }
369
+ }
370
+
371
+ /**
372
+ * Add the hit count to the publish widget in the post/pages editor.
373
+ */
374
+ static function post_init() {
375
+ global $post;
376
+
377
+ $id = $post->ID;
378
+
379
+ echo "<div class='misc-pub-section'>" .
380
+ __('WP Statistics - Hits', 'wp-statistics') .
381
+ ": <b><a href='" .
382
+ get_admin_url() .
383
+ "admin.php?page=" .
384
+ WP_Statistics::$page['pages'] .
385
+ "&page-id={$id}'>" .
386
+ wp_statistics_pages('total', "", $id) .
387
+ "</a></b></div>";
388
+ }
389
+
390
+ /**
391
+ * This function adds the primary menu to WordPress.
392
+ */
393
+ static function menu() {
394
+ GLOBAL $WP_Statistics;
395
+
396
+ // Get the read/write capabilities required to view/manage the plugin as set by the user.
397
+ $read_cap = wp_statistics_validate_capability(
398
+ $WP_Statistics->get_option('read_capability', 'manage_options')
399
+ );
400
+ $manage_cap = wp_statistics_validate_capability(
401
+ $WP_Statistics->get_option('manage_capability', 'manage_options')
402
+ );
403
+
404
+ // Add the top level menu.
405
+ $WP_Statistics->menu_slugs['top'] = add_menu_page(
406
+ __('Statistics', 'wp-statistics'),
407
+ __('Statistics', 'wp-statistics'),
408
+ $read_cap,
409
+ WP_Statistics::$page['overview'],
410
+ 'WP_Statistics_Bootstrap::log',
411
+ 'dashicons-chart-pie'
412
+ );
413
+
414
+ // Add the sub items.
415
+ $WP_Statistics->menu_slugs['overview'] = add_submenu_page(
416
+ WP_Statistics::$page['overview'],
417
+ __('Overview', 'wp-statistics'),
418
+ __('Overview', 'wp-statistics'),
419
+ $read_cap,
420
+ WP_Statistics::$page['overview'],
421
+ 'WP_Statistics_Bootstrap::log'
422
+ );
423
+
424
+ if ( $WP_Statistics->get_option('visitors') ) {
425
+ $WP_Statistics->menu_slugs['browsers'] = add_submenu_page(
426
+ WP_Statistics::$page['overview'],
427
+ __('Browsers', 'wp-statistics'),
428
+ __('Browsers', 'wp-statistics'),
429
+ $read_cap,
430
+ WP_Statistics::$page['browser'],
431
+ 'WP_Statistics_Bootstrap::log'
432
+ );
433
+ }
434
+ if ( $WP_Statistics->get_option('geoip') && $WP_Statistics->get_option('visitors') ) {
435
+ $WP_Statistics->menu_slugs['countries'] = add_submenu_page(
436
+ WP_Statistics::$page['overview'],
437
+ __('Countries', 'wp-statistics'),
438
+ __('Countries', 'wp-statistics'),
439
+ $read_cap,
440
+ WP_Statistics::$page['countries'],
441
+ 'WP_Statistics_Bootstrap::log'
442
+ );
443
+ }
444
+ if ( $WP_Statistics->get_option('record_exclusions') ) {
445
+ $WP_Statistics->menu_slugs['exclusions'] = add_submenu_page(
446
+ WP_Statistics::$page['overview'],
447
+ __('Exclusions', 'wp-statistics'),
448
+ __('Exclusions', 'wp-statistics'),
449
+ $read_cap,
450
+ WP_Statistics::$page['exclusions'],
451
+ 'WP_Statistics_Bootstrap::log'
452
+ );
453
+ }
454
+ if ( $WP_Statistics->get_option('visits') ) {
455
+ $WP_Statistics->menu_slugs['hits'] = add_submenu_page(
456
+ WP_Statistics::$page['overview'],
457
+ __('Hits', 'wp-statistics'),
458
+ __('Hits', 'wp-statistics'),
459
+ $read_cap,
460
+ WP_Statistics::$page['hits'],
461
+ 'WP_Statistics_Bootstrap::log'
462
+ );
463
+ }
464
+ if ( $WP_Statistics->get_option('useronline') ) {
465
+ $WP_Statistics->menu_slugs['online'] = add_submenu_page(
466
+ WP_Statistics::$page['overview'],
467
+ __('Online', 'wp-statistics'),
468
+ __('Online', 'wp-statistics'),
469
+ $read_cap,
470
+ WP_Statistics::$page['online'],
471
+ 'WP_Statistics_Bootstrap::log'
472
+ );
473
+ }
474
+ if ( $WP_Statistics->get_option('pages') ) {
475
+ $WP_Statistics->menu_slugs['pages'] = add_submenu_page(
476
+ WP_Statistics::$page['overview'],
477
+ __('Pages', 'wp-statistics'),
478
+ __('Pages', 'wp-statistics'),
479
+ $read_cap,
480
+ WP_Statistics::$page['pages'],
481
+ 'WP_Statistics_Bootstrap::log'
482
+ );
483
+ }
484
+ if ( $WP_Statistics->get_option('pages') ) {
485
+ $WP_Statistics->menu_slugs['categories'] = add_submenu_page(
486
+ WP_Statistics::$page['overview'],
487
+ __('Categories', 'wp-statistics'),
488
+ __('Categories', 'wp-statistics'),
489
+ $read_cap,
490
+ WP_Statistics::$page['categories'],
491
+ 'WP_Statistics_Bootstrap::log'
492
+ );
493
+ }
494
+ if ( $WP_Statistics->get_option('pages') ) {
495
+ $WP_Statistics->menu_slugs['tags'] = add_submenu_page(
496
+ WP_Statistics::$page['overview'],
497
+ __('Tags', 'wp-statistics'),
498
+ __('Tags', 'wp-statistics'),
499
+ $read_cap,
500
+ WP_Statistics::$page['tags'],
501
+ 'WP_Statistics_Bootstrap::log'
502
+ );
503
+ }
504
+ if ( $WP_Statistics->get_option('pages') ) {
505
+ $WP_Statistics->menu_slugs['authors'] = add_submenu_page(
506
+ WP_Statistics::$page['overview'],
507
+ __('Authors', 'wp-statistics'),
508
+ __('Authors', 'wp-statistics'),
509
+ $read_cap,
510
+ WP_Statistics::$page['authors'],
511
+ 'WP_Statistics_Bootstrap::log'
512
+ );
513
+ }
514
+ if ( $WP_Statistics->get_option('visitors') ) {
515
+ $WP_Statistics->menu_slugs['referrers'] = add_submenu_page(
516
+ WP_Statistics::$page['overview'],
517
+ __('Referrers', 'wp-statistics'),
518
+ __('Referrers', 'wp-statistics'),
519
+ $read_cap,
520
+ WP_Statistics::$page['referrers'],
521
+ 'WP_Statistics_Bootstrap::log'
522
+ );
523
+ }
524
+ if ( $WP_Statistics->get_option('visitors') ) {
525
+ $WP_Statistics->menu_slugs['searches'] = add_submenu_page(
526
+ WP_Statistics::$page['overview'],
527
+ __('Search Engines', 'wp-statistics'),
528
+ __('Search Engines', 'wp-statistics'),
529
+ $read_cap,
530
+ WP_Statistics::$page['searches'],
531
+ 'WP_Statistics_Bootstrap::log'
532
+ );
533
+ }
534
+ if ( $WP_Statistics->get_option('visitors') ) {
535
+ $WP_Statistics->menu_slugs['words'] = add_submenu_page(
536
+ WP_Statistics::$page['overview'],
537
+ __('Search Words', 'wp-statistics'),
538
+ __('Search Words', 'wp-statistics'),
539
+ $read_cap,
540
+ WP_Statistics::$page['words'],
541
+ 'WP_Statistics_Bootstrap::log'
542
+ );
543
+ }
544
+ if ( $WP_Statistics->get_option('visitors') ) {
545
+ $WP_Statistics->menu_slugs['searched.phrases'] = add_submenu_page(
546
+ WP_Statistics::$page['overview'],
547
+ __('Top Search Words', 'wp-statistics'),
548
+ __('Top Search Words', 'wp-statistics'),
549
+ $read_cap,
550
+ WP_Statistics::$page['searched-phrases'],
551
+ 'WP_Statistics_Bootstrap::log'
552
+ );
553
+ }
554
+ if ( $WP_Statistics->get_option('visitors') ) {
555
+ $WP_Statistics->menu_slugs['top.visotors'] = add_submenu_page(
556
+ WP_Statistics::$page['overview'],
557
+ __('Top Visitors Today', 'wp-statistics'),
558
+ __('Top Visitors Today', 'wp-statistics'),
559
+ $read_cap,
560
+ WP_Statistics::$page['top-visitors'],
561
+ 'WP_Statistics_Bootstrap::log'
562
+ );
563
+ }
564
+ if ( $WP_Statistics->get_option('visitors') ) {
565
+ $WP_Statistics->menu_slugs['visitors'] = add_submenu_page(
566
+ WP_Statistics::$page['overview'],
567
+ __('Visitors', 'wp-statistics'),
568
+ __('Visitors', 'wp-statistics'),
569
+ $read_cap,
570
+ WP_Statistics::$page['visitors'],
571
+ 'WP_Statistics_Bootstrap::log'
572
+ );
573
+ }
574
+
575
+ $WP_Statistics->menu_slugs['break'] = add_submenu_page(
576
+ WP_Statistics::$page['overview'],
577
+ '',
578
+ '',
579
+ $read_cap,
580
+ 'wps_break_menu',
581
+ 'WP_Statistics_Bootstrap::log'
582
+ );
583
+
584
+ $WP_Statistics->menu_slugs['optimize'] = add_submenu_page(
585
+ WP_Statistics::$page['overview'],
586
+ __('Optimization', 'wp-statistics'),
587
+ __('Optimization', 'wp-statistics'),
588
+ $manage_cap,
589
+ WP_Statistics::$page['optimization'],
590
+ 'WP_Statistics_Bootstrap::optimization'
591
+ );
592
+ $WP_Statistics->menu_slugs['settings'] = add_submenu_page(
593
+ WP_Statistics::$page['overview'],
594
+ __('Settings', 'wp-statistics'),
595
+ __('Settings', 'wp-statistics'),
596
+ $read_cap,
597
+ WP_Statistics::$page['settings'],
598
+ 'WP_Statistics_Bootstrap::settings'
599
+ );
600
+ $WP_Statistics->menu_slugs['plugins'] = add_submenu_page(
601
+ WP_Statistics::$page['overview'],
602
+ __('Add-Ons', 'wp-statistics'),
603
+ '<span style="color:#dc6b26">' . __('Add-Ons', 'wp-statistics') . '</span>',
604
+ $read_cap,
605
+ WP_Statistics::$page['plugins'],
606
+ 'WP_Statistics_Bootstrap::plugins'
607
+ );
608
+ $WP_Statistics->menu_slugs['donate'] = add_submenu_page(
609
+ WP_Statistics::$page['overview'],
610
+ __('Donate', 'wp-statistics'),
611
+ '<span style="color:#459605">' . __('Donate', 'wp-statistics') . '</span>',
612
+ $read_cap,
613
+ WP_Statistics::$page['donate'],
614
+ 'WP_Statistics_Bootstrap::donate'
615
+ );
616
+
617
+ // Add action to load the meta boxes to the overview page.
618
+ add_action('load-' . $WP_Statistics->menu_slugs['overview'], 'WP_Statistics_Bootstrap::load_overview_page');
619
+ }
620
+
621
+
622
+ /**
623
+ * Load Overview Page
624
+ */
625
+ static function load_overview_page() {
626
+ global $WP_Statistics;
627
+
628
+ // Right side "wide" widgets
629
+ if ( $WP_Statistics->get_option('visits') ) {
630
+ add_meta_box(
631
+ 'wps_hits_postbox',
632
+ __('Hit Statistics', 'wp-statistics'),
633
+ 'wp_statistics_generate_overview_postbox_contents',
634
+ $WP_Statistics->menu_slugs['overview'],
635
+ 'normal',
636
+ null,
637
+ array( 'widget' => 'hits' )
638
+ );
639
+ }
640
+
641
+ if ( $WP_Statistics->get_option('visitors') ) {
642
+ add_meta_box(
643
+ 'wps_top_visitors_postbox',
644
+ __('Top Visitors', 'wp-statistics'),
645
+ 'wp_statistics_generate_overview_postbox_contents',
646
+ $WP_Statistics->menu_slugs['overview'],
647
+ 'normal',
648
+ null,
649
+ array( 'widget' => 'top.visitors' )
650
+ );
651
+ add_meta_box(
652
+ 'wps_search_postbox',
653
+ __('Search Engine Referrals', 'wp-statistics'),
654
+ 'wp_statistics_generate_overview_postbox_contents',
655
+ $WP_Statistics->menu_slugs['overview'],
656
+ 'normal',
657
+ null,
658
+ array( 'widget' => 'search' )
659
+ );
660
+ add_meta_box(
661
+ 'wps_words_postbox',
662
+ __('Top Searched Phrases (30 Days)', 'wp-statistics'),
663
+ 'wp_statistics_generate_overview_postbox_contents',
664
+ $WP_Statistics->menu_slugs['overview'],
665
+ 'normal',
666
+ null,
667
+ array( 'widget' => 'searched.phrases' )
668
+ );
669
+ add_meta_box(
670
+ 'wps_words_postbox',
671
+ __('Latest Search Words', 'wp-statistics'),
672
+ 'wp_statistics_generate_overview_postbox_contents',
673
+ $WP_Statistics->menu_slugs['overview'],
674
+ 'normal',
675
+ null,
676
+ array( 'widget' => 'words' )
677
+ );
678
+ add_meta_box(
679
+ 'wps_recent_postbox',
680
+ __('Recent Visitors', 'wp-statistics'),
681
+ 'wp_statistics_generate_overview_postbox_contents',
682
+ $WP_Statistics->menu_slugs['overview'],
683
+ 'normal',
684
+ null,
685
+ array( 'widget' => 'recent' )
686
+ );
687
+
688
+ if ( $WP_Statistics->get_option('geoip') ) {
689
+ add_meta_box(
690
+ 'wps_map_postbox',
691
+ __('Today\'s Visitors Map', 'wp-statistics'),
692
+ 'wp_statistics_generate_overview_postbox_contents',
693
+ $WP_Statistics->menu_slugs['overview'],
694
+ 'normal',
695
+ null,
696
+ array( 'widget' => 'map' )
697
+ );
698
+ }
699
+ }
700
+
701
+ if ( $WP_Statistics->get_option('pages') ) {
702
+ add_meta_box(
703
+ 'wps_pages_postbox',
704
+ __('Top 10 Pages', 'wp-statistics'),
705
+ 'wp_statistics_generate_overview_postbox_contents',
706
+ $WP_Statistics->menu_slugs['overview'],
707
+ 'normal',
708
+ null,
709
+ array( 'widget' => 'pages' )
710
+ );
711
+ }
712
+
713
+ // Left side "thin" widgets.
714
+ if ( $WP_Statistics->get_option('visitors') ) {
715
+ add_meta_box(
716
+ 'wps_summary_postbox',
717
+ __('Summary', 'wp-statistics'),
718
+ 'wp_statistics_generate_overview_postbox_contents',
719
+ $WP_Statistics->menu_slugs['overview'],
720
+ 'side',
721
+ null,
722
+ array( 'widget' => 'summary' )
723
+ );
724
+ add_meta_box(
725
+ 'wps_browsers_postbox',
726
+ __('Browsers', 'wp-statistics'),
727
+ 'wp_statistics_generate_overview_postbox_contents',
728
+ $WP_Statistics->menu_slugs['overview'],
729
+ 'side',
730
+ null,
731
+ array( 'widget' => 'browsers' )
732
+ );
733
+ add_meta_box(
734
+ 'wps_referring_postbox',
735
+ __('Top Referring Sites', 'wp-statistics'),
736
+ 'wp_statistics_generate_overview_postbox_contents',
737
+ $WP_Statistics->menu_slugs['overview'],
738
+ 'side',
739
+ null,
740
+ array( 'widget' => 'referring' )
741
+ );
742
+
743
+ if ( $WP_Statistics->get_option('geoip') ) {
744
+ add_meta_box(
745
+ 'wps_countries_postbox',
746
+ __('Top 10 Countries', 'wp-statistics'),
747
+ 'wp_statistics_generate_overview_postbox_contents',
748
+ $WP_Statistics->menu_slugs['overview'],
749
+ 'side',
750
+ null,
751
+ array( 'widget' => 'countries' )
752
+ );
753
+ }
754
+ }
755
+ }
756
+
757
+
758
+ /**
759
+ * This function adds the primary menu to WordPress network.
760
+ */
761
+ static function networkmenu() {
762
+ global $WP_Statistics;
763
+
764
+ // Get the read/write capabilities required to view/manage the plugin as set by the user.
765
+ $read_cap = wp_statistics_validate_capability(
766
+ $WP_Statistics->get_option('read_capability', 'manage_options')
767
+ );
768
+ $manage_cap = wp_statistics_validate_capability(
769
+ $WP_Statistics->get_option('manage_capability', 'manage_options')
770
+ );
771
+
772
+ // Add the top level menu.
773
+ add_menu_page(
774
+ __('Statistics', 'wp-statistics'),
775
+ __('Statistics', 'wp-statistics'),
776
+ $read_cap,
777
+ WP_Statistics::$reg['main-file'],
778
+ 'WP_Statistics_Bootstrap::network_overview',
779
+ 'dashicons-chart-pie'
780
+ );
781
+
782
+ // Add the sub items.
783
+ add_submenu_page(
784
+ WP_Statistics::$reg['main-file'],
785
+ __('Overview', 'wp-statistics'),
786
+ __('Overview', 'wp-statistics'),
787
+ $read_cap,
788
+ WP_Statistics::$reg['main-file'],
789
+ 'WP_Statistics_Bootstrap::network_overview'
790
+ );
791
+
792
+ $count = 0;
793
+ $sites = $WP_Statistics->get_wp_sites_list();
794
+
795
+ foreach ( $sites as $blog_id ) {
796
+ $details = get_blog_details($blog_id);
797
+ add_submenu_page(
798
+ WP_Statistics::$reg['main-file'],
799
+ $details->blogname,
800
+ $details->blogname,
801
+ $manage_cap,
802
+ 'wp_statistics_blogid_' . $blog_id,
803
+ 'WP_Statistics_Bootstrap::goto_network_blog'
804
+ );
805
+
806
+ $count++;
807
+ if ( $count > 15 ) {
808
+ break;
809
+ }
810
+ }
811
+ }
812
+
813
+
814
+ /**
815
+ * Network Overview
816
+ */
817
+ static function network_overview() {
818
+ global $WP_Statistics;
819
+ ?>
820
+ <div id="wrap">
821
+ <br/>
822
+
823
+ <table class="widefat wp-list-table" style="width: auto;">
824
+ <thead>
825
+ <tr>
826
+ <th style='text-align: left'><?php _e('Site', 'wp-statistics'); ?></th>
827
+ <th style='text-align: left'><?php _e('Options', 'wp-statistics'); ?></th>
828
+ </tr>
829
+ </thead>
830
+
831
+ <tbody>
832
+ <?php
833
+ $i = 0;
834
+
835
+ $options = array(
836
+ __('Overview', 'wp-statistics') => WP_Statistics::$page['overview'],
837
+ __('Browsers', 'wp-statistics') => WP_Statistics::$page['browser'],
838
+ __('Countries', 'wp-statistics') => WP_Statistics::$page['countries'],
839
+ __('Exclusions', 'wp-statistics') => WP_Statistics::$page['exclusions'],
840
+ __('Hits', 'wp-statistics') => WP_Statistics::$page['hits'],
841
+ __('Online', 'wp-statistics') => WP_Statistics::$page['online'],
842
+ __('Pages', 'wp-statistics') => WP_Statistics::$page['pages'],
843
+ __('Referrers', 'wp-statistics') => WP_Statistics::$page['referrers'],
844
+ __('Searched Phrases', 'wp-statistics') => WP_Statistics::$page['searched-phrases'],
845
+ __('Searches', 'wp-statistics') => WP_Statistics::$page['searches'],
846
+ __('Search Words', 'wp-statistics') => WP_Statistics::$page['words'],
847
+ __('Top Visitors Today', 'wp-statistics') => WP_Statistics::$page['top-visitors'],
848
+ __('Visitors', 'wp-statistics') => WP_Statistics::$page['visitors'],
849
+ __('Optimization', 'wp-statistics') => WP_Statistics::$page['optimization'],
850
+ __('Settings', 'wp-statistics') => WP_Statistics::$page['settings'],
851
+ );
852
+
853
+ $sites = $WP_Statistics->get_wp_sites_list();
854
+
855
+ foreach ( $sites as $blog_id ) {
856
+ $details = get_blog_details($blog_id);
857
+ $url = get_admin_url($blog_id, '/') . 'admin.php?page=';
858
+ $alternate = '';
859
+
860
+ if ( $i % 2 == 0 ) {
861
+ $alternate = ' class="alternate"';
862
+ }
863
+ ?>
864
+
865
+ <tr<?php echo $alternate; ?>>
866
+ <td style='text-align: left'>
867
+ <?php echo $details->blogname; ?>
868
+ </td>
869
+ <td style='text-align: left'>
870
+ <?php
871
+ $options_len = count($options);
872
+ $j = 0;
873
+
874
+ foreach ( $options as $key => $value ) {
875
+ echo '<a href="' . $url . $value . '">' . $key . '</a>';
876
+ $j++;
877
+ if ( $j < $options_len ) {
878
+ echo ' - ';
879
+ }
880
+ }
881
+ ?>
882
+ </td>
883
+ </tr>
884
+ <?php
885
+ $i++;
886
+ }
887
+ ?>
888
+ </tbody>
889
+ </table>
890
+ </div>
891
+ <?php
892
+ }
893
+
894
+ /**
895
+ * Goto Network Blog
896
+ */
897
+ static function goto_network_blog() {
898
+ global $plugin_page;
899
+
900
+ $blog_id = str_replace('wp_statistics_blogid_', '', $plugin_page);
901
+
902
+ $details = get_blog_details($blog_id);
903
+
904
+ // Get the admin url for the current site.
905
+ $url = get_admin_url($blog_id) . '/admin.php?page=' . WP_Statistics::$page['overview'];
906
+
907
+ echo "<script>window.location.href = '$url';</script>";
908
+ }
909
+
910
+
911
+ /**
912
+ * Plugins
913
+ */
914
+ static function plugins() {
915
+ // Load our CSS to be used.
916
+ wp_enqueue_style(
917
+ 'wpstatistics-admin-css',
918
+ WP_Statistics::$reg['plugin-url'] . 'assets/css/admin.css',
919
+ true,
920
+ '1.1'
921
+ );
922
+
923
+ // Activate or deactivate the selected plugin
924
+ if ( isset( $_GET['action'] ) ) {
925
+ if ( $_GET['action'] == 'activate' ) {
926
+ $result = activate_plugin($_GET['plugin'] . '/' . $_GET['plugin'] . '.php');
927
+ if ( is_wp_error($result) ) {
928
+ wp_statistics_admin_notice_result('error', $result->get_error_message());
929
+ } else {
930
+ wp_statistics_admin_notice_result('success', __('Add-On activated.', 'wp-statistics'));
931
+ }
932
+ }
933
+ if ( $_GET['action'] == 'deactivate' ) {
934
+ $result = deactivate_plugins($_GET['plugin'] . '/' . $_GET['plugin'] . '.php');
935
+ if ( is_wp_error($result) ) {
936
+ wp_statistics_admin_notice_result('error', $result->get_error_message());
937
+ } else {
938
+ wp_statistics_admin_notice_result('success', __('Add-On deactivated.', 'wp-statistics'));
939
+ }
940
+ }
941
+ }
942
+ $response = wp_remote_get('https://wp-statistics.com/wp-json/plugin/addons');
943
+ $response_code = wp_remote_retrieve_response_code($response);
944
+ $error = null;
945
+ $plugins = array();
946
+ // Check response
947
+ if ( is_wp_error($response) ) {
948
+ $error = $response->get_error_message();
949
+ } else {
950
+ if ( $response_code == '200' ) {
951
+ $plugins = json_decode($response['body']);
952
+ } else {
953
+ $error = $response['body'];
954
+ }
955
+ }
956
+ include WP_Statistics::$reg['plugin-dir'] . 'includes/templates/plugins.php';
957
+ }
958
+
959
+ /**
960
+ * Donate
961
+ */
962
+ static function donate() {
963
+ echo "<script>window.location.href='http://wp-statistics.com/donate';</script>";
964
+ }
965
+
966
+
967
+ /**
968
+ * Adds the admin bar menu if the user has selected it.
969
+ */
970
+ static function menubar() {
971
+ GLOBAL $wp_admin_bar, $wp_version, $WP_Statistics;
972
+
973
+ // Find out if the user can read or manage statistics.
974
+ $read = current_user_can(
975
+ wp_statistics_validate_capability(
976
+ $WP_Statistics->get_option(
977
+ 'read_capability',
978
+ 'manage_options'
979
+ )
980
+ )
981
+ );
982
+ $manage = current_user_can(
983
+ wp_statistics_validate_capability(
984
+ $WP_Statistics->get_option(
985
+ 'manage_capability',
986
+ 'manage_options'
987
+ )
988
+ )
989
+ );
990
+
991
+ if ( is_admin_bar_showing() && ( $read || $manage ) ) {
992
+
993
+ $AdminURL = get_admin_url();
994
+
995
+ if ( version_compare($wp_version, '3.8-RC', '>=') || version_compare($wp_version, '3.8', '>=') ) {
996
+ $wp_admin_bar->add_menu(
997
+ array(
998
+ 'id' => 'wp-statistic-menu',
999
+ 'title' => '<span class="ab-icon"></span>',
1000
+ 'href' => $AdminURL . 'admin.php?page=' . WP_Statistics::$page['overview'],
1001
+ )
1002
+ );
1003
+ } else {
1004
+ $wp_admin_bar->add_menu(
1005
+ array(
1006
+ 'id' => 'wp-statistic-menu',
1007
+ 'title' => '<img src="' . WP_Statistics::$reg['plugin-url'] . 'assets/images/icon.png"/>',
1008
+ 'href' => $AdminURL . 'admin.php?page=' . WP_Statistics::$page['overview'],
1009
+ )
1010
+ );
1011
+ }
1012
+
1013
+ $wp_admin_bar->add_menu(
1014
+ array(
1015
+ 'id' => 'wp-statistics-menu-useronline',
1016
+ 'parent' => 'wp-statistic-menu',
1017
+ 'title' => __(
1018
+ 'Online User',
1019
+ 'wp-statistics'
1020
+ ) . ": " . wp_statistics_useronline(),
1021
+ 'href' => $AdminURL . 'admin.php?page=' . WP_Statistics::$page['online'],
1022
+ )
1023
+ );
1024
+
1025
+ $wp_admin_bar->add_menu(
1026
+ array(
1027
+ 'id' => 'wp-statistics-menu-todayvisitor',
1028
+ 'parent' => 'wp-statistic-menu',
1029
+ 'title' => __('Today\'s Visitors', 'wp-statistics') . ": " . wp_statistics_visitor('today'),
1030
+ )
1031
+ );
1032
+
1033
+ $wp_admin_bar->add_menu(
1034
+ array(
1035
+ 'id' => 'wp-statistics-menu-todayvisit',
1036
+ 'parent' => 'wp-statistic-menu',
1037
+ 'title' => __('Today\'s Visits', 'wp-statistics') . ": " . wp_statistics_visit('today'),
1038
+ )
1039
+ );
1040
+
1041
+ $wp_admin_bar->add_menu(
1042
+ array(
1043
+ 'id' => 'wp-statistics-menu-yesterdayvisitor',
1044
+ 'parent' => 'wp-statistic-menu',
1045
+ 'title' => __('Yesterday\'s Visitors', 'wp-statistics') . ": " . wp_statistics_visitor(
1046
+ 'yesterday'
1047
+ ),
1048
+ )
1049
+ );
1050
+
1051
+ $wp_admin_bar->add_menu(
1052
+ array(
1053
+ 'id' => 'wp-statistics-menu-yesterdayvisit',
1054
+ 'parent' => 'wp-statistic-menu',
1055
+ 'title' => __('Yesterday\'s Visits', 'wp-statistics') .
1056
+ ": " .
1057
+ wp_statistics_visit('yesterday'),
1058
+ )
1059
+ );
1060
+
1061
+ $wp_admin_bar->add_menu(
1062
+ array(
1063
+ 'id' => 'wp-statistics-menu-viewstats',
1064
+ 'parent' => 'wp-statistic-menu',
1065
+ 'title' => __('View Stats', 'wp-statistics'),
1066
+ 'href' => $AdminURL . 'admin.php?page=' . WP_Statistics::$page['overview'],
1067
+ )
1068
+ );
1069
+ }
1070
+ }
1071
+
1072
+ /**
1073
+ * @param string $log_type Log Type
1074
+ */
1075
+ static function log( $log_type = "" ) {
1076
+ global $wpdb, $WP_Statistics, $plugin_page;
1077
+
1078
+ switch ( $plugin_page ) {
1079
+ case WP_Statistics::$page['browser']:
1080
+ $log_type = 'all-browsers';
1081
+
1082
+ break;
1083
+ case WP_Statistics::$page['countries']:
1084
+ $log_type = 'top-countries';
1085
+
1086
+ break;
1087
+ case WP_Statistics::$page['exclusions']:
1088
+ $log_type = 'exclusions';
1089
+
1090
+ break;
1091
+ case WP_Statistics::$page['hits']:
1092
+ $log_type = 'hit-statistics';
1093
+
1094
+ break;
1095
+ case WP_Statistics::$page['online']:
1096
+ $log_type = 'online';
1097
+
1098
+ break;
1099
+ case WP_Statistics::$page['pages']:
1100
+ $log_type = 'top-pages';
1101
+
1102
+ break;
1103
+ case WP_Statistics::$page['categories']:
1104
+ $log_type = 'categories';
1105
+
1106
+ break;
1107
+ case WP_Statistics::$page['tags']:
1108
+ $log_type = 'tags';
1109
+
1110
+ break;
1111
+ case WP_Statistics::$page['authors']:
1112
+ $log_type = 'authors';
1113
+
1114
+ break;
1115
+ case WP_Statistics::$page['referrers']:
1116
+ $log_type = 'top-referring-site';
1117
+
1118
+ break;
1119
+ case WP_Statistics::$page['searched-phrases']:
1120
+ $log_type = 'searched-phrases';
1121
+
1122
+ break;
1123
+ case WP_Statistics::$page['searches']:
1124
+ $log_type = 'search-statistics';
1125
+
1126
+ break;
1127
+ case WP_Statistics::$page['words']:
1128
+ $log_type = 'last-all-search';
1129
+
1130
+ break;
1131
+ case WP_Statistics::$page['top-visitors']:
1132
+ $log_type = 'top-visitors';
1133
+
1134
+ break;
1135
+ case WP_Statistics::$page['visitors']:
1136
+ $log_type = 'last-all-visitor';
1137
+
1138
+ break;
1139
+ default:
1140
+ $log_type = "";
1141
+ }
1142
+
1143
+ // When we create $WP_Statistics the user has not been authenticated yet so we cannot load the user preferences
1144
+ // during the creation of the class. Instead load them now that the user exists.
1145
+ $WP_Statistics->load_user_options();
1146
+
1147
+ // We allow for a get style variable to be passed to define which function to use.
1148
+ if ( $log_type == "" && array_key_exists('type', $_GET) ) {
1149
+ $log_type = $_GET['type'];
1150
+ }
1151
+
1152
+ // Verify the user has the rights to see the statistics.
1153
+ if ( ! current_user_can(
1154
+ wp_statistics_validate_capability(
1155
+ $WP_Statistics->get_option(
1156
+ 'read_capability',
1157
+ 'manage_option'
1158
+ )
1159
+ )
1160
+ )
1161
+ ) {
1162
+ wp_die(__('You do not have sufficient permissions to access this page.'));
1163
+ }
1164
+
1165
+ // We want to make sure the tables actually exist before we blindly start access them.
1166
+ $dbname = DB_NAME;
1167
+ $result = $wpdb->query(
1168
+ "SHOW TABLES WHERE `Tables_in_{$dbname}` = '{$wpdb->prefix}statistics_visitor' OR `Tables_in_{$dbname}` = '{$wpdb->prefix}statistics_visit' OR `Tables_in_{$dbname}` = '{$wpdb->prefix}statistics_exclusions' OR `Tables_in_{$dbname}` = '{$wpdb->prefix}statistics_historical' OR `Tables_in_{$dbname}` = '{$wpdb->prefix}statistics_pages' OR `Tables_in_{$dbname}` = '{$wpdb->prefix}statistics_useronline' OR `Tables_in_{$dbname}` = '{$wpdb->prefix}statistics_search'"
1169
+ );
1170
+
1171
+ if ( $result != 7 ) {
1172
+ $get_bloginfo_url = get_admin_url() .
1173
+ "admin.php?page=" .
1174
+ WP_Statistics::$page['optimization'] .
1175
+ "&tab=database";
1176
+
1177
+ $missing_tables = array();
1178
+
1179
+ $result = $wpdb->query("SHOW TABLES WHERE `Tables_in_{$dbname}` = '{$wpdb->prefix}statistics_visitor'");
1180
+ if ( $result != 1 ) {
1181
+ $missing_tables[] = $wpdb->prefix . 'statistics_visitor';
1182
+ }
1183
+ $result = $wpdb->query("SHOW TABLES WHERE `Tables_in_{$dbname}` = '{$wpdb->prefix}statistics_visit'");
1184
+ if ( $result != 1 ) {
1185
+ $missing_tables[] = $wpdb->prefix . 'statistics_visit';
1186
+ }
1187
+ $result = $wpdb->query(
1188
+ "SHOW TABLES WHERE `Tables_in_{$dbname}` = '{$wpdb->prefix}statistics_exclusions'"
1189
+ );
1190
+ if ( $result != 1 ) {
1191
+ $missing_tables[] = $wpdb->prefix . 'statistics_exclusions';
1192
+ }
1193
+ $result = $wpdb->query(
1194
+ "SHOW TABLES WHERE `Tables_in_{$dbname}` = '{$wpdb->prefix}statistics_historical'"
1195
+ );
1196
+ if ( $result != 1 ) {
1197
+ $missing_tables[] = $wpdb->prefix . 'statistics_historical';
1198
+ }
1199
+ $result = $wpdb->query(
1200
+ "SHOW TABLES WHERE `Tables_in_{$dbname}` = '{$wpdb->prefix}statistics_useronline'"
1201
+ );
1202
+ if ( $result != 1 ) {
1203
+ $missing_tables[] = $wpdb->prefix . 'statistics_useronline';
1204
+ }
1205
+ $result = $wpdb->query("SHOW TABLES WHERE `Tables_in_{$dbname}` = '{$wpdb->prefix}statistics_pages'");
1206
+ if ( $result != 1 ) {
1207
+ $missing_tables[] = $wpdb->prefix . 'statistics_pages';
1208
+ }
1209
+ $result = $wpdb->query("SHOW TABLES WHERE `Tables_in_{$dbname}` = '{$wpdb->prefix}statistics_search'");
1210
+ if ( $result != 1 ) {
1211
+ $missing_tables[] = $wpdb->prefix . 'statistics_search';
1212
+ }
1213
+
1214
+ wp_die(
1215
+ '<div class="error"><p>' . sprintf(
1216
+ __(
1217
+ 'The following plugin table(s) do not exist in the database, please re-run the %s install routine %s: ',
1218
+ 'wp-statistics'
1219
+ ),
1220
+ '<a href="' . $get_bloginfo_url . '">',
1221
+ '</a>'
1222
+ ) . implode(', ', $missing_tables) . '</p></div>'
1223
+ );
1224
+ }
1225
+
1226
+ // Load the postbox script that provides the widget style boxes.
1227
+ wp_enqueue_script('common');
1228
+ wp_enqueue_script('wp-lists');
1229
+ wp_enqueue_script('postbox');
1230
+
1231
+ // Load the css we use for the statistics pages.
1232
+ wp_enqueue_style(
1233
+ 'wpstatistics-log-css',
1234
+ WP_Statistics::$reg['plugin-url'] . 'assets/css/log.css',
1235
+ true,
1236
+ '1.2'
1237
+ );
1238
+ wp_enqueue_style(
1239
+ 'wpstatistics-pagination-css',
1240
+ WP_Statistics::$reg['plugin-url'] . 'assets/css/pagination.css',
1241
+ true,
1242
+ '1.0'
1243
+ );
1244
+
1245
+ // Don't forget the right to left support.
1246
+ if ( is_rtl() ) {
1247
+ wp_enqueue_style(
1248
+ 'wpstatistics-rtl-css',
1249
+ WP_Statistics::$reg['plugin-url'] . 'assets/css/rtl.css',
1250
+ true,
1251
+ '1.1'
1252
+ );
1253
+ }
1254
+
1255
+ // The different pages have different files to load.
1256
+ switch ( $log_type ) {
1257
+ case 'all-browsers':
1258
+ case 'top-countries':
1259
+ case 'hit-statistics':
1260
+ case 'search-statistics':
1261
+ case 'exclusions':
1262
+ case 'online':
1263
+ case 'top-visitors':
1264
+ case 'categories':
1265
+ case 'tags':
1266
+ case 'authors':
1267
+ include WP_Statistics::$reg['plugin-dir'] . 'includes/log/' . $log_type . '.php';
1268
+ break;
1269
+ case 'last-all-search':
1270
+ include WP_Statistics::$reg['plugin-dir'] . 'includes/log/last-search.php';
1271
+
1272
+ break;
1273
+ case 'last-all-visitor':
1274
+ include WP_Statistics::$reg['plugin-dir'] . 'includes/log/last-visitor.php';
1275
+
1276
+ break;
1277
+ case 'top-referring-site':
1278
+ include WP_Statistics::$reg['plugin-dir'] . 'includes/log/top-referring.php';
1279
+
1280
+ break;
1281
+ case 'searched-phrases':
1282
+ include WP_Statistics::$reg['plugin-dir'] . 'includes/log/searched-phrases.php';
1283
+
1284
+ break;
1285
+ case 'top-pages':
1286
+ // If we've been given a page id or uri to get statistics for, load the page stats, otherwise load the page stats overview page.
1287
+ if ( array_key_exists('page-id', $_GET) || array_key_exists('page-uri', $_GET) ) {
1288
+ include WP_Statistics::$reg['plugin-dir'] . 'includes/log/page-statistics.php';
1289
+ } else {
1290
+ include WP_Statistics::$reg['plugin-dir'] . 'includes/log/top-pages.php';
1291
+ }
1292
+
1293
+ break;
1294
+ default:
1295
+ wp_enqueue_style(
1296
+ 'wpstatistics-jqvmap-css',
1297
+ WP_Statistics::$reg['plugin-url'] . 'assets/jqvmap/jqvmap.css',
1298
+ true,
1299
+ '1.5.1'
1300
+ );
1301
+ wp_enqueue_script(
1302
+ 'wpstatistics-jquery-vmap',
1303
+ WP_Statistics::$reg['plugin-url'] . 'assets/jqvmap/jquery.vmap.js',
1304
+ true,
1305
+ '1.5.1'
1306
+ );
1307
+ wp_enqueue_script(
1308
+ 'wpstatistics-jquery-vmap-world',
1309
+ WP_Statistics::$reg['plugin-url'] . 'assets/jqvmap/maps/jquery.vmap.world.js',
1310
+ true,
1311
+ '1.5.1'
1312
+ );
1313
+
1314
+ // Load our custom widgets handling javascript.
1315
+ wp_enqueue_script('wp_statistics_log', WP_Statistics::$reg['plugin-url'] . 'assets/js/log.js');
1316
+
1317
+ include WP_Statistics::$reg['plugin-dir'] . 'includes/log/log.php';
1318
+
1319
+ break;
1320
+ }
1321
+ }
1322
+
1323
+
1324
+ /**
1325
+ * Loads the optimization page code.
1326
+ */
1327
+ static function optimization() {
1328
+ GLOBAL $wpdb, $WP_Statistics;
1329
+
1330
+ // Check the current user has the rights to be here.
1331
+ if ( ! current_user_can(
1332
+ wp_statistics_validate_capability(
1333
+ $WP_Statistics->get_option(
1334
+ 'manage_capability',
1335
+ 'manage_options'
1336
+ )
1337
+ )
1338
+ )
1339
+ ) {
1340
+ wp_die(__('You do not have sufficient permissions to access this page.'));
1341
+ }
1342
+
1343
+ // When we create $WP_Statistics the user has not been authenticated yet so we cannot load the user preferences
1344
+ // during the creation of the class. Instead load them now that the user exists.
1345
+ $WP_Statistics->load_user_options();
1346
+
1347
+ // Load our JS to be used.
1348
+ wp_enqueue_script(
1349
+ 'wp-statistics-admin-js',
1350
+ WP_Statistics::$reg['plugin-url'] . 'assets/js/admin.js',
1351
+ array( 'jquery' ),
1352
+ '1.0'
1353
+ );
1354
+
1355
+ // Load our CSS to be used.
1356
+ wp_enqueue_style(
1357
+ 'wpstatistics-admin-css',
1358
+ WP_Statistics::$reg['plugin-url'] . 'assets/css/admin.css',
1359
+ true,
1360
+ '1.1'
1361
+ );
1362
+
1363
+ if ( is_rtl() ) {
1364
+ wp_enqueue_style('rtl-css', WP_Statistics::$reg['plugin-url'] . 'assets/css/rtl.css', true, '1.1');
1365
+ }
1366
+
1367
+ // Get the row count for each of the tables, we'll use this later on in the wps_optimization.php file.
1368
+ $result['useronline'] = $wpdb->get_var("SELECT COUNT(ID) FROM `{$wpdb->prefix}statistics_useronline`");
1369
+ $result['visit'] = $wpdb->get_var("SELECT COUNT(ID) FROM `{$wpdb->prefix}statistics_visit`");
1370
+ $result['visitor'] = $wpdb->get_var("SELECT COUNT(ID) FROM `{$wpdb->prefix}statistics_visitor`");
1371
+ $result['exclusions'] = $wpdb->get_var("SELECT COUNT(ID) FROM `{$wpdb->prefix}statistics_exclusions`");
1372
+ $result['pages'] = $wpdb->get_var("SELECT COUNT(uri) FROM `{$wpdb->prefix}statistics_pages`");
1373
+ $result['historical'] = $wpdb->get_var("SELECT COUNT(ID) FROM `{$wpdb->prefix}statistics_historical`");
1374
+ $result['search'] = $wpdb->get_var("SELECT COUNT(ID) FROM `{$wpdb->prefix}statistics_search`");
1375
+
1376
+ include WP_Statistics::$reg['plugin-dir'] . "includes/optimization/wps-optimization.php";
1377
+ }
1378
+
1379
+
1380
+ /**
1381
+ * This function displays the HTML for the settings page.
1382
+ */
1383
+ static function settings() {
1384
+ global $WP_Statistics;
1385
+
1386
+ // Check the current user has the rights to be here.
1387
+ if ( ! current_user_can(
1388
+ wp_statistics_validate_capability(
1389
+ $WP_Statistics->get_option(
1390
+ 'read_capability',
1391
+ 'manage_options'
1392
+ )
1393
+ )
1394
+ )
1395
+ ) {
1396
+ wp_die(__('You do not have sufficient permissions to access this page.'));
1397
+ }
1398
+
1399
+ // When we create $WP_Statistics the user has not been authenticated yet so we cannot load the user preferences
1400
+ // during the creation of the class. Instead load them now that the user exists.
1401
+ $WP_Statistics->load_user_options();
1402
+
1403
+ // Load our JS to be used.
1404
+ wp_enqueue_script(
1405
+ 'wp-statistics-admin-js',
1406
+ WP_Statistics::$reg['plugin-url'] . 'assets/js/admin.js',
1407
+ array( 'jquery' ),
1408
+ '1.0'
1409
+ );
1410
+
1411
+ // Load our CSS to be used.
1412
+ wp_enqueue_style(
1413
+ 'wpstatistics-admin-css',
1414
+ WP_Statistics::$reg['plugin-url'] . 'assets/css/admin.css',
1415
+ true,
1416
+ '1.1'
1417
+ );
1418
+
1419
+ if ( is_rtl() ) {
1420
+ wp_enqueue_style('rtl-css', WP_Statistics::$reg['plugin-url'] . 'assets/css/rtl.css', true, '1.1');
1421
+ }
1422
+
1423
+ // We could let the download happen at the end of the page, but this way we get to give some
1424
+ // feedback to the users about the result.
1425
+ if ( $WP_Statistics->get_option('update_geoip') == true ) {
1426
+ echo WP_Statistics_Updates::download_geoip();
1427
+ }
1428
+
1429
+ include WP_Statistics::$reg['plugin-dir'] . "includes/settings/wps-settings.php";
1430
+ }
1431
+
1432
+
1433
+ /**
1434
+ * Enqueue Scripts
1435
+ *
1436
+ * @param string $hook Not Used
1437
+ */
1438
+ static function enqueue_scripts( $hook ) {
1439
+ if ( ! isset( $_GET['page'] ) ) {
1440
+ return;
1441
+ }
1442
+
1443
+ $pages_required_chart = array(
1444
+ 'wps_overview_page',
1445
+ 'wps_browsers_page',
1446
+ 'wps_hits_page',
1447
+ 'wps_pages_page',
1448
+ 'wps_categories_page',
1449
+ 'wps_tags_page',
1450
+ 'wps_authors_page',
1451
+ 'wps_searches_page',
1452
+ );
1453
+
1454
+ if ( array_search($_GET['page'], $pages_required_chart) !== false ) {
1455
+ $load_in_footer = true;
1456
+ $pages_required_load_in_head = array(
1457
+ 'wps_browsers_page',
1458
+ 'wps_hits_page',
1459
+ 'wps_pages_page',
1460
+ 'wps_categories_page',
1461
+ 'wps_tags_page',
1462
+ 'wps_authors_page',
1463
+ 'wps_searches_page',
1464
+ );
1465
+
1466
+ if ( array_search($_GET['page'], $pages_required_load_in_head) !== false ) {
1467
+ $load_in_footer = false;
1468
+ }
1469
+
1470
+ wp_enqueue_script(
1471
+ 'wp-statistics-chart-js',
1472
+ WP_Statistics::$reg['plugin-url'] . 'assets/js/Chart.bundle.min.js',
1473
+ false,
1474
+ '2.7.0',
1475
+ $load_in_footer
1476
+ );
1477
+ }
1478
+ }
1479
+
1480
+
1481
+ }
1482
+ }
includes/classes/class-wp-statistics-dashboard.php ADDED
@@ -0,0 +1,359 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace {
3
+ /**
4
+ * Class WP_Statistics_Dashboard
5
+ */
6
+ class WP_Statistics_Dashboard {
7
+
8
+ static function widget_load() {
9
+ GLOBAL $WP_Statistics;
10
+
11
+ $WP_Statistics->load_user_options();
12
+
13
+ // We need to fudge the display settings for first time users so not all of the widgets are displayed, we only want to do this on
14
+ // the first time they visit the dashboard though so check to see if we've been here before.
15
+ if ( ! $WP_Statistics->get_user_option('dashboard_set') ) {
16
+ $WP_Statistics->update_user_option('dashboard_set', WP_Statistics::$reg['version']);
17
+
18
+ $hidden_widgets = get_user_meta($WP_Statistics->user_id, 'metaboxhidden_dashboard', true);
19
+ if ( ! is_array($hidden_widgets) ) {
20
+ $hidden_widgets = array();
21
+ }
22
+
23
+ $default_hidden = array(
24
+ 'wp-statistics-browsers-widget',
25
+ 'wp-statistics-countries-widget',
26
+ 'wp-statistics-hitsmap-widget',
27
+ 'wp-statistics-hits-widget',
28
+ 'wp-statistics-pages-widget',
29
+ 'wp-statistics-recent-widget',
30
+ 'wp-statistics-referring-widget',
31
+ 'wp-statistics-search-widget',
32
+ 'wp-statistics-summary-widget',
33
+ 'wp-statistics-words-widget',
34
+ 'wp-statistics-top-visitors-widget',
35
+ 'wp-statistics-searched-phrases-widget',
36
+ );
37
+
38
+ foreach ( $default_hidden as $widget ) {
39
+ if ( ! in_array($widget, $hidden_widgets) ) {
40
+ $hidden_widgets[] = $widget;
41
+ }
42
+ }
43
+
44
+ update_user_meta($WP_Statistics->user_id, 'metaboxhidden_dashboard', $hidden_widgets);
45
+ } elseif ( $WP_Statistics->get_user_option('dashboard_set') != WP_Statistics::$reg['version'] ) {
46
+ // We also have to fudge things when we add new widgets to the code base.
47
+ if ( version_compare($WP_Statistics->get_user_option('dashboard_set'), '8.7', '<') ) {
48
+
49
+ $WP_Statistics->update_user_option('dashboard_set', WP_Statistics::$reg['version']);
50
+
51
+ $hidden_widgets = get_user_meta($WP_Statistics->user_id, 'metaboxhidden_dashboard', true);
52
+ if ( ! is_array($hidden_widgets) ) {
53
+ $hidden_widgets = array();
54
+ }
55
+
56
+ $default_hidden = array( 'wp-statistics-top-visitors-widget' );
57
+
58
+ foreach ( $default_hidden as $widget ) {
59
+ if ( ! in_array($widget, $hidden_widgets) ) {
60
+ $hidden_widgets[] = $widget;
61
+ }
62
+ }
63
+
64
+ update_user_meta($WP_Statistics->user_id, 'metaboxhidden_dashboard', $hidden_widgets);
65
+ }
66
+ }
67
+
68
+ // If the user does not have at least read access to the status plugin, just return without adding the widgets.
69
+ if ( ! current_user_can(
70
+ wp_statistics_validate_capability(
71
+ $WP_Statistics->get_option(
72
+ 'read_capability',
73
+ 'manage_option'
74
+ )
75
+ )
76
+ )
77
+ ) {
78
+ return;
79
+ }
80
+
81
+ // If the admin has disabled the widgets, don't display them.
82
+ if ( ! $WP_Statistics->get_option('disable_dashboard') ) {
83
+ wp_add_dashboard_widget(
84
+ 'wp-statistics-quickstats-widget',
85
+ __('Quick Stats', 'wp-statistics'),
86
+ 'WP_Statistics_Dashboard::generate_postbox_contents',
87
+ $control_callback = null,
88
+ array( 'widget' => 'quickstats' )
89
+ );
90
+ if ( $WP_Statistics->get_option('visitors') ) {
91
+ wp_add_dashboard_widget(
92
+ 'wp-statistics-browsers-widget',
93
+ __('Top 10 Browsers', 'wp-statistics'),
94
+ 'WP_Statistics_Dashboard::generate_postbox_contents',
95
+ $control_callback = null,
96
+ array( 'widget' => 'browsers' )
97
+ );
98
+ }
99
+ if ( $WP_Statistics->get_option('geoip') && $WP_Statistics->get_option('visitors') ) {
100
+ wp_add_dashboard_widget(
101
+ 'wp-statistics-countries-widget',
102
+ __('Top 10 Countries', 'wp-statistics'),
103
+ 'WP_Statistics_Dashboard::generate_postbox_contents',
104
+ $control_callback = null,
105
+ array( 'widget' => 'countries' )
106
+ );
107
+ }
108
+ if ( $WP_Statistics->get_option('visitors') ) {
109
+ wp_add_dashboard_widget(
110
+ 'wp-statistics-hitsmap-widget',
111
+ __('Today\'s Visitors Map', 'wp-statistics'),
112
+ 'WP_Statistics_Dashboard::generate_postbox_contents',
113
+ $control_callback = null,
114
+ array( 'widget' => 'hitsmap' )
115
+ );
116
+ }
117
+ if ( $WP_Statistics->get_option('visits') ) {
118
+ wp_add_dashboard_widget(
119
+ 'wp-statistics-hits-widget',
120
+ __('Hit Statistics', 'wp-statistics'),
121
+ 'WP_Statistics_Dashboard::generate_postbox_contents',
122
+ $control_callback = null,
123
+ array( 'widget' => 'hits' )
124
+ );
125
+ }
126
+ if ( $WP_Statistics->get_option('pages') ) {
127
+ wp_add_dashboard_widget(
128
+ 'wp-statistics-pages-widget',
129
+ __('Top 10 Pages', 'wp-statistics'),
130
+ 'WP_Statistics_Dashboard::generate_postbox_contents',
131
+ $control_callback = null,
132
+ array( 'widget' => 'pages' )
133
+ );
134
+ }
135
+ if ( $WP_Statistics->get_option('visitors') ) {
136
+ wp_add_dashboard_widget(
137
+ 'wp-statistics-recent-widget',
138
+ __('Recent Visitors', 'wp-statistics'),
139
+ 'WP_Statistics_Dashboard::generate_postbox_contents',
140
+ $control_callback = null,
141
+ array( 'widget' => 'recent' )
142
+ );
143
+ }
144
+ if ( $WP_Statistics->get_option('visitors') ) {
145
+ wp_add_dashboard_widget(
146
+ 'wp-statistics-referring-widget',
147
+ __('Top Referring Sites', 'wp-statistics'),
148
+ 'WP_Statistics_Dashboard::generate_postbox_contents',
149
+ $control_callback = null,
150
+ array( 'widget' => 'referring' )
151
+ );
152
+ }
153
+ if ( $WP_Statistics->get_option('visitors') ) {
154
+ wp_add_dashboard_widget(
155
+ 'wp-statistics-search-widget',
156
+ __('Search Engine Referrals', 'wp-statistics'),
157
+ 'WP_Statistics_Dashboard::generate_postbox_contents',
158
+ $control_callback = null,
159
+ array( 'widget' => 'search' )
160
+ );
161
+ }
162
+ wp_add_dashboard_widget(
163
+ 'wp-statistics-summary-widget',
164
+ __('Summary', 'wp-statistics'),
165
+ 'WP_Statistics_Dashboard::generate_postbox_contents',
166
+ $control_callback = null,
167
+ array( 'widget' => 'summary' )
168
+ );
169
+ if ( $WP_Statistics->get_option('visitors') ) {
170
+ wp_add_dashboard_widget(
171
+ 'wp-statistics-words-widget',
172
+ __('Latest Search Words', 'wp-statistics'),
173
+ 'WP_Statistics_Dashboard::generate_postbox_contents',
174
+ $control_callback = null,
175
+ array( 'widget' => 'words' )
176
+ );
177
+ }
178
+ if ( $WP_Statistics->get_option('visitors') ) {
179
+ wp_add_dashboard_widget(
180
+ 'wp-statistics-top-visitors-widget',
181
+ __('Top 10 Visitors Today', 'wp-statistics'),
182
+ 'WP_Statistics_Dashboard::generate_postbox_contents',
183
+ $control_callback = null,
184
+ array( 'widget' => 'top.visitors' )
185
+ );
186
+ }
187
+ if ( $WP_Statistics->get_option('visitors') ) {
188
+ wp_add_dashboard_widget(
189
+ 'wp-statistics-searched-phrases-widget',
190
+ __('Top Searched Phrases (30 Days)', 'wp-statistics'),
191
+ 'WP_Statistics_Dashboard::generate_postbox_contents',
192
+ $control_callback = null,
193
+ array( 'widget' => 'searched.phrases' )
194
+ );
195
+ }
196
+ }
197
+ }
198
+
199
+ static function load_widget_css_and_scripts() {
200
+ global $WP_Statistics;
201
+
202
+ // Load the css we use for the statistics pages.
203
+ wp_enqueue_style('wpstatistics-log-css', WP_Statistics::$reg['plugin-url'] . 'assets/css/log.css', true, '1.2');
204
+ wp_enqueue_style('wpstatistics-admin-css', WP_Statistics::$reg['plugin-url'] . 'assets/css/admin.css', true, '1.1');
205
+
206
+ // Don't forget the right to left support.
207
+ if ( is_rtl() ) {
208
+ wp_enqueue_style('rtl-css', WP_Statistics::$reg['plugin-url'] . 'assets/css/rtl.css', true, '1.1');
209
+ }
210
+
211
+ // Load the map code.
212
+ wp_enqueue_style('jqvmap-css', WP_Statistics::$reg['plugin-url'] . 'assets/jqvmap/jqvmap.css', true, '1.5.1');
213
+ wp_enqueue_script('jquery-vmap', WP_Statistics::$reg['plugin-url'] . 'assets/jqvmap/jquery.vmap.js', true, '1.5.1');
214
+ wp_enqueue_script(
215
+ 'jquery-vmap-world',
216
+ WP_Statistics::$reg['plugin-url'] . 'assets/jqvmap/maps/jquery.vmap.world.js',
217
+ true,
218
+ '1.5.1'
219
+ );
220
+
221
+ // Load chart library
222
+ if ( ! isset( $_GET['post'] ) ) {
223
+ wp_enqueue_script(
224
+ 'wp-statistics-chart-js',
225
+ WP_Statistics::$reg['plugin-url'] . 'assets/js/Chart.bundle.min.js',
226
+ false,
227
+ '2.7.0'
228
+ );
229
+ }
230
+
231
+ $screen = get_current_screen();
232
+
233
+ // Load our custom widgets handling javascript.
234
+ if ( 'post' == $screen->id || 'page' == $screen->id ) {
235
+ wp_enqueue_script('wp_statistics_editor', WP_Statistics::$reg['plugin-url'] . 'assets/js/editor.js');
236
+ } else {
237
+ wp_enqueue_script('wp_statistics_dashboard', WP_Statistics::$reg['plugin-url'] . 'assets/js/dashboard.js');
238
+ }
239
+ }
240
+
241
+ static function inline_javascript() {
242
+ $screen = get_current_screen();
243
+
244
+ if ( 'dashboard' != $screen->id ) {
245
+ return;
246
+ }
247
+
248
+ \WP_Statistics_Dashboard::load_widget_css_and_scripts();
249
+
250
+ $loading_img = '<div style="width: 100%; text-align: center;"><img src=" ' .
251
+ plugins_url('wp-statistics/assets/images/') .
252
+ 'ajax-loading.gif" alt="' .
253
+ __('Reloading...', 'wp-statistics') .
254
+ '"></div>';
255
+
256
+ $new_buttons
257
+ = '</button><button class="handlediv button-link wps-refresh" type="button" id="{{refreshid}}">' .
258
+ wp_statistics_icons('dashicons-update') .
259
+ '<span class="screen-reader-text">' .
260
+ __('Reload', 'wp-statistics') .
261
+ '</span></button><button class="handlediv button-link wps-more" type="button" id="{{moreid}}">' .
262
+ wp_statistics_icons('dashicons-migrate') .
263
+ '<span class="screen-reader-text">' .
264
+ __('More Details', 'wp-statistics') .
265
+ '</span></button>';
266
+ $new_button
267
+ = '</button><button class="handlediv button-link wps-refresh" type="button" id="{{refreshid}}">' .
268
+ wp_statistics_icons('dashicons-update') .
269
+ '<span class="screen-reader-text">' .
270
+ __('Reload', 'wp-statistics') .
271
+ '</span></button>';
272
+
273
+ $admin_url = get_admin_url() . "admin.php?page=";
274
+
275
+ $page_urls = array();
276
+
277
+ $page_urls['wp-statistics-browsers-widget_more_button'] = $admin_url . WP_Statistics::$page['browser'];
278
+ $page_urls['wp-statistics-countries-widget_more_button'] = $admin_url . WP_Statistics::$page['countries'];
279
+ $page_urls['wp-statistics-exclusions-widget_more_button'] = $admin_url . WP_Statistics::$page['exclusions'];
280
+ $page_urls['wp-statistics-hits-widget_more_button'] = $admin_url . WP_Statistics::$page['hits'];
281
+ $page_urls['wp-statistics-online-widget_more_button'] = $admin_url . WP_Statistics::$page['online'];
282
+ $page_urls['wp-statistics-pages-widget_more_button'] = $admin_url . WP_Statistics::$page['pages'];
283
+ $page_urls['wp-statistics-referring-widget_more_button'] = $admin_url . WP_Statistics::$page['referrers'];
284
+ $page_urls['wp-statistics-searched-phrases-widget_more_button'] = $admin_url . WP_Statistics::$page['searched-phrases'];
285
+ $page_urls['wp-statistics-search-widget_more_button'] = $admin_url . WP_Statistics::$page['searches'];
286
+ $page_urls['wp-statistics-words-widget_more_button'] = $admin_url . WP_Statistics::$page['words'];
287
+ $page_urls['wp-statistics-top-visitors-widget_more_button'] = $admin_url . WP_Statistics::$page['top-visitors'];
288
+ $page_urls['wp-statistics-recent-widget_more_button'] = $admin_url . WP_Statistics::$page['visitors'];
289
+ $page_urls['wp-statistics-quickstats-widget_more_button'] = $admin_url . WP_Statistics::$page['overview'];
290
+
291
+ ?>
292
+ <script type="text/javascript">
293
+ var wp_statistics_destinations = <?php echo json_encode( $page_urls ); ?>;
294
+ var wp_statistics_loading_image = '<?php echo $loading_img; ?>';
295
+
296
+ function wp_statistics_wait_for_postboxes() {
297
+
298
+ if (!jQuery('#show-settings-link').is(':visible')) {
299
+ setTimeout(wp_statistics_wait_for_postboxes, 500);
300
+ }
301
+
302
+ jQuery('.wps-refresh').unbind('click').on('click', wp_statistics_refresh_widget);
303
+ jQuery('.wps-more').unbind('click').on('click', wp_statistics_goto_more);
304
+
305
+ jQuery('.hide-postbox-tog').on('click', wp_statistics_refresh_on_toggle_widget);
306
+ }
307
+
308
+ jQuery(document).ready(function () {
309
+
310
+ // Add the "more" and "refresh" buttons.
311
+ jQuery('.postbox').each(function () {
312
+ var temp = jQuery(this);
313
+ var temp_id = temp.attr('id');
314
+
315
+ if (temp_id.substr(0, 14) != 'wp-statistics-') {
316
+ return;
317
+ }
318
+
319
+ var temp_html = temp.html();
320
+
321
+ if (temp_id == 'wp-statistics-summary-widget') {
322
+ new_text = '<?php echo $new_button;?>';
323
+ new_text = new_text.replace('{{refreshid}}', temp_id + '_refresh_button');
324
+
325
+ temp_html = temp_html.replace('</button>', new_text);
326
+ } else {
327
+ new_text = '<?php echo $new_buttons;?>';
328
+ new_text = new_text.replace('{{refreshid}}', temp_id + '_refresh_button');
329
+ new_text = new_text.replace('{{moreid}}', temp_id + '_more_button');
330
+
331
+ temp_html = temp_html.replace('</button>', new_text);
332
+ }
333
+
334
+ temp.html(temp_html);
335
+ });
336
+
337
+ // We have use a timeout here because we don't now what order this code will run in comparison to the postbox code.
338
+ // Any timeout value should work as the timeout won't run until the rest of the javascript as run through once.
339
+ setTimeout(wp_statistics_wait_for_postboxes, 100);
340
+ });
341
+ </script>
342
+ <?php
343
+ }
344
+
345
+ static function generate_postbox_contents( $post, $args ) {
346
+ $loading_img = '<div style="width: 100%; text-align: center;"><img src=" ' .
347
+ plugins_url('wp-statistics/assets/images/') .
348
+ 'ajax-loading.gif" alt="' .
349
+ __('Loading...', 'wp-statistics') .
350
+ '"></div>';
351
+ $widget = $args['args']['widget'];
352
+ $container_id = 'wp-statistics-' . str_replace('.', '-', $widget) . '-div';
353
+
354
+ echo '<div id="' . $container_id . '">' . $loading_img . '</div>';
355
+ wp_statistics_generate_widget_load_javascript($widget, $container_id);
356
+ }
357
+
358
+ }
359
+ }
includes/classes/class-wp-statistics-editor.php ADDED
@@ -0,0 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace {
4
+ /**
5
+ * Class WP_Statistics_Editor
6
+ */
7
+ class WP_Statistics_Editor {
8
+
9
+ /**
10
+ * Adds a box to the main column on the Post and Page edit screens.
11
+ */
12
+ static function add_meta_box() {
13
+ global $WP_Statistics;
14
+
15
+ $WP_Statistics->load_user_options();
16
+
17
+ // We need to fudge the display settings for first time users so not all of the widgets are displayed, we only want to do this on
18
+ // the first time they visit the dashboard though so check to see if we've been here before.
19
+ if ( ! $WP_Statistics->get_user_option('editor_set') ) {
20
+ $WP_Statistics->update_user_option('editor_set', WP_Statistics::$reg['version']);
21
+
22
+ $hidden_widgets = get_user_meta($WP_Statistics->user_id, 'metaboxhidden_post', true);
23
+ if ( ! is_array($hidden_widgets) ) {
24
+ $hidden_widgets = array();
25
+ }
26
+
27
+ if ( ! in_array('wp_statistics_editor_meta_box', $hidden_widgets) ) {
28
+ $hidden_widgets[] = 'wp_statistics_editor_meta_box';
29
+ }
30
+
31
+ update_user_meta($WP_Statistics->user_id, 'metaboxhidden_post', $hidden_widgets);
32
+
33
+ $hidden_widgets = get_user_meta($WP_Statistics->user_id, 'metaboxhidden_page', true);
34
+ if ( ! is_array($hidden_widgets) ) {
35
+ $hidden_widgets = array();
36
+ }
37
+
38
+ if ( ! in_array('wp_statistics_editor_meta_box', $hidden_widgets) ) {
39
+ $hidden_widgets[] = 'wp_statistics_editor_meta_box';
40
+ }
41
+
42
+ update_user_meta($WP_Statistics->user_id, 'metaboxhidden_page', $hidden_widgets);
43
+ }
44
+
45
+ // If the user does not have at least read access to the status plugin, just return without adding the widgets.
46
+ if ( ! current_user_can(
47
+ wp_statistics_validate_capability($WP_Statistics->get_option('read_capability', 'manage_option'))
48
+ )
49
+ ) {
50
+ return;
51
+ }
52
+
53
+ // If the admin has disabled the widgets don't display them.
54
+ if ( $WP_Statistics->get_option('disable_editor') ) {
55
+ return;
56
+ }
57
+
58
+ $screens = array( 'post', 'page' );
59
+
60
+ foreach ( $screens as $screen ) {
61
+
62
+ add_meta_box(
63
+ 'wp_statistics_editor_meta_box',
64
+ __('Hit Statistics', 'wp-statistics'),
65
+ 'WP_Statistics_Editor::meta_box',
66
+ $screen,
67
+ 'normal',
68
+ 'high'
69
+ );
70
+ }
71
+ }
72
+
73
+
74
+ static function meta_box( $post ) {
75
+ // If the post isn't published yet, don't output the stats as they take too much memory and CPU to compute for no reason.
76
+ if ( $post->post_status != 'publish' && $post->post_status != 'private' ) {
77
+ _e('This post is not yet published.', 'wp-statistics');
78
+
79
+ return;
80
+ }
81
+
82
+ add_action('admin_footer', 'WP_Statistics_Editor::inline_javascript');
83
+
84
+ WP_Statistics_Editor::generate_postbox_contents($post->ID, array( 'args' => array( 'widget' => 'page' ) ));
85
+ }
86
+
87
+ static function generate_postbox_contents( $post, $args ) {
88
+ $loading_img = '<div style="width: 100%; text-align: center;"><img src=" ' .
89
+ plugins_url('wp-statistics/assets/images/') .
90
+ 'ajax-loading.gif" alt="' .
91
+ __('Loading...', 'wp-statistics') .
92
+ '"></div>';
93
+ $widget = $args['args']['widget'];
94
+ $container_id = 'wp-statistics-' . str_replace('.', '-', $widget) . '-div';
95
+
96
+ echo '<div id="' . $container_id . '">' . $loading_img . '</div>';
97
+ echo '<script type="text/javascript">var wp_statistics_current_id = \'' . $post . '\';</script>';
98
+ wp_statistics_generate_widget_load_javascript($widget, $container_id);
99
+ }
100
+
101
+ static function inline_javascript() {
102
+ $screen = get_current_screen();
103
+
104
+ if ( 'post' != $screen->id && 'page' != $screen->id ) {
105
+ return;
106
+ }
107
+
108
+ WP_Statistics_Dashboard::load_widget_css_and_scripts();
109
+
110
+ $loading_img = '<div style="width: 100%; text-align: center;"><img src=" ' .
111
+ plugins_url('wp-statistics/assets/images/') .
112
+ 'ajax-loading.gif" alt="' .
113
+ __('Reloading...', 'wp-statistics') .
114
+ '"></div>';
115
+
116
+ $new_buttons
117
+ = '</button><button class="handlediv button-link wps-refresh" type="button" id="{{refreshid}}">' .
118
+ wp_statistics_icons('dashicons-update') .
119
+ '<span class="screen-reader-text">' .
120
+ __('Reload', 'wp-statistics') .
121
+ '</span></button><button class="handlediv button-link wps-more" type="button" id="{{moreid}}">' .
122
+ wp_statistics_icons('dashicons-migrate') .
123
+ '<span class="screen-reader-text">' .
124
+ __('More Details', 'wp-statistics') .
125
+ '</span></button>';
126
+ $new_button
127
+ = '</button><button class="handlediv button-link wps-refresh" type="button" id="{{refreshid}}">' .
128
+ wp_statistics_icons('dashicons-update') .
129
+ '<span class="screen-reader-text">' .
130
+ __('Reload', 'wp-statistics') .
131
+ '</span></button>';
132
+
133
+ $admin_url = get_admin_url() . "/admin.php?page=";
134
+
135
+ $page_urls = array();
136
+
137
+ $page_urls['wp_statistics_editor_meta_box_more_button'] = $admin_url .
138
+ WP_Statistics::$page['pages'] .
139
+ '&page-id=';
140
+
141
+ ?>
142
+ <script type="text/javascript">
143
+ var wp_statistics_destinations = <?php echo json_encode( $page_urls ); ?>;
144
+ var wp_statistics_loading_image = '<?php echo $loading_img; ?>';
145
+
146
+ function wp_statistics_wait_for_postboxes() {
147
+
148
+ if (!jQuery('#show-settings-link').is(':visible')) {
149
+ setTimeout(wp_statistics_wait_for_postboxes, 500);
150
+ }
151
+
152
+ jQuery('.wps-refresh').unbind('click').on('click', wp_statistics_refresh_widget);
153
+ jQuery('.wps-more').unbind('click').on('click', wp_statistics_goto_more);
154
+
155
+ jQuery('.hide-postbox-tog').on('click', wp_statistics_refresh_on_toggle_widget);
156
+ }
157
+
158
+ jQuery(document).ready(function () {
159
+
160
+ // Add the "more" and "refresh" buttons.
161
+ jQuery('.postbox').each(function () {
162
+ var temp = jQuery(this);
163
+ var temp_id = temp.attr('id');
164
+
165
+ if (temp_id == 'wp_statistics_editor_meta_box') {
166
+
167
+ var temp_html = temp.html();
168
+
169
+ new_text = '<?php echo $new_buttons;?>';
170
+ new_text = new_text.replace('{{refreshid}}', temp_id + '_refresh_button');
171
+ new_text = new_text.replace('{{moreid}}', temp_id + '_more_button');
172
+
173
+ temp_html = temp_html.replace('</button>', new_text);
174
+
175
+ temp.html(temp_html);
176
+ }
177
+ });
178
+
179
+ // We have use a timeout here because we don't now what order this code will run in comparison to the postbox code.
180
+ // Any timeout value should work as the timeout won't run until the rest of the javascript as run through once.
181
+ setTimeout(wp_statistics_wait_for_postboxes, 100);
182
+ });
183
+ </script>
184
+ <?php
185
+ }
186
+ }
187
+ }
includes/classes/{hits.geoip.class.php → class-wp-statistics-geo-ip-hits.php} RENAMED
@@ -6,7 +6,7 @@
6
  // Load the classes.
7
  use GeoIp2\Database\Reader;
8
 
9
- class GeoIPHits extends Hits {
10
  public function __construct() {
11
 
12
  // Call the parent constructor (WP_Statistics::__constructor).
@@ -21,10 +21,10 @@ class GeoIPHits extends Hits {
21
  $upload_dir = wp_upload_dir();
22
 
23
  // Create a new Reader and point it to the database.
24
- $reader = new Reader( $upload_dir['basedir'] . '/wp-statistics/GeoLite2-Country.mmdb' );
25
 
26
  // Look up the IP address
27
- $record = $reader->country( $this->ip );
28
 
29
  // Get the location.
30
  $location = $record->country->isoCode;
@@ -44,22 +44,27 @@ class GeoIPHits extends Hits {
44
  // Check to see if we are excluded by the GeoIP rules.
45
  if ( ! $this->exclusion_match ) {
46
  // Grab the excluded/included countries lists, force the country codes to be in upper case to match what the GeoIP code uses.
47
- $excluded_countries = explode( "\n", strtoupper( str_replace( "\r\n", "\n", $this->get_option( 'excluded_countries' ) ) ) );
48
- $included_countries_string = trim( strtoupper( str_replace( "\r\n", "\n", $this->get_option( 'included_countries' ) ) ) );
 
 
 
 
 
49
 
50
  // We need to be really sure this isn't an empty string or explode will return an array with one entry instead of none.
51
  if ( $included_countries_string == '' ) {
52
  $included_countries = array();
53
  } else {
54
- $included_countries = explode( "\n", $included_countries_string );
55
  }
56
 
57
  // Check to see if the current location is in the excluded countries list.
58
- if ( in_array( $this->location, $excluded_countries ) ) {
59
  $this->exclusion_match = true;
60
  $this->exclusion_reason = "geoip";
61
  } // Check to see if the current location is not the included countries list.
62
- else if ( ! in_array( $this->location, $included_countries ) && count( $included_countries ) > 0 ) {
63
  $this->exclusion_match = true;
64
  $this->exclusion_reason = "geoip";
65
  }
6
  // Load the classes.
7
  use GeoIp2\Database\Reader;
8
 
9
+ class WP_Statistics_GEO_IP_Hits extends WP_Statistics_Hits {
10
  public function __construct() {
11
 
12
  // Call the parent constructor (WP_Statistics::__constructor).
21
  $upload_dir = wp_upload_dir();
22
 
23
  // Create a new Reader and point it to the database.
24
+ $reader = new Reader($upload_dir['basedir'] . '/wp-statistics/GeoLite2-Country.mmdb');
25
 
26
  // Look up the IP address
27
+ $record = $reader->country($this->ip);
28
 
29
  // Get the location.
30
  $location = $record->country->isoCode;
44
  // Check to see if we are excluded by the GeoIP rules.
45
  if ( ! $this->exclusion_match ) {
46
  // Grab the excluded/included countries lists, force the country codes to be in upper case to match what the GeoIP code uses.
47
+ $excluded_countries = explode(
48
+ "\n",
49
+ strtoupper(str_replace("\r\n", "\n", $this->get_option('excluded_countries')))
50
+ );
51
+ $included_countries_string = trim(
52
+ strtoupper(str_replace("\r\n", "\n", $this->get_option('included_countries')))
53
+ );
54
 
55
  // We need to be really sure this isn't an empty string or explode will return an array with one entry instead of none.
56
  if ( $included_countries_string == '' ) {
57
  $included_countries = array();
58
  } else {
59
+ $included_countries = explode("\n", $included_countries_string);
60
  }
61
 
62
  // Check to see if the current location is in the excluded countries list.
63
+ if ( in_array($this->location, $excluded_countries) ) {
64
  $this->exclusion_match = true;
65
  $this->exclusion_reason = "geoip";
66
  } // Check to see if the current location is not the included countries list.
67
+ else if ( ! in_array($this->location, $included_countries) && count($included_countries) > 0 ) {
68
  $this->exclusion_match = true;
69
  $this->exclusion_reason = "geoip";
70
  }
includes/classes/{hits.class.php → class-wp-statistics-hits.php} RENAMED
@@ -1,25 +1,22 @@
1
  <?php
2
  /*
3
- This is the primary class for recording hits on the WordPress site. It extends the WP_Statistics class and is itself extended by the GeoIPHits class.
4
 
5
  This class handles; visits, visitors and pages.
6
  */
7
 
8
- // The GeoIP library from MaxMind and the IP Tools library are complex and have many dependencies, use the autoload.php file to handle them all.
9
- require_once( plugin_dir_path( __FILE__ ) . '../../vendor/autoload.php' );
10
-
11
  use phpbrowscap\Browscap;
12
  use IPTools\IP;
13
  use IPTools\Network;
14
  use IPTools\Range;
15
 
16
- class Hits extends WP_Statistics {
17
 
18
  // Setup our public/private/protected variables.
19
  public $result = null;
20
 
21
- protected $location = '000';
22
- protected $exclusion_match = false;
23
  protected $exclusion_reason = '';
24
 
25
  private $exclusion_record = false;
@@ -31,48 +28,48 @@ class Hits extends WP_Statistics {
31
  public function __construct() {
32
  global $wp_version, $WP_Statistics;
33
 
34
- // Call the parent constructor (WP_Statistics::__construct)
35
  parent::__construct();
36
 
37
  // Set the timestamp value.
38
- $this->timestamp = $this->current_date( 'U' );
39
 
40
  // Set the default seconds a user needs to visit the site before they are considered offline.
41
  $this->second = 30;
42
 
43
  // Get the user set value for seconds to check for users online.
44
- if ( $this->get_option( 'check_online' ) ) {
45
- $this->second = $this->get_option( 'check_online' );
46
  }
47
 
48
  // Check to see if the user wants us to record why we're excluding hits.
49
- if ( $this->get_option( 'record_exclusions' ) ) {
50
  $this->exclusion_record = true;
51
  }
52
 
53
  // Create a IP Tools instance from the current IP address for use later.
54
  // Fall back to the localhost if it can't be parsed.
55
  try {
56
- $ip = new IP( $this->ip );
57
  } catch ( Exception $e ) {
58
- $ip = new IP( '127.0.0.1' );
59
  }
60
 
61
  // Let's check to see if our subnet matches a private IP address range, if so go ahead and set the location information now.
62
- if ( $this->get_option( 'private_country_code' ) != '000' && $this->get_option( 'private_country_code' ) != '' ) {
63
  $private_subnets = array( '10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16', '127.0.0.1/24', 'fc00::/7' );
64
 
65
  foreach ( $private_subnets as $psub ) {
66
  $contains_ip = false;
67
 
68
  try {
69
- $contains_ip = Range::parse( $psub )->contains( $ip );
70
  } catch ( Exception $e ) {
71
  $contains_ip = false;
72
  }
73
 
74
  if ( $contains_ip ) {
75
- $this->location = $this->get_option( 'private_country_code' );
76
  break;
77
  }
78
  }
@@ -99,7 +96,7 @@ class Hits extends WP_Statistics {
99
  $page_uri = wp_statistics_get_uri();
100
  $ajax_string = 'admin-ajax.php';
101
 
102
- if ( substr( $page_uri, 0, strlen( $ajax_string ) ) === $ajax_string ) {
103
  $this->exclusion_match = true;
104
  $this->exclusion_reason = 'ajax';
105
 
@@ -110,11 +107,11 @@ class Hits extends WP_Statistics {
110
  $crawler = false;
111
  $ua_string = '';
112
 
113
- if ( array_key_exists( 'HTTP_USER_AGENT', $_SERVER ) ) {
114
  $ua_string = $_SERVER['HTTP_USER_AGENT'];
115
  }
116
 
117
- if ( $this->get_option( 'last_browscap_dl' ) > 1 && $this->get_option( 'browscap' ) ) {
118
  // Get the upload directory from WordPress.
119
  $upload_dir = wp_upload_dir();
120
 
@@ -122,12 +119,12 @@ class Hits extends WP_Statistics {
122
  $BrowscapFile = $upload_dir['basedir'] . '/wp-statistics';
123
 
124
  // Get the Browser Capabilities use Browscap.
125
- $bc = new Browscap( $BrowscapFile );
126
  $bc->doAutoUpdate = false; // We don't want to auto update.
127
  try {
128
  $current_browser = $bc->getBrowser();
129
  // Make sure we got an object back and it has the Crawler property before accessing it.
130
- if ( is_object( $current_browser ) && property_exists( $current_browser, 'Crawler' ) ) {
131
  $crawler = $current_browser->Crawler;
132
  } else {
133
  $crawler = false;
@@ -136,7 +133,7 @@ class Hits extends WP_Statistics {
136
  $crawler = false;
137
  }
138
  } else {
139
- $this->update_option( 'update_browscap', true );
140
  }
141
 
142
  // If we're a crawler as per browscap, exclude us, otherwise double check based on the WP Statistics robot list.
@@ -147,15 +144,15 @@ class Hits extends WP_Statistics {
147
  return;
148
  } else {
149
  // Pull the robots from the database.
150
- $robots = explode( "\n", $this->get_option( 'robotlist' ) );
151
 
152
  // Check to see if we match any of the robots.
153
  foreach ( $robots as $robot ) {
154
- $robot = trim( $robot );
155
 
156
  // If the match case is less than 4 characters long, it might match too much so don't execute it.
157
- if ( strlen( $robot ) > 3 ) {
158
- if ( stripos( $ua_string, $robot ) !== false ) {
159
  $this->exclusion_match = true;
160
  $this->exclusion_reason = 'robot';
161
 
@@ -165,7 +162,7 @@ class Hits extends WP_Statistics {
165
  }
166
 
167
  // Finally check to see if we have corrupt header information.
168
- if ( ! $this->exclusion_match && $this->get_option( 'corrupt_browser_info' ) ) {
169
  if ( $ua_string == '' || $this->ip == '' ) {
170
  $this->exclusion_match = true;
171
  $this->exclusion_reason = 'robot';
@@ -178,18 +175,18 @@ class Hits extends WP_Statistics {
178
  // If we didn't match a robot, check ip subnets.
179
 
180
  // Pull the subnets from the database.
181
- $subnets = explode( "\n", $this->get_option( 'exclude_ip' ) );
182
 
183
  // Check to see if we match any of the excluded addresses.
184
  foreach ( $subnets as $subnet ) {
185
- $subnet = trim( $subnet );
186
 
187
  // The shortest ip address is 1.1.1.1, anything less must be a malformed entry.
188
- if ( strlen( $subnet ) > 6 ) {
189
  $range_prased = false;
190
 
191
  try {
192
- $range_prased = Range::parse( $subnet )->contains( $ip );
193
  } catch ( Exception $e ) {
194
  $range_parased = false;
195
  }
@@ -204,7 +201,9 @@ class Hits extends WP_Statistics {
204
  }
205
 
206
  // Check to see if we are being referred to ourselves.
207
- if ( $ua_string == 'WordPress/' . $wp_version . '; ' . get_home_url( null, '/' ) || $ua_string == 'WordPress/' . $wp_version . '; ' . get_home_url() ) {
 
 
208
  $this->exclusion_match = true;
209
  $this->exclusion_reason = 'self referral';
210
 
@@ -212,8 +211,8 @@ class Hits extends WP_Statistics {
212
  }
213
 
214
  // Check to see if we're excluding the login page.
215
- if ( $this->get_option( 'exclude_loginpage' ) ) {
216
- $protocol = strpos( strtolower( $_SERVER['SERVER_PROTOCOL'] ), 'https' ) === false ? 'http' : 'https';
217
  $host = $_SERVER['HTTP_HOST'];
218
  $script = $_SERVER['SCRIPT_NAME'];
219
 
@@ -229,15 +228,15 @@ class Hits extends WP_Statistics {
229
  }
230
 
231
  // Check to see if we're excluding the admin pages.
232
- if ( $this->get_option( 'exclude_adminpage' ) ) {
233
- $protocol = strpos( strtolower( $_SERVER['SERVER_PROTOCOL'] ), 'https' ) === false ? 'http' : 'https';
234
  $host = $_SERVER['HTTP_HOST'];
235
  $script = $_SERVER['SCRIPT_NAME'];
236
 
237
  $currentURL = $protocol . '://' . $host . $script;
238
  $adminURL = get_admin_url();
239
 
240
- $currentURL = substr( $currentURL, 0, strlen( $adminURL ) );
241
 
242
  if ( $currentURL == $adminURL ) {
243
  $this->exclusion_match = true;
@@ -248,19 +247,19 @@ class Hits extends WP_Statistics {
248
  }
249
 
250
  // Check to see if we're excluding referrer spam.
251
- if ( $this->get_option( 'referrerspam' ) ) {
252
  $referrer = $this->get_Referred();
253
 
254
  // Pull the referrer spam list from the database.
255
- $referrerspamlist = explode( "\n", $this->get_option( 'referrerspamlist' ) );
256
 
257
  // Check to see if we match any of the robots.
258
  foreach ( $referrerspamlist as $item ) {
259
- $item = trim( $item );
260
 
261
  // If the match case is less than 4 characters long, it might match too much so don't execute it.
262
- if ( strlen( $item ) > 3 ) {
263
- if ( stripos( $referrer, $item ) !== false ) {
264
  $this->exclusion_match = true;
265
  $this->exclusion_reason = 'referrer_spam';
266
 
@@ -271,8 +270,8 @@ class Hits extends WP_Statistics {
271
  }
272
 
273
  // Check to see if we're excluding RSS feeds.
274
- if ( $this->get_option( 'exclude_feeds' ) ) {
275
- if ( is_object( $WP_Statistics ) ) {
276
  if ( $WP_Statistics->check_feed() ) {
277
  $this->exclusion_match = true;
278
  $this->exclusion_reason = 'feed';
@@ -283,7 +282,7 @@ class Hits extends WP_Statistics {
283
  }
284
 
285
  // Check to see if we're excluding 404 pages.
286
- if ( $this->get_option( 'exclude_404s' ) ) {
287
  if ( is_404() ) {
288
  $this->exclusion_match = true;
289
  $this->exclusion_reason = '404';
@@ -293,20 +292,20 @@ class Hits extends WP_Statistics {
293
  }
294
 
295
  // Check to see if we're excluding the current page url.
296
- if ( $this->get_option( 'excluded_urls' ) ) {
297
  $script = $_SERVER['REQUEST_URI'];
298
- $delimiter = strpos( $script, '?' );
299
  if ( $delimiter > 0 ) {
300
- $script = substr( $script, 0, $delimiter );
301
  }
302
 
303
- $excluded_urls = explode( "\n", $this->get_option( 'excluded_urls' ) );
304
 
305
  foreach ( $excluded_urls as $url ) {
306
- $this_url = trim( $url );
307
 
308
- if ( strlen( $this_url ) > 2 ) {
309
- if ( stripos( $script, $this_url ) === 0 ) {
310
  $this->exclusion_match = true;
311
  $this->exclusion_reason = 'excluded url';
312
 
@@ -321,8 +320,8 @@ class Hits extends WP_Statistics {
321
  $current_user = wp_get_current_user();
322
 
323
  foreach ( $current_user->roles as $role ) {
324
- $option_name = 'exclude_' . str_replace( ' ', '_', strtolower( $role ) );
325
- if ( $this->get_option( $option_name ) == true ) {
326
  $this->exclusion_match = true;
327
  $this->exclusion_reason = 'user role';
328
 
@@ -333,14 +332,14 @@ class Hits extends WP_Statistics {
333
 
334
  // Check to see if we are excluded by the host name.
335
  if ( ! $this->exclusion_match ) {
336
- $excluded_host = explode( "\n", $this->get_option( 'excluded_hosts' ) );
337
 
338
  // If there's nothing in the excluded host list, don't do anything.
339
- if ( count( $excluded_host ) > 0 ) {
340
  $transient_name = 'wps_excluded_hostname_to_ip_cache';
341
 
342
  // Get the transient with the hostname cache.
343
- $hostname_cache = get_transient( $transient_name );
344
 
345
  // If the transient has expired (or has never been set), create one now.
346
  if ( $hostname_cache === false ) {
@@ -349,18 +348,18 @@ class Hits extends WP_Statistics {
349
 
350
  // Loop through the list of hosts and look them up.
351
  foreach ( $excluded_host as $host ) {
352
- if ( strpos( $host, '.' ) > 0 ) {
353
  // We add the extra period to the end of the host name to make sure we don't append the local dns suffix to the resolution cycle.
354
- $hostname_cache[ $host ] = gethostbyname( $host . '.' );
355
  }
356
  }
357
 
358
  // Set the transient and store it for 1 hour.
359
- set_transient( $transient_name, $hostname_cache, 360 );
360
  }
361
 
362
  // Check if the current IP address matches one of the ones in the excluded hosts list.
363
- if ( in_array( $this->ip, $hostname_cache ) ) {
364
  $this->exclusion_match = true;
365
  $this->exclusion_reason = 'hostname';
366
 
@@ -377,19 +376,36 @@ class Hits extends WP_Statistics {
377
  if ( ! $this->exclusion_match ) {
378
 
379
  // Check to see if we're a returning visitor.
380
- $this->result = $this->db->get_row( "SELECT * FROM {$this->tb_prefix}statistics_visit ORDER BY `{$this->tb_prefix}statistics_visit`.`ID` DESC" );
 
 
381
 
382
  // If we're a returning visitor, update the current record in the database, otherwise, create a new one.
383
- if ( $this->result->last_counter != $this->Current_Date( 'Y-m-d' ) ) {
384
  // We'd normally use the WordPress insert function, but since we may run in to a race condition where another hit to the site has already created a new entry in the database
385
  // for this IP address we want to do an "INSERT ... ON DUPLICATE KEY" which WordPress doesn't support.
386
- $sqlstring = $this->db->prepare( 'INSERT INTO ' . $this->tb_prefix . 'statistics_visit (last_visit, last_counter, visit) VALUES ( %s, %s, %d) ON DUPLICATE KEY UPDATE visit = visit + ' . $this->coefficient, $this->Current_Date(), $this->Current_date( 'Y-m-d' ), $this->coefficient );
387
-
388
- $this->db->query( $sqlstring );
 
 
 
 
 
 
 
 
389
  } else {
390
- $sqlstring = $this->db->prepare( 'UPDATE ' . $this->tb_prefix . 'statistics_visit SET `visit` = `visit` + %d, `last_visit` = %s WHERE `last_counter` = %s', $this->coefficient, $this->Current_Date(), $this->result->last_counter );
391
-
392
- $this->db->query( $sqlstring );
 
 
 
 
 
 
 
393
  }
394
  }
395
  }
@@ -399,11 +415,15 @@ class Hits extends WP_Statistics {
399
  global $wp_query, $WP_Statistics;
400
 
401
  // Get the pages or posts ID if it exists.
402
- if ( is_object( $wp_query ) ) {
403
  $this->current_page_id = $wp_query->get_queried_object_id();
404
  }
405
 
406
- if ( $this->get_option( 'use_honeypot' ) && $this->get_option( 'honeypot_postid' ) > 0 && $this->get_option( 'honeypot_postid' ) == $this->current_page_id && $this->current_page_id > 0 ) {
 
 
 
 
407
  $this->exclusion_match = true;
408
  $this->exclusion_reason = 'honeypot';
409
  }
@@ -415,9 +435,13 @@ class Hits extends WP_Statistics {
415
 
416
  // Check to see if we already have an entry in the database.
417
  if ( $this->ip_hash != false ) {
418
- $this->result = $this->db->get_row( "SELECT * FROM {$this->tb_prefix}statistics_visitor WHERE `last_counter` = '{$this->Current_Date('Y-m-d')}' AND `ip` = '{$this->ip_hash}'" );
 
 
419
  } else {
420
- $this->result = $this->db->get_row( "SELECT * FROM {$this->tb_prefix}statistics_visitor WHERE `last_counter` = '{$this->Current_Date('Y-m-d')}' AND `ip` = '{$this->ip}' AND `agent` = '{$this->agent['browser']}' AND `platform` = '{$this->agent['platform']}' AND `version` = '{$this->agent['version']}'" );
 
 
421
  }
422
 
423
  // Check to see if this is a visit to the honey pot page, flag it when we create the new entry.
@@ -430,7 +454,7 @@ class Hits extends WP_Statistics {
430
  if ( ! $this->result ) {
431
 
432
  // If we've been told to store the entire user agent, do so.
433
- if ( $this->get_option( 'store_ua' ) == true ) {
434
  $ua = $_SERVER['HTTP_USER_AGENT'];
435
  } else {
436
  $ua = '';
@@ -439,30 +463,43 @@ class Hits extends WP_Statistics {
439
  // Store the result.
440
  // We'd normally use the WordPress insert function, but since we may run in to a race condition where another hit to the site has already created a new entry in the database
441
  // for this IP address we want to do an "INSERT IGNORE" which WordPress doesn't support.
442
- $sqlstring = $this->db->prepare( 'INSERT IGNORE INTO ' . $this->tb_prefix . 'statistics_visitor (last_counter, referred, agent, platform, version, ip, location, UAString, hits, honeypot) VALUES ( %s, %s, %s, %s, %s, %s, %s, %s, 1, %s )', $this->Current_date( 'Y-m-d' ), $this->get_Referred(), $this->agent['browser'], $this->agent['platform'], $this->agent['version'], $this->ip_hash ? $this->ip_hash : $this->ip, $this->location, $ua, $honeypot );
443
-
444
- $this->db->query( $sqlstring );
 
 
 
 
 
 
 
 
 
 
 
 
 
445
 
446
  // Now parse the referrer and store the results in the search table if the database has been converted.
447
  // Also make sure we actually inserted a row on the INSERT IGNORE above or we'll create duplicate entries.
448
- if ( $this->get_option( 'search_converted' ) && $this->db->insert_id ) {
449
 
450
  $search_engines = wp_statistics_searchengine_list();
451
  $referred = $this->get_Referred();
452
 
453
  // Parse the URL in to it's component parts.
454
- $parts = parse_url( $referred );
455
 
456
  // Loop through the SE list until we find which search engine matches.
457
  foreach ( $search_engines as $key => $value ) {
458
- $search_regex = wp_statistics_searchengine_regex( $key );
459
 
460
- preg_match( '/' . $search_regex . '/', $parts['host'], $matches );
461
 
462
  if ( isset( $matches[1] ) ) {
463
- $data['last_counter'] = $this->Current_date( 'Y-m-d' );
464
  $data['engine'] = $key;
465
- $data['words'] = $WP_Statistics->Search_Engine_QueryString( $referred );
466
  $data['host'] = $parts['host'];
467
  $data['visitor'] = $this->db->insert_id;
468
 
@@ -470,13 +507,15 @@ class Hits extends WP_Statistics {
470
  $data['words'] = '';
471
  }
472
 
473
- $this->db->insert( $this->db->prefix . 'statistics_search', $data );
474
  }
475
  }
476
  }
477
  } else {
478
  // Normally we've done all of our exclusion matching during the class creation, however for the robot threshold is calculated here to avoid another call the database.
479
- if ( $this->get_option( 'robot_threshold' ) > 0 && $this->result->hits + 1 > $this->get_option( 'robot_threshold' ) ) {
 
 
480
  $this->exclusion_match = true;
481
  $this->exclusion_reason = 'robot_threshold';
482
  } else if ( $this->result->honeypot ) {
@@ -484,9 +523,16 @@ class Hits extends WP_Statistics {
484
  $this->exclusion_reason = 'honeypot';
485
  } else {
486
 
487
- $sqlstring = $this->db->prepare( 'UPDATE ' . $this->tb_prefix . 'statistics_visitor SET `hits` = `hits` + %d, `honeypot` = %d WHERE `ID` = %d', 1 - $honeypot, $honeypot, $this->result->ID );
 
 
 
 
 
 
 
488
 
489
- $this->db->query( $sqlstring );
490
  }
491
  }
492
  }
@@ -502,15 +548,17 @@ class Hits extends WP_Statistics {
502
  return;
503
  }
504
 
505
- $this->result = $this->db->query( "UPDATE {$this->tb_prefix}statistics_exclusions SET `count` = `count` + 1 WHERE `date` = '{$this->Current_Date( 'Y-m-d' )}' AND `reason` = '{$this->exclusion_reason}'" );
 
 
506
 
507
  if ( ! $this->result ) {
508
  $this->db->insert(
509
  $this->tb_prefix . 'statistics_exclusions',
510
  array(
511
- 'date' => $this->Current_date( 'Y-m-d' ),
512
  'reason' => $this->exclusion_reason,
513
- 'count' => 1
514
  )
515
  );
516
  }
@@ -524,9 +572,9 @@ class Hits extends WP_Statistics {
524
  if ( ! $this->exclusion_match ) {
525
 
526
  // Don't track anything but actual pages and posts, unless we've been told to.
527
- if ( $this->get_option( 'track_all_pages' ) || is_page() || is_single() || is_front_page() ) {
528
  // Get the pages or posts ID if it exists and we haven't set it in the visitors code.
529
- if ( ! $this->current_page_id && is_object( $wp_query ) ) {
530
  $this->current_page_id = $wp_query->get_queried_object_id();
531
  }
532
 
@@ -538,19 +586,22 @@ class Hits extends WP_Statistics {
538
  // Get the current page URI.
539
  $page_uri = wp_statistics_get_uri();
540
 
541
- if ( $this->get_option( 'strip_uri_parameters' ) ) {
542
- $temp = explode( '?', $page_uri );
543
  if ( $temp !== false ) {
544
  $page_uri = $temp[0];
545
  }
546
  }
547
 
548
  // Limit the URI length to 255 characters, otherwise we may overrun the SQL field size.
549
- $page_uri = substr( $page_uri, 0, 255 );
550
 
551
  // If we have already been to this page today (a likely scenario), just update the count on the record.
552
- $sql = $this->db->prepare( "UPDATE {$this->tb_prefix}statistics_pages SET `count` = `count` + 1 WHERE `date` = '{$this->Current_Date( 'Y-m-d' )}' AND `uri` = %s", $page_uri );
553
- $this->result = $this->db->query( $sql );
 
 
 
554
 
555
  // If the update failed (aka the record doesn't exist), insert a new one. Note this may drop a page hit if a race condition
556
  // exists where two people load the same page a the roughly the same time. In that case two inserts would be attempted but
@@ -561,9 +612,9 @@ class Hits extends WP_Statistics {
561
  $this->tb_prefix . 'statistics_pages',
562
  array(
563
  'uri' => $page_uri,
564
- 'date' => $this->Current_date( 'Y-m-d' ),
565
  'count' => 1,
566
- 'id' => $this->current_page_id
567
  )
568
  );
569
  }
@@ -576,9 +627,13 @@ class Hits extends WP_Statistics {
576
  public function Is_user() {
577
 
578
  if ( $this->ip_hash != false ) {
579
- $this->result = $this->db->query( "SELECT * FROM {$this->tb_prefix}statistics_useronline WHERE `ip` = '{$this->ip_hash}'" );
 
 
580
  } else {
581
- $this->result = $this->db->query( "SELECT * FROM {$this->tb_prefix}statistics_useronline WHERE `ip` = '{$this->ip}' AND `agent` = '{$this->agent['browser']}' AND `platform` = '{$this->agent['platform']}' AND `version` = '{$this->agent['version']}'" );
 
 
582
  }
583
 
584
  if ( $this->result ) {
@@ -589,7 +644,7 @@ class Hits extends WP_Statistics {
589
  // This function add/update/delete the online users in the database.
590
  public function Check_online() {
591
  // If we're a webcrawler or referral from ourselves or an excluded address don't record the user as online, unless we've been told to anyway.
592
- if ( ! $this->exclusion_match || $this->get_option( 'all_online' ) ) {
593
 
594
  // If the current user exists in the database already, just update them, otherwise add them
595
  if ( $this->Is_user() ) {
@@ -656,6 +711,6 @@ class Hits extends WP_Statistics {
656
  $timediff = $this->timestamp - $this->second;
657
 
658
  // Call the deletion query.
659
- $this->db->query( "DELETE FROM {$this->tb_prefix}statistics_useronline WHERE timestamp < '{$timediff}'" );
660
  }
661
  }
1
  <?php
2
  /*
3
+ This is the primary class for recording hits on the WordPress site. It extends the WP_Statistics class and is itself extended by the GEO_IP_Hits class.
4
 
5
  This class handles; visits, visitors and pages.
6
  */
7
 
 
 
 
8
  use phpbrowscap\Browscap;
9
  use IPTools\IP;
10
  use IPTools\Network;
11
  use IPTools\Range;
12
 
13
+ class WP_Statistics_Hits extends WP_Statistics {
14
 
15
  // Setup our public/private/protected variables.
16
  public $result = null;
17
 
18
+ protected $location = '000';
19
+ protected $exclusion_match = false;
20
  protected $exclusion_reason = '';
21
 
22
  private $exclusion_record = false;
28
  public function __construct() {
29
  global $wp_version, $WP_Statistics;
30
 
31
+ // Call the parent constructor (WpStatistics::__construct)
32
  parent::__construct();
33
 
34
  // Set the timestamp value.
35
+ $this->timestamp = $this->current_date('U');
36
 
37
  // Set the default seconds a user needs to visit the site before they are considered offline.
38
  $this->second = 30;
39
 
40
  // Get the user set value for seconds to check for users online.
41
+ if ( $this->get_option('check_online') ) {
42
+ $this->second = $this->get_option('check_online');
43
  }
44
 
45
  // Check to see if the user wants us to record why we're excluding hits.
46
+ if ( $this->get_option('record_exclusions') ) {
47
  $this->exclusion_record = true;
48
  }
49
 
50
  // Create a IP Tools instance from the current IP address for use later.
51
  // Fall back to the localhost if it can't be parsed.
52
  try {
53
+ $ip = new IP($this->ip);
54
  } catch ( Exception $e ) {
55
+ $ip = new IP('127.0.0.1');
56
  }
57
 
58
  // Let's check to see if our subnet matches a private IP address range, if so go ahead and set the location information now.
59
+ if ( $this->get_option('private_country_code') != '000' && $this->get_option('private_country_code') != '' ) {
60
  $private_subnets = array( '10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16', '127.0.0.1/24', 'fc00::/7' );
61
 
62
  foreach ( $private_subnets as $psub ) {
63
  $contains_ip = false;
64
 
65
  try {
66
+ $contains_ip = Range::parse($psub)->contains($ip);
67
  } catch ( Exception $e ) {
68
  $contains_ip = false;
69
  }
70
 
71
  if ( $contains_ip ) {
72
+ $this->location = $this->get_option('private_country_code');
73
  break;
74
  }
75
  }
96
  $page_uri = wp_statistics_get_uri();
97
  $ajax_string = 'admin-ajax.php';
98
 
99
+ if ( substr($page_uri, 0, strlen($ajax_string)) === $ajax_string ) {
100
  $this->exclusion_match = true;
101
  $this->exclusion_reason = 'ajax';
102
 
107
  $crawler = false;
108
  $ua_string = '';
109
 
110
+ if ( array_key_exists('HTTP_USER_AGENT', $_SERVER) ) {
111
  $ua_string = $_SERVER['HTTP_USER_AGENT'];
112
  }
113
 
114
+ if ( $this->get_option('last_browscap_dl') > 1 && $this->get_option('browscap') ) {
115
  // Get the upload directory from WordPress.
116
  $upload_dir = wp_upload_dir();
117
 
119
  $BrowscapFile = $upload_dir['basedir'] . '/wp-statistics';
120
 
121
  // Get the Browser Capabilities use Browscap.
122
+ $bc = new Browscap($BrowscapFile);
123
  $bc->doAutoUpdate = false; // We don't want to auto update.
124
  try {
125
  $current_browser = $bc->getBrowser();
126
  // Make sure we got an object back and it has the Crawler property before accessing it.
127
+ if ( is_object($current_browser) && property_exists($current_browser, 'Crawler') ) {
128
  $crawler = $current_browser->Crawler;
129
  } else {
130
  $crawler = false;
133
  $crawler = false;
134
  }
135
  } else {
136
+ $this->update_option('update_browscap', true);
137
  }
138
 
139
  // If we're a crawler as per browscap, exclude us, otherwise double check based on the WP Statistics robot list.
144
  return;
145
  } else {
146
  // Pull the robots from the database.
147
+ $robots = explode("\n", $this->get_option('robotlist'));
148
 
149
  // Check to see if we match any of the robots.
150
  foreach ( $robots as $robot ) {
151
+ $robot = trim($robot);
152
 
153
  // If the match case is less than 4 characters long, it might match too much so don't execute it.
154
+ if ( strlen($robot) > 3 ) {
155
+ if ( stripos($ua_string, $robot) !== false ) {
156
  $this->exclusion_match = true;
157
  $this->exclusion_reason = 'robot';
158
 
162
  }
163
 
164
  // Finally check to see if we have corrupt header information.
165
+ if ( ! $this->exclusion_match && $this->get_option('corrupt_browser_info') ) {
166
  if ( $ua_string == '' || $this->ip == '' ) {
167
  $this->exclusion_match = true;
168
  $this->exclusion_reason = 'robot';
175
  // If we didn't match a robot, check ip subnets.
176
 
177
  // Pull the subnets from the database.
178
+ $subnets = explode("\n", $this->get_option('exclude_ip'));
179
 
180
  // Check to see if we match any of the excluded addresses.
181
  foreach ( $subnets as $subnet ) {
182
+ $subnet = trim($subnet);
183
 
184
  // The shortest ip address is 1.1.1.1, anything less must be a malformed entry.
185
+ if ( strlen($subnet) > 6 ) {
186
  $range_prased = false;
187
 
188
  try {
189
+ $range_prased = Range::parse($subnet)->contains($ip);
190
  } catch ( Exception $e ) {
191
  $range_parased = false;
192
  }
201
  }
202
 
203
  // Check to see if we are being referred to ourselves.
204
+ if ( $ua_string == 'WordPress/' . $wp_version . '; ' . get_home_url(null, '/') ||
205
+ $ua_string == 'WordPress/' . $wp_version . '; ' . get_home_url()
206
+ ) {
207
  $this->exclusion_match = true;
208
  $this->exclusion_reason = 'self referral';
209
 
211
  }
212
 
213
  // Check to see if we're excluding the login page.
214
+ if ( $this->get_option('exclude_loginpage') ) {
215
+ $protocol = strpos(strtolower($_SERVER['SERVER_PROTOCOL']), 'https') === false ? 'http' : 'https';
216
  $host = $_SERVER['HTTP_HOST'];
217
  $script = $_SERVER['SCRIPT_NAME'];
218
 
228
  }
229
 
230
  // Check to see if we're excluding the admin pages.
231
+ if ( $this->get_option('exclude_adminpage') ) {
232
+ $protocol = strpos(strtolower($_SERVER['SERVER_PROTOCOL']), 'https') === false ? 'http' : 'https';
233
  $host = $_SERVER['HTTP_HOST'];
234
  $script = $_SERVER['SCRIPT_NAME'];
235
 
236
  $currentURL = $protocol . '://' . $host . $script;
237
  $adminURL = get_admin_url();
238
 
239
+ $currentURL = substr($currentURL, 0, strlen($adminURL));
240
 
241
  if ( $currentURL == $adminURL ) {
242
  $this->exclusion_match = true;
247
  }
248
 
249
  // Check to see if we're excluding referrer spam.
250
+ if ( $this->get_option('referrerspam') ) {
251
  $referrer = $this->get_Referred();
252
 
253
  // Pull the referrer spam list from the database.
254
+ $referrerspamlist = explode("\n", $this->get_option('referrerspamlist'));
255
 
256
  // Check to see if we match any of the robots.
257
  foreach ( $referrerspamlist as $item ) {
258
+ $item = trim($item);
259
 
260
  // If the match case is less than 4 characters long, it might match too much so don't execute it.
261
+ if ( strlen($item) > 3 ) {
262
+ if ( stripos($referrer, $item) !== false ) {
263
  $this->exclusion_match = true;
264
  $this->exclusion_reason = 'referrer_spam';
265
 
270
  }
271
 
272
  // Check to see if we're excluding RSS feeds.
273
+ if ( $this->get_option('exclude_feeds') ) {
274
+ if ( is_object($WP_Statistics) ) {
275
  if ( $WP_Statistics->check_feed() ) {
276
  $this->exclusion_match = true;
277
  $this->exclusion_reason = 'feed';
282
  }
283
 
284
  // Check to see if we're excluding 404 pages.
285
+ if ( $this->get_option('exclude_404s') ) {
286
  if ( is_404() ) {
287
  $this->exclusion_match = true;
288
  $this->exclusion_reason = '404';
292
  }
293
 
294
  // Check to see if we're excluding the current page url.
295
+ if ( $this->get_option('excluded_urls') ) {
296
  $script = $_SERVER['REQUEST_URI'];
297
+ $delimiter = strpos($script, '?');
298
  if ( $delimiter > 0 ) {
299
+ $script = substr($script, 0, $delimiter);
300
  }
301
 
302
+ $excluded_urls = explode("\n", $this->get_option('excluded_urls'));
303
 
304
  foreach ( $excluded_urls as $url ) {
305
+ $this_url = trim($url);
306
 
307
+ if ( strlen($this_url) > 2 ) {
308
+ if ( stripos($script, $this_url) === 0 ) {
309
  $this->exclusion_match = true;
310
  $this->exclusion_reason = 'excluded url';
311
 
320
  $current_user = wp_get_current_user();
321
 
322
  foreach ( $current_user->roles as $role ) {
323
+ $option_name = 'exclude_' . str_replace(' ', '_', strtolower($role));
324
+ if ( $this->get_option($option_name) == true ) {
325
  $this->exclusion_match = true;
326
  $this->exclusion_reason = 'user role';
327
 
332
 
333
  // Check to see if we are excluded by the host name.
334
  if ( ! $this->exclusion_match ) {
335
+ $excluded_host = explode("\n", $this->get_option('excluded_hosts'));
336
 
337
  // If there's nothing in the excluded host list, don't do anything.
338
+ if ( count($excluded_host) > 0 ) {
339
  $transient_name = 'wps_excluded_hostname_to_ip_cache';
340
 
341
  // Get the transient with the hostname cache.
342
+ $hostname_cache = get_transient($transient_name);
343
 
344
  // If the transient has expired (or has never been set), create one now.
345
  if ( $hostname_cache === false ) {
348
 
349
  // Loop through the list of hosts and look them up.
350
  foreach ( $excluded_host as $host ) {
351
+ if ( strpos($host, '.') > 0 ) {
352
  // We add the extra period to the end of the host name to make sure we don't append the local dns suffix to the resolution cycle.
353
+ $hostname_cache[ $host ] = gethostbyname($host . '.');
354
  }
355
  }
356
 
357
  // Set the transient and store it for 1 hour.
358
+ set_transient($transient_name, $hostname_cache, 360);
359
  }
360
 
361
  // Check if the current IP address matches one of the ones in the excluded hosts list.
362
+ if ( in_array($this->ip, $hostname_cache) ) {
363
  $this->exclusion_match = true;
364
  $this->exclusion_reason = 'hostname';
365
 
376
  if ( ! $this->exclusion_match ) {
377
 
378
  // Check to see if we're a returning visitor.
379
+ $this->result = $this->db->get_row(
380
+ "SELECT * FROM {$this->tb_prefix}statistics_visit ORDER BY `{$this->tb_prefix}statistics_visit`.`ID` DESC"
381
+ );
382
 
383
  // If we're a returning visitor, update the current record in the database, otherwise, create a new one.
384
+ if ( $this->result->last_counter != $this->Current_Date('Y-m-d') ) {
385
  // We'd normally use the WordPress insert function, but since we may run in to a race condition where another hit to the site has already created a new entry in the database
386
  // for this IP address we want to do an "INSERT ... ON DUPLICATE KEY" which WordPress doesn't support.
387
+ $sqlstring = $this->db->prepare(
388
+ 'INSERT INTO ' .
389
+ $this->tb_prefix .
390
+ 'statistics_visit (last_visit, last_counter, visit) VALUES ( %s, %s, %d) ON DUPLICATE KEY UPDATE visit = visit + ' .
391
+ $this->coefficient,
392
+ $this->Current_Date(),
393
+ $this->Current_date('Y-m-d'),
394
+ $this->coefficient
395
+ );
396
+
397
+ $this->db->query($sqlstring);
398
  } else {
399
+ $sqlstring = $this->db->prepare(
400
+ 'UPDATE ' .
401
+ $this->tb_prefix .
402
+ 'statistics_visit SET `visit` = `visit` + %d, `last_visit` = %s WHERE `last_counter` = %s',
403
+ $this->coefficient,
404
+ $this->Current_Date(),
405
+ $this->result->last_counter
406
+ );
407
+
408
+ $this->db->query($sqlstring);
409
  }
410
  }
411
  }
415
  global $wp_query, $WP_Statistics;
416
 
417
  // Get the pages or posts ID if it exists.
418
+ if ( is_object($wp_query) ) {
419
  $this->current_page_id = $wp_query->get_queried_object_id();
420
  }
421
 
422
+ if ( $this->get_option('use_honeypot') &&
423
+ $this->get_option('honeypot_postid') > 0 &&
424
+ $this->get_option('honeypot_postid') == $this->current_page_id &&
425
+ $this->current_page_id > 0
426
+ ) {
427
  $this->exclusion_match = true;
428
  $this->exclusion_reason = 'honeypot';
429
  }
435
 
436
  // Check to see if we already have an entry in the database.
437
  if ( $this->ip_hash != false ) {
438
+ $this->result = $this->db->get_row(
439
+ "SELECT * FROM {$this->tb_prefix}statistics_visitor WHERE `last_counter` = '{$this->Current_Date('Y-m-d')}' AND `ip` = '{$this->ip_hash}'"
440
+ );
441
  } else {
442
+ $this->result = $this->db->get_row(
443
+ "SELECT * FROM {$this->tb_prefix}statistics_visitor WHERE `last_counter` = '{$this->Current_Date('Y-m-d')}' AND `ip` = '{$this->ip}' AND `agent` = '{$this->agent['browser']}' AND `platform` = '{$this->agent['platform']}' AND `version` = '{$this->agent['version']}'"
444
+ );
445
  }
446
 
447
  // Check to see if this is a visit to the honey pot page, flag it when we create the new entry.
454
  if ( ! $this->result ) {
455
 
456
  // If we've been told to store the entire user agent, do so.
457
+ if ( $this->get_option('store_ua') == true ) {
458
  $ua = $_SERVER['HTTP_USER_AGENT'];
459
  } else {
460
  $ua = '';
463
  // Store the result.
464
  // We'd normally use the WordPress insert function, but since we may run in to a race condition where another hit to the site has already created a new entry in the database
465
  // for this IP address we want to do an "INSERT IGNORE" which WordPress doesn't support.
466
+ $sqlstring = $this->db->prepare(
467
+ 'INSERT IGNORE INTO ' .
468
+ $this->tb_prefix .
469
+ 'statistics_visitor (last_counter, referred, agent, platform, version, ip, location, UAString, hits, honeypot) VALUES ( %s, %s, %s, %s, %s, %s, %s, %s, 1, %s )',
470
+ $this->Current_date('Y-m-d'),
471
+ $this->get_Referred(),
472
+ $this->agent['browser'],
473
+ $this->agent['platform'],
474
+ $this->agent['version'],
475
+ $this->ip_hash ? $this->ip_hash : $this->ip,
476
+ $this->location,
477
+ $ua,
478
+ $honeypot
479
+ );
480
+
481
+ $this->db->query($sqlstring);
482
 
483
  // Now parse the referrer and store the results in the search table if the database has been converted.
484
  // Also make sure we actually inserted a row on the INSERT IGNORE above or we'll create duplicate entries.
485
+ if ( $this->get_option('search_converted') && $this->db->insert_id ) {
486
 
487
  $search_engines = wp_statistics_searchengine_list();
488
  $referred = $this->get_Referred();
489
 
490
  // Parse the URL in to it's component parts.
491
+ $parts = parse_url($referred);
492
 
493
  // Loop through the SE list until we find which search engine matches.
494
  foreach ( $search_engines as $key => $value ) {
495
+ $search_regex = wp_statistics_searchengine_regex($key);
496
 
497
+ preg_match('/' . $search_regex . '/', $parts['host'], $matches);
498
 
499
  if ( isset( $matches[1] ) ) {
500
+ $data['last_counter'] = $this->Current_date('Y-m-d');
501
  $data['engine'] = $key;
502
+ $data['words'] = $WP_Statistics->Search_Engine_QueryString($referred);
503
  $data['host'] = $parts['host'];
504
  $data['visitor'] = $this->db->insert_id;
505
 
507
  $data['words'] = '';
508
  }
509
 
510
+ $this->db->insert($this->db->prefix . 'statistics_search', $data);
511
  }
512
  }
513
  }
514
  } else {
515
  // Normally we've done all of our exclusion matching during the class creation, however for the robot threshold is calculated here to avoid another call the database.
516
+ if ( $this->get_option('robot_threshold') > 0 &&
517
+ $this->result->hits + 1 > $this->get_option('robot_threshold')
518
+ ) {
519
  $this->exclusion_match = true;
520
  $this->exclusion_reason = 'robot_threshold';
521
  } else if ( $this->result->honeypot ) {
523
  $this->exclusion_reason = 'honeypot';
524
  } else {
525
 
526
+ $sqlstring = $this->db->prepare(
527
+ 'UPDATE ' .
528
+ $this->tb_prefix .
529
+ 'statistics_visitor SET `hits` = `hits` + %d, `honeypot` = %d WHERE `ID` = %d',
530
+ 1 - $honeypot,
531
+ $honeypot,
532
+ $this->result->ID
533
+ );
534
 
535
+ $this->db->query($sqlstring);
536
  }
537
  }
538
  }
548
  return;
549
  }
550
 
551
+ $this->result = $this->db->query(
552
+ "UPDATE {$this->tb_prefix}statistics_exclusions SET `count` = `count` + 1 WHERE `date` = '{$this->Current_Date( 'Y-m-d' )}' AND `reason` = '{$this->exclusion_reason}'"
553
+ );
554
 
555
  if ( ! $this->result ) {
556
  $this->db->insert(
557
  $this->tb_prefix . 'statistics_exclusions',
558
  array(
559
+ 'date' => $this->Current_date('Y-m-d'),
560
  'reason' => $this->exclusion_reason,
561
+ 'count' => 1,
562
  )
563
  );
564
  }
572
  if ( ! $this->exclusion_match ) {
573
 
574
  // Don't track anything but actual pages and posts, unless we've been told to.
575
+ if ( $this->get_option('track_all_pages') || is_page() || is_single() || is_front_page() ) {
576
  // Get the pages or posts ID if it exists and we haven't set it in the visitors code.
577
+ if ( ! $this->current_page_id && is_object($wp_query) ) {
578
  $this->current_page_id = $wp_query->get_queried_object_id();
579
  }
580
 
586
  // Get the current page URI.
587
  $page_uri = wp_statistics_get_uri();
588
 
589
+ if ( $this->get_option('strip_uri_parameters') ) {
590
+ $temp = explode('?', $page_uri);
591
  if ( $temp !== false ) {
592
  $page_uri = $temp[0];
593
  }
594
  }
595
 
596
  // Limit the URI length to 255 characters, otherwise we may overrun the SQL field size.
597
+ $page_uri = substr($page_uri, 0, 255);
598
 
599
  // If we have already been to this page today (a likely scenario), just update the count on the record.
600
+ $sql = $this->db->prepare(
601
+ "UPDATE {$this->tb_prefix}statistics_pages SET `count` = `count` + 1 WHERE `date` = '{$this->Current_Date( 'Y-m-d' )}' AND `uri` = %s",
602
+ $page_uri
603
+ );
604
+ $this->result = $this->db->query($sql);
605
 
606
  // If the update failed (aka the record doesn't exist), insert a new one. Note this may drop a page hit if a race condition
607
  // exists where two people load the same page a the roughly the same time. In that case two inserts would be attempted but
612
  $this->tb_prefix . 'statistics_pages',
613
  array(
614
  'uri' => $page_uri,
615
+ 'date' => $this->Current_date('Y-m-d'),
616
  'count' => 1,
617
+ 'id' => $this->current_page_id,
618
  )
619
  );
620
  }
627
  public function Is_user() {
628
 
629
  if ( $this->ip_hash != false ) {
630
+ $this->result = $this->db->query(
631
+ "SELECT * FROM {$this->tb_prefix}statistics_useronline WHERE `ip` = '{$this->ip_hash}'"
632
+ );
633
  } else {
634
+ $this->result = $this->db->query(
635
+ "SELECT * FROM {$this->tb_prefix}statistics_useronline WHERE `ip` = '{$this->ip}' AND `agent` = '{$this->agent['browser']}' AND `platform` = '{$this->agent['platform']}' AND `version` = '{$this->agent['version']}'"
636
+ );
637
  }
638
 
639
  if ( $this->result ) {
644
  // This function add/update/delete the online users in the database.
645
  public function Check_online() {
646
  // If we're a webcrawler or referral from ourselves or an excluded address don't record the user as online, unless we've been told to anyway.
647
+ if ( ! $this->exclusion_match || $this->get_option('all_online') ) {
648
 
649
  // If the current user exists in the database already, just update them, otherwise add them
650
  if ( $this->Is_user() ) {
711
  $timediff = $this->timestamp - $this->second;
712
 
713
  // Call the deletion query.
714
+ $this->db->query("DELETE FROM {$this->tb_prefix}statistics_useronline WHERE timestamp < '{$timediff}'");
715
  }
716
  }
includes/classes/class-wp-statistics-install.php ADDED
@@ -0,0 +1,453 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace {
4
+ /**
5
+ * Class WP_Statistics_Install
6
+ */
7
+ class WP_Statistics_Install {
8
+
9
+ /**
10
+ * WP_Statistics_Install constructor.
11
+ *
12
+ * @param $WP_Statistics
13
+ */
14
+ function __construct( $WP_Statistics ) {
15
+ global $wpdb;
16
+ if ( is_admin() ) {
17
+
18
+ // The follow variables are used to define the table structure for new and upgrade installations.
19
+ $create_useronline_table = ( "
20
+ CREATE TABLE {$wpdb->prefix}statistics_useronline (
21
+ ID int(11) NOT NULL AUTO_INCREMENT,
22
+ ip varchar(60) NOT NULL,
23
+ created int(11),
24
+ timestamp int(10) NOT NULL,
25
+ date datetime NOT NULL,
26
+ referred text CHARACTER SET utf8 NOT NULL,
27
+ agent varchar(255) NOT NULL,
28
+ platform varchar(255),
29
+ version varchar(255),
30
+ location varchar(10),
31
+ PRIMARY KEY (ID)
32
+ ) CHARSET=utf8" );
33
+
34
+ $create_visit_table = ( "
35
+ CREATE TABLE {$wpdb->prefix}statistics_visit (
36
+ ID int(11) NOT NULL AUTO_INCREMENT,
37
+ last_visit datetime NOT NULL,
38
+ last_counter date NOT NULL,
39
+ visit int(10) NOT NULL,
40
+ PRIMARY KEY (ID),
41
+ UNIQUE KEY unique_date (last_counter)
42
+ ) CHARSET=utf8" );
43
+
44
+ $create_visitor_table = ( "
45
+ CREATE TABLE {$wpdb->prefix}statistics_visitor (
46
+ ID int(11) NOT NULL AUTO_INCREMENT,
47
+ last_counter date NOT NULL,
48
+ referred text NOT NULL,
49
+ agent varchar(255) NOT NULL,
50
+ platform varchar(255),
51
+ version varchar(255),
52
+ UAString varchar(255),
53
+ ip varchar(60) NOT NULL,
54
+ location varchar(10),
55
+ hits int(11),
56
+ honeypot int(11),
57
+ PRIMARY KEY (ID),
58
+ UNIQUE KEY date_ip_agent (last_counter,ip,agent(75),platform(75),version(75)),
59
+ KEY agent (agent),
60
+ KEY platform (platform),
61
+ KEY version (version),
62
+ KEY location (location)
63
+ ) CHARSET=utf8" );
64
+
65
+ $create_visitor_table_old = ( "
66
+ CREATE TABLE {$wpdb->prefix}statistics_visitor (
67
+ ID int(11) NOT NULL AUTO_INCREMENT,
68
+ last_counter date NOT NULL,
69
+ referred text NOT NULL,
70
+ agent varchar(255) NOT NULL,
71
+ platform varchar(255),
72
+ version varchar(255),
73
+ UAString varchar(255),
74
+ ip varchar(60) NOT NULL,
75
+ location varchar(10),
76
+ hits int(11),
77
+ honeypot int(11),
78
+ PRIMARY KEY (ID),
79
+ UNIQUE KEY date_ip_agent (last_counter,ip,agent (75),platform (75),version (75)),
80
+ KEY agent (agent),
81
+ KEY platform (platform),
82
+ KEY version (version),
83
+ KEY location (location)
84
+ ) CHARSET=utf8" );
85
+
86
+ $create_exclusion_table = ( "
87
+ CREATE TABLE {$wpdb->prefix}statistics_exclusions (
88
+ ID int(11) NOT NULL AUTO_INCREMENT,
89
+ date date NOT NULL,
90
+ reason varchar(255) DEFAULT NULL,
91
+ count bigint(20) NOT NULL,
92
+ PRIMARY KEY (ID),
93
+ KEY date (date),
94
+ KEY reason (reason)
95
+ ) CHARSET=utf8" );
96
+
97
+ $create_pages_table = ( "
98
+ CREATE TABLE {$wpdb->prefix}statistics_pages (
99
+ uri varchar(255) NOT NULL,
100
+ date date NOT NULL,
101
+ count int(11) NOT NULL,
102
+ id int(11) NOT NULL,
103
+ UNIQUE KEY date_2 (date,uri),
104
+ KEY url (uri),
105
+ KEY date (date),
106
+ KEY id (id)
107
+ ) CHARSET=utf8" );
108
+
109
+ $create_historical_table = ( "
110
+ CREATE TABLE {$wpdb->prefix}statistics_historical (
111
+ ID bigint(20) NOT NULL AUTO_INCREMENT,
112
+ category varchar(25) NOT NULL,
113
+ page_id bigint(20) NOT NULL,
114
+ uri varchar(255) NOT NULL,
115
+ value bigint(20) NOT NULL,
116
+ PRIMARY KEY (ID),
117
+ KEY category (category),
118
+ UNIQUE KEY page_id (page_id),
119
+ UNIQUE KEY uri (uri)
120
+ ) CHARSET=utf8" );
121
+
122
+ $create_search_table = ( "
123
+ CREATE TABLE {$wpdb->prefix}statistics_search (
124
+ ID bigint(20) NOT NULL AUTO_INCREMENT,
125
+ last_counter date NOT NULL,
126
+ engine varchar(64) NOT NULL,
127
+ host varchar(255),
128
+ words varchar(255),
129
+ visitor bigint(20),
130
+ PRIMARY KEY (ID),
131
+ KEY last_counter (last_counter),
132
+ KEY engine (engine),
133
+ KEY host (host)
134
+ ) CHARSET=utf8" );
135
+
136
+ // Check to see if the historical table exists yet, aka if this is a upgrade instead of a first install.
137
+ $result = $wpdb->query(
138
+ "SHOW TABLES WHERE `Tables_in_{$wpdb->dbname}` = '{$wpdb->prefix}statistics_historical'"
139
+ );
140
+
141
+ if ( $result == 1 ) {
142
+ // Before we update the historical table, check to see if it exists with the old keys
143
+ $result = $wpdb->query("SHOW COLUMNS FROM {$wpdb->prefix}statistics_historical LIKE 'key'");
144
+
145
+ if ( $result > 0 ) {
146
+ $wpdb->query(
147
+ "ALTER TABLE `{$wpdb->prefix}statistics_historical` CHANGE `id` `page_id` bigint(20)"
148
+ );
149
+ $wpdb->query("ALTER TABLE `{$wpdb->prefix}statistics_historical` CHANGE `key` `ID` bigint(20)");
150
+ $wpdb->query(
151
+ "ALTER TABLE `{$wpdb->prefix}statistics_historical` CHANGE `type` `category` varchar(25)"
152
+ );
153
+ }
154
+ }
155
+
156
+ // This includes the dbDelta function from WordPress.
157
+ if ( ! function_exists('dbDelta') ) {
158
+ require( ABSPATH . 'wp-admin/includes/upgrade.php' );
159
+ }
160
+
161
+ // Create/update the plugin tables.
162
+ dbDelta($create_useronline_table);
163
+ dbDelta($create_visit_table);
164
+ dbDelta($create_visitor_table);
165
+ dbDelta($create_exclusion_table);
166
+ dbDelta($create_pages_table);
167
+ dbDelta($create_historical_table);
168
+ dbDelta($create_search_table);
169
+
170
+ // Some old versions (in the 5.0.x line) of MySQL have issue with the compound index on the visitor table
171
+ // so let's make sure it was created, if not, use the older format to create the table manually instead of
172
+ // using the dbDelta() call.
173
+ $result = $wpdb->query(
174
+ "SHOW TABLES WHERE `Tables_in_{$wpdb->dbname}` = '{$wpdb->prefix}statistics_visitor'"
175
+ );
176
+
177
+ if ( $result != 1 ) {
178
+ $wpdb->query($create_visitor_table_old);
179
+ }
180
+
181
+ // Check to see if the date_ip index still exists, if so get rid of it.
182
+ $result = $wpdb->query("SHOW INDEX FROM {$wpdb->prefix}statistics_visitor WHERE Key_name = 'date_ip'");
183
+
184
+ // Note, the result will be the number of fields contained in the index.
185
+ if ( $result > 1 ) {
186
+ $wpdb->query("DROP INDEX `date_ip` ON {$wpdb->prefix}statistics_visitor");
187
+ }
188
+
189
+ // One final database change, drop the 'AString' column from visitors if it exists as it's a typo from an old version.
190
+ $result = $wpdb->query("SHOW COLUMNS FROM {$wpdb->prefix}statistics_visitor LIKE 'AString'");
191
+
192
+ if ( $result > 0 ) {
193
+ $wpdb->query("ALTER TABLE `{$wpdb->prefix}statistics_visitor` DROP `AString`");
194
+ }
195
+
196
+ // Store the new version information.
197
+ update_option('wp_statistics_plugin_version', WP_Statistics::$reg['version']);
198
+ update_option('wp_statistics_db_version', WP_Statistics::$reg['version']);
199
+
200
+ // Now check to see what database updates may be required and record them for a user notice later.
201
+ $dbupdates = array( 'date_ip_agent' => false, 'unique_date' => false );
202
+
203
+ // Check the number of index's on the visitors table, if it's only 5 we need to check for duplicate entries and remove them
204
+ $result = $wpdb->query(
205
+ "SHOW INDEX FROM {$wpdb->prefix}statistics_visitor WHERE Key_name = 'date_ip_agent'"
206
+ );
207
+
208
+ // Note, the result will be the number of fields contained in the index, so in our case 5.
209
+ if ( $result != 5 ) {
210
+ $dbupdates['date_ip_agent'] = true;
211
+ }
212
+
213
+ // Check the number of index's on the visits table, if it's only 5 we need to check for duplicate entries and remove them
214
+ $result = $wpdb->query(
215
+ "SHOW INDEX FROM {$wpdb->prefix}statistics_visit WHERE Key_name = 'unique_date'"
216
+ );
217
+
218
+ // Note, the result will be the number of fields contained in the index, so in our case 1.
219
+ if ( $result != 1 ) {
220
+ $dbupdates['unique_date'] = true;
221
+ }
222
+
223
+ $WP_Statistics->update_option('pending_db_updates', $dbupdates);
224
+
225
+ $default_options = $WP_Statistics->Default_Options();
226
+
227
+ if ( $WP_Statistics->installed_version == false ) {
228
+
229
+ // If this is a first time install, we just need to setup the primary values in the tables.
230
+
231
+ $WP_Statistics->Primary_Values();
232
+
233
+ // By default, on new installs, use the new search table.
234
+ $WP_Statistics->update_option('search_converted', 1);
235
+
236
+ } else {
237
+
238
+ // If this is an upgrade, we need to check to see if we need to convert anything from old to new formats.
239
+
240
+ // Check to see if the "new" settings code is in place or not, if not, upgrade the old settings to the new system.
241
+ if ( get_option('wp_statistics') === false ) {
242
+ $core_options = array(
243
+ 'wps_disable_map',
244
+ 'wps_map_location',
245
+ 'wps_google_coordinates',
246
+ 'wps_schedule_dbmaint',
247
+ 'wps_schedule_dbmaint_days',
248
+ 'wps_geoip',
249
+ 'wps_update_geoip',
250
+ 'wps_schedule_geoip',
251
+ 'wps_last_geoip_dl',
252
+ 'wps_auto_pop',
253
+ 'wps_useronline',
254
+ 'wps_check_online',
255
+ 'wps_visits',
256
+ 'wps_visitors',
257
+ 'wps_store_ua',
258
+ 'wps_coefficient',
259
+ 'wps_pages',
260
+ 'wps_track_all_pages',
261
+ 'wps_disable_column',
262
+ 'wps_menu_bar',
263
+ 'wps_hide_notices',
264
+ 'wps_chart_totals',
265
+ 'wps_stats_report',
266
+ 'wps_time_report',
267
+ 'wps_send_report',
268
+ 'wps_content_report',
269
+ 'wps_read_capability',
270
+ 'wps_manage_capability',
271
+ 'wps_record_exclusions',
272
+ 'wps_robotlist',
273
+ 'wps_exclude_ip',
274
+ 'wps_exclude_loginpage',
275
+ 'wps_exclude_adminpage',
276
+ );
277
+ $var_options = array( 'wps_disable_se_%', 'wps_exclude_%' );
278
+ $widget_options = array(
279
+ 'name_widget',
280
+ 'useronline_widget',
281
+ 'tvisit_widget',
282
+ 'tvisitor_widget',
283
+ 'yvisit_widget',
284
+ 'yvisitor_widget',
285
+ 'wvisit_widget',
286
+ 'mvisit_widget',
287
+ 'ysvisit_widget',
288
+ 'ttvisit_widget',
289
+ 'ttvisitor_widget',
290
+ 'tpviews_widget',
291
+ 'ser_widget',
292
+ 'select_se',
293
+ 'tp_widget',
294
+ 'tpg_widget',
295
+ 'tc_widget',
296
+ 'ts_widget',
297
+ 'tu_widget',
298
+ 'ap_widget',
299
+ 'ac_widget',
300
+ 'au_widget',
301
+ 'lpd_widget',
302
+ 'select_lps',
303
+ );
304
+
305
+ // Handle the core options, we're going to strip off the 'wps_' header as we store them in the new settings array.
306
+ foreach ( $core_options as $option ) {
307
+ $new_name = substr($option, 4);
308
+
309
+ $WP_Statistics->store_option($new_name, get_option($option));
310
+
311
+ delete_option($option);
312
+ }
313
+
314
+ $widget = array();
315
+
316
+ // Handle the widget options, we're going to store them in a sub-array.
317
+ foreach ( $widget_options as $option ) {
318
+ $widget[ $option ] = get_option($option);
319
+
320
+ delete_option($option);
321
+ }
322
+
323
+ $WP_Statistics->store_option('widget', $widget);
324
+
325
+ foreach ( $var_options as $option ) {
326
+ // Handle the special variables options.
327
+ $result = $wpdb->get_results(
328
+ "SELECT * FROM {$wpdb->prefix}options WHERE option_name LIKE '{$option}'"
329
+ );
330
+
331
+ foreach ( $result as $opt ) {
332
+ $new_name = substr($opt->option_name, 4);
333
+
334
+ $WP_Statistics->store_option($new_name, $opt->option_value);
335
+
336
+ delete_option($opt->option_name);
337
+ }
338
+ }
339
+
340
+ $WP_Statistics->save_options();
341
+ }
342
+
343
+ // If the robot list is empty, fill in the defaults.
344
+ $wps_temp_robotslist = $WP_Statistics->get_option('robotlist');
345
+
346
+ if ( trim($wps_temp_robotslist) == "" ||
347
+ $WP_Statistics->get_option('force_robot_update') == true
348
+ ) {
349
+ $WP_Statistics->update_option('robotlist', $default_options['robotlist']);
350
+ }
351
+
352
+ // WP Statistics V4.2 and below automatically exclude the administrator for statistics collection
353
+ // newer versions allow the option to be set for any role in WordPress, however we should mimic
354
+ // 4.2 behaviour when we upgrade, so see if the option exists in the database and if not, set it.
355
+ // This will not work correctly on a WordPress install that has removed the administrator role.
356
+ // However that seems VERY unlikely.
357
+ $exclude_admins = $WP_Statistics->get_option('exclude_administrator', '2');
358
+ if ( $exclude_admins == '2' ) {
359
+ $WP_Statistics->update_option('exclude_administrator', '1');
360
+ }
361
+
362
+ // WordPress 4.3 broke the diplay of the sidebar widget because it no longer accepted a null value
363
+ // to be returned from the widget update function, let's look to see if we need to update any
364
+ // occurances in the options table.
365
+ $widget_options = get_option('widget_wpstatistics_widget');
366
+ if ( is_array($widget_options) ) {
367
+ foreach ( $widget_options as $key => $value ) {
368
+ // We want to update all null array keys that are integers.
369
+ if ( $value === null && is_int($key) ) {
370
+ $widget_options[ $key ] = array();
371
+ }
372
+ }
373
+
374
+ // Store the widget options back to the database.
375
+ update_option('widget_wpstatistics_widget', $widget_options);
376
+ }
377
+ }
378
+
379
+ // We've already handled some of the default or need to do more logic checks on them so create a list to exclude from the next loop.
380
+ $excluded_defaults = array( 'force_robot_update', 'robot_list' );
381
+
382
+ // If this is a first time install or an upgrade and we've added options, set some intelligent defaults.
383
+ foreach ( $default_options as $key => $value ) {
384
+ if ( ! in_array($key, $excluded_defaults) && false === $WP_Statistics->get_option($key) ) {
385
+ $WP_Statistics->store_option($key, $value);
386
+ }
387
+ }
388
+
389
+ if ( $WP_Statistics->installed_version == false ) {
390
+ // We now need to set the robot list to update during the next release. This is only done for new installs to ensure we don't overwrite existing custom robot lists.
391
+ $WP_Statistics->store_option('force_robot_update', true);
392
+ }
393
+
394
+ // For version 8.0, we're removing the old %option% types from the reports, so let's upgrade anyone who still has them to short codes.
395
+ $report_content = $WP_Statistics->get_option('content_report');
396
+
397
+ // Check to make sure we have a report to process.
398
+ if ( trim($report_content) == '' ) {
399
+ // These are the variables we can replace in the template and the short codes we're going to replace them with.
400
+ $template_vars = array(
401
+ 'user_online' => '[wpstatistics stat=usersonline]',
402
+ 'today_visitor' => '[wpstatistics stat=visitors time=today]',
403
+ 'today_visit' => '[wpstatistics stat=visits time=today]',
404
+ 'yesterday_visitor' => '[wpstatistics stat=visitors time=yesterday]',
405
+ 'yesterday_visit' => '[wpstatistics stat=visits time=yesterday]',
406
+ 'total_visitor' => '[wpstatistics stat=visitors time=total]',
407
+ 'total_visit' => '[wpstatistics stat=visits time=total]',
408
+ );
409
+
410
+ // Replace the items in the template.
411
+ $final_report = preg_replace_callback(
412
+ '/%(.*?)%/im',
413
+ function ( $m ) {
414
+ return $template_vars[ $m[1] ];
415
+ },
416
+ $report_content
417
+ );
418
+
419
+ // Store the updated report content.
420
+ $WP_Statistics->store_option('content_report', $final_report);
421
+ }
422
+
423
+ // Save the settings now that we've set them.
424
+ $WP_Statistics->save_options();
425
+
426
+ if ( $WP_Statistics->get_option('upgrade_report') == true ) {
427
+ $WP_Statistics->update_option('send_upgrade_email', true);
428
+ }
429
+
430
+ // Handle multi site implementations
431
+ if ( is_multisite() ) {
432
+ $current_blog = get_current_blog_id();
433
+
434
+ // Loop through each of the sites.
435
+ $sites = $WP_Statistics->get_wp_sites_list();
436
+ foreach ( $sites as $blog_id ) {
437
+
438
+ // Since we've just upgraded/installed the current blog, don't execute a remote call for us.
439
+ if ( $blog_id != $current_blog ) {
440
+
441
+ // Get the admin url for the current site.
442
+ $url = get_admin_url($blog_id);
443
+
444
+ // Go and visit the admin url of the site, this will rerun the install script for each site.
445
+ // We turn blocking off because we don't really care about the response so why wait for it.
446
+ wp_remote_request($url, array( 'blocking' => false ));
447
+ }
448
+ }
449
+ }
450
+ }
451
+ }
452
+ }
453
+ }
includes/classes/{pagination.class.php → class-wp-statistics-pagination.php} RENAMED
@@ -9,15 +9,15 @@
9
  *
10
  * PHP version 5
11
  *
12
- * @author Dane Gardow <dane.g87@gmail.com>
13
- * @copyright 2013 Dane Gardow
14
  * @date 01 January 2013
15
- * @version 1.0
16
- * @license Free
17
  *
18
  ******************************************************************************************/
19
 
20
- if ( ! class_exists( "WP_Statistics_Pagination" ) ): // Prevent multiple class definitions
21
 
22
  class WP_Statistics_Pagination {
23
  /*******************************************************
@@ -26,19 +26,19 @@ if ( ! class_exists( "WP_Statistics_Pagination" ) ): // Prevent multiple clas
26
 
27
  // Edit these as you desire
28
  const DEFAULT_ENTRIES_DISPLAY = 10; // Default number of entries to display per page
29
- const PAGE_GETVAR_NAME = "page"; // Name of GET variable name for page values (i.e., example.php?page=1)
30
 
31
  private $_paginationID = "pagination"; // ID Name of pagination object "pagination" is default
32
  // used also for form name for select options
33
 
34
  // Do not edit these values; they are simply null initializations
35
- private $_totalEntries = null; // Total number of entries (usually supplied by MySQL query)
36
  private $_pagesPerSection = null; // Total number of pages displayed per section (supplied by admin)
37
- private $_entriesPerPage = null; // Total number of entries displayed per page (supplied by user)
38
- private $_currentPage = null; // Current page viewed by user
39
- private $_displayOptions = array(); // Array of options for viewing how many entries per page (supplied by user)
40
- private $_errors = array(); // Array of encountered error messages
41
- private $_styles = array(); // Array of CSS styles for pagination navigation display
42
 
43
 
44
  /*******************************************************
@@ -46,18 +46,28 @@ if ( ! class_exists( "WP_Statistics_Pagination" ) ): // Prevent multiple clas
46
  *******************************************************/
47
 
48
  function __construct(
49
- $totalEntries, $pagesPerSection, $options = "", $paginationID = "", $stylePageOff = "",
50
- $stylePageOn = "", $styleErrors = "", $styleSelect = ""
 
 
 
 
 
 
51
  ) {
52
- $this->setPaginationID( $paginationID ); // Set ID name of pagination object
53
- $this->setTotalEntries( $totalEntries ); // Set total entries
54
- $this->setPagesPerSection( $pagesPerSection ); // Set pages per section
55
- $this->setDisplayOptions( $options ); // Set viewing display options
56
  $this->setEntriesPerPage(); // Set entries per page (input from POST or cookies)
57
  $this->setCurrentPage(); // Set current page (input from GET)
58
  // ! This function must follow after setEntriesPerPage()
59
- $this->setStyles( $stylePageOff, $stylePageOn,
60
- $styleSelect, $styleErrors ); // Set CSS styles for pagination navigation display
 
 
 
 
61
  }
62
 
63
 
@@ -72,11 +82,12 @@ if ( ! class_exists( "WP_Statistics_Pagination" ) ): // Prevent multiple clas
72
  if ( isset( $_COOKIE[ $cookieVar ] ) ) // If cookie is set
73
  {
74
  $_COOKIE[ $cookieVar ] = ""; // Clear cookie
75
- setcookie( $cookieVar, "", time() - 3600, "/" ); // Delete cookie
76
  }
77
  }
78
 
79
- private function _getURL( $input = 1 ) // returns appropriate URL with all GET variables intact
 
80
  { // updates only the particular GET variable in question
81
  $getVars = $_GET; // Get all GET variables
82
 
@@ -85,7 +96,7 @@ if ( ! class_exists( "WP_Statistics_Pagination" ) ): // Prevent multiple clas
85
  unset($getVars["foo"], $getVars["bar"], ... ); // Remove any so they do not appear in URL
86
  */
87
 
88
- $output = '?' . http_build_query( array_merge( $getVars, array( $this->_getIDGETVarName() => $input ) ) );
89
  $output .= '#' . $this->getPaginationID(); // Add #xxx at the end of URL for auto-scrolling
90
 
91
  return $output;
@@ -123,10 +134,11 @@ if ( ! class_exists( "WP_Statistics_Pagination" ) ): // Prevent multiple clas
123
 
124
  private function _validEntry( $input ) // determines if input is valid
125
  {
126
- if ( is_array( $input ) ) // If array
127
  {
128
- foreach ( $input as $element ) { // Recursion: evaluate each array element
129
- if ( ! $this->_validEntry( $element ) ) // If invalid
 
130
  {
131
  return false;
132
  }
@@ -135,7 +147,9 @@ if ( ! class_exists( "WP_Statistics_Pagination" ) ): // Prevent multiple clas
135
  return true; // If function makes it to this point, it is valid
136
  } else // If not array
137
  {
138
- if ( ( preg_match( "/^\d+$/", $input ) && $input > 0 ) || strtolower( $input ) == "all" ) // If positive digit or "all"
 
 
139
  {
140
  return true;
141
  } else {
@@ -144,24 +158,28 @@ if ( ! class_exists( "WP_Statistics_Pagination" ) ): // Prevent multiple clas
144
  }
145
  }
146
 
147
- private function _navBox( $text, $destinationPage, $end = 0 ) // returns span-encased link for pagination bar
 
 
 
 
148
  {
149
  switch ( $end ) {
150
  case 1:
151
  $title = "First page";
152
- break;
153
  case 2:
154
  $title = "Previous page";
155
- break;
156
  case 3:
157
  $title = "Next page";
158
- break;
159
  case 4:
160
  $title = "Last page (" . $this->getTotalPages() . ")";
161
- break;
162
  default:
163
  $title = "";
164
- break;
165
  }
166
 
167
  $title = ( $end > 0 && $title != "" ) ? 'title="' . $title . '"' : '';
@@ -169,7 +187,8 @@ if ( ! class_exists( "WP_Statistics_Pagination" ) ): // Prevent multiple clas
169
  $style = $this->_styles["pageOff"];
170
 
171
  // Determine Style
172
- $style = ( $this->_currentPage == $destinationPage && ! $end ) ? $this->_styles["pageOn"] : $this->_styles["pageOff"];
 
173
 
174
  // Determine Link URL/Text
175
  $url = "";
@@ -179,14 +198,19 @@ if ( ! class_exists( "WP_Statistics_Pagination" ) ): // Prevent multiple clas
179
  && $destinationPage >= 1
180
  ) // and destination page is not less than first page
181
  {
182
- $text = '<a href="' . $this->_getURL( $destinationPage ) . '">' . $text . '</a>'; // then make $text a link
 
 
 
 
183
  }
184
 
185
  if ( $style ) {
186
  $style = 'class="' . $style . '"';
187
  }
188
 
189
- $onClick = ( $url ) ? "onclick=\"location.href='" . $url . "'\"" : ""; // Determine if span element is clickable
 
190
 
191
  return '<span ' . $style . $title . ' ' . $onClick . '>' . $text . '</span>';
192
  }
@@ -212,32 +236,43 @@ if ( ! class_exists( "WP_Statistics_Pagination" ) ): // Prevent multiple clas
212
 
213
  $pagesPerSection = $this->getPagesPerSection();
214
 
215
- $sectionStart = $this->_currentPage - floor( $pagesPerSection / 2 ); // Section start is current page # minus half the # of pages per section
 
 
 
216
 
217
- if ( $sectionStart <= 0 ) // Adjust section start to 1 (first page) if # pages between 1st page
 
 
218
  {
219
  $sectionStart = 1;
220
  } // and current page is less than half the # of pages per section
221
 
222
- $sectionEnd = $sectionStart + $pagesPerSection - 1; // Section end is # pages per section after section start,
 
 
223
  // minus 1 (otherwise # of pages per section will exceed given amount by 1)
224
 
225
- if ( $sectionEnd > $lastPage ) // Adjust section end to last page if section end exceeds last page
 
 
226
  {
227
  $sectionEnd = $lastPage;
228
  }
229
 
230
- $sectionStart = $sectionEnd - $pagesPerSection + 1; // Adjust section start to # of pages behind section end
 
 
231
 
232
- $output = $this->_navBox( "&lt;&lt;", $firstPage, 1 ); // First page
233
- $output .= $this->_navBox( "&lt;", $previousPage, 2 ); // Previous page
234
 
235
- for ( $i = $sectionStart; $i <= $sectionEnd; ++ $i ) {
236
- $output .= $this->_navBox( $i, $i );
237
  } // Pagination
238
 
239
- $output .= $this->_navBox( "&gt;", $nextPage, 3 ); // Next Page
240
- $output .= $this->_navBox( "&gt;&gt;", $lastPage, 4 ); // Last Page
241
 
242
  return $output;
243
  }
@@ -248,7 +283,7 @@ if ( ! class_exists( "WP_Statistics_Pagination" ) ): // Prevent multiple clas
248
  return "No errors were encountered.";
249
  }
250
 
251
- $words = ( count( $this->_errors ) > 1 ) ? "errors were" : "error was";
252
 
253
  // Determine CSS styling for error reporting
254
  if ( $this->_styles["errors"] ) {
@@ -257,16 +292,18 @@ if ( ! class_exists( "WP_Statistics_Pagination" ) ): // Prevent multiple clas
257
  $css = '';
258
  }
259
 
260
- $output = '
 
261
  <div ' . $css . '>
262
- The following ' . $words . ' encountered while using the ' . get_class( $this ) . ' class:<br/><br/>
263
  <ul>';
264
 
265
  foreach ( $this->_errors as $error ) {
266
  $output .= '<li>' . $error . '</li>';
267
  }
268
 
269
- $output .= '
 
270
  </ul>
271
  </div>';
272
 
@@ -275,7 +312,7 @@ if ( ! class_exists( "WP_Statistics_Pagination" ) ): // Prevent multiple clas
275
 
276
  public function displaySelectInterface() // displays the <select> interface for choosing display amount
277
  {
278
- if ( count( $this->_displayOptions ) < 2 ) // If only 1 or fewer options, do not display
279
  {
280
  return;
281
  }
@@ -302,13 +339,28 @@ if ( ! class_exists( "WP_Statistics_Pagination" ) ): // Prevent multiple clas
302
 
303
  $formNumber = ( $count ) ? $count : "";
304
 
305
- $output = '
306
- <form name="' . $formName . $formNumber . '" method="post" style="display:inline-block;" action="' . $this->_getURL( $this->_currentPage ) . '">
 
 
 
 
 
 
307
  Show:
308
- <select ' . $css . ' name="' . $this->_getPOSTVarName() . '" OnChange ="' . $formName . $formNumber . '.submit()">';
 
 
 
 
 
 
 
309
 
310
  foreach ( $this->_displayOptions as $line ) {
311
- if ( $this->_entriesPerPage == $line || $this->_entriesPerPage == $this->_totalEntries ) // If option equals entries per page
 
 
312
  {
313
  $selected = "selected";
314
  } // or entries per page equals total entries
@@ -320,12 +372,13 @@ if ( ! class_exists( "WP_Statistics_Pagination" ) ): // Prevent multiple clas
320
  $output .= '<option value="' . $line . '" ' . $selected . '>' . $line . '</option>';
321
  }
322
 
323
- $output .= '
 
324
  </select>
325
  <noscript><input type="submit" name="paginationDisplaySubmit" value="Display"/></noscript>
326
  </form>';
327
 
328
- ++ $count; // Increase # of times this function has run
329
 
330
  return $output;
331
  }
@@ -347,15 +400,17 @@ if ( ! class_exists( "WP_Statistics_Pagination" ) ): // Prevent multiple clas
347
  $page = 1;
348
  } // Otherwise use first page
349
 
350
- if ( $page < 1 || ! preg_match( "/^\d+$/", $page ) ) // If page is less than 1 or page value not a digit
 
 
351
  {
352
- header( "Location: " . $this->_getURL() ); // No argument for _getURL() sets it to 1 (first page)
353
  exit;
354
  }
355
 
356
  if ( $page > $this->getTotalPages() && $this->getTotalPages() != 0 ) // If page exceeds last page
357
  { // 2nd condition prevents infinite loop should it equal 0
358
- header( "Location: " . $this->_getURL( $this->getTotalPages() ) );
359
  exit;
360
  }
361
 
@@ -364,9 +419,12 @@ if ( ! class_exists( "WP_Statistics_Pagination" ) ): // Prevent multiple clas
364
 
365
  public function setDisplayOptions( $input ) // sets the user-specified display amount
366
  {
367
- if ( ! $this->_validEntry( $input ) ) // If invalid entry encountered, register error and exit function
 
 
 
368
  {
369
- if ( is_array( $input ) ) // If array
370
  {
371
  $argument = "";
372
 
@@ -387,7 +445,7 @@ if ( ! class_exists( "WP_Statistics_Pagination" ) ): // Prevent multiple clas
387
  return;
388
  }
389
 
390
- if ( ! is_array( $input ) && strtolower( $input ) == "all" ) // If Not Array and "All" selected
391
  {
392
  $input = $this->_totalEntries;
393
  } // Set total entries value
@@ -404,30 +462,33 @@ if ( ! class_exists( "WP_Statistics_Pagination" ) ): // Prevent multiple clas
404
 
405
  $varName = $this->_getPOSTVarName();
406
 
407
- if ( count( $this->_displayOptions ) > 1 ) // If more than 1 display option
408
  {
409
  $value = $this->_displayOptions[0]; // Default is first selection
410
 
411
  if ( isset( $_POST[ $varName ] ) ) // If POST is set
412
  {
413
- if ( in_array( $_POST[ $varName ], $this->_displayOptions ) ) // Check for valid post value
414
  {
415
  $value = $_POST[ $varName ];
416
- setcookie( $varName, $value, 604800 + time(), "/" ); // Set cookie
417
  $_COOKIE[ $varName ] = $value;
418
  } else // If invalid post value
419
  {
420
- $value = self::DEFAULT_ENTRIES_DISPLAY; // Set to default if invalid
 
421
  }
422
  } elseif ( isset( $_COOKIE[ $varName ] ) ) // If POST not set, but COOKIE set
423
  {
424
  // Check for valid cookie value
425
- if ( in_array( $_COOKIE[ $varName ], $this->_displayOptions ) ) // Check for valid cookie value
426
  {
427
  $value = $_COOKIE[ $varName ]; // Set to value if valid
428
  } else {
429
- $value = self::DEFAULT_ENTRIES_DISPLAY; // Set to default if invalid
430
- $this->deleteCookie(); // Delete invalid cookie
 
 
431
  }
432
  }
433
  } else // If only one option, set either to default or displayOptions value
@@ -435,7 +496,7 @@ if ( ! class_exists( "WP_Statistics_Pagination" ) ): // Prevent multiple clas
435
  $value = ( $this->_displayOptions ) ? $this->_displayOptions : self::DEFAULT_ENTRIES_DISPLAY;
436
  }
437
 
438
- if ( strtolower( $value ) == "all" ) // If set to "All", use total entries
439
  {
440
  $value = $this->_totalEntries;
441
  }
@@ -445,7 +506,7 @@ if ( ! class_exists( "WP_Statistics_Pagination" ) ): // Prevent multiple clas
445
 
446
  public function setPagesPerSection( $input ) // sets # of pages per section
447
  {
448
- if ( ! $this->_validEntry( $input ) ) {
449
  $this->_errors[] = "The value set for <strong>pages per section</strong> is invalid: " . $input;
450
 
451
  return;
@@ -456,9 +517,10 @@ if ( ! class_exists( "WP_Statistics_Pagination" ) ): // Prevent multiple clas
456
 
457
  public function setPaginationID( $input ) {
458
  if ( $input ) {
459
- if ( preg_match( "/^\d+$/", $input[0] ) ) // Check if first character is a digit
460
  {
461
- $this->_errors[] = "The first character of the <strong>pagination ID</strong> cannot be a number: " . $input;
 
462
 
463
  return; // cannot be a digit because variable names cannot start with digits,
464
  } // and this value will be used as a variable name
@@ -467,19 +529,24 @@ if ( ! class_exists( "WP_Statistics_Pagination" ) ): // Prevent multiple clas
467
  }
468
  }
469
 
470
- public function setStyles( $pageOff = "", $pageOn = "", $select = "", $errors = "" ) // sets CSS style class names
 
 
 
 
 
471
  {
472
  $this->_styles = array(
473
  "pageOff" => $pageOff,
474
  "pageOn" => $pageOn,
475
  "select" => $select,
476
- "errors" => $errors
477
  );
478
  }
479
 
480
  public function setTotalEntries( $input ) // sets total number of entries
481
  {
482
- if ( ! $this->_validEntry( $input ) ) {
483
  $this->_errors[] = "The value set for <strong>total entries</strong> is invalid: " . $input;
484
 
485
  return;
@@ -522,7 +589,9 @@ if ( ! class_exists( "WP_Statistics_Pagination" ) ): // Prevent multiple clas
522
  return 0;
523
  }
524
 
525
- if ( $this->_pagesPerSection > $this->getTotalPages() ) // If per section is greater than total pages
 
 
526
  {
527
  return $this->getTotalPages();
528
  } // Return total pages
@@ -548,7 +617,9 @@ if ( ! class_exists( "WP_Statistics_Pagination" ) ): // Prevent multiple clas
548
  return 0;
549
  }
550
 
551
- return ceil( $this->_totalEntries / $this->_entriesPerPage ); // Total pages: total # of entries divided by total entries per page
 
 
552
  }
553
 
554
  public function getEntryStart() // returns the start entry for the page
@@ -558,7 +629,8 @@ if ( ! class_exists( "WP_Statistics_Pagination" ) ): // Prevent multiple clas
558
  return 0;
559
  }
560
 
561
- return ( $this->_currentPage - 1 ) * $this->_entriesPerPage; // Entry start: 1 less than current page multiplied by total entries per page
 
562
  }
563
 
564
  public function getEntryEnd() // returns the last entry for the page
@@ -595,4 +667,3 @@ if ( ! class_exists( "WP_Statistics_Pagination" ) ): // Prevent multiple clas
595
  }
596
 
597
  endif; // Prevent multiple class definitions
598
- ?>
9
  *
10
  * PHP version 5
11
  *
12
+ * @author Dane Gardow <dane.g87@gmail.com>
13
+ * @copyright 2013 Dane Gardow
14
  * @date 01 January 2013
15
+ * @version 1.0
16
+ * @license Free
17
  *
18
  ******************************************************************************************/
19
 
20
+ if ( ! class_exists("WP_Statistics_Pagination") ): // Prevent multiple class definitions
21
 
22
  class WP_Statistics_Pagination {
23
  /*******************************************************
26
 
27
  // Edit these as you desire
28
  const DEFAULT_ENTRIES_DISPLAY = 10; // Default number of entries to display per page
29
+ const PAGE_GETVAR_NAME = "page"; // Name of GET variable name for page values (i.e., example.php?page=1)
30
 
31
  private $_paginationID = "pagination"; // ID Name of pagination object "pagination" is default
32
  // used also for form name for select options
33
 
34
  // Do not edit these values; they are simply null initializations
35
+ private $_totalEntries = null; // Total number of entries (usually supplied by MySQL query)
36
  private $_pagesPerSection = null; // Total number of pages displayed per section (supplied by admin)
37
+ private $_entriesPerPage = null; // Total number of entries displayed per page (supplied by user)
38
+ private $_currentPage = null; // Current page viewed by user
39
+ private $_displayOptions = array(); // Array of options for viewing how many entries per page (supplied by user)
40
+ private $_errors = array(); // Array of encountered error messages
41
+ private $_styles = array(); // Array of CSS styles for pagination navigation display
42
 
43
 
44
  /*******************************************************
46
  *******************************************************/
47
 
48
  function __construct(
49
+ $totalEntries,
50
+ $pagesPerSection,
51
+ $options = "",
52
+ $paginationID = "",
53
+ $stylePageOff = "",
54
+ $stylePageOn = "",
55
+ $styleErrors = "",
56
+ $styleSelect = ""
57
  ) {
58
+ $this->setPaginationID($paginationID); // Set ID name of pagination object
59
+ $this->setTotalEntries($totalEntries); // Set total entries
60
+ $this->setPagesPerSection($pagesPerSection); // Set pages per section
61
+ $this->setDisplayOptions($options); // Set viewing display options
62
  $this->setEntriesPerPage(); // Set entries per page (input from POST or cookies)
63
  $this->setCurrentPage(); // Set current page (input from GET)
64
  // ! This function must follow after setEntriesPerPage()
65
+ $this->setStyles(
66
+ $stylePageOff,
67
+ $stylePageOn,
68
+ $styleSelect,
69
+ $styleErrors
70
+ ); // Set CSS styles for pagination navigation display
71
  }
72
 
73
 
82
  if ( isset( $_COOKIE[ $cookieVar ] ) ) // If cookie is set
83
  {
84
  $_COOKIE[ $cookieVar ] = ""; // Clear cookie
85
+ setcookie($cookieVar, "", time() - 3600, "/"); // Delete cookie
86
  }
87
  }
88
 
89
+ private function _getURL( $input = 1
90
+ ) // returns appropriate URL with all GET variables intact
91
  { // updates only the particular GET variable in question
92
  $getVars = $_GET; // Get all GET variables
93
 
96
  unset($getVars["foo"], $getVars["bar"], ... ); // Remove any so they do not appear in URL
97
  */
98
 
99
+ $output = '?' . http_build_query(array_merge($getVars, array( $this->_getIDGETVarName() => $input )));
100
  $output .= '#' . $this->getPaginationID(); // Add #xxx at the end of URL for auto-scrolling
101
 
102
  return $output;
134
 
135
  private function _validEntry( $input ) // determines if input is valid
136
  {
137
+ if ( is_array($input) ) // If array
138
  {
139
+ foreach ( $input as $element )
140
+ { // Recursion: evaluate each array element
141
+ if ( ! $this->_validEntry($element) ) // If invalid
142
  {
143
  return false;
144
  }
147
  return true; // If function makes it to this point, it is valid
148
  } else // If not array
149
  {
150
+ if ( ( preg_match("/^\d+$/", $input) && $input > 0 ) ||
151
+ strtolower($input) == "all"
152
+ ) // If positive digit or "all"
153
  {
154
  return true;
155
  } else {
158
  }
159
  }
160
 
161
+ private function _navBox(
162
+ $text,
163
+ $destinationPage,
164
+ $end = 0
165
+ ) // returns span-encased link for pagination bar
166
  {
167
  switch ( $end ) {
168
  case 1:
169
  $title = "First page";
170
+ break;
171
  case 2:
172
  $title = "Previous page";
173
+ break;
174
  case 3:
175
  $title = "Next page";
176
+ break;
177
  case 4:
178
  $title = "Last page (" . $this->getTotalPages() . ")";
179
+ break;
180
  default:
181
  $title = "";
182
+ break;
183
  }
184
 
185
  $title = ( $end > 0 && $title != "" ) ? 'title="' . $title . '"' : '';
187
  $style = $this->_styles["pageOff"];
188
 
189
  // Determine Style
190
+ $style = ( $this->_currentPage == $destinationPage && ! $end ) ? $this->_styles["pageOn"]
191
+ : $this->_styles["pageOff"];
192
 
193
  // Determine Link URL/Text
194
  $url = "";
198
  && $destinationPage >= 1
199
  ) // and destination page is not less than first page
200
  {
201
+ $text = '<a href="' .
202
+ $this->_getURL($destinationPage) .
203
+ '">' .
204
+ $text .
205
+ '</a>'; // then make $text a link
206
  }
207
 
208
  if ( $style ) {
209
  $style = 'class="' . $style . '"';
210
  }
211
 
212
+ $onClick = ( $url ) ? "onclick=\"location.href='" . $url . "'\""
213
+ : ""; // Determine if span element is clickable
214
 
215
  return '<span ' . $style . $title . ' ' . $onClick . '>' . $text . '</span>';
216
  }
236
 
237
  $pagesPerSection = $this->getPagesPerSection();
238
 
239
+ $sectionStart = $this->_currentPage -
240
+ floor(
241
+ $pagesPerSection / 2
242
+ ); // Section start is current page # minus half the # of pages per section
243
 
244
+ if ( $sectionStart <=
245
+ 0
246
+ ) // Adjust section start to 1 (first page) if # pages between 1st page
247
  {
248
  $sectionStart = 1;
249
  } // and current page is less than half the # of pages per section
250
 
251
+ $sectionEnd = $sectionStart +
252
+ $pagesPerSection -
253
+ 1; // Section end is # pages per section after section start,
254
  // minus 1 (otherwise # of pages per section will exceed given amount by 1)
255
 
256
+ if ( $sectionEnd >
257
+ $lastPage
258
+ ) // Adjust section end to last page if section end exceeds last page
259
  {
260
  $sectionEnd = $lastPage;
261
  }
262
 
263
+ $sectionStart = $sectionEnd -
264
+ $pagesPerSection +
265
+ 1; // Adjust section start to # of pages behind section end
266
 
267
+ $output = $this->_navBox("&lt;&lt;", $firstPage, 1); // First page
268
+ $output .= $this->_navBox("&lt;", $previousPage, 2); // Previous page
269
 
270
+ for ( $i = $sectionStart; $i <= $sectionEnd; ++$i ) {
271
+ $output .= $this->_navBox($i, $i);
272
  } // Pagination
273
 
274
+ $output .= $this->_navBox("&gt;", $nextPage, 3); // Next Page
275
+ $output .= $this->_navBox("&gt;&gt;", $lastPage, 4); // Last Page
276
 
277
  return $output;
278
  }
283
  return "No errors were encountered.";
284
  }
285
 
286
+ $words = ( count($this->_errors) > 1 ) ? "errors were" : "error was";
287
 
288
  // Determine CSS styling for error reporting
289
  if ( $this->_styles["errors"] ) {
292
  $css = '';
293
  }
294
 
295
+ $output
296
+ = '
297
  <div ' . $css . '>
298
+ The following ' . $words . ' encountered while using the ' . get_class($this) . ' class:<br/><br/>
299
  <ul>';
300
 
301
  foreach ( $this->_errors as $error ) {
302
  $output .= '<li>' . $error . '</li>';
303
  }
304
 
305
+ $output
306
+ .= '
307
  </ul>
308
  </div>';
309
 
312
 
313
  public function displaySelectInterface() // displays the <select> interface for choosing display amount
314
  {
315
+ if ( count($this->_displayOptions) < 2 ) // If only 1 or fewer options, do not display
316
  {
317
  return;
318
  }
339
 
340
  $formNumber = ( $count ) ? $count : "";
341
 
342
+ $output
343
+ = '
344
+ <form name="' .
345
+ $formName .
346
+ $formNumber .
347
+ '" method="post" style="display:inline-block;" action="' .
348
+ $this->_getURL($this->_currentPage) .
349
+ '">
350
  Show:
351
+ <select ' .
352
+ $css .
353
+ ' name="' .
354
+ $this->_getPOSTVarName() .
355
+ '" OnChange ="' .
356
+ $formName .
357
+ $formNumber .
358
+ '.submit()">';
359
 
360
  foreach ( $this->_displayOptions as $line ) {
361
+ if ( $this->_entriesPerPage == $line ||
362
+ $this->_entriesPerPage == $this->_totalEntries
363
+ ) // If option equals entries per page
364
  {
365
  $selected = "selected";
366
  } // or entries per page equals total entries
372
  $output .= '<option value="' . $line . '" ' . $selected . '>' . $line . '</option>';
373
  }
374
 
375
+ $output
376
+ .= '
377
  </select>
378
  <noscript><input type="submit" name="paginationDisplaySubmit" value="Display"/></noscript>
379
  </form>';
380
 
381
+ ++$count; // Increase # of times this function has run
382
 
383
  return $output;
384
  }
400
  $page = 1;
401
  } // Otherwise use first page
402
 
403
+ if ( $page < 1 ||
404
+ ! preg_match("/^\d+$/", $page)
405
+ ) // If page is less than 1 or page value not a digit
406
  {
407
+ header("Location: " . $this->_getURL()); // No argument for _getURL() sets it to 1 (first page)
408
  exit;
409
  }
410
 
411
  if ( $page > $this->getTotalPages() && $this->getTotalPages() != 0 ) // If page exceeds last page
412
  { // 2nd condition prevents infinite loop should it equal 0
413
+ header("Location: " . $this->_getURL($this->getTotalPages()));
414
  exit;
415
  }
416
 
419
 
420
  public function setDisplayOptions( $input ) // sets the user-specified display amount
421
  {
422
+ if ( ! $this->_validEntry(
423
+ $input
424
+ )
425
+ ) // If invalid entry encountered, register error and exit function
426
  {
427
+ if ( is_array($input) ) // If array
428
  {
429
  $argument = "";
430
 
445
  return;
446
  }
447
 
448
+ if ( ! is_array($input) && strtolower($input) == "all" ) // If Not Array and "All" selected
449
  {
450
  $input = $this->_totalEntries;
451
  } // Set total entries value
462
 
463
  $varName = $this->_getPOSTVarName();
464
 
465
+ if ( count($this->_displayOptions) > 1 ) // If more than 1 display option
466
  {
467
  $value = $this->_displayOptions[0]; // Default is first selection
468
 
469
  if ( isset( $_POST[ $varName ] ) ) // If POST is set
470
  {
471
+ if ( in_array($_POST[ $varName ], $this->_displayOptions) ) // Check for valid post value
472
  {
473
  $value = $_POST[ $varName ];
474
+ setcookie($varName, $value, 604800 + time(), "/"); // Set cookie
475
  $_COOKIE[ $varName ] = $value;
476
  } else // If invalid post value
477
  {
478
+ $value
479
+ = self::DEFAULT_ENTRIES_DISPLAY; // Set to default if invalid
480
  }
481
  } elseif ( isset( $_COOKIE[ $varName ] ) ) // If POST not set, but COOKIE set
482
  {
483
  // Check for valid cookie value
484
+ if ( in_array($_COOKIE[ $varName ], $this->_displayOptions) ) // Check for valid cookie value
485
  {
486
  $value = $_COOKIE[ $varName ]; // Set to value if valid
487
  } else {
488
+ $value
489
+ = self::DEFAULT_ENTRIES_DISPLAY; // Set to default if invalid
490
+ $this->deleteCookie(
491
+ ); // Delete invalid cookie
492
  }
493
  }
494
  } else // If only one option, set either to default or displayOptions value
496
  $value = ( $this->_displayOptions ) ? $this->_displayOptions : self::DEFAULT_ENTRIES_DISPLAY;
497
  }
498
 
499
+ if ( strtolower($value) == "all" ) // If set to "All", use total entries
500
  {
501
  $value = $this->_totalEntries;
502
  }
506
 
507
  public function setPagesPerSection( $input ) // sets # of pages per section
508
  {
509
+ if ( ! $this->_validEntry($input) ) {
510
  $this->_errors[] = "The value set for <strong>pages per section</strong> is invalid: " . $input;
511
 
512
  return;
517
 
518
  public function setPaginationID( $input ) {
519
  if ( $input ) {
520
+ if ( preg_match("/^\d+$/", $input[0]) ) // Check if first character is a digit
521
  {
522
+ $this->_errors[]
523
+ = "The first character of the <strong>pagination ID</strong> cannot be a number: " . $input;
524
 
525
  return; // cannot be a digit because variable names cannot start with digits,
526
  } // and this value will be used as a variable name
529
  }
530
  }
531
 
532
+ public function setStyles(
533
+ $pageOff = "",
534
+ $pageOn = "",
535
+ $select = "",
536
+ $errors = ""
537
+ ) // sets CSS style class names
538
  {
539
  $this->_styles = array(
540
  "pageOff" => $pageOff,
541
  "pageOn" => $pageOn,
542
  "select" => $select,
543
+ "errors" => $errors,
544
  );
545
  }
546
 
547
  public function setTotalEntries( $input ) // sets total number of entries
548
  {
549
+ if ( ! $this->_validEntry($input) ) {
550
  $this->_errors[] = "The value set for <strong>total entries</strong> is invalid: " . $input;
551
 
552
  return;
589
  return 0;
590
  }
591
 
592
+ if ( $this->_pagesPerSection >
593
+ $this->getTotalPages()
594
+ ) // If per section is greater than total pages
595
  {
596
  return $this->getTotalPages();
597
  } // Return total pages
617
  return 0;
618
  }
619
 
620
+ return ceil(
621
+ $this->_totalEntries / $this->_entriesPerPage
622
+ ); // Total pages: total # of entries divided by total entries per page
623
  }
624
 
625
  public function getEntryStart() // returns the start entry for the page
629
  return 0;
630
  }
631
 
632
+ return ( $this->_currentPage - 1 ) *
633
+ $this->_entriesPerPage; // Entry start: 1 less than current page multiplied by total entries per page
634
  }
635
 
636
  public function getEntryEnd() // returns the last entry for the page
667
  }
668
 
669
  endif; // Prevent multiple class definitions
 
includes/classes/class-wp-statistics-schedule.php ADDED
@@ -0,0 +1,312 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace {
4
+ /**
5
+ * Class WP_Statistics_Schedule
6
+ */
7
+ class WP_Statistics_Schedule {
8
+
9
+ /**
10
+ * WP_Statistics_Schedule constructor.
11
+ *
12
+ * @param $WP_Statistics
13
+ */
14
+ function __construct( $WP_Statistics ) {
15
+
16
+ // before construct
17
+ add_filter('cron_schedules', 'WP_Statistics_Schedule::addcron');
18
+
19
+ // Add the report schedule if it doesn't exist and is enabled.
20
+ if ( ! wp_next_scheduled('report_hook') && $WP_Statistics->get_option('stats_report') ) {
21
+
22
+ wp_schedule_event(time(), $WP_Statistics->get_option('time_report'), 'report_hook');
23
+ }
24
+
25
+ // Remove the report schedule if it does exist and is disabled.
26
+ if ( wp_next_scheduled('report_hook') && ! $WP_Statistics->get_option('stats_report') ) {
27
+
28
+ wp_unschedule_event(wp_next_scheduled('report_hook'), 'report_hook');
29
+ }
30
+
31
+ // Add the GeoIP update schedule if it doesn't exist and it should be.
32
+ if ( ! wp_next_scheduled('wp_statistics_geoip_hook') &&
33
+ $WP_Statistics->get_option('schedule_geoip') &&
34
+ $WP_Statistics->get_option('geoip')
35
+ ) {
36
+
37
+ wp_schedule_event(time(), 'daily', 'wp_statistics_geoip_hook');
38
+ }
39
+
40
+ // Remove the GeoIP update schedule if it does exist and it should shouldn't.
41
+ if ( wp_next_scheduled('wp_statistics_geoip_hook') &&
42
+ ( ! $WP_Statistics->get_option('schedule_geoip') || ! $WP_Statistics->get_option('geoip') )
43
+ ) {
44
+
45
+ wp_unschedule_event(wp_next_scheduled('wp_statistics_geoip_hook'), 'wp_statistics_geoip_hook');
46
+ }
47
+
48
+ // Add the browscap update schedule if it doesn't exist and it should be.
49
+ if ( ! wp_next_scheduled('wp_statistics_browscap_hook') &&
50
+ $WP_Statistics->get_option('schedule_browscap')
51
+ ) {
52
+
53
+ wp_schedule_event(time(), 'weekly', 'wp_statistics_browscap_hook');
54
+ }
55
+
56
+ // Remove the browscap update schedule if it does exist and it should shouldn't.
57
+ if ( wp_next_scheduled('wp_statistics_browscap_hook') &&
58
+ ! $WP_Statistics->get_option('schedule_browscap')
59
+ ) {
60
+
61
+ wp_unschedule_event(wp_next_scheduled('wp_statistics_browscap_hook'), 'wp_statistics_browscap_hook');
62
+ }
63
+
64
+ // Add the referrerspam update schedule if it doesn't exist and it should be.
65
+ if ( ! wp_next_scheduled('wp_statistics_referrerspam_hook') &&
66
+ $WP_Statistics->get_option('schedule_referrerspam')
67
+ ) {
68
+
69
+ wp_schedule_event(time(), 'weekly', 'wp_statistics_referrerspam_hook');
70
+ }
71
+
72
+ // Remove the referrerspam update schedule if it does exist and it should shouldn't.
73
+ if ( wp_next_scheduled('wp_statistics_referrerspam_hook') &&
74
+ ! $WP_Statistics->get_option('schedule_referrerspam')
75
+ ) {
76
+
77
+ wp_unschedule_event(
78
+ wp_next_scheduled('wp_statistics_referrerspam_hook'),
79
+ 'wp_statistics_referrerspam_hook'
80
+ );
81
+ }
82
+
83
+ // Add the database maintenance schedule if it doesn't exist and it should be.
84
+ if ( ! wp_next_scheduled('wp_statistics_dbmaint_hook') && $WP_Statistics->get_option('schedule_dbmaint') ) {
85
+
86
+ wp_schedule_event(time(), 'daily', 'wp_statistics_dbmaint_hook');
87
+ }
88
+
89
+ // Remove the database maintenance schedule if it does exist and it shouldn't.
90
+ if ( wp_next_scheduled('wp_statistics_dbmaint_hook') &&
91
+ ( ! $WP_Statistics->get_option('schedule_dbmaint') )
92
+ ) {
93
+
94
+ wp_unschedule_event(wp_next_scheduled('wp_statistics_dbmaint_hook'), 'wp_statistics_dbmaint_hook');
95
+ }
96
+
97
+ // Add the visitor database maintenance schedule if it doesn't exist and it should be.
98
+ if ( ! wp_next_scheduled('wp_statistics_dbmaint_visitor_hook') &&
99
+ $WP_Statistics->get_option('schedule_dbmaint_visitor')
100
+ ) {
101
+
102
+ wp_schedule_event(time(), 'daily', 'wp_statistics_dbmaint_visitor_hook');
103
+ }
104
+
105
+ // Remove the visitor database maintenance schedule if it does exist and it shouldn't.
106
+ if ( wp_next_scheduled('wp_statistics_dbmaint_visitor_hook') &&
107
+ ( ! $WP_Statistics->get_option('schedule_dbmaint_visitor') )
108
+ ) {
109
+
110
+ wp_unschedule_event(
111
+ wp_next_scheduled('wp_statistics_dbmaint_visitor_hook'),
112
+ 'wp_statistics_dbmaint_visitor_hook'
113
+ );
114
+ }
115
+
116
+ // Remove the add visit row schedule if it does exist and it shouldn't.
117
+ if ( wp_next_scheduled('wp_statistics_add_visit_hook') && ( ! $WP_Statistics->get_option('visits') ) ) {
118
+
119
+ wp_unschedule_event(wp_next_scheduled('wp_statistics_add_visit_hook'), 'wp_statistics_add_visit_hook');
120
+ }
121
+
122
+ // Add the add visit table row schedule if it does exist and it should.
123
+ if ( ! wp_next_scheduled('wp_statistics_add_visit_hook') && $WP_Statistics->get_option('visits') ) {
124
+
125
+ wp_schedule_event(time(), 'daily', 'wp_statistics_add_visit_hook');
126
+ }
127
+
128
+ //after construct
129
+ add_action('wp_statistics_add_visit_hook', 'WP_Statistics_Schedule::add_visit_event');
130
+ add_action('wp_statistics_geoip_hook', 'WP_Statistics_Schedule::geoip_event');
131
+ add_action('wp_statistics_browscap_hook', 'WP_Statistics_Schedule::browscap_event');
132
+ add_action('wp_statistics_referrerspam_hook', 'WP_Statistics_Schedule::referrerspam_event');
133
+ add_action('wp_statistics_dbmaint_hook', 'WP_Statistics_Schedule::dbmaint_event');
134
+ add_action('wp_statistics_dbmaint_visitor_hook', 'WP_Statistics_Schedule::dbmaint_visitor_event');
135
+ add_action('report_hook', 'WP_Statistics_Schedule::send_report');
136
+
137
+ }
138
+
139
+ /**
140
+ * @param array $schedules
141
+ *
142
+ * @return mixed
143
+ */
144
+ static function addcron( $schedules ) {
145
+ // Adds once weekly to the existing schedules.
146
+ if ( ! array_key_exists('weekly', $schedules) ) {
147
+ $schedules['weekly'] = array(
148
+ 'interval' => 604800,
149
+ 'display' => __('Once Weekly'),
150
+ );
151
+ }
152
+
153
+ if ( ! array_key_exists('biweekly', $schedules) ) {
154
+ $schedules['biweekly'] = array(
155
+ 'interval' => 1209600,
156
+ 'display' => __('Once Every 2 Weeks'),
157
+ );
158
+ }
159
+
160
+ if ( ! array_key_exists('4weeks', $schedules) ) {
161
+ $schedules['4weeks'] = array(
162
+ 'interval' => 2419200,
163
+ 'display' => __('Once Every 4 Weeks'),
164
+ );
165
+ }
166
+
167
+ return $schedules;
168
+ }
169
+
170
+
171
+ /**
172
+ * adds a record for tomorrow to the visit table to avoid a race condition.
173
+ *
174
+ */
175
+ static function add_visit_event() {
176
+ GLOBAL $wpdb, $WP_Statistics;
177
+
178
+ $sqlstring = $wpdb->prepare(
179
+ 'INSERT INTO ' .
180
+ $wpdb->prefix .
181
+ 'statistics_visit (last_visit, last_counter, visit) VALUES ( %s, %s, %d)',
182
+ $WP_Statistics->Current_Date(null, '+1'),
183
+ $WP_Statistics->Current_date('Y-m-d', '+1'),
184
+ 0
185
+ );
186
+
187
+ $wpdb->query($sqlstring);
188
+ }
189
+
190
+ /**
191
+ * Updates the GeoIP database from MaxMind.
192
+ */
193
+ static function geoip_event() {
194
+
195
+ GLOBAL $WP_Statistics;
196
+
197
+ // Maxmind updates the geoip database on the first Tuesday of the month, to make sure we don't update before they post
198
+ // the update, download it two days later.
199
+ $thisupdate = strtotime(__('First Tuesday of this month', 'wp-statistics')) + ( 86400 * 2 );
200
+
201
+ $lastupdate = $WP_Statistics->get_option('last_geoip_dl');
202
+
203
+ $upload_dir = wp_upload_dir();
204
+
205
+ // We're also going to look to see if our filesize is to small, this means the plugin stub still exists and should
206
+ // be replaced with a proper file.
207
+ $dbsize = filesize($upload_dir['basedir'] . '/wp-statistics/GeoLite2-Country.mmdb');
208
+
209
+ if ( $lastupdate < $thisupdate || $dbsize < 1024 ) {
210
+
211
+ // We can't fire the download function directly here as we rely on some functions that haven't been loaded yet
212
+ // in WordPress, so instead just set the flag in the options table and the shutdown hook will take care of the
213
+ // actual download at the end of the page.
214
+ $WP_Statistics->update_option('update_geoip', true);
215
+ }
216
+ }
217
+
218
+ /**
219
+ * Updates the browscap database.
220
+ */
221
+ static function browscap_event() {
222
+
223
+ GLOBAL $WP_Statistics;
224
+
225
+ // Check for a new browscap once a week
226
+ $WP_Statistics->update_option('update_browscap', true);
227
+ }
228
+
229
+ /**
230
+ * Updates the browscap database.
231
+ */
232
+ static function referrerspam_event() {
233
+
234
+ GLOBAL $WP_Statistics;
235
+
236
+ // Check for a new referrerspam once a week
237
+ $WP_Statistics->update_option('update_referrerspam', true);
238
+ }
239
+
240
+ /**
241
+ * Purges old records on a schedule based on age.
242
+ */
243
+ static function dbmaint_event() {
244
+ global $WP_Statistics;
245
+ if ( ! function_exists('wp_statistics_purge_data') ) {
246
+ require( WP_Statistics::$reg['plugin-dir'] . 'includes/functions/purge.php' );
247
+ }
248
+ $purge_days = intval($WP_Statistics->get_option('schedule_dbmaint_days', false));
249
+ wp_statistics_purge_data($purge_days);
250
+ }
251
+
252
+ /**
253
+ * Purges visitors with more than a defined number of hits in a day.
254
+ */
255
+ static function dbmaint_visitor_event() {
256
+ global $WP_Statistics;
257
+ if(! function_exists('wp_statistics_purge_visitor_hits')){
258
+ require( WP_Statistics::$reg['plugin-dir'] . 'includes/functions/purge-hits.php' );
259
+ }
260
+ $purge_hits = intval($WP_Statistics->get_option('schedule_dbmaint_visitor_hits', false));
261
+ wp_statistics_purge_visitor_hits($purge_hits);
262
+ }
263
+
264
+ /**
265
+ * Sends the statistics report to the selected users.
266
+ */
267
+ static function send_report() {
268
+ global $WP_Statistics, $sms;
269
+
270
+ // Retrieve the template from the options.
271
+ $final_text_report = $WP_Statistics->get_option('content_report');
272
+
273
+ // Process shortcodes in the template. Note that V8.0 upgrade script replaced the old %option% codes with the appropriate short codes.
274
+ $final_text_report = do_shortcode($final_text_report);
275
+ $final_text_report = apply_filters('wp_statistics_final_text_report_email', $final_text_report);
276
+
277
+ // Send the report through the selected transport agent.
278
+ if ( $WP_Statistics->get_option('send_report') == 'mail' ) {
279
+
280
+ $blogname = get_bloginfo('name');
281
+ $blogemail = get_bloginfo('admin_email');
282
+
283
+ $headers[] = "From: $blogname <$blogemail>";
284
+ $headers[] = "MIME-Version: 1.0";
285
+ $headers[] = "Content-type: text/html; charset=utf-8";
286
+
287
+ if ( $WP_Statistics->get_option('email_list') == '' ) {
288
+ $WP_Statistics->update_option('email_list', $blogemail);
289
+ }
290
+
291
+ wp_mail(
292
+ $WP_Statistics->get_option('email_list'),
293
+ __('Statistical reporting', 'wp-statistics'),
294
+ $final_text_report,
295
+ $headers
296
+ );
297
+
298
+ } else if ( $WP_Statistics->get_option('send_report') == 'sms' ) {
299
+
300
+ if ( class_exists(get_option('wp_webservice')) ) {
301
+
302
+ $sms->to = array( get_option('wp_admin_mobile') );
303
+ $sms->msg = $final_text_report;
304
+ $sms->SendSMS();
305
+ }
306
+
307
+ }
308
+ }
309
+
310
+
311
+ }
312
+ }
includes/classes/class-wp-statistics-shortcode.php ADDED
@@ -0,0 +1,222 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace {
4
+ /**
5
+ * Class WP_Statistics_Shortcode
6
+ */
7
+ class WP_Statistics_Shortcode {
8
+
9
+ /**
10
+ * @param $atts
11
+ *
12
+ * WP-Statistics shortcode is in the format of:
13
+ * [wpstatistics stat=xxx time=xxxx provider=xxxx format=xxxxxx id=xxx]
14
+
15
+ * Where:
16
+ * stat = the statistic you want.
17
+ * time = is the timeframe, strtotime() (http://php.net/manual/en/datetime.formats.php) will be used to calculate it.
18
+ * provider = the search provider to get stats on.
19
+ * format = i18n, english, none.
20
+ * id = the page/post id to get stats on.
21
+ *
22
+ * @return array|false|int|null|object|string|void
23
+ */
24
+ static function shortcodes( $atts ) {
25
+
26
+ if ( ! is_array($atts) ) {
27
+ return;
28
+ }
29
+ if ( ! array_key_exists('stat', $atts) ) {
30
+ return;
31
+ }
32
+
33
+ if ( ! array_key_exists('time', $atts) ) {
34
+ $atts['time'] = null;
35
+ }
36
+ if ( ! array_key_exists('provider', $atts) ) {
37
+ $atts['provider'] = 'all';
38
+ }
39
+ if ( ! array_key_exists('format', $atts) ) {
40
+ $atts['format'] = null;
41
+ }
42
+ if ( ! array_key_exists('id', $atts) ) {
43
+ $atts['id'] = -1;
44
+ }
45
+
46
+ $formatnumber = array_key_exists('format', $atts);
47
+
48
+ switch ( $atts['stat'] ) {
49
+ case 'usersonline':
50
+ $result = wp_statistics_useronline();
51
+ break;
52
+
53
+ case 'visits':
54
+ $result = wp_statistics_visit($atts['time']);
55
+ break;
56
+
57
+ case 'visitors':
58
+ $result = wp_statistics_visitor($atts['time'], null, true);
59
+ break;
60
+
61
+ case 'pagevisits':
62
+ $result = wp_statistics_pages($atts['time'], null, $atts['id']);
63
+ break;
64
+
65
+ case 'searches':
66
+ $result = wp_statistics_searchengine($atts['provider'], $atts['time']);
67
+ break;
68
+
69
+ case 'postcount':
70
+ $result = wp_statistics_countposts();
71
+ break;
72
+
73
+ case 'pagecount':
74
+ $result = wp_statistics_countpages();
75
+ break;
76
+
77
+ case 'commentcount':
78
+ $result = wp_statistics_countcomment();
79
+ break;
80
+
81
+ case 'spamcount':
82
+ $result = wp_statistics_countspam();
83
+ break;
84
+
85
+ case 'usercount':
86
+ $result = wp_statistics_countusers();
87
+ break;
88
+
89
+ case 'postaverage':
90
+ $result = wp_statistics_average_post();
91
+ break;
92
+
93
+ case 'commentaverage':
94
+ $result = wp_statistics_average_comment();
95
+ break;
96
+
97
+ case 'useraverage':
98
+ $result = wp_statistics_average_registeruser();
99
+ break;
100
+
101
+ case 'lpd':
102
+ $result = wp_statistics_lastpostdate();
103
+ $formatnumber = false;
104
+ break;
105
+ }
106
+
107
+ if ( $formatnumber ) {
108
+ switch ( strtolower($atts['format']) ) {
109
+ case 'i18n':
110
+ $result = number_format_i18n($result);
111
+
112
+ break;
113
+ case 'english':
114
+ $result = number_format($result);
115
+
116
+ break;
117
+ }
118
+ }
119
+
120
+ return $result;
121
+ }
122
+
123
+ /**
124
+ *
125
+ */
126
+ static function shortcake() {
127
+ // ShortCake support if loaded.
128
+ if ( function_exists('shortcode_ui_register_for_shortcode') ) {
129
+ $se_list = wp_statistics_searchengine_list();
130
+
131
+ $se_options = array( '' => 'None' );
132
+
133
+ foreach ( $se_list as $se ) {
134
+ $se_options[ $se['tag'] ] = $se['translated'];
135
+ }
136
+
137
+ shortcode_ui_register_for_shortcode(
138
+ 'wpstatistics',
139
+ array(
140
+
141
+ // Display label. String. Required.
142
+ 'label' => 'WP Statistics',
143
+
144
+ // Icon/image for shortcode. Optional. src or dashicons-$icon. Defaults to carrot.
145
+ 'listItemImage' => '<img src="' .
146
+ WP_Statistics::$reg['plugin-url'] .
147
+ 'assets/images/logo-250.png" width="128" height="128">',
148
+
149
+ // Available shortcode attributes and default values. Required. Array.
150
+ // Attribute model expects 'attr', 'type' and 'label'
151
+ // Supported field types: text, checkbox, textarea, radio, select, email, url, number, and date.
152
+ 'attrs' => array(
153
+ array(
154
+ 'label' => __('Statistic', 'wp-statistics'),
155
+ 'attr' => 'stat',
156
+ 'type' => 'select',
157
+ 'description' => __('Select the statistic you wish to display.', 'wp-statistics'),
158
+ 'value' => 'usersonline',
159
+ 'options' => array(
160
+ 'usersonline' => __('Online Users', 'wp-statistics'),
161
+ 'visits' => __('Visits', 'wp-statistics'),
162
+ 'visitors' => __('Visitors', 'wp-statistics'),
163
+ 'pagevisits' => __('Page Visits', 'wp-statistics'),
164
+ 'searches' => __('Searches', 'wp-statistics'),
165
+ 'postcount' => __('Post Count', 'wp-statistics'),
166
+ 'pagecount' => __('Page Count', 'wp-statistics'),
167
+ 'commentcount' => __('Comment Count', 'wp-statistics'),
168
+ 'spamcount' => __('Spam Count', 'wp-statistics'),
169
+ 'usercount' => __('User Count', 'wp-statistics'),
170
+ 'postaverage' => __('Post Average', 'wp-statistics'),
171
+ 'commentaverage' => __('Comment Average', 'wp-statistics'),
172
+ 'useraverage' => __('User Average', 'wp-statistics'),
173
+ 'lpd' => __('Last Post Date', 'wp-statistics'),
174
+ ),
175
+ ),
176
+ array(
177
+ 'label' => __('Time Frame', 'wp-statistics'),
178
+ 'attr' => 'time',
179
+ 'type' => 'url',
180
+ 'description' => __(
181
+ 'The time frame to get the statistic for, strtotime() (http://php.net/manual/en/datetime.formats.php) will be used to calculate it. Use "total" to get all recorded dates.',
182
+ 'wp-statistics'
183
+ ),
184
+ 'meta' => array( 'size' => '10' ),
185
+ ),
186
+ array(
187
+ 'label' => __('Search Provider', 'wp-statistics'),
188
+ 'attr' => 'provider',
189
+ 'type' => 'select',
190
+ 'description' => __('The search provider to get statistics on.', 'wp-statistics'),
191
+ 'options' => $se_options,
192
+ ),
193
+ array(
194
+ 'label' => __('Number Format', 'wp-statistics'),
195
+ 'attr' => 'format',
196
+ 'type' => 'select',
197
+ 'description' => __(
198
+ 'The format to display numbers in: i18n, english, none.',
199
+ 'wp-statistics'
200
+ ),
201
+ 'value' => 'none',
202
+ 'options' => array(
203
+ 'none' => __('None', 'wp-statistics'),
204
+ 'english' => __('English', 'wp-statistics'),
205
+ 'i18n' => __('International', 'wp-statistics'),
206
+ ),
207
+ ),
208
+ array(
209
+ 'label' => __('Post/Page ID', 'wp-statistics'),
210
+ 'attr' => 'id',
211
+ 'type' => 'number',
212
+ 'description' => __('The post/page id to get page statistics on.', 'wp-statistics'),
213
+ 'meta' => array( 'size' => '5' ),
214
+ ),
215
+ ),
216
+ )
217
+ );
218
+ }
219
+
220
+ }
221
+ }
222
+ }
includes/classes/class-wp-statistics-uninstall.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace {
4
+
5
+ /**
6
+ * Class WP_Statistics_Uninstall
7
+ */
8
+ class WP_Statistics_Uninstall {
9
+
10
+ /**
11
+ * WP_Statistics_Uninstall constructor.
12
+ */
13
+ function __construct() {
14
+ if ( is_admin() ) {
15
+ global $wpdb, $WP_Statistics;
16
+
17
+ // Handle multi site implementations
18
+ if ( is_multisite() ) {
19
+
20
+ // Loop through each of the sites.
21
+ $sites = $WP_Statistics->get_wp_sites_list();
22
+ foreach ( $sites as $blog_id ) {
23
+ switch_to_blog($blog_id);
24
+ $this->wp_statistics_site_removal();
25
+ }
26
+ restore_current_blog();
27
+ } else {
28
+ $this->wp_statistics_site_removal();
29
+
30
+ }
31
+ // Make sure we don't try and remove the data more than once.
32
+ update_option('wp_statistics_removal', 'done');
33
+ }
34
+
35
+ }
36
+
37
+ /**
38
+ * Removes database options, user meta keys & tables
39
+ */
40
+ public function wp_statistics_site_removal() {
41
+ global $wpdb;
42
+
43
+ // Delete the options from the WordPress options table.
44
+ delete_option('wp_statistics');
45
+ delete_option('wp_statistics_db_version');
46
+ delete_option('wp_statistics_plugin_version');
47
+
48
+ // Delete the user options.
49
+ $wpdb->query("DELETE FROM {$wpdb->prefix}usermeta WHERE meta_key LIKE 'wp_statistics%'");
50
+
51
+ // Drop the tables
52
+ $wpdb->query(
53
+ "DROP TABLE IF EXISTS {$wpdb->prefix}statistics_useronline, {$wpdb->prefix}statistics_visit, {$wpdb->prefix}statistics_visitor, {$wpdb->prefix}statistics_exclusions, {$wpdb->prefix}statistics_pages, {$wpdb->prefix}statistics_historical"
54
+ );
55
+ }
56
+ }
57
+ }
includes/classes/class-wp-statistics-updates.php ADDED
@@ -0,0 +1,573 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace {
3
+
4
+ use phpbrowscap\Browscap;
5
+ use GeoIp2\Database\Reader;
6
+
7
+ /**
8
+ * Class WP_Statistics_Updates
9
+ */
10
+ class WP_Statistics_Updates {
11
+
12
+ /**
13
+ * This function downloads the GeoIP database from MaxMind.
14
+ *
15
+ * @return string
16
+ */
17
+ static function download_geoip() {
18
+
19
+ GLOBAL $WP_Statistics;
20
+
21
+ // We need the download_url() and gzopen() functions, it should exists on virtually all installs of PHP, but if it doesn't for some reason, bail out.
22
+ // Also stop trying to update the database as it just won't work :)
23
+ if ( false === function_exists('download_url') || false === function_exists('gzopen') ) {
24
+ $WP_Statistics->update_option('update_geoip', false);
25
+
26
+ $result = "<div class='updated settings-error'><p><strong>" .
27
+ __('Error the download_url() or gzopen() functions do not exist!', 'wp-statistics') .
28
+ "</strong></p></div>";
29
+
30
+ return $result;
31
+ }
32
+
33
+ // If GeoIP is disabled, bail out.
34
+ if ( $WP_Statistics->get_option('geoip') == false ) {
35
+ return '';
36
+ }
37
+
38
+ // This is the location of the file to download.
39
+ $download_url = 'http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.mmdb.gz';
40
+
41
+ // Get the upload directory from WordPRess.
42
+ $upload_dir = wp_upload_dir();
43
+
44
+ // Create a variable with the name of the database file to download.
45
+ $DBFile = $upload_dir['basedir'] . '/wp-statistics/GeoLite2-Country.mmdb';
46
+
47
+ // Check to see if the subdirectory we're going to upload to exists, if not create it.
48
+ if ( ! file_exists($upload_dir['basedir'] . '/wp-statistics') ) {
49
+ if ( ! @mkdir($upload_dir['basedir'] . '/wp-statistics', 0755) ) {
50
+ $WP_Statistics->update_option('update_geoip', false);
51
+
52
+ $result = "<div class='updated settings-error'><p><strong>" . sprintf(
53
+ __(
54
+ 'Error creating GeoIP database directory, make sure your web server has permissions to create directories in : %s',
55
+ 'wp-statistics'
56
+ ),
57
+ $upload_dir['basedir']
58
+ ) . "</strong></p></div>";
59
+
60
+ return $result;
61
+ }
62
+ }
63
+
64
+ if ( ! is_writable($upload_dir['basedir'] . '/wp-statistics') ) {
65
+ $WP_Statistics->update_option('update_geoip', false);
66
+
67
+ $result = "<div class='updated settings-error'><p><strong>" . sprintf(
68
+ __(
69
+ 'Error setting permissions of the GeoIP database directory, make sure your web server has permissions to write to directories in : %s',
70
+ 'wp-statistics'
71
+ ),
72
+ $upload_dir['basedir']
73
+ ) . "</strong></p></div>";
74
+
75
+ return $result;
76
+ }
77
+
78
+ // Download the file from MaxMind, this places it in a temporary location.
79
+ $TempFile = download_url($download_url);
80
+
81
+ // If we failed, through a message, otherwise proceed.
82
+ if ( is_wp_error($TempFile) ) {
83
+ $result = "<div class='updated settings-error'><p><strong>" . sprintf(
84
+ __('Error downloading GeoIP database from: %s - %s', 'wp-statistics'),
85
+ $download_url,
86
+ $TempFile->get_error_message()
87
+ ) . "</strong></p></div>";
88
+ } else {
89
+ // Open the downloaded file to unzip it.
90
+ $ZipHandle = gzopen($TempFile, 'rb');
91
+
92
+ // Create th new file to unzip to.
93
+ $DBfh = fopen($DBFile, 'wb');
94
+
95
+ // If we failed to open the downloaded file, through an error and remove the temporary file. Otherwise do the actual unzip.
96
+ if ( ! $ZipHandle ) {
97
+ $result = "<div class='updated settings-error'><p><strong>" . sprintf(
98
+ __('Error could not open downloaded GeoIP database for reading: %s', 'wp-statistics'),
99
+ $TempFile
100
+ ) . "</strong></p></div>";
101
+
102
+ unlink($TempFile);
103
+ } else {
104
+ // If we failed to open the new file, throw and error and remove the temporary file. Otherwise actually do the unzip.
105
+ if ( ! $DBfh ) {
106
+ $result = "<div class='updated settings-error'><p><strong>" . sprintf(
107
+ __('Error could not open destination GeoIP database for writing %s', 'wp-statistics'),
108
+ $DBFile
109
+ ) . "</strong></p></div>";
110
+ unlink($TempFile);
111
+ } else {
112
+ while ( ( $data = gzread($ZipHandle, 4096) ) != false ) {
113
+ fwrite($DBfh, $data);
114
+ }
115
+
116
+ // Close the files.
117
+ gzclose($ZipHandle);
118
+ fclose($DBfh);
119
+
120
+ // Delete the temporary file.
121
+ unlink($TempFile);
122
+
123
+ // Display the success message.
124
+ $result = "<div class='updated settings-error'><p><strong>" .
125
+ __('GeoIP Database updated successfully!', 'wp-statistics') .
126
+ "</strong></p></div>";
127
+
128
+ // Update the options to reflect the new download.
129
+ $WP_Statistics->update_option('last_geoip_dl', time());
130
+ $WP_Statistics->update_option('update_geoip', false);
131
+
132
+ // Populate any missing GeoIP information if the user has selected the option.
133
+ if ( $WP_Statistics->get_option('geoip') &&
134
+ wp_statistics_geoip_supported() &&
135
+ $WP_Statistics->get_option('auto_pop')
136
+ ) {
137
+ $result .= \WP_Statistics_Updates::populate_geoip_info();
138
+ }
139
+ }
140
+ }
141
+ }
142
+
143
+ if ( $WP_Statistics->get_option('geoip_report') == true ) {
144
+ $blogname = get_bloginfo('name');
145
+ $blogemail = get_bloginfo('admin_email');
146
+
147
+ $headers[] = "From: $blogname <$blogemail>";
148
+ $headers[] = "MIME-Version: 1.0";
149
+ $headers[] = "Content-type: text/html; charset=utf-8";
150
+
151
+ if ( $WP_Statistics->get_option('email_list') == '' ) {
152
+ $WP_Statistics->update_option('email_list', $blogemail);
153
+ }
154
+
155
+ wp_mail(
156
+ $WP_Statistics->get_option('email_list'),
157
+ __('GeoIP update on', 'wp-statistics') . ' ' . $blogname,
158
+ $result,
159
+ $headers
160
+ );
161
+ }
162
+
163
+ // All of the messages displayed above are stored in a stirng, now it's time to actually output the messages.
164
+ return $result;
165
+ }
166
+
167
+ /**
168
+ * This function downloads the browscap database from browscap.org.
169
+ *
170
+ * @return string
171
+ * @throws \phpbrowscap\Exception
172
+ */
173
+ static function download_browscap() {
174
+
175
+ GLOBAL $WP_Statistics;
176
+
177
+ // We need the download_url() function, it should exists on virtually all installs of PHP, but if it doesn't for some reason, bail out.
178
+ if ( ! function_exists('download_url') ) {
179
+ return '';
180
+ }
181
+
182
+ // If browscap is disabled, bail out.
183
+ if ( $WP_Statistics->get_option('browscap') == false ) {
184
+ return '';
185
+ }
186
+
187
+ // This is the location of the file to download.
188
+ $download_url = 'http://browscap.org/stream?q=Full_PHP_BrowsCapINI';
189
+ $download_version = 'http://browscap.org/version-number';
190
+
191
+ // Get the upload directory from WordPress.
192
+ $upload_dir = wp_upload_dir();
193
+
194
+ // Check to see if the subdirectory we're going to upload to exists, if not create it.
195
+ if ( ! file_exists($upload_dir['basedir'] . '/wp-statistics') ) {
196
+ mkdir($upload_dir['basedir'] . '/wp-statistics');
197
+ }
198
+
199
+ $LocalVersion = 0;
200
+
201
+ // Get the Browscap object, tell it NOT to autoupdate.
202
+ $bc = new Browscap($upload_dir['basedir'] . '/wp-statistics');
203
+ $bc->doAutoUpdate = false; // We don't want to auto update.
204
+
205
+ // If we already have a browscap.ini file (aka we're already done a download in the past) we can get it's version number.
206
+ // We can't execute this code if no browscap.ini exists as then the library will automatically download a full version, even
207
+ // though we've told it not to autoupdate above.
208
+ if ( $WP_Statistics->get_option('last_browscap_dl') > 1 ) {
209
+ // Get the current browser so that the version information is populated.
210
+ try {
211
+ $bc->getBrowser();
212
+ $LocalVersion = $bc->getSourceVersion();
213
+ } catch ( Exception $e ) {
214
+ $crawler = false;
215
+ $LocalVersion = 0;
216
+ }
217
+
218
+ }
219
+
220
+ // Get the remote version info from browscap.org.
221
+ $TempVersionFile = download_url($download_version);
222
+
223
+ // Read the version we just downloaded in to a string.
224
+ $RemoteVersion = file_get_contents($TempVersionFile);
225
+
226
+ // Get rid of the temporary file.
227
+ unlink($TempVersionFile);
228
+
229
+ // If there is a new version, let's go get it.
230
+ if ( intval($RemoteVersion) > $LocalVersion ) {
231
+
232
+ // Download the file from browscap.org, this places it in a temporary location.
233
+ $TempFile = download_url($download_url);
234
+
235
+ // If we failed, through a message, otherwise proceed.
236
+ if ( is_wp_error($TempFile) ) {
237
+ $result = "<div class='updated settings-error'><p><strong>" . sprintf(
238
+ __('Error downloading browscap database from: %s - %s', 'wp-statistics'),
239
+ $download_url,
240
+ $TempFile->get_error_message()
241
+ ) . "</strong></p></div>";
242
+ } else {
243
+ // Keep the current version just in case by renaming it.
244
+ if ( file_exists($upload_dir['basedir'] . '/wp-statistics/browscap.old') ) {
245
+ unlink($upload_dir['basedir'] . '/wp-statistics/browscap.old');
246
+ }
247
+ if ( file_exists($upload_dir['basedir'] . '/wp-statistics/cache.old') ) {
248
+ unlink($upload_dir['basedir'] . '/wp-statistics/cache.old');
249
+ }
250
+ if ( file_exists($upload_dir['basedir'] . '/wp-statistics/browscap.ini') ) {
251
+ rename(
252
+ $upload_dir['basedir'] . '/wp-statistics/browscap.ini',
253
+ $upload_dir['basedir'] . '/wp-statistics/browscap.old'
254
+ );
255
+ }
256
+ if ( file_exists($upload_dir['basedir'] . '/wp-statistics/cache.php') ) {
257
+ rename(
258
+ $upload_dir['basedir'] . '/wp-statistics/cache.php',
259
+ $upload_dir['basedir'] . '/wp-statistics/cache.old'
260
+ );
261
+ }
262
+
263
+ // Setup our file handles.
264
+ $infile = fopen($TempFile, 'r');
265
+ $outfile = fopen($upload_dir['basedir'] . '/wp-statistics/browscap.ini', 'w');
266
+
267
+ // We're going to need some variables to use as we process the new browscap.ini.
268
+ // $crawler has three possible settings:
269
+ // 0 = no setting found
270
+ // 1 = setting found but not a crawler
271
+ // 2 = setting found and a crawler
272
+ $parent = '';
273
+ $title = '';
274
+ $crawler = 0;
275
+ $parents = array( '' => false );
276
+
277
+ // Now read in the browscap.ini file we downloaded one line at a time.
278
+ while ( ( $buffer = fgets($infile) ) !== false ) {
279
+ // Let's get rid of the tailing carriage return extra spaces.
280
+ $buffer = trim($buffer);
281
+
282
+ // We're going to do some things based on the first charater on the line so let's just get it once.
283
+ $firstchar = substr($buffer, 0, 1);
284
+
285
+ // The first character will tell us what kind of line we're dealing with.
286
+ switch ( $firstchar ) {
287
+ // A square bracket means it's a section title.
288
+ case '[':
289
+
290
+ // We have three sections we need to copy verbatium so don't do the standard processing for them.
291
+ if ( $title != 'GJK_Browscap_Version' &&
292
+ $title != 'DefaultProperties' &&
293
+ $title != '*' &&
294
+ $title != ''
295
+ ) {
296
+ // Write out the section if:
297
+ // the current section is a crawler and there is no parent
298
+ // OR
299
+ // the current section is a crawler, has a parent and the parent is a crawler as well
300
+ // (Note, this will drop some crawlers who's parent's aren't because we haven't written
301
+ // out all the parent's that aren't crawlers this could cause mis-identificaton of
302
+ // some users as crawlers).
303
+ // OR
304
+ // the current section isn't a crawler but the parent is
305
+ //
306
+ if ( ( $crawler == 2 && $parent == '' ) ||
307
+ ( $crawler == 2 && $parent != '' && array_key_exists($parent, $parents) ) ||
308
+ ( $crawler == 0 && array_key_exists($parent, $parents) )
309
+ ) {
310
+ // Write out the section with just the parent/crawler setting saved.
311
+ fwrite($outfile, "[" . $title . "]\n");
312
+ fwrite($outfile, "Crawler=\"true\"\n");
313
+ }
314
+ }
315
+
316
+ // Reset our variables.
317
+ $crawler = 0;
318
+ $parent = '';
319
+ $title = substr($buffer, 1, strlen($buffer) - 2);
320
+
321
+ // We have three sections we need to copy verbatium so write out their
322
+ // headings immediatly instead of waiting to see if they are a crawler.
323
+ if ( $title == 'GJK_Browscap_Version' ||
324
+ $title == 'DefaultProperties' ||
325
+ $title == "*"
326
+ ) {
327
+ fwrite($outfile, "[" . $title . "]\n");
328
+ }
329
+
330
+ break;
331
+ // A space or semi-colan means it's a comment.
332
+ case ' ':
333
+ case ';':
334
+ // Since we're hacking out lots of data the only comments we want to keep
335
+ // are the first few in the file before the first section is processed.
336
+ if ( $title == '' ) {
337
+ fwrite($outfile, $buffer . "\n");
338
+ }
339
+
340
+ break;
341
+ // Otherwise its a real setting line.
342
+ default:
343
+ // If the setting is for the crawler let's inidicate we found it and it's true.
344
+ // We can also set the parents array.
345
+ if ( $buffer == 'Crawler="true"' ) {
346
+ $crawler = 2;
347
+ $parents[ $title ] = true;
348
+ }
349
+
350
+ // If the setting for the parent then set it now.
351
+ if ( substr($buffer, 0, 7) == 'Parent=' ) {
352
+ $parent = substr($buffer, 8, -1);
353
+ }
354
+
355
+ // We have three sections we need to copy verbatium so write out their settings.
356
+ if ( $title == 'GJK_Browscap_Version' ||
357
+ $title == 'DefaultProperties' ||
358
+ $title == "*"
359
+ ) {
360
+ fwrite($outfile, $buffer . "\n");
361
+ }
362
+ }
363
+ }
364
+
365
+ // Close the files.
366
+ fclose($outfile);
367
+ fclose($infile);
368
+
369
+ // Delete the temporary file.
370
+ unlink($TempFile);
371
+
372
+ // Check to see if an old (more than a minute old) lock file exists, if so delete it.
373
+ $cache_lock = $upload_dir['basedir'] . '/wp-statistics/cache.lock';
374
+ if ( file_exists($cache_lock) ) {
375
+ if ( time() - filemtime($cache_lock) > 60 ) {
376
+ unlink($cache_lock);
377
+ }
378
+ }
379
+
380
+ // Force the cache to be updated.
381
+ $bc->updateCache();
382
+
383
+ // Update the options to reflect the new download.
384
+ $WP_Statistics->update_option('last_browscap_dl', time());
385
+ $WP_Statistics->update_option('update_browscap', false);
386
+
387
+ $result = "<div class='updated settings-error'><p><strong>" .
388
+ __('browscap database updated successfully!', 'wp-statistics') .
389
+ "</strong></p></div>";
390
+
391
+ // Do some sanity checks on the new ini/cache file
392
+ $ini_fs = filesize($upload_dir['basedir'] . '/wp-statistics/browscap.ini');
393
+ $cache_fs = filesize($upload_dir['basedir'] . '/wp-statistics/cache.php');
394
+ $fail = false;
395
+
396
+ // Check to make sure the cache file isn't any more than 15% larger than then ini file
397
+ if ( $cache_fs - $ini_fs > $ini_fs * 0.15 ) {
398
+ $fail = true;
399
+ $result = "<div class='updated settings-error'><p><strong>" . __(
400
+ 'browscap database updated failed! Cache file too large, reverting to previous browscap.ini.',
401
+ 'wp-statistics'
402
+ ) . "</strong></p></div>";
403
+ } else {
404
+ // Check to make sure we don't resolve a typical user agent as a robot.
405
+ $test_browser = $bc->getBrowser(
406
+ "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:33.0) Gecko/20100101 Firefox/33.0"
407
+ );
408
+ $crawler = $test_browser->Crawler;
409
+
410
+ if ( $crawler == true ) {
411
+ $fail = true;
412
+ $result = "<div class='updated settings-error'><p><strong>" . __(
413
+ 'browscap database updated failed! New browscap.ini is mis-identifing user agents as crawlers, reverting to previous browscap.ini.',
414
+ 'wp-statistics'
415
+ ) . "</strong></p></div>";
416
+ }
417
+ }
418
+
419
+ // If we failed, roll back the update, otherwise just delete the old files.
420
+ if ( $fail == true ) {
421
+ if ( file_exists($upload_dir['basedir'] . '/wp-statistics/browscap.ini') ) {
422
+ unlink($upload_dir['basedir'] . '/wp-statistics/browscap.ini');
423
+ }
424
+ if ( file_exists($upload_dir['basedir'] . '/wp-statistics/cache.php') ) {
425
+ unlink($upload_dir['basedir'] . '/wp-statistics/cache.php');
426
+ }
427
+ if ( file_exists($upload_dir['basedir'] . '/wp-statistics/browscap.old') ) {
428
+ rename(
429
+ $upload_dir['basedir'] . '/wp-statistics/browscap.old',
430
+ $upload_dir['basedir'] . '/wp-statistics/browscap.ini'
431
+ );
432
+ }
433
+ if ( file_exists($upload_dir['basedir'] . '/wp-statistics/cache.old') ) {
434
+ rename(
435
+ $upload_dir['basedir'] . '/wp-statistics/cache.old',
436
+ $upload_dir['basedir'] . '/wp-statistics/cache.php'
437
+ );
438
+ }
439
+ } else {
440
+ if ( file_exists($upload_dir['basedir'] . '/wp-statistics/browscap.old') ) {
441
+ unlink($upload_dir['basedir'] . '/wp-statistics/browscap.old');
442
+ }
443
+ if ( file_exists($upload_dir['basedir'] . '/wp-statistics/cache.old') ) {
444
+ unlink($upload_dir['basedir'] . '/wp-statistics/cache.old');
445
+ }
446
+ }
447
+ }
448
+ } else {
449
+ // Update the options to reflect the new download.
450
+ $WP_Statistics->update_option('last_browscap_dl', time());
451
+ $WP_Statistics->update_option('update_browscap', false);
452
+
453
+ $result = "<div class='updated settings-error'><p><strong>" .
454
+ __('browscap already at current version!', 'wp-statistics') .
455
+ "</strong></p></div>";
456
+ }
457
+
458
+ if ( $WP_Statistics->get_option('browscap_report') == true ) {
459
+ $blogname = get_bloginfo('name');
460
+ $blogemail = get_bloginfo('admin_email');
461
+
462
+ $headers[] = "From: $blogname <$blogemail>";
463
+ $headers[] = "MIME-Version: 1.0";
464
+ $headers[] = "Content-type: text/html; charset=utf-8";
465
+
466
+ if ( $WP_Statistics->get_option('email_list') == '' ) {
467
+ $WP_Statistics->update_option('email_list', $blogemail);
468
+ }
469
+
470
+ wp_mail(
471
+ $WP_Statistics->get_option('email_list'),
472
+ __('Browscap.ini update on', 'wp-statistics') . ' ' . $blogname,
473
+ $result,
474
+ $headers
475
+ );
476
+ }
477
+
478
+ // All of the messages displayed above are stored in a stirng, now it's time to actually output the messages.
479
+ return $result;
480
+ }
481
+
482
+ /**
483
+ * Downloads the referrerspam database from https://github.com/piwik/referrer-spam-blacklist.
484
+ *
485
+ * @return string
486
+ */
487
+ static function download_referrerspam() {
488
+
489
+ GLOBAL $WP_Statistics;
490
+
491
+ // If referrerspam is disabled, bail out.
492
+ if ( $WP_Statistics->get_option('referrerspam') == false ) {
493
+ return '';
494
+ }
495
+
496
+ // This is the location of the file to download.
497
+ $download_url = 'https://raw.githubusercontent.com/piwik/referrer-spam-blacklist/master/spammers.txt';
498
+
499
+ // Download the file from MaxMind, this places it in a temporary location.
500
+ $referrerspamlist = file_get_contents($download_url);
501
+ if ( $referrerspamlist === false ) {
502
+ $referrerspamlist = '';
503
+ }
504
+
505
+ if ( $referrerspamlist != '' || $WP_Statistics->get_option('referrerspamlist') != '' ) {
506
+ $WP_Statistics->update_option('referrerspamlist', $referrerspamlist);
507
+ }
508
+
509
+ $WP_Statistics->update_option('update_referrerspam', false);
510
+
511
+ return;
512
+ }
513
+
514
+ /**
515
+ * Populate GeoIP infomration in to the database.
516
+ * It is used in two different parts of the plugin;
517
+ * When a user manual requests the update to happen and after a new GeoIP database has been download
518
+ * (if the option is selected).
519
+ *
520
+ * @return string
521
+ */
522
+ static function populate_geoip_info() {
523
+ global $wpdb;
524
+
525
+ // Find all rows in the table that currently don't have GeoIP info or have an unknown ('000') location.
526
+ $result = $wpdb->get_results(
527
+ "SELECT id,ip FROM `{$wpdb->prefix}statistics_visitor` WHERE location = '' or location = '000' or location IS NULL"
528
+ );
529
+
530
+ // Try create a new reader instance.
531
+ try {
532
+ $upload_dir = wp_upload_dir();
533
+ $reader = new Reader($upload_dir['basedir'] . '/wp-statistics/GeoLite2-Country.mmdb');
534
+ } catch ( Exception $e ) {
535
+ return "<div class='updated settings-error'><p><strong>" . __(
536
+ 'Unable to load the GeoIP database, make sure you have downloaded it in the settings page.',
537
+ 'wp-statistics'
538
+ ) . "</strong></p></div>";
539
+ }
540
+
541
+ $count = 0;
542
+
543
+ // Loop through all the missing rows and update them if we find a locaiton for them.
544
+ foreach ( $result as $item ) {
545
+ $count++;
546
+
547
+ // If the IP address is only a hash, don't bother updating the record.
548
+ if ( substr($item->ip, 0, 6) != '#hash#' ) {
549
+ try {
550
+ $record = $reader->country($item->ip);
551
+ $location = $record->country->isoCode;
552
+ if ( $location == "" ) {
553
+ $location = "000";
554
+ }
555
+ } catch ( Exception $e ) {
556
+ $location = "000";
557
+ }
558
+
559
+ // Update the row in the database.
560
+ $wpdb->update(
561
+ $wpdb->prefix . "statistics_visitor",
562
+ array( 'location' => $location ),
563
+ array( 'id' => $item->id )
564
+ );
565
+ }
566
+ }
567
+
568
+ return "<div class='updated settings-error'><p><strong>" .
569
+ sprintf(__('Updated %s GeoIP records in the visitors database.', 'wp-statistics'), $count) .
570
+ "</strong></p></div>";
571
+ }
572
+ }
573
+ }
includes/classes/class-wp-statistics-widget.php ADDED
@@ -0,0 +1,437 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WP_Statistics_Widget extends WP_Widget {
4
+
5
+ /**
6
+ * Sets up the widgets name etc
7
+ */
8
+ public function __construct() {
9
+ parent::__construct(
10
+ 'WP_Statistics_Widget', // Base ID
11
+ __('Statistics', 'wp-statistics'), // Name
12
+ array( 'description' => __('Show site stats in sidebar.', 'wp-statistics') ) // Args
13
+ );
14
+ }
15
+
16
+ /**
17
+ * Outputs the content of the widget
18
+ *
19
+ * @param array $args
20
+ * @param array $instance
21
+ */
22
+ public function widget( $args, $instance ) {
23
+ global $WP_Statistics;
24
+ extract($args);
25
+ $widget_options = $WP_Statistics->get_option('widget');
26
+
27
+ echo $before_widget;
28
+ echo $before_title . $widget_options['name_widget'] . $after_title;
29
+ echo '<ul>';
30
+
31
+ if ( $widget_options['useronline_widget'] ) {
32
+ echo '<li>';
33
+ echo '<label>' . __('Online Users', 'wp-statistics') . ': </label>';
34
+ echo number_format_i18n(wp_statistics_useronline());
35
+ echo '</li>';
36
+ }
37
+
38
+ if ( $widget_options['tvisit_widget'] ) {
39
+ echo '<li>';
40
+ echo '<label>' . __('Today\'s Visits', 'wp-statistics') . ': </label>';
41
+ echo number_format_i18n(wp_statistics_visit('today'));
42
+ echo '</li>';
43
+ }
44
+
45
+ if ( $widget_options['tvisitor_widget'] ) {
46
+ echo '<li>';
47
+ echo '<label>' . __('Today\'s Visitors', 'wp-statistics') . ': </label>';
48
+ echo number_format_i18n(wp_statistics_visitor('today', null, true));
49
+ echo '</li>';
50
+ }
51
+
52
+ if ( $widget_options['yvisit_widget'] ) {
53
+ echo '<li>';
54
+ echo '<label>' . __('Yesterday\'s Visits', 'wp-statistics') . ': </label>';
55
+ echo number_format_i18n(wp_statistics_visit('yesterday'));
56
+ echo '</li>';
57
+ }
58
+
59
+ if ( $widget_options['yvisitor_widget'] ) {
60
+ echo '<li>';
61
+ echo '<label>' . __('Yesterday\'s Visitors', 'wp-statistics') . ': </label>';
62
+ echo number_format_i18n(wp_statistics_visitor('yesterday', null, true));
63
+ echo '</li>';
64
+ }
65
+
66
+ if ( $widget_options['wvisit_widget'] ) {
67
+ echo '<li>';
68
+ echo '<label>' . __('Last 7 Days Visits', 'wp-statistics') . ': </label>';
69
+ echo number_format_i18n(wp_statistics_visit('week'));
70
+ echo '</li>';
71
+ }
72
+
73
+ if ( $widget_options['mvisit_widget'] ) {
74
+ echo '<li>';
75
+ echo '<label>' . __('Last 30 Days Visits', 'wp-statistics') . ': </label>';
76
+ echo number_format_i18n(wp_statistics_visit('month'));
77
+ echo '</li>';
78
+ }
79
+
80
+ if ( $widget_options['ysvisit_widget'] ) {
81
+ echo '<li>';
82
+ echo '<label>' . __('Last 365 Days Visits', 'wp-statistics') . ': </label>';
83
+ echo number_format_i18n(wp_statistics_visit('year'));
84
+ echo '</li>';
85
+ }
86
+
87
+ if ( $widget_options['ttvisit_widget'] ) {
88
+ echo '<li>';
89
+ echo '<label>' . __('Total Visits', 'wp-statistics') . ': </label>';
90
+ echo number_format_i18n(wp_statistics_visit('total'));
91
+ echo '</li>';
92
+ }
93
+
94
+ if ( $widget_options['ttvisitor_widget'] ) {
95
+ echo '<li>';
96
+ echo '<label>' . __('Total Visitors', 'wp-statistics') . ': </label>';
97
+ echo number_format_i18n(wp_statistics_visitor('total', null, true));
98
+ echo '</li>';
99
+ }
100
+
101
+ if ( $widget_options['tpviews_widget'] ) {
102
+ echo '<li>';
103
+ echo '<label>' . __('Total Page Views', 'wp-statistics') . ': </label>';
104
+ echo number_format_i18n(wp_statistics_pages('total'));
105
+ echo '</li>';
106
+ }
107
+
108
+ if ( $widget_options['ser_widget'] ) {
109
+
110
+ echo '<li>';
111
+ echo '<label>' . __('Search Engine Referrals', 'wp-statistics') . ': </label>';
112
+ echo number_format_i18n(wp_statistics_searchengine($widget_options['select_se']));
113
+ echo '</li>';
114
+ }
115
+
116
+ if ( $widget_options['tp_widget'] ) {
117
+ echo '<li>';
118
+ echo '<label>' . __('Total Posts', 'wp-statistics') . ': </label>';
119
+ echo number_format_i18n(wp_statistics_countposts());
120
+ echo '</li>';
121
+ }
122
+
123
+ if ( $widget_options['tpg_widget'] ) {
124
+ echo '<li>';
125
+ echo '<label>' . __('Total Pages', 'wp-statistics') . ': </label>';
126
+ echo number_format_i18n(wp_statistics_countpages());
127
+ echo '</li>';
128
+ }
129
+
130
+ if ( $widget_options['tc_widget'] ) {
131
+ echo '<li>';
132
+ echo '<label>' . __('Total Comments', 'wp-statistics') . ': </label>';
133
+ echo number_format_i18n(wp_statistics_countcomment());
134
+ echo '</li>';
135
+ }
136
+
137
+ if ( $widget_options['ts_widget'] ) {
138
+ echo '<li>';
139
+ echo '<label>' . __('Total Spams', 'wp-statistics') . ': </label>';
140
+ echo wp_statistics_countspam();
141
+ echo '</li>';
142
+ }
143
+
144
+ if ( $widget_options['tu_widget'] ) {
145
+ echo '<li>';
146
+ echo '<label>' . __('Total Users', 'wp-statistics') . ': </label>';
147
+ echo number_format_i18n(wp_statistics_countusers());
148
+ echo '</li>';
149
+ }
150
+
151
+ if ( $widget_options['ap_widget'] ) {
152
+ echo '<li>';
153
+ echo '<label>' . __('Average Posts', 'wp-statistics') . ': </label>';
154
+ echo number_format_i18n(wp_statistics_average_post());
155
+ echo '</li>';
156
+ }
157
+
158
+ if ( $widget_options['ac_widget'] ) {
159
+ echo '<li>';
160
+ echo '<label>' . __('Average Comments', 'wp-statistics') . ': </label>';
161
+ echo number_format_i18n(wp_statistics_average_comment());
162
+ echo '</li>';
163
+ }
164
+
165
+ if ( $widget_options['au_widget'] ) {
166
+ echo '<li>';
167
+ echo '<label>' . __('Average Users', 'wp-statistics') . ': </label>';
168
+ echo number_format_i18n(wp_statistics_average_registeruser());
169
+ echo '</li>';
170
+ }
171
+
172
+ if ( $widget_options['lpd_widget'] ) {
173
+ echo '<li>';
174
+ echo '<label>' . __('Last Post Date', 'wp-statistics') . ': </label>';
175
+ echo wp_statistics_lastpostdate();
176
+ echo '</li>';
177
+ }
178
+
179
+ echo '</ul>';
180
+ echo $after_widget;
181
+ }
182
+
183
+ /**
184
+ * Processing widget options on save
185
+ *
186
+ * @param array $new_instance The new options
187
+ * @param array $old_instance The previous options
188
+ *
189
+ * @return array
190
+ */
191
+ public function update( $new_instance, $old_instance ) {
192
+ GLOBAL $WP_Statistics;
193
+
194
+ if ( array_key_exists('wp_statistics_control_widget_submit', $_POST) ) {
195
+ $keys = array(
196
+ 'name_widget' => 'name_widget',
197
+ 'useronline_widget' => 'useronline_widget',
198
+ 'tvisit_widget' => 'tvisit_widget',
199
+ 'tvisitor_widget' => 'tvisitor_widget',
200
+ 'yvisit_widget' => 'yvisit_widget',
201
+ 'yvisitor_widget' => 'yvisitor_widget',
202
+ 'wvisit_widget' => 'wvisit_widget',
203
+ 'mvisit_widget' => 'mvisit_widget',
204
+ 'ysvisit_widget' => 'ysvisit_widget',
205
+ 'ttvisit_widget' => 'ttvisit_widget',
206
+ 'ttvisitor_widget' => 'ttvisitor_widget',
207
+ 'tpviews_widget' => 'tpviews_widget',
208
+ 'ser_widget' => 'ser_widget',
209
+ 'select_se' => 'select_se',
210
+ 'tp_widget' => 'tp_widget',
211
+ 'tpg_widget' => 'tpg_widget',
212
+ 'tc_widget' => 'tc_widget',
213
+ 'ts_widget' => 'ts_widget',
214
+ 'tu_widget' => 'tu_widget',
215
+ 'ap_widget' => 'ap_widget',
216
+ 'ac_widget' => 'ac_widget',
217
+ 'au_widget' => 'au_widget',
218
+ 'lpd_widget' => 'lpd_widget',
219
+ 'select_lps' => 'select_lps',
220
+ );
221
+
222
+ foreach ( $keys as $key => $post ) {
223
+ if ( array_key_exists($post, $_POST) ) {
224
+ $widget_options[ $key ] = $_POST[ $post ];
225
+ } else {
226
+ $widget_options[ $key ] = '';
227
+ }
228
+ }
229
+
230
+ $WP_Statistics->update_option('widget', $widget_options);
231
+ }
232
+
233
+ return array();
234
+ }
235
+
236
+ /**
237
+ * Outputs the options form on admin
238
+ *
239
+ * @param array $instance The widget options
240
+ *
241
+ * @return string|void
242
+ */
243
+ public function form( $instance ) {
244
+ GLOBAL $WP_Statistics;
245
+
246
+ $widget_options = $WP_Statistics->get_option('widget');
247
+
248
+ ?>
249
+ <p>
250
+ <label for="name_widget"><?php _e('Name', 'wp-statistics'); ?>:
251
+ <input id="name_widget" name="name_widget" type="text"
252
+ value="<?php echo $widget_options['name_widget']; ?>"/>
253
+ </label>
254
+ </p>
255
+
256
+ <?php _e('Items', 'wp-statistics'); ?>:<br/>
257
+ <ul>
258
+ <li>
259
+ <input type="checkbox" id="useronline_widget" name="useronline_widget" <?php checked(
260
+ 'on',
261
+ $widget_options['useronline_widget']
262
+ ); ?>/>
263
+ <label for="useronline_widget"><?php _e('Online Users', 'wp-statistics'); ?></label>
264
+ </li>
265
+ <li>
266
+ <input type="checkbox" id="tvisit_widget" name="tvisit_widget" <?php checked(
267
+ 'on',
268
+ $widget_options['tvisit_widget']
269
+ ); ?>/>
270
+ <label for="tvisit_widget"><?php _e('Today\'s Visits', 'wp-statistics'); ?></label>
271
+ </li>
272
+ <li>
273
+ <input type="checkbox" id="tvisitor_widget" name="tvisitor_widget" <?php checked(
274
+ 'on',
275
+ $widget_options['tvisitor_widget']
276
+ ); ?>/>
277
+ <label for="tvisitor_widget"><?php _e('Today\'s Visitors', 'wp-statistics'); ?></label>
278
+ </li>
279
+ <li>
280
+ <input type="checkbox" id="yvisit_widget" name="yvisit_widget" <?php checked(
281
+ 'on',
282
+ $widget_options['yvisit_widget']
283
+ ); ?>/>
284
+ <label for="yvisit_widget"><?php _e('Yesterday\'s Visits', 'wp-statistics'); ?></label>
285
+ </li>
286
+ <li>
287
+ <input type="checkbox" id="yvisitor_widget" name="yvisitor_widget" <?php checked(
288
+ 'on',
289
+ $widget_options['yvisitor_widget']
290
+ ); ?>/>
291
+ <label for="yvisitor_widget"><?php _e('Yesterday\'s Visitors', 'wp-statistics'); ?></label>
292
+ </li>
293
+ <li>
294
+ <input type="checkbox" id="wvisit_widget" name="wvisit_widget" <?php checked(
295
+ 'on',
296
+ $widget_options['wvisit_widget']
297
+ ); ?>/>
298
+ <label for="wvisit_widget"><?php _e('Last 7 Days Visits', 'wp-statistics'); ?></label>
299
+ </li>
300
+ <li>
301
+ <input type="checkbox" id="mvisit_widget" name="mvisit_widget" <?php checked(
302
+ 'on',
303
+ $widget_options['mvisit_widget']
304
+ ); ?>/>
305
+ <label for="mvisit_widget"><?php _e('Last 30 Days Visits', 'wp-statistics'); ?></label>
306
+ </li>
307
+ <li>
308
+ <input type="checkbox" id="ysvisit_widget" name="ysvisit_widget" <?php checked(
309
+ 'on',
310
+ $widget_options['ysvisit_widget']
311
+ ); ?>/>
312
+ <label for="ysvisit_widget"><?php _e('Last 365 Days Visits', 'wp-statistics'); ?></label>
313
+ </li>
314
+ <li>
315
+ <input type="checkbox" id="ttvisit_widget" name="ttvisit_widget" <?php checked(
316
+ 'on',
317
+ $widget_options['ttvisit_widget']
318
+ ); ?>/>
319
+ <label for="ttvisit_widget"><?php _e('Total Visits', 'wp-statistics'); ?></label>
320
+ </li>
321
+ <li>
322
+ <input type="checkbox" id="ttvisitor_widget" name="ttvisitor_widget" <?php checked(
323
+ 'on',
324
+ $widget_options['ttvisitor_widget']
325
+ ); ?>/>
326
+ <label for="ttvisitor_widget"><?php _e('Total Visitors', 'wp-statistics'); ?></label>
327
+ </li>
328
+ <li>
329
+ <input type="checkbox" id="tpviews_widget" name="tpviews_widget" <?php checked(
330
+ 'on',
331
+ $widget_options['tpviews_widget']
332
+ ); ?>/>
333
+ <label for="tpviews_widget"><?php _e('Total Page Views', 'wp-statistics'); ?></label>
334
+ </li>
335
+ <li>
336
+ <input type="checkbox" id="ser_widget" class="ser_widget" name="ser_widget" <?php checked(
337
+ 'on',
338
+ $widget_options['ser_widget']
339
+ ); ?>/>
340
+ <label for="ser_widget"><?php _e('Search Engine Referrals', 'wp-statistics'); ?></label>
341
+
342
+ <p id="ser_option" style="<?php if ( ! $widget_options['ser_widget'] ) {
343
+ echo "display: none;";
344
+ } ?>">
345
+ <?php _e('Select type of search engine', 'wp-statistics'); ?>:<br/>
346
+ <?php
347
+ $search_engines = wp_statistics_searchengine_list();
348
+
349
+ foreach ( $search_engines as $se ) {
350
+ echo ' <input type="radio" id="select_' .
351
+ $se['tag'] .
352
+ '" name="select_se" value="' .
353
+ $se['tag'] .
354
+ '" ';
355
+ checked($se['tag'], $widget_options['select_se']);
356
+ echo "/>\n";
357
+ echo ' <label for="' . $se['name'] . '">' . $se['translated'] . "</label>\n";
358
+ echo "\n";
359
+ }
360
+ ?>
361
+ <input type="radio" id="select_all" name="select_se" value="all" <?php checked(
362
+ 'all',
363
+ $widget_options['select_se']
364
+ ); ?>/>
365
+ <label for="select_all"><?php _e('All', 'wp-statistics'); ?></label>
366
+ </p>
367
+ </li>
368
+ <li>
369
+ <input type="checkbox" id="tp_widget" name="tp_widget" <?php checked(
370
+ 'on',
371
+ $widget_options['tp_widget']
372
+ ); ?>/>
373
+ <label for="tp_widget"><?php _e('Total Posts', 'wp-statistics'); ?></label>
374
+ </li>
375
+ <li>
376
+ <input type="checkbox" id="tpg_widget" name="tpg_widget" <?php checked(
377
+ 'on',
378
+ $widget_options['tpg_widget']
379
+ ); ?>/>
380
+ <label for="tpg_widget"><?php _e('Total Pages', 'wp-statistics'); ?></label>
381
+ </li>
382
+ <li>
383
+ <input type="checkbox" id="tc_widget" name="tc_widget" <?php checked(
384
+ 'on',
385
+ $widget_options['tc_widget']
386
+ ); ?>/>
387
+ <label for="tc_widget"><?php _e('Total Comments', 'wp-statistics'); ?></label>
388
+ </li>
389
+ <li>
390
+ <input type="checkbox" id="ts_widget" name="ts_widget" <?php checked(
391
+ 'on',
392
+ $widget_options['ts_widget']
393
+ ); ?>/>
394
+ <label for="ts_widget"><?php _e('Total Spams', 'wp-statistics'); ?></label>
395
+ </li>
396
+ <li>
397
+ <input type="checkbox" id="tu_widget" name="tu_widget" <?php checked(
398
+ 'on',
399
+ $widget_options['tu_widget']
400
+ ); ?>/>
401
+ <label for="tu_widget"><?php _e('Total Users', 'wp-statistics'); ?></label>
402
+ </li>
403
+ <li>
404
+ <input type="checkbox" id="ap_widget" name="ap_widget" <?php checked(
405
+ 'on',
406
+ $widget_options['ap_widget']
407
+ ); ?>/>
408
+ <label for="ap_widget"><?php _e('Average Posts', 'wp-statistics'); ?></label>
409
+ </li>
410
+ <li>
411
+ <input type="checkbox" id="ac_widget" name="ac_widget" <?php checked(
412
+ 'on',
413
+ $widget_options['ac_widget']
414
+ ); ?>/>
415
+ <label for="ac_widget"><?php _e('Average Comments', 'wp-statistics'); ?></label>
416
+ </li>
417
+ <li>
418
+ <input type="checkbox" id="au_widget" name="au_widget" <?php checked(
419
+ 'on',
420
+ $widget_options['au_widget']
421
+ ); ?>/>
422
+ <label for="au_widget"><?php _e('Average Users', 'wp-statistics'); ?></label>
423
+ </li>
424
+ <li>
425
+ <input type="checkbox" id="lpd_widget" class="lpd_widget" name="lpd_widget" <?php checked(
426
+ 'on',
427
+ $widget_options['lpd_widget']
428
+ ); ?>/>
429
+ <label for="lpd_widget"><?php _e('Last Post Date', 'wp-statistics'); ?></label>
430
+ </li>
431
+ </ul>
432
+
433
+ <input type="hidden" id="wp_statistics_control_widget_submit" name="wp_statistics_control_widget_submit"
434
+ value="1"/>
435
+ <?php
436
+ }
437
+ }
includes/classes/class-wp-statistics.php ADDED
@@ -0,0 +1,1166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace {
4
+ /**
5
+ * Class WP_Statistics
6
+ *
7
+ * This is the primary class for WP Statistics recording hits on the WordPress site.
8
+ * It is extended by the Hits class and the GEO_IP_Hits class.
9
+ * This class handles; visits, visitors and pages.
10
+ */
11
+ class WP_Statistics {
12
+
13
+ // Setup our protected, private and public variables.
14
+ protected $db;
15
+ protected $tb_prefix;
16
+ protected $ip = false;
17
+ protected $ip_hash = false;
18
+ protected $agent;
19
+
20
+ private $result;
21
+ private $historical;
22
+ private $user_options_loaded = false;
23
+ private $is_feed = false;
24
+ private $tz_offset = 0;
25
+ private $country_codes = false;
26
+ private $referrer = false;
27
+
28
+ public $coefficient = 1;
29
+ public $user_id = 0;
30
+ public $options = array();
31
+ public $user_options = array();
32
+ public $menu_slugs = array();
33
+ public $installed_version;
34
+
35
+ public static $reg = array();
36
+ public static $page = array();
37
+
38
+ /**
39
+ * __construct
40
+ * WP_Statistics constructor.
41
+ */
42
+ public function __construct() {
43
+ global $wpdb;
44
+
45
+ if ( ! isset( WP_Statistics::$reg['plugin-url'] ) ) {
46
+ /**
47
+ * Plugin URL
48
+ */
49
+ WP_Statistics::$reg['plugin-url'] = plugin_dir_url(WP_STATISTICS_MAIN_FILE);
50
+ //define('WP_STATISTICS_PLUGIN_URL', plugin_dir_url(WP_STATISTICS_MAIN_FILE));
51
+ /**
52
+ * Plugin DIR
53
+ */
54
+ WP_Statistics::$reg['plugin-dir'] = plugin_dir_path(WP_STATISTICS_MAIN_FILE);
55
+ //define('WP_STATISTICS_PLUGIN_DIR', plugin_dir_path(WP_STATISTICS_MAIN_FILE));
56
+ /**
57
+ * Plugin Main File
58
+ */
59
+ WP_Statistics::$reg['main-file'] = WP_STATISTICS_MAIN_FILE;
60
+ /**
61
+ * WP Statistics Version
62
+ */
63
+
64
+ if ( ! function_exists( 'get_plugin_data' ) ){
65
+ require( ABSPATH . 'wp-admin/includes/plugin.php' );
66
+ }
67
+ WP_Statistics::$reg['plugin-data'] = get_plugin_data( WP_STATISTICS_MAIN_FILE );
68
+ WP_Statistics::$reg['version'] = WP_Statistics::$reg['plugin-data']['Version'];
69
+ //define('WP_STATISTICS_VERSION', '12.1.3');
70
+
71
+ /**
72
+ * Required PHP Version
73
+ */
74
+ WP_Statistics::$reg['required-php-version'] = '5.4.0';
75
+ //define('WP_STATISTICS_REQUIRED_PHP_VERSION', '5.4.0');
76
+ /**
77
+ * Required GEO IP PHP Version
78
+ */
79
+ WP_Statistics::$reg['geoip-php-version'] = WP_Statistics::$reg['required-php-version'];
80
+ //define('WP_STATISTICS_REQUIRED_GEOIP_PHP_VERSION', WP_Statistics::$reg['required_php_version']);
81
+
82
+ $this->set_pages();
83
+ }
84
+
85
+ require( WP_Statistics::$reg['plugin-dir'] . 'includes/vendor/autoload.php' );
86
+
87
+ // define an autoload method to automatically load classes in /includes/classes
88
+ spl_autoload_register(array( $this, 'autoload' ));
89
+
90
+ // Add init actions.
91
+ // For the main init we're going to set our priority to 9 to execute before most plugins
92
+ // so we can export data before and set the headers without
93
+ // worrying about bugs in other plugins that output text and don't allow us to set the headers.
94
+ add_action('init', array( $this, 'init' ), 9);
95
+
96
+ // Check the PHP version,
97
+ // if we don't meet the minimum version to run WP Statistics return so we don't cause a critical error.
98
+ if ( ! version_compare(phpversion(), WP_Statistics::$reg['required-php-version'], ">=") ) {
99
+ add_action('admin_notices', array( $this, 'unsupported_version_admin_notice' ), 10, 2);
100
+
101
+ return;
102
+ }
103
+
104
+ // If we've been flagged to remove all of the data, then do so now.
105
+ if ( get_option('wp_statistics_removal') == 'true' ) {
106
+ new \WP_Statistics_Uninstall;
107
+ }
108
+
109
+ // If we've been removed, return without doing anything else.
110
+ if ( get_option('wp_statistics_removal') == 'done' ) {
111
+ add_action('admin_notices', array( $this, 'removal_admin_notice' ), 10, 2);
112
+
113
+ return;
114
+ }
115
+
116
+ if ( get_option('timezone_string') ) {
117
+ $this->tz_offset = timezone_offset_get(timezone_open(get_option('timezone_string')), new DateTime());
118
+ } else if ( get_option('gmt_offset') ) {
119
+ $this->tz_offset = get_option('gmt_offset') * 60 * 60;
120
+ }
121
+
122
+ $this->db = $wpdb;
123
+ $this->tb_prefix = $wpdb->prefix;
124
+ $this->agent = $this->get_UserAgent();
125
+ $this->historical = array();
126
+
127
+ // Load the options from the database
128
+ $this->options = get_option('wp_statistics');
129
+
130
+ if ( ! is_array($this->options) ) {
131
+ $this->user_options = array();
132
+ }
133
+
134
+ // Set the default co-efficient.
135
+ $this->coefficient = $this->get_option('coefficient', 1);
136
+
137
+ // Double check the co-efficient setting to make sure it's not been set to 0.
138
+ if ( $this->coefficient <= 0 ) {
139
+ $this->coefficient = 1;
140
+ }
141
+
142
+ $this->get_IP();
143
+
144
+ if ( $this->get_option('hash_ips') == true ) {
145
+ $this->ip_hash = '#hash#' . sha1($this->ip . $_SERVER['HTTP_USER_AGENT']);
146
+ }
147
+
148
+ // Check to see if we're installed and are the current version.
149
+ $this->installed_version = get_option('wp_statistics_plugin_version');
150
+ if ( $this->installed_version != WP_Statistics::$reg['version'] ) {
151
+ new \WP_Statistics_Install($this);
152
+ }
153
+
154
+ // Load the rest of the required files for our global functions, online user tracking and hit tracking.
155
+ if ( ! function_exists('wp_statistics_useronline') ) {
156
+ include WP_Statistics::$reg['plugin-dir'] . 'includes/functions/functions.php';
157
+ }
158
+
159
+
160
+ add_action('widgets_init', array( $this, 'widget' ));
161
+ add_action('wp_dashboard_setup', 'WP_Statistics_Dashboard::widget_load');
162
+ add_action('admin_footer', 'WP_Statistics_Dashboard::inline_javascript');
163
+
164
+ add_action('add_meta_boxes', 'WP_Statistics_Editor::add_meta_box');
165
+
166
+ add_shortcode('wpstatistics', 'WP_Statistics_Shortcode::shortcodes');
167
+ add_filter('widget_text', 'do_shortcode');
168
+ add_action('admin_init', 'WP_Statistics_Shortcode::shortcake');
169
+
170
+ new \WP_Statistics_Schedule($this);
171
+ new \WP_Statistics_Ajax();
172
+
173
+ new \WP_Statistics_Bootstrap($this);
174
+ }
175
+
176
+ /**
177
+ * Autoload classes of the plugin
178
+ *
179
+ * @param string $class Class name
180
+ */
181
+ public function autoload( $class ) {
182
+ if ( ! class_exists($class) &&
183
+ // This check is for performance of loading plugin classes
184
+ substr($class, 0, 14) === 'WP_Statistics_'
185
+ ) {
186
+ $lower_class_name = str_replace('_', '-', strtolower($class));
187
+ $class_full_path = WP_Statistics::$reg['plugin-dir'] .
188
+ 'includes/classes/class-' .
189
+ $lower_class_name .
190
+ '.php';
191
+ if ( file_exists($class_full_path) ) {
192
+ require $class_full_path;
193
+ }
194
+ }
195
+ }
196
+
197
+ public function set_pages() {
198
+ if ( ! isset( WP_Statistics::$page['overview'] ) ) {
199
+ /**
200
+ * Overview Page
201
+ */
202
+ WP_Statistics::$page['overview'] = 'wps_overview_page';
203
+ //define('WP_STATISTICS_OVERVIEW_PAGE', 'wps_overview_page');
204
+ /**
205
+ * Browsers Page
206
+ */
207
+ WP_Statistics::$page['browser'] = 'wps_browsers_page';
208
+ //define('WP_STATISTICS_BROWSERS_PAGE', 'wps_browsers_page');
209
+ /**
210
+ * Countries Page
211
+ */
212
+ WP_Statistics::$page['countries'] = 'wps_countries_page';
213
+ //define('WP_STATISTICS_COUNTRIES_PAGE', 'wps_countries_page');
214
+ /**
215
+ * Exclusions Page
216
+ */
217
+ WP_Statistics::$page['exclusions'] = 'wps_exclusions_page';
218
+ //define('WP_STATISTICS_EXCLUSIONS_PAGE', 'wps_exclusions_page');
219
+ /**
220
+ * Hits Page
221
+ */
222
+ WP_Statistics::$page['hits'] = 'wps_hits_page';
223
+ //define('WP_STATISTICS_HITS_PAGE', 'wps_hits_page');
224
+ /**
225
+ * Online Page
226
+ */
227
+ WP_Statistics::$page['online'] = 'wps_online_page';
228
+ //define('WP_STATISTICS_ONLINE_PAGE', 'wps_online_page');
229
+ /**
230
+ * Pages Page
231
+ */
232
+ WP_Statistics::$page['pages'] = 'wps_pages_page';
233
+ //define('WP_STATISTICS_PAGES_PAGE', 'wps_pages_page');
234
+ /**
235
+ * Categories Page
236
+ */
237
+ WP_Statistics::$page['categories'] = 'wps_categories_page';
238
+ //define('WP_STATISTICS_CATEGORIES_PAGE', 'wps_categories_page');
239
+ /**
240
+ * Authors Page
241
+ */
242
+ WP_Statistics::$page['authors'] = 'wps_authors_page';
243
+ //define('WP_STATISTICS_AUTHORS_PAGE', 'wps_authors_page');
244
+ /**
245
+ * Tags Page
246
+ */
247
+ WP_Statistics::$page['tags'] = 'wps_tags_page';
248
+ //define('WP_STATISTICS_TAGS_PAGE', 'wps_tags_page');
249
+ /**
250
+ * Referer Page
251
+ */
252
+ WP_Statistics::$page['referrers'] = 'wps_referrers_page';
253
+ //define('WP_STATISTICS_REFERRERS_PAGE', 'wps_referrers_page');
254
+ /**
255
+ * Searched Phrases Page
256
+ */
257
+ WP_Statistics::$page['searched-phrases'] = 'wps_searched_phrases_page';
258
+ //define('WP_STATISTICS_SEARCHED_PHRASES_PAGE', 'wps_searched_phrases_page');
259
+ /**
260
+ * Searches Page
261
+ */
262
+ WP_Statistics::$page['searches'] = 'wps_searches_page';
263
+ //define('WP_STATISTICS_SEARCHES_PAGE', 'wps_searches_page');
264
+ /**
265
+ * Words Page
266
+ */
267
+ WP_Statistics::$page['words'] = 'wps_words_page';
268
+ //define('WP_STATISTICS_WORDS_PAGE', 'wps_words_page');
269
+ /**
270
+ * Top Visitors Page
271
+ */
272
+ WP_Statistics::$page['top-visitors'] = 'wps_top_visitors_page';
273
+ //define('WP_STATISTICS_TOP_VISITORS_PAGE', 'wps_top_visitors_page');
274
+ /**
275
+ * Visitors Page
276
+ */
277
+ WP_Statistics::$page['visitors'] = 'wps_visitors_page';
278
+ //define('WP_STATISTICS_VISITORS_PAGE', 'wps_visitors_page');
279
+ /**
280
+ * Optimization Page
281
+ */
282
+ WP_Statistics::$page['optimization'] = 'wps_optimization_page';
283
+ //define('WP_STATISTICS_OPTIMIZATION_PAGE', 'wps_optimization_page');
284
+ /**
285
+ * Settings Page
286
+ */
287
+ WP_Statistics::$page['settings'] = 'wps_settings_page';
288
+ //define('WP_STATISTICS_SETTINGS_PAGE', 'wps_settings_page');
289
+ /**
290
+ * Plugins Page
291
+ */
292
+ WP_Statistics::$page['plugins'] = 'wps_plugins_page';
293
+ //define('WP_STATISTICS_PLUGINS_PAGE', 'wps_plugins_page');
294
+ /**
295
+ * Donate Page
296
+ */
297
+ WP_Statistics::$page['donate'] = 'wps_donate_page';
298
+ //define('WP_STATISTICS_DONATE_PAGE', 'wps_donate_page');
299
+ }
300
+ }
301
+
302
+ /**
303
+ * Loads the init code.
304
+ */
305
+ public function init() {
306
+ // Check to see if we're exporting data, if so, do so now.
307
+ // Note this will set the headers to download the export file and then stop running WordPress.
308
+ if ( array_key_exists('wps_export', $_POST) ) {
309
+ if ( ! function_exists('wp_statistics_export_data') ) {
310
+ include WP_Statistics::$reg['plugin-dir'] . 'includes/functions/export.php';
311
+ }
312
+ wp_statistics_export_data();
313
+ }
314
+ }
315
+
316
+ /**
317
+ * Registers Widget
318
+ */
319
+ public function widget() {
320
+ register_widget('WP_Statistics_Widget');
321
+ }
322
+
323
+ /**
324
+ * Unsupported Version Admin Notice
325
+ */
326
+ public function unsupported_version_admin_notice() {
327
+
328
+ $screen = get_current_screen();
329
+
330
+ if ( 'plugins' !== $screen->id ) {
331
+ return;
332
+ }
333
+ ?>
334
+ <div class="error">
335
+ <p style="max-width:800px;">
336
+ <b><?php _e(
337
+ 'WP Statistics Disabled',
338
+ 'wp-statistics'
339
+ ); ?></b> <?php _e(
340
+ '&#151; You are running an unsupported version of PHP.',
341
+ 'wp-statistics'
342
+ ); ?>
343
+ </p>
344
+
345
+ <p style="max-width:800px;"><?php
346
+
347
+ echo sprintf(
348
+ __(
349
+ 'WP Statistics has detected PHP version %s which is unsupported, WP Statistics requires PHP Version %s or higher!',
350
+ 'wp-statistics'
351
+ ),
352
+ phpversion(),
353
+ WP_Statistics::$reg['required-php-version']
354
+ );
355
+ echo '</p><p>';
356
+ echo __(
357
+ 'Please contact your hosting provider to upgrade to a supported version or disable WP Statistics to remove this message.',
358
+ 'wp-statistics'
359
+ );
360
+ ?></p>
361
+ </div>
362
+
363
+ <?php
364
+ }
365
+
366
+ /**
367
+ * This adds a row after WP Statistics in the plugin page
368
+ * IF we've been removed via the settings page.
369
+ */
370
+ public function removal_admin_notice() {
371
+ $screen = get_current_screen();
372
+
373
+ if ( 'plugins' !== $screen->id ) {
374
+ return;
375
+ }
376
+
377
+ ?>
378
+ <div class="error">
379
+ <p style="max-width:800px;"><?php
380
+
381
+ echo '<p>';
382
+ echo __('WP Statistics has been removed, please disable and delete it.', 'wp-statistics');
383
+ echo '</p>';
384
+ ?></p>
385
+ </div>
386
+ <?php
387
+ }
388
+
389
+ // This function sets the current WordPress user id for the class.
390
+ public function set_user_id() {
391
+ if ( $this->user_id == 0 ) {
392
+ $this->user_id = get_current_user_id();
393
+ }
394
+ }
395
+
396
+ // This function loads the options from WordPress, it is included here for completeness as the options are loaded automatically in the class constructor.
397
+ public function load_options() {
398
+ $this->options = get_option('wp_statistics');
399
+
400
+ if ( ! is_array($this->options) ) {
401
+ $this->user_options = array();
402
+ }
403
+ }
404
+
405
+ // This function loads the user options from WordPress. It is NOT called during the class constructor.
406
+ public function load_user_options( $force = false ) {
407
+ if ( $this->user_options_loaded == true && $force != true ) {
408
+ return;
409
+ }
410
+
411
+ $this->set_user_id();
412
+
413
+ // Not sure why, but get_user_meta() is returning an array or array's unless $single is set to true.
414
+ $this->user_options = get_user_meta($this->user_id, 'wp_statistics', true);
415
+
416
+ if ( ! is_array($this->user_options) ) {
417
+ $this->user_options = array();
418
+ }
419
+
420
+ $this->user_options_loaded = true;
421
+ }
422
+
423
+ // The function mimics WordPress's get_option() function but uses the array instead of individual options.
424
+ public function get_option( $option, $default = null ) {
425
+ // If no options array exists, return FALSE.
426
+ if ( ! is_array($this->options) ) {
427
+ return false;
428
+ }
429
+
430
+ // if the option isn't set yet, return the $default if it exists, otherwise FALSE.
431
+ if ( ! array_key_exists($option, $this->options) ) {
432
+ if ( isset( $default ) ) {
433
+ return $default;
434
+ } else {
435
+ return false;
436
+ }
437
+ }
438
+
439
+ // Return the option.
440
+ return $this->options[ $option ];
441
+ }
442
+
443
+ // This function mimics WordPress's get_user_meta() function but uses the array instead of individual options.
444
+ public function get_user_option( $option, $default = null ) {
445
+ // If the user id has not been set or no options array exists, return FALSE.
446
+ if ( $this->user_id == 0 ) {
447
+ return false;
448
+ }
449
+ if ( ! is_array($this->user_options) ) {
450
+ return false;
451
+ }
452
+
453
+ // if the option isn't set yet, return the $default if it exists, otherwise FALSE.
454
+ if ( ! array_key_exists($option, $this->user_options) ) {
455
+ if ( isset( $default ) ) {
456
+ return $default;
457
+ } else {
458
+ return false;
459
+ }
460
+ }
461
+
462
+ // Return the option.
463
+ return $this->user_options[ $option ];
464
+ }
465
+
466
+ // The function mimics WordPress's update_option() function but uses the array instead of individual options.
467
+ public function update_option( $option, $value ) {
468
+ // Store the value in the array.
469
+ $this->options[ $option ] = $value;
470
+
471
+ // Write the array to the database.
472
+ update_option('wp_statistics', $this->options);
473
+ }
474
+
475
+ // The function mimics WordPress's update_user_meta() function but uses the array instead of individual options.
476
+ public function update_user_option( $option, $value ) {
477
+ // If the user id has not been set return FALSE.
478
+ if ( $this->user_id == 0 ) {
479
+ return false;
480
+ }
481
+
482
+ // Store the value in the array.
483
+ $this->user_options[ $option ] = $value;
484
+
485
+ // Write the array to the database.
486
+ update_user_meta($this->user_id, 'wp_statistics', $this->user_options);
487
+ }
488
+
489
+ // This function is similar to update_option, but it only stores the option in the array. This save some writing to the database if you have multiple values to update.
490
+ public function store_option( $option, $value ) {
491
+ $this->options[ $option ] = $value;
492
+ }
493
+
494
+ // This function is similar to update_user_option, but it only stores the option in the array. This save some writing to the database if you have multiple values to update.
495
+ public function store_user_option( $option, $value ) {
496
+ // If the user id has not been set return FALSE.
497
+ if ( $this->user_id == 0 ) {
498
+ return false;
499
+ }
500
+
501
+ $this->user_options[ $option ] = $value;
502
+ }
503
+
504
+ // This function saves the current options array to the database.
505
+ public function save_options() {
506
+ update_option('wp_statistics', $this->options);
507
+ }
508
+
509
+ // This function saves the current user options array to the database.
510
+ public function save_user_options() {
511
+ if ( $this->user_id == 0 ) {
512
+ return false;
513
+ }
514
+
515
+ update_user_meta($this->user_id, 'wp_statistics', $this->user_options);
516
+ }
517
+
518
+ // This function check to see if an option is currently set or not.
519
+ public function isset_option( $option ) {
520
+ if ( ! is_array($this->options) ) {
521
+ return false;
522
+ }
523
+
524
+ return array_key_exists($option, $this->options);
525
+ }
526
+
527
+ // This function check to see if a user option is currently set or not.
528
+ public function isset_user_option( $option ) {
529
+ if ( $this->user_id == 0 ) {
530
+ return false;
531
+ }
532
+ if ( ! is_array($this->user_options) ) {
533
+ return false;
534
+ }
535
+
536
+ return array_key_exists($option, $this->user_options);
537
+ }
538
+
539
+ // During installation of WP Statistics some initial data needs to be loaded in to the database so errors are not displayed.
540
+ // This function will add some initial data if the tables are empty.
541
+ public function Primary_Values() {
542
+
543
+ $this->result = $this->db->query("SELECT * FROM {$this->tb_prefix}statistics_useronline");
544
+
545
+ if ( ! $this->result ) {
546
+
547
+ $this->db->insert(
548
+ $this->tb_prefix . "statistics_useronline",
549
+ array(
550
+ 'ip' => $this->get_IP(),
551
+ 'timestamp' => $this->Current_Date('U'),
552
+ 'date' => $this->Current_Date(),
553
+ 'referred' => $this->get_Referred(),
554
+ 'agent' => $this->agent['browser'],
555
+ 'platform' => $this->agent['platform'],
556
+ 'version' => $this->agent['version'],
557
+ )
558
+ );
559
+ }
560
+
561
+ $this->result = $this->db->query("SELECT * FROM {$this->tb_prefix}statistics_visit");
562
+
563
+ if ( ! $this->result ) {
564
+
565
+ $this->db->insert(
566
+ $this->tb_prefix . "statistics_visit",
567
+ array(
568
+ 'last_visit' => $this->Current_Date(),
569
+ 'last_counter' => $this->Current_date('Y-m-d'),
570
+ 'visit' => 1,
571
+ )
572
+ );
573
+ }
574
+
575
+ $this->result = $this->db->query("SELECT * FROM {$this->tb_prefix}statistics_visitor");
576
+
577
+ if ( ! $this->result ) {
578
+
579
+ $this->db->insert(
580
+ $this->tb_prefix . "statistics_visitor",
581
+ array(
582
+ 'last_counter' => $this->Current_date('Y-m-d'),
583
+ 'referred' => $this->get_Referred(),
584
+ 'agent' => $this->agent['browser'],
585
+ 'platform' => $this->agent['platform'],
586
+ 'version' => $this->agent['version'],
587
+ 'ip' => $this->get_IP(),
588
+ 'location' => '000',
589
+ )
590
+ );
591
+ }
592
+ }
593
+
594
+ // During installation of WP Statistics some initial options need to be set.
595
+ // This function will save a set of default options for the plugin.
596
+ public function Default_Options() {
597
+ $options = array();
598
+
599
+ if ( ! isset( $wps_robotarray ) ) {
600
+ // Get the robots list, we'll use this for both upgrades and new installs.
601
+ include( WP_Statistics::$reg['plugin-dir'] . 'includes/robotslist.php' );
602
+ }
603
+
604
+ $options['robotlist'] = trim($wps_robotslist);
605
+
606
+ // By default, on new installs, use the new search table.
607
+ $options['search_converted'] = 1;
608
+
609
+ // If this is a first time install or an upgrade and we've added options, set some intelligent defaults.
610
+ $options['geoip'] = false;
611
+ $options['browscap'] = false;
612
+ $options['useronline'] = true;
613
+ $options['visits'] = true;
614
+ $options['visitors'] = true;
615
+ $options['pages'] = true;
616
+ $options['check_online'] = '30';
617
+ $options['menu_bar'] = false;
618
+ $options['coefficient'] = '1';
619
+ $options['stats_report'] = false;
620
+ $options['time_report'] = 'daily';
621
+ $options['send_report'] = 'mail';
622
+ $options['content_report'] = '';
623
+ $options['update_geoip'] = true;
624
+ $options['store_ua'] = false;
625
+ $options['robotlist'] = $wps_robotslist;
626
+ $options['exclude_administrator'] = true;
627
+ $options['disable_se_clearch'] = true;
628
+ $options['disable_se_ask'] = true;
629
+ $options['map_type'] = 'jqvmap';
630
+
631
+ $options['force_robot_update'] = true;
632
+
633
+ return $options;
634
+ }
635
+
636
+ // This function processes a string that represents an IP address and returns either FALSE if it's invalid or a valid IP4 address.
637
+ private function get_ip_value( $ip ) {
638
+ // Reject anything that's not a string.
639
+ if ( ! is_string($ip) ) {
640
+ return false;
641
+ }
642
+
643
+ // Trim off any spaces.
644
+ $ip = trim($ip);
645
+
646
+ // Process IPv4 and v6 addresses separately.
647
+ if ( $this->isValidIPv6($ip) ) {
648
+ // Reject any IPv6 addresses if IPv6 is not compiled in to this version of PHP.
649
+ if ( ! defined('AF_INET6') ) {
650
+ return false;
651
+ }
652
+ } else {
653
+ // Trim off any port values that exist.
654
+ if ( strstr($ip, ':') !== false ) {
655
+ $temp = explode(':', $ip);
656
+ $ip = $temp[0];
657
+ }
658
+
659
+ // Check to make sure the http header is actually an IP address and not some kind of SQL injection attack.
660
+ $long = ip2long($ip);
661
+
662
+ // ip2long returns either -1 or FALSE if it is not a valid IP address depending on the PHP version, so check for both.
663
+ if ( $long == -1 || $long === false ) {
664
+ return false;
665
+ }
666
+ }
667
+
668
+ // If the ip address is blank, reject it.
669
+ if ( $ip == '' ) {
670
+ return false;
671
+ }
672
+
673
+ // We're got a real IP address, return it.
674
+ return $ip;
675
+
676
+ }
677
+
678
+ // This function returns the current IP address of the remote client.
679
+ public function get_IP() {
680
+
681
+ // Check to see if we've already retrieved the IP address and if so return the last result.
682
+ if ( $this->ip !== false ) {
683
+ return $this->ip;
684
+ }
685
+
686
+ // By default we use the remote address the server has.
687
+ if ( array_key_exists('REMOTE_ADDR', $_SERVER) ) {
688
+ $temp_ip = $this->get_ip_value($_SERVER['REMOTE_ADDR']);
689
+ } else {
690
+ $temp_ip = '127.0.0.1';
691
+ }
692
+
693
+ if ( false !== $temp_ip ) {
694
+ $this->ip = $temp_ip;
695
+ }
696
+
697
+ /* Check to see if any of the HTTP headers are set to identify the remote user.
698
+ * These often give better results as they can identify the remote user even through firewalls etc,
699
+ * but are sometimes used in SQL injection attacks.
700
+ *
701
+ * We only want to take the first one we find, so search them in order and break when we find the first
702
+ * one.
703
+ *
704
+ */
705
+ $envs = array(
706
+ 'HTTP_CLIENT_IP',
707
+ 'HTTP_X_FORWARDED_FOR',
708
+ 'HTTP_X_FORWARDED',
709
+ 'HTTP_FORWARDED_FOR',
710
+ 'HTTP_FORWARDED',
711
+ );
712
+
713
+ foreach ( $envs as $env ) {
714
+ $temp_ip = $this->get_ip_value(getenv($env));
715
+
716
+ if ( false !== $temp_ip ) {
717
+ $this->ip = $temp_ip;
718
+
719
+ break;
720
+ }
721
+ }
722
+
723
+ // If no valid ip address has been found, use 127.0.0.1 (aka localhost).
724
+ if ( false === $this->ip ) {
725
+ $this->ip = '127.0.0.1';
726
+ }
727
+
728
+ return $this->ip;
729
+ }
730
+
731
+ /**
732
+ * Validate an IPv6 IP address
733
+ *
734
+ * @param string $ip
735
+ *
736
+ * @return boolean - true/false
737
+ */
738
+ private function isValidIPv6( $ip ) {
739
+ if ( false === filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) ) {
740
+ return false;
741
+ } else {
742
+ return true;
743
+ }
744
+ }
745
+
746
+ // This function calls the user agent parsing code.
747
+ public function get_UserAgent() {
748
+
749
+ // Parse the agent stirng.
750
+ try {
751
+ $agent = parse_user_agent();
752
+ } catch ( Exception $e ) {
753
+ $agent = array(
754
+ 'browser' => _x('Unknown', 'Browser', 'wp-statistics'),
755
+ 'platform' => _x('Unknown', 'Platform', 'wp-statistics'),
756
+ 'version' => _x('Unknown', 'Version', 'wp-statistics'),
757
+ );
758
+ }
759
+
760
+ // null isn't a very good default, so set it to Unknown instead.
761
+ if ( $agent['browser'] == null ) {
762
+ $agent['browser'] = _x('Unknown', 'Browser', 'wp-statistics');
763
+ }
764
+ if ( $agent['platform'] == null ) {
765
+ $agent['platform'] = _x('Unknown', 'Platform', 'wp-statistics');
766
+ }
767
+ if ( $agent['version'] == null ) {
768
+ $agent['version'] = _x('Unknown', 'Version', 'wp-statistics');
769
+ }
770
+
771
+ // Uncommon browsers often have some extra cruft, like brackets, http:// and other strings that we can strip out.
772
+ $strip_strings = array( '"', "'", '(', ')', ';', ':', '/', '[', ']', '{', '}', 'http' );
773
+ foreach ( $agent as $key => $value ) {
774
+ $agent[ $key ] = str_replace($strip_strings, '', $agent[ $key ]);
775
+ }
776
+
777
+ return $agent;
778
+ }
779
+
780
+ // This function will return the referrer link for the current user.
781
+ public function get_Referred( $default_referrer = false ) {
782
+
783
+ if ( $this->referrer !== false ) {
784
+ return $this->referrer;
785
+ }
786
+
787
+ $this->referrer = '';
788
+
789
+ if ( isset( $_SERVER['HTTP_REFERER'] ) ) {
790
+ $this->referrer = $_SERVER['HTTP_REFERER'];
791
+ }
792
+ if ( $default_referrer ) {
793
+ $this->referrer = $default_referrer;
794
+ }
795
+
796
+ $this->referrer = esc_sql(strip_tags($this->referrer));
797
+
798
+ if ( ! $this->referrer ) {
799
+ $this->referrer = get_bloginfo('url');
800
+ }
801
+
802
+ if ( $this->get_option('addsearchwords', false) ) {
803
+ // Check to see if this is a search engine referrer
804
+ $SEInfo = $this->Search_Engine_Info($this->referrer);
805
+
806
+ if ( is_array($SEInfo) ) {
807
+ // If we're a known SE, check the query string
808
+ if ( $SEInfo['tag'] != '' ) {
809
+ $result = $this->Search_Engine_QueryString($this->referrer);
810
+
811
+ // If there were no search words, let's add the page title
812
+ if ( $result == '' || $result == 'No search query found!' ) {
813
+ $result = wp_title('', false);
814
+ if ( $result != '' ) {
815
+ $this->referrer = esc_url(
816
+ add_query_arg(
817
+ $SEInfo['querykey'],
818
+ urlencode('~"' . $result . '"'),
819
+ $this->referrer
820
+ )
821
+ );
822
+ }
823
+ }
824
+ }
825
+ }
826
+ }
827
+
828
+ return $this->referrer;
829
+ }
830
+
831
+ // This function returns a date string in the desired format with a passed in timestamp.
832
+ public function Local_Date( $format, $timestamp ) {
833
+ return date($format, $timestamp + $this->tz_offset);
834
+ }
835
+
836
+ // This function returns a date string in the desired format.
837
+ public function Current_Date( $format = 'Y-m-d H:i:s', $strtotime = null, $relative = null ) {
838
+
839
+ if ( $strtotime ) {
840
+ if ( $relative ) {
841
+ return date($format, strtotime("{$strtotime} day", $relative) + $this->tz_offset);
842
+ } else {
843
+ return date($format, strtotime("{$strtotime} day") + $this->tz_offset);
844
+ }
845
+ } else {
846
+ return date($format, time() + $this->tz_offset);
847
+ }
848
+ }
849
+
850
+ // This function returns a date string in the desired format.
851
+ public function Real_Current_Date( $format = 'Y-m-d H:i:s', $strtotime = null, $relative = null ) {
852
+
853
+ if ( $strtotime ) {
854
+ if ( $relative ) {
855
+ return date($format, strtotime("{$strtotime} day", $relative));
856
+ } else {
857
+ return date($format, strtotime("{$strtotime} day"));
858
+ }
859
+ } else {
860
+ return date($format, time());
861
+ }
862
+ }
863
+
864
+ // This function returns an internationalized date string in the desired format.
865
+ public function Current_Date_i18n( $format = 'Y-m-d H:i:s', $strtotime = null, $day = ' day' ) {
866
+
867
+ if ( $strtotime ) {
868
+ return date_i18n($format, strtotime("{$strtotime}{$day}") + $this->tz_offset);
869
+ } else {
870
+ return date_i18n($format, time() + $this->tz_offset);
871
+ }
872
+ }
873
+
874
+ public function strtotimetz( $timestring ) {
875
+ return strtotime($timestring) + $this->tz_offset;
876
+ }
877
+
878
+ public function timetz() {
879
+ return time() + $this->tz_offset;
880
+ }
881
+
882
+ // This function checks to see if a search engine exists in the current list of search engines.
883
+ public function Check_Search_Engines( $search_engine_name, $search_engine = null ) {
884
+
885
+ if ( strstr($search_engine, $search_engine_name) ) {
886
+ return 1;
887
+ }
888
+ }
889
+
890
+ // This function returns an array of information about a given search engine based on the url passed in.
891
+ // It is used in several places to get the SE icon or the sql query to select an individual SE from the database.
892
+ public function Search_Engine_Info( $url = false ) {
893
+
894
+ // If no URL was passed in, get the current referrer for the session.
895
+ if ( ! $url ) {
896
+ $url = isset( $_SERVER['HTTP_REFERER'] ) ? $this->get_Referred() : false;
897
+ }
898
+
899
+ // If there is no URL and no referrer, always return false.
900
+ if ( $url == false ) {
901
+ return false;
902
+ }
903
+
904
+ // Parse the URL in to it's component parts.
905
+ $parts = parse_url($url);
906
+
907
+ // Get the list of search engines we currently support.
908
+ $search_engines = wp_statistics_searchengine_list();
909
+
910
+ // Loop through the SE list until we find which search engine matches.
911
+ foreach ( $search_engines as $key => $value ) {
912
+ $search_regex = wp_statistics_searchengine_regex($key);
913
+
914
+ preg_match('/' . $search_regex . '/', $parts['host'], $matches);
915
+
916
+ if ( isset( $matches[1] ) ) {
917
+ // Return the first matched SE.
918
+ return $value;
919
+ }
920
+ }
921
+
922
+ // If no SE matched, return some defaults.
923
+ return array(
924
+ 'name' => _x('Unknown', 'Search Engine', 'wp-statistics'),
925
+ 'tag' => '',
926
+ 'sqlpattern' => '',
927
+ 'regexpattern' => '',
928
+ 'querykey' => 'q',
929
+ 'image' => 'unknown.png',
930
+ );
931
+ }
932
+
933
+ // This function returns an array of information about a given search engine based on the url passed in.
934
+ // It is used in several places to get the SE icon or the sql query to select an individual SE from the database.
935
+ public function Search_Engine_Info_By_Engine( $engine = false ) {
936
+
937
+ // If there is no URL and no referrer, always return false.
938
+ if ( $engine == false ) {
939
+ return false;
940
+ }
941
+
942
+ // Get the list of search engines we currently support.
943
+ $search_engines = wp_statistics_searchengine_list();
944
+
945
+ if ( array_key_exists($engine, $search_engines) ) {
946
+ return $search_engines[ $engine ];
947
+ }
948
+
949
+ // If no SE matched, return some defaults.
950
+ return array(
951
+ 'name' => _x('Unknown', 'Search Engine', 'wp-statistics'),
952
+ 'tag' => '',
953
+ 'sqlpattern' => '',
954
+ 'regexpattern' => '',
955
+ 'querykey' => 'q',
956
+ 'image' => 'unknown.png',
957
+ );
958
+ }
959
+
960
+ // This function will parse a URL from a referrer and return the search query words used.
961
+ public function Search_Engine_QueryString( $url = false ) {
962
+
963
+ // If no URL was passed in, get the current referrer for the session.
964
+ if ( ! $url ) {
965
+ $url = isset( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : false;
966
+ }
967
+
968
+ // If there is no URL and no referrer, always return false.
969
+ if ( $url == false ) {
970
+ return false;
971
+ }
972
+
973
+ // Parse the URL in to it's component parts.
974
+ $parts = parse_url($url);
975
+
976
+ // Check to see if there is a query component in the URL (everything after the ?). If there isn't one
977
+ // set an empty array so we don't get errors later.
978
+ if ( array_key_exists('query', $parts) ) {
979
+ parse_str($parts['query'], $query);
980
+ } else {
981
+ $query = array();
982
+ }
983
+
984
+ // Get the list of search engines we currently support.
985
+ $search_engines = wp_statistics_searchengine_list();
986
+
987
+ // Loop through the SE list until we find which search engine matches.
988
+ foreach ( $search_engines as $key => $value ) {
989
+ $search_regex = wp_statistics_searchengine_regex($key);
990
+
991
+ preg_match('/' . $search_regex . '/', $parts['host'], $matches);
992
+
993
+ if ( isset( $matches[1] ) ) {
994
+ // Check to see if the query key the SE uses exists in the query part of the URL.
995
+ if ( array_key_exists($search_engines[ $key ]['querykey'], $query) ) {
996
+ $words = strip_tags($query[ $search_engines[ $key ]['querykey'] ]);
997
+ } else {
998
+ $words = '';
999
+ }
1000
+
1001
+ // If no words were found, return a pleasant default.
1002
+ if ( $words == '' ) {
1003
+ $words = 'No search query found!';
1004
+ }
1005
+
1006
+ return $words;
1007
+ }
1008
+ }
1009
+
1010
+ // We should never actually get to this point, but let's make sure we return something
1011
+ // just in case something goes terribly wrong.
1012
+ return 'No search query found!';
1013
+ }
1014
+
1015
+ public function Get_Historical_Data( $type, $id = '' ) {
1016
+
1017
+ $count = 0;
1018
+
1019
+ switch ( $type ) {
1020
+ case 'visitors':
1021
+ if ( array_key_exists('visitors', $this->historical) ) {
1022
+ return $this->historical['visitors'];
1023
+ } else {
1024
+ $result
1025
+ = $this->db->get_var(
1026
+ "SELECT value FROM {$this->tb_prefix}statistics_historical WHERE category = 'visitors'"
1027
+ );
1028
+ if ( $result > $count ) {
1029
+ $count = $result;
1030
+ }
1031
+ $this->historical['visitors'] = $count;
1032
+ }
1033
+
1034
+ break;
1035
+ case 'visits':
1036
+ if ( array_key_exists('visits', $this->historical) ) {
1037
+ return $this->historical['visits'];
1038
+ } else {
1039
+ $result
1040
+ = $this->db->get_var(
1041
+ "SELECT value FROM {$this->tb_prefix}statistics_historical WHERE category = 'visits'"
1042
+ );
1043
+ if ( $result > $count ) {
1044
+ $count = $result;
1045
+ }
1046
+ $this->historical['visits'] = $count;
1047
+ }
1048
+
1049
+ break;
1050
+ case 'uri':
1051
+ if ( array_key_exists($id, $this->historical) ) {
1052
+ return $this->historical[ $id ];
1053
+ } else {
1054
+ $result
1055
+ = $this->db->get_var(
1056
+ $this->db->prepare(
1057
+ "SELECT value FROM {$this->tb_prefix}statistics_historical WHERE category = 'uri' AND uri = %s",
1058
+ $id
1059
+ )
1060
+ );
1061
+ if ( $result > $count ) {
1062
+ $count = $result;
1063
+ }
1064
+ $this->historical[ $id ] = $count;
1065
+ }
1066
+
1067
+ break;
1068
+ case 'page':
1069
+ if ( array_key_exists($id, $this->historical) ) {
1070
+ return $this->historical[ $id ];
1071
+ } else {
1072
+ $result
1073
+ = $this->db->get_var(
1074
+ $this->db->prepare(
1075
+ "SELECT value FROM {$this->tb_prefix}statistics_historical WHERE category = 'uri' AND page_id = %d",
1076
+ $id
1077
+ )
1078
+ );
1079
+ if ( $result > $count ) {
1080
+ $count = $result;
1081
+ }
1082
+ $this->historical[ $id ] = $count;
1083
+ }
1084
+
1085
+ break;
1086
+ }
1087
+
1088
+ return $count;
1089
+ }
1090
+
1091
+ public function feed_detected() {
1092
+ $this->is_feed = true;
1093
+ }
1094
+
1095
+ public function check_feed() {
1096
+ return $this->is_feed;
1097
+ }
1098
+
1099
+ public function get_country_codes() {
1100
+ if ( $this->country_codes == false ) {
1101
+ $ISOCountryCode = array();
1102
+ include( WP_Statistics::$reg['plugin-dir'] . "includes/functions/country-codes.php" );
1103
+ $this->country_codes = $ISOCountryCode;
1104
+ }
1105
+
1106
+ return $this->country_codes;
1107
+ }
1108
+
1109
+ // Returns an array of site id's
1110
+ public function get_wp_sites_list() {
1111
+ GLOBAL $wp_version;
1112
+
1113
+ $site_list = array();
1114
+
1115
+ // wp_get_sites() is deprecated in 4.6 or above and replaced with get_sites().
1116
+ if ( version_compare($wp_version, '4.6', '>=') ) {
1117
+ $sites = get_sites();
1118
+
1119
+ foreach ( $sites as $site ) {
1120
+ $site_list[] = $site->blog_id;
1121
+ }
1122
+ } else {
1123
+ $sites = wp_get_sites();
1124
+
1125
+ foreach ( $sites as $site ) {
1126
+ $site_list[] = $site['blog_id'];
1127
+ }
1128
+ }
1129
+
1130
+ return $site_list;
1131
+ }
1132
+
1133
+ public function html_sanitize_referrer( $referrer, $length = -1 ) {
1134
+ $referrer = trim($referrer);
1135
+
1136
+ if ( 'data:' == strtolower(substr($referrer, 0, 5)) ) {
1137
+ $referrer = 'http://127.0.0.1';
1138
+ }
1139
+
1140
+ if ( 'javascript:' == strtolower(substr($referrer, 0, 11)) ) {
1141
+ $referrer = 'http://127.0.0.1';
1142
+ }
1143
+
1144
+ if ( $length > 0 ) {
1145
+ $referrer = substr($referrer, 0, $length);
1146
+ }
1147
+
1148
+ return htmlentities($referrer, ENT_QUOTES);
1149
+ }
1150
+
1151
+ public function get_referrer_link( $referrer, $length = -1 ) {
1152
+ $html_referrer = $this->html_sanitize_referrer($referrer);
1153
+
1154
+ if ( $length > 0 && strlen($referrer) > $length ) {
1155
+ $html_referrer_limited = $this->html_sanitize_referrer($referrer, $length);
1156
+ $eplises = '[...]';
1157
+ } else {
1158
+ $html_referrer_limited = $html_referrer;
1159
+ $eplises = '';
1160
+ }
1161
+
1162
+ return "<a href='{$html_referrer}'><div class='dashicons dashicons-admin-links'></div>{$html_referrer_limited}{$eplises}</a>";
1163
+ }
1164
+
1165
+ }
1166
+ }
includes/classes/important.txt ADDED
@@ -0,0 +1,2 @@
 
 
1
+ Please add "WP_Statistics_" before any class name
2
+ This is for an internal rule to load classes fast!
includes/classes/statistics.class.php DELETED
@@ -1,822 +0,0 @@
1
- <?php
2
-
3
- /*
4
- This is the primary class for WP Statistics recording hits on the WordPress site. It is extended by the Hits class and the GeoIPHits class.
5
-
6
- This class handles; visits, visitors and pages.
7
- */
8
-
9
- class WP_Statistics {
10
-
11
- // Setup our protected, private and public variables.
12
- protected $db;
13
- protected $tb_prefix;
14
- protected $ip = false;
15
- protected $ip_hash = false;
16
- protected $agent;
17
-
18
- private $result;
19
- private $historical;
20
- private $user_options_loaded = false;
21
- private $is_feed = false;
22
- private $tz_offset = 0;
23
- private $country_codes = false;
24
- private $referrer = false;
25
-
26
- public $coefficient = 1;
27
- public $plugin_dir = '';
28
- public $plugin_url = '';
29
- public $user_id = 0;
30
- public $options = array();
31
- public $user_options = array();
32
- public $menu_slugs = array();
33
-
34
- // Construction function.
35
- public function __construct() {
36
-
37
- global $wpdb;
38
-
39
- if ( get_option( 'timezone_string' ) ) {
40
- $this->tz_offset = timezone_offset_get( timezone_open( get_option( 'timezone_string' ) ), new DateTime() );
41
- } else if ( get_option( 'gmt_offset' ) ) {
42
- $this->tz_offset = get_option( 'gmt_offset' ) * 60 * 60;
43
- }
44
-
45
- $this->db = $wpdb;
46
- $this->tb_prefix = $wpdb->prefix;
47
- $this->agent = $this->get_UserAgent();
48
- $this->historical = array();
49
-
50
- // Load the options from the database
51
- $this->options = get_option( 'wp_statistics' );
52
-
53
- if ( ! is_array( $this->options ) ) {
54
- $this->user_options = array();
55
- }
56
-
57
- // Set the default co-efficient.
58
- $this->coefficient = $this->get_option( 'coefficient', 1 );
59
-
60
- // Double check the co-efficient setting to make sure it's not been set to 0.
61
- if ( $this->coefficient <= 0 ) {
62
- $this->coefficient = 1;
63
- }
64
-
65
- // This is a bit of a hack, we strip off the "includes/classes" at the end of the current class file's path.
66
- $this->plugin_dir = substr( dirname( __FILE__ ), 0, - 17 );
67
- $this->plugin_url = substr( plugin_dir_url( __FILE__ ), 0, - 17 );
68
-
69
- $this->get_IP();
70
-
71
- if ( $this->get_option( 'hash_ips' ) == true ) {
72
- $this->ip_hash = '#hash#' . sha1( $this->ip . $_SERVER['HTTP_USER_AGENT'] );
73
- }
74
-
75
- }
76
-
77
- // This function sets the current WordPress user id for the class.
78
- public function set_user_id() {
79
- if ( $this->user_id == 0 ) {
80
- $this->user_id = get_current_user_id();
81
- }
82
- }
83
-
84
- // This function loads the options from WordPress, it is included here for completeness as the options are loaded automatically in the class constructor.
85
- public function load_options() {
86
- $this->options = get_option( 'wp_statistics' );
87
-
88
- if ( ! is_array( $this->options ) ) {
89
- $this->user_options = array();
90
- }
91
- }
92
-
93
- // This function loads the user options from WordPress. It is NOT called during the class constructor.
94
- public function load_user_options( $force = false ) {
95
- if ( $this->user_options_loaded == true && $force != true ) {
96
- return;
97
- }
98
-
99
- $this->set_user_id();
100
-
101
- // Not sure why, but get_user_meta() is returning an array or array's unless $single is set to true.
102
- $this->user_options = get_user_meta( $this->user_id, 'wp_statistics', true );
103
-
104
- if ( ! is_array( $this->user_options ) ) {
105
- $this->user_options = array();
106
- }
107
-
108
- $this->user_options_loaded = true;
109
- }
110
-
111
- // The function mimics WordPress's get_option() function but uses the array instead of individual options.
112
- public function get_option( $option, $default = null ) {
113
- // If no options array exists, return FALSE.
114
- if ( ! is_array( $this->options ) ) {
115
- return false;
116
- }
117
-
118
- // if the option isn't set yet, return the $default if it exists, otherwise FALSE.
119
- if ( ! array_key_exists( $option, $this->options ) ) {
120
- if ( isset( $default ) ) {
121
- return $default;
122
- } else {
123
- return false;
124
- }
125
- }
126
-
127
- // Return the option.
128
- return $this->options[ $option ];
129
- }
130
-
131
- // This function mimics WordPress's get_user_meta() function but uses the array instead of individual options.
132
- public function get_user_option( $option, $default = null ) {
133
- // If the user id has not been set or no options array exists, return FALSE.
134
- if ( $this->user_id == 0 ) {
135
- return false;
136
- }
137
- if ( ! is_array( $this->user_options ) ) {
138
- return false;
139
- }
140
-
141
- // if the option isn't set yet, return the $default if it exists, otherwise FALSE.
142
- if ( ! array_key_exists( $option, $this->user_options ) ) {
143
- if ( isset( $default ) ) {
144
- return $default;
145
- } else {
146
- return false;
147
- }
148
- }
149
-
150
- // Return the option.
151
- return $this->user_options[ $option ];
152
- }
153
-
154
- // The function mimics WordPress's update_option() function but uses the array instead of individual options.
155
- public function update_option( $option, $value ) {
156
- // Store the value in the array.
157
- $this->options[ $option ] = $value;
158
-
159
- // Write the array to the database.
160
- update_option( 'wp_statistics', $this->options );
161
- }
162
-
163
- // The function mimics WordPress's update_user_meta() function but uses the array instead of individual options.
164
- public function update_user_option( $option, $value ) {
165
- // If the user id has not been set return FALSE.
166
- if ( $this->user_id == 0 ) {
167
- return false;
168
- }
169
-
170
- // Store the value in the array.
171
- $this->user_options[ $option ] = $value;
172
-
173
- // Write the array to the database.
174
- update_user_meta( $this->user_id, 'wp_statistics', $this->user_options );
175
- }
176
-
177
- // This function is similar to update_option, but it only stores the option in the array. This save some writing to the database if you have multiple values to update.
178
- public function store_option( $option, $value ) {
179
- $this->options[ $option ] = $value;
180
- }
181
-
182
- // This function is similar to update_user_option, but it only stores the option in the array. This save some writing to the database if you have multiple values to update.
183
- public function store_user_option( $option, $value ) {
184
- // If the user id has not been set return FALSE.
185
- if ( $this->user_id == 0 ) {
186
- return false;
187
- }
188
-
189
- $this->user_options[ $option ] = $value;
190
- }
191
-
192
- // This function saves the current options array to the database.
193
- public function save_options() {
194
- update_option( 'wp_statistics', $this->options );
195
- }
196
-
197
- // This function saves the current user options array to the database.
198
- public function save_user_options() {
199
- if ( $this->user_id == 0 ) {
200
- return false;
201
- }
202
-
203
- update_user_meta( $this->user_id, 'wp_statistics', $this->user_options );
204
- }
205
-
206
- // This function check to see if an option is currently set or not.
207
- public function isset_option( $option ) {
208
- if ( ! is_array( $this->options ) ) {
209
- return false;
210
- }
211
-
212
- return array_key_exists( $option, $this->options );
213
- }
214
-
215
- // This function check to see if a user option is currently set or not.
216
- public function isset_user_option( $option ) {
217
- if ( $this->user_id == 0 ) {
218
- return false;
219
- }
220
- if ( ! is_array( $this->user_options ) ) {
221
- return false;
222
- }
223
-
224
- return array_key_exists( $option, $this->user_options );
225
- }
226
-
227
- // During installation of WP Statistics some initial data needs to be loaded in to the database so errors are not displayed.
228
- // This function will add some initial data if the tables are empty.
229
- public function Primary_Values() {
230
-
231
- $this->result = $this->db->query( "SELECT * FROM {$this->tb_prefix}statistics_useronline" );
232
-
233
- if ( ! $this->result ) {
234
-
235
- $this->db->insert(
236
- $this->tb_prefix . "statistics_useronline",
237
- array(
238
- 'ip' => $this->get_IP(),
239
- 'timestamp' => $this->Current_Date( 'U' ),
240
- 'date' => $this->Current_Date(),
241
- 'referred' => $this->get_Referred(),
242
- 'agent' => $this->agent['browser'],
243
- 'platform' => $this->agent['platform'],
244
- 'version' => $this->agent['version']
245
- )
246
- );
247
- }
248
-
249
- $this->result = $this->db->query( "SELECT * FROM {$this->tb_prefix}statistics_visit" );
250
-
251
- if ( ! $this->result ) {
252
-
253
- $this->db->insert(
254
- $this->tb_prefix . "statistics_visit",
255
- array(
256
- 'last_visit' => $this->Current_Date(),
257
- 'last_counter' => $this->Current_date( 'Y-m-d' ),
258
- 'visit' => 1
259
- )
260
- );
261
- }
262
-
263
- $this->result = $this->db->query( "SELECT * FROM {$this->tb_prefix}statistics_visitor" );
264
-
265
- if ( ! $this->result ) {
266
-
267
- $this->db->insert(
268
- $this->tb_prefix . "statistics_visitor",
269
- array(
270
- 'last_counter' => $this->Current_date( 'Y-m-d' ),
271
- 'referred' => $this->get_Referred(),
272
- 'agent' => $this->agent['browser'],
273
- 'platform' => $this->agent['platform'],
274
- 'version' => $this->agent['version'],
275
- 'ip' => $this->get_IP(),
276
- 'location' => '000'
277
- )
278
- );
279
- }
280
- }
281
-
282
- // During installation of WP Statistics some initial options need to be set.
283
- // This function will save a set of default options for the plugin.
284
- public function Default_Options() {
285
- $options = array();
286
-
287
- // Get the robots list, we'll use this for both upgrades and new installs.
288
- include_once( $this->plugin_dir . '/robotslist.php' );
289
-
290
- $options['robotlist'] = trim( $wps_robotslist );
291
-
292
- // By default, on new installs, use the new search table.
293
- $options['search_converted'] = 1;
294
-
295
- // If this is a first time install or an upgrade and we've added options, set some intelligent defaults.
296
- $options['geoip'] = false;
297
- $options['browscap'] = false;
298
- $options['useronline'] = true;
299
- $options['visits'] = true;
300
- $options['visitors'] = true;
301
- $options['pages'] = true;
302
- $options['check_online'] = '30';
303
- $options['menu_bar'] = false;
304
- $options['coefficient'] = '1';
305
- $options['stats_report'] = false;
306
- $options['time_report'] = 'daily';
307
- $options['send_report'] = 'mail';
308
- $options['content_report'] = '';
309
- $options['update_geoip'] = true;
310
- $options['store_ua'] = false;
311
- $options['robotlist'] = $wps_robotslist;
312
- $options['exclude_administrator'] = true;
313
- $options['disable_se_clearch'] = true;
314
- $options['disable_se_ask'] = true;
315
- $options['map_type'] = 'jqvmap';
316
-
317
- $options['force_robot_update'] = true;
318
-
319
- return $options;
320
- }
321
-
322
- // This function processes a string that represents an IP address and returns either FALSE if it's invalid or a valid IP4 address.
323
- private function get_ip_value( $ip ) {
324
- // Reject anything that's not a string.
325
- if ( ! is_string( $ip ) ) {
326
- return false;
327
- }
328
-
329
- // Trim off any spaces.
330
- $ip = trim( $ip );
331
-
332
- // Process IPv4 and v6 addresses separately.
333
- if ( $this->isValidIPv6( $ip ) ) {
334
- // Reject any IPv6 addresses if IPv6 is not compiled in to this version of PHP.
335
- if ( ! defined( 'AF_INET6' ) ) {
336
- return false;
337
- }
338
- } else {
339
- // Trim off any port values that exist.
340
- if ( strstr( $ip, ':' ) !== false ) {
341
- $temp = explode( ':', $ip );
342
- $ip = $temp[0];
343
- }
344
-
345
- // Check to make sure the http header is actually an IP address and not some kind of SQL injection attack.
346
- $long = ip2long( $ip );
347
-
348
- // ip2long returns either -1 or FALSE if it is not a valid IP address depending on the PHP version, so check for both.
349
- if ( $long == - 1 || $long === false ) {
350
- return false;
351
- }
352
- }
353
-
354
- // If the ip address is blank, reject it.
355
- if ( $ip == '' ) {
356
- return false;
357
- }
358
-
359
- // We're got a real IP address, return it.
360
- return $ip;
361
-
362
- }
363
-
364
- // This function returns the current IP address of the remote client.
365
- public function get_IP() {
366
-
367
- // Check to see if we've already retrieved the IP address and if so return the last result.
368
- if ( $this->ip !== false ) {
369
- return $this->ip;
370
- }
371
-
372
- // By default we use the remote address the server has.
373
- if ( array_key_exists( 'REMOTE_ADDR', $_SERVER ) ) {
374
- $temp_ip = $this->get_ip_value( $_SERVER['REMOTE_ADDR'] );
375
- } else {
376
- $temp_ip = '127.0.0.1';
377
- }
378
-
379
- if ( false !== $temp_ip ) {
380
- $this->ip = $temp_ip;
381
- }
382
-
383
- /* Check to see if any of the HTTP headers are set to identify the remote user.
384
- * These often give better results as they can identify the remote user even through firewalls etc,
385
- * but are sometimes used in SQL injection attacks.
386
- *
387
- * We only want to take the first one we find, so search them in order and break when we find the first
388
- * one.
389
- *
390
- */
391
- $envs = array(
392
- 'HTTP_CLIENT_IP',
393
- 'HTTP_X_FORWARDED_FOR',
394
- 'HTTP_X_FORWARDED',
395
- 'HTTP_FORWARDED_FOR',
396
- 'HTTP_FORWARDED'
397
- );
398
-
399
- foreach ( $envs as $env ) {
400
- $temp_ip = $this->get_ip_value( getenv( $env ) );
401
-
402
- if ( false !== $temp_ip ) {
403
- $this->ip = $temp_ip;
404
-
405
- break;
406
- }
407
- }
408
-
409
- // If no valid ip address has been found, use 127.0.0.1 (aka localhost).
410
- if ( false === $this->ip ) {
411
- $this->ip = '127.0.0.1';
412
- }
413
-
414
- return $this->ip;
415
- }
416
-
417
- /**
418
- * Validate an IPv6 IP address
419
- *
420
- * @param string $ip
421
- *
422
- * @return boolean - true/false
423
- */
424
- private function isValidIPv6( $ip ) {
425
- if ( false === filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) ) {
426
- return false;
427
- } else {
428
- return true;
429
- }
430
- }
431
-
432
- // This function calls the user agent parsing code.
433
- public function get_UserAgent() {
434
-
435
- // Parse the agent stirng.
436
- try {
437
- $agent = parse_user_agent();
438
- } catch ( Exception $e ) {
439
- $agent = array( 'browser' => _x( 'Unknown', 'Browser', 'wp-statistics' ), 'platform' => _x( 'Unknown', 'Platform', 'wp-statistics' ), 'version' => _x( 'Unknown', 'Version', 'wp-statistics' ) );
440
- }
441
-
442
- // null isn't a very good default, so set it to Unknown instead.
443
- if ( $agent['browser'] == null ) {
444
- $agent['browser'] = _x( 'Unknown', 'Browser', 'wp-statistics' );
445
- }
446
- if ( $agent['platform'] == null ) {
447
- $agent['platform'] = _x( 'Unknown', 'Platform', 'wp-statistics' );
448
- }
449
- if ( $agent['version'] == null ) {
450
- $agent['version'] = _x( 'Unknown', 'Version', 'wp-statistics' );
451
- }
452
-
453
- // Uncommon browsers often have some extra cruft, like brackets, http:// and other strings that we can strip out.
454
- $strip_strings = array( '"', "'", '(', ')', ';', ':', '/', '[', ']', '{', '}', 'http' );
455
- foreach ( $agent as $key => $value ) {
456
- $agent[ $key ] = str_replace( $strip_strings, '', $agent[ $key ] );
457
- }
458
-
459
- return $agent;
460
- }
461
-
462
- // This function will return the referrer link for the current user.
463
- public function get_Referred( $default_referrer = false ) {
464
-
465
- if ( $this->referrer !== false ) {
466
- return $this->referrer;
467
- }
468
-
469
- $this->referrer = '';
470
-
471
- if ( isset( $_SERVER['HTTP_REFERER'] ) ) {
472
- $this->referrer = $_SERVER['HTTP_REFERER'];
473
- }
474
- if ( $default_referrer ) {
475
- $this->referrer = $default_referrer;
476
- }
477
-
478
- $this->referrer = esc_sql( strip_tags( $this->referrer ) );
479
-
480
- if ( ! $this->referrer ) {
481
- $this->referrer = get_bloginfo( 'url' );
482
- }
483
-
484
- if ( $this->get_option( 'addsearchwords', false ) ) {
485
- // Check to see if this is a search engine referrer
486
- $SEInfo = $this->Search_Engine_Info( $this->referrer );
487
-
488
- if ( is_array( $SEInfo ) ) {
489
- // If we're a known SE, check the query string
490
- if ( $SEInfo['tag'] != '' ) {
491
- $result = $this->Search_Engine_QueryString( $this->referrer );
492
-
493
- // If there were no search words, let's add the page title
494
- if ( $result == '' || $result == 'No search query found!' ) {
495
- $result = wp_title( '', false );
496
- if ( $result != '' ) {
497
- $this->referrer = esc_url( add_query_arg( $SEInfo['querykey'], urlencode( '~"' . $result . '"' ), $this->referrer ) );
498
- }
499
- }
500
- }
501
- }
502
- }
503
-
504
- return $this->referrer;
505
- }
506
-
507
- // This function returns a date string in the desired format with a passed in timestamp.
508
- public function Local_Date( $format, $timestamp ) {
509
- return date( $format, $timestamp + $this->tz_offset );
510
- }
511
-
512
- // This function returns a date string in the desired format.
513
- public function Current_Date( $format = 'Y-m-d H:i:s', $strtotime = null, $relative = null ) {
514
-
515
- if ( $strtotime ) {
516
- if ( $relative ) {
517
- return date( $format, strtotime( "{$strtotime} day", $relative ) + $this->tz_offset );
518
- } else {
519
- return date( $format, strtotime( "{$strtotime} day" ) + $this->tz_offset );
520
- }
521
- } else {
522
- return date( $format, time() + $this->tz_offset );
523
- }
524
- }
525
-
526
- // This function returns a date string in the desired format.
527
- public function Real_Current_Date( $format = 'Y-m-d H:i:s', $strtotime = null, $relative = null ) {
528
-
529
- if ( $strtotime ) {
530
- if ( $relative ) {
531
- return date( $format, strtotime( "{$strtotime} day", $relative ) );
532
- } else {
533
- return date( $format, strtotime( "{$strtotime} day" ) );
534
- }
535
- } else {
536
- return date( $format, time() );
537
- }
538
- }
539
-
540
- // This function returns an internationalized date string in the desired format.
541
- public function Current_Date_i18n( $format = 'Y-m-d H:i:s', $strtotime = null, $day = ' day' ) {
542
-
543
- if ( $strtotime ) {
544
- return date_i18n( $format, strtotime( "{$strtotime}{$day}" ) + $this->tz_offset );
545
- } else {
546
- return date_i18n( $format, time() + $this->tz_offset );
547
- }
548
- }
549
-
550
- public function strtotimetz( $timestring ) {
551
- return strtotime( $timestring ) + $this->tz_offset;
552
- }
553
-
554
- public function timetz() {
555
- return time() + $this->tz_offset;
556
- }
557
-
558
- // This function checks to see if a search engine exists in the current list of search engines.
559
- public function Check_Search_Engines( $search_engine_name, $search_engine = null ) {
560
-
561
- if ( strstr( $search_engine, $search_engine_name ) ) {
562
- return 1;
563
- }
564
- }
565
-
566
- // This function returns an array of information about a given search engine based on the url passed in.
567
- // It is used in several places to get the SE icon or the sql query to select an individual SE from the database.
568
- public function Search_Engine_Info( $url = false ) {
569
-
570
- // If no URL was passed in, get the current referrer for the session.
571
- if ( ! $url ) {
572
- $url = isset( $_SERVER['HTTP_REFERER'] ) ? $this->get_Referred() : false;
573
- }
574
-
575
- // If there is no URL and no referrer, always return false.
576
- if ( $url == false ) {
577
- return false;
578
- }
579
-
580
- // Parse the URL in to it's component parts.
581
- $parts = parse_url( $url );
582
-
583
- // Get the list of search engines we currently support.
584
- $search_engines = wp_statistics_searchengine_list();
585
-
586
- // Loop through the SE list until we find which search engine matches.
587
- foreach ( $search_engines as $key => $value ) {
588
- $search_regex = wp_statistics_searchengine_regex( $key );
589
-
590
- preg_match( '/' . $search_regex . '/', $parts['host'], $matches );
591
-
592
- if ( isset( $matches[1] ) ) {
593
- // Return the first matched SE.
594
- return $value;
595
- }
596
- }
597
-
598
- // If no SE matched, return some defaults.
599
- return array(
600
- 'name' => _x( 'Unknown', 'Search Engine', 'wp-statistics' ),
601
- 'tag' => '',
602
- 'sqlpattern' => '',
603
- 'regexpattern' => '',
604
- 'querykey' => 'q',
605
- 'image' => 'unknown.png'
606
- );
607
- }
608
-
609
- // This function returns an array of information about a given search engine based on the url passed in.
610
- // It is used in several places to get the SE icon or the sql query to select an individual SE from the database.
611
- public function Search_Engine_Info_By_Engine( $engine = false ) {
612
-
613
- // If there is no URL and no referrer, always return false.
614
- if ( $engine == false ) {
615
- return false;
616
- }
617
-
618
- // Get the list of search engines we currently support.
619
- $search_engines = wp_statistics_searchengine_list();
620
-
621
- if ( array_key_exists( $engine, $search_engines ) ) {
622
- return $search_engines[ $engine ];
623
- }
624
-
625
- // If no SE matched, return some defaults.
626
- return array(
627
- 'name' => _x( 'Unknown', 'Search Engine', 'wp-statistics' ),
628
- 'tag' => '',
629
- 'sqlpattern' => '',
630
- 'regexpattern' => '',
631
- 'querykey' => 'q',
632
- 'image' => 'unknown.png'
633
- );
634
- }
635
-
636
- // This function will parse a URL from a referrer and return the search query words used.
637
- public function Search_Engine_QueryString( $url = false ) {
638
-
639
- // If no URL was passed in, get the current referrer for the session.
640
- if ( ! $url ) {
641
- $url = isset( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : false;
642
- }
643
-
644
- // If there is no URL and no referrer, always return false.
645
- if ( $url == false ) {
646
- return false;
647
- }
648
-
649
- // Parse the URL in to it's component parts.
650
- $parts = parse_url( $url );
651
-
652
- // Check to see if there is a query component in the URL (everything after the ?). If there isn't one
653
- // set an empty array so we don't get errors later.
654
- if ( array_key_exists( 'query', $parts ) ) {
655
- parse_str( $parts['query'], $query );
656
- } else {
657
- $query = array();
658
- }
659
-
660
- // Get the list of search engines we currently support.
661
- $search_engines = wp_statistics_searchengine_list();
662
-
663
- // Loop through the SE list until we find which search engine matches.
664
- foreach ( $search_engines as $key => $value ) {
665
- $search_regex = wp_statistics_searchengine_regex( $key );
666
-
667
- preg_match( '/' . $search_regex . '/', $parts['host'], $matches );
668
-
669
- if ( isset( $matches[1] ) ) {
670
- // Check to see if the query key the SE uses exists in the query part of the URL.
671
- if ( array_key_exists( $search_engines[ $key ]['querykey'], $query ) ) {
672
- $words = strip_tags( $query[ $search_engines[ $key ]['querykey'] ] );
673
- } else {
674
- $words = '';
675
- }
676
-
677
- // If no words were found, return a pleasant default.
678
- if ( $words == '' ) {
679
- $words = 'No search query found!';
680
- }
681
-
682
- return $words;
683
- }
684
- }
685
-
686
- // We should never actually get to this point, but let's make sure we return something
687
- // just in case something goes terribly wrong.
688
- return 'No search query found!';
689
- }
690
-
691
- public function Get_Historical_Data( $type, $id = '' ) {
692
-
693
- $count = 0;
694
-
695
- switch ( $type ) {
696
- case 'visitors':
697
- if ( array_key_exists( 'visitors', $this->historical ) ) {
698
- return $this->historical['visitors'];
699
- } else {
700
- $result = $this->db->get_var( "SELECT value FROM {$this->tb_prefix}statistics_historical WHERE category = 'visitors'" );
701
- if ( $result > $count ) {
702
- $count = $result;
703
- }
704
- $this->historical['visitors'] = $count;
705
- }
706
-
707
- break;
708
- case 'visits':
709
- if ( array_key_exists( 'visits', $this->historical ) ) {
710
- return $this->historical['visits'];
711
- } else {
712
- $result = $this->db->get_var( "SELECT value FROM {$this->tb_prefix}statistics_historical WHERE category = 'visits'" );
713
- if ( $result > $count ) {
714
- $count = $result;
715
- }
716
- $this->historical['visits'] = $count;
717
- }
718
-
719
- break;
720
- case 'uri':
721
- if ( array_key_exists( $id, $this->historical ) ) {
722
- return $this->historical[ $id ];
723
- } else {
724
- $result = $this->db->get_var( $this->db->prepare( "SELECT value FROM {$this->tb_prefix}statistics_historical WHERE category = 'uri' AND uri = %s", $id ) );
725
- if ( $result > $count ) {
726
- $count = $result;
727
- }
728
- $this->historical[ $id ] = $count;
729
- }
730
-
731
- break;
732
- case 'page':
733
- if ( array_key_exists( $id, $this->historical ) ) {
734
- return $this->historical[ $id ];
735
- } else {
736
- $result = $this->db->get_var( $this->db->prepare( "SELECT value FROM {$this->tb_prefix}statistics_historical WHERE category = 'uri' AND page_id = %d", $id ) );
737
- if ( $result > $count ) {
738
- $count = $result;
739
- }
740
- $this->historical[ $id ] = $count;
741
- }
742
-
743
- break;
744
- }
745
-
746
- return $count;
747
- }
748
-
749
- public function feed_detected() {
750
- $this->is_feed = true;
751
- }
752
-
753
- public function check_feed() {
754
- return $this->is_feed;
755
- }
756
-
757
- public function get_country_codes() {
758
- if ( $this->country_codes == false ) {
759
- $ISOCountryCode = array();
760
- include( $this->plugin_dir . "/includes/functions/country-codes.php" );
761
- $this->country_codes = $ISOCountryCode;
762
- }
763
-
764
- return $this->country_codes;
765
- }
766
-
767
- // Returns an array of site id's
768
- public function get_wp_sites_list() {
769
- GLOBAL $wp_version;
770
-
771
- $site_list = array();
772
-
773
- // wp_get_sites() is deprecated in 4.6 or above and replaced with get_sites().
774
- if ( version_compare( $wp_version, '4.6', '>=' ) ) {
775
- $sites = get_sites();
776
-
777
- foreach ( $sites as $site ) {
778
- $site_list[] = $site->blog_id;
779
- }
780
- } else {
781
- $sites = wp_get_sites();
782
-
783
- foreach ( $sites as $site ) {
784
- $site_list[] = $site['blog_id'];
785
- }
786
- }
787
-
788
- return $site_list;
789
- }
790
-
791
- public function html_sanitize_referrer( $referrer, $length = - 1 ) {
792
- $referrer = trim( $referrer );
793
-
794
- if ( 'data:' == strtolower( substr( $referrer, 0, 5 ) ) ) {
795
- $referrer = 'http://127.0.0.1';
796
- }
797
-
798
- if ( 'javascript:' == strtolower( substr( $referrer, 0, 11 ) ) ) {
799
- $referrer = 'http://127.0.0.1';
800
- }
801
-
802
- if ( $length > 0 ) {
803
- $referrer = substr( $referrer, 0, $length );
804
- }
805
-
806
- return htmlentities( $referrer, ENT_QUOTES );
807
- }
808
-
809
- public function get_referrer_link( $referrer, $length = - 1 ) {
810
- $html_referrer = $this->html_sanitize_referrer( $referrer );
811
-
812
- if ( $length > 0 && strlen( $referrer ) > $length ) {
813
- $html_referrer_limited = $this->html_sanitize_referrer( $referrer, $length );
814
- $eplises = '[...]';
815
- } else {
816
- $html_referrer_limited = $html_referrer;
817
- $eplises = '';
818
- }
819
-
820
- return "<a href='{$html_referrer}'><div class='dashicons dashicons-admin-links'></div>{$html_referrer_limited}{$eplises}</a>";
821
- }
822
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/functions/country-codes.php CHANGED
@@ -4,7 +4,7 @@
4
 
5
  It is used in several places in the plugin and is therefore centralized here for ease of update.
6
  */
7
- $ISOCountryCode['000'] = _x( 'Unknown', 'Country', 'wp-statistics' );
8
  $ISOCountryCode['AF'] = "Afghanistan";
9
  $ISOCountryCode['AX'] = "Åland Islands";
10
  $ISOCountryCode['AL'] = "Albania";
@@ -285,4 +285,3 @@ $ISOCountryCode['YU'] = "Yugoslavia";
285
  $ISOCountryCode['ZR'] = "Zaire";
286
  $ISOCountryCode['ZM'] = "Zambia";
287
  $ISOCountryCode['ZW'] = "Zimbabwe";
288
- ?>
4
 
5
  It is used in several places in the plugin and is therefore centralized here for ease of update.
6
  */
7
+ $ISOCountryCode['000'] = _x('Unknown', 'Country', 'wp-statistics');
8
  $ISOCountryCode['AF'] = "Afghanistan";
9
  $ISOCountryCode['AX'] = "Åland Islands";
10
  $ISOCountryCode['AL'] = "Albania";
285
  $ISOCountryCode['ZR'] = "Zaire";
286
  $ISOCountryCode['ZM'] = "Zambia";
287
  $ISOCountryCode['ZW'] = "Zimbabwe";
 
includes/functions/country-coordinates.php CHANGED
@@ -247,4 +247,3 @@ $CountryCoordinates["EH"] = array( "lat" => "24.5", "lng" => "-13" );
247
  $CountryCoordinates["YE"] = array( "lat" => "15", "lng" => "48" );
248
  $CountryCoordinates["ZM"] = array( "lat" => "-15", "lng" => "30" );
249
  $CountryCoordinates["ZW"] = array( "lat" => "-20", "lng" => "30" );
250
- ?>
247
  $CountryCoordinates["YE"] = array( "lat" => "15", "lng" => "48" );
248
  $CountryCoordinates["ZM"] = array( "lat" => "-15", "lng" => "30" );
249
  $CountryCoordinates["ZW"] = array( "lat" => "-20", "lng" => "30" );
 
includes/functions/export.php CHANGED
@@ -1,16 +1,31 @@
1
  <?php
2
  function wp_statistics_export_data() {
 
 
 
 
 
3
  GLOBAL $WP_Statistics, $wpdb; // this is how you get access to the database
4
 
5
- $manage_cap = wp_statistics_validate_capability( $WP_Statistics->get_option( 'manage_capability', 'manage_options' ) );
 
 
 
 
 
6
 
7
- if ( current_user_can( $manage_cap ) ) {
8
- $table = $_POST['table-to-export'];
9
- $type = $_POST['export-file-type'];
10
- $headers = $_POST['export-headers'];
11
 
12
  // Validate the table name the user passed to us.
13
- if ( ! ( $table == "useronline" || $table == "visit" || $table == "visitor" || $table == "exclusions" || $table == "pages" || $table == "search" ) ) {
 
 
 
 
 
 
14
  $table = false;
15
  }
16
 
@@ -20,24 +35,20 @@ function wp_statistics_export_data() {
20
  }
21
 
22
  if ( $table && $type ) {
23
-
24
- require( $WP_Statistics->plugin_dir . '/includes/classes/php-export-data.class.php' );
25
-
26
- $file_name = WPS_EXPORT_FILE_NAME . '-' . $WP_Statistics->Current_Date( 'Y-m-d-H-i' );
27
 
28
  switch ( $type ) {
29
  case 'xml':
30
- $exporter = new ExportDataExcel( 'browser', "{$file_name}.xml" );
31
-
32
- break;
33
  case 'csv':
34
- $exporter = new ExportDataCSV( 'browser', "{$file_name}.csv" );
35
-
36
- break;
37
  case 'tsv':
38
- $exporter = new ExportDataTSV( 'browser', "{$file_name}.tsv" );
39
-
40
- break;
41
  }
42
 
43
  $exporter->initialize();
@@ -48,25 +59,24 @@ function wp_statistics_export_data() {
48
 
49
  $i = 1;
50
  $more_results = true;
51
- $result = $wpdb->get_results( $query, ARRAY_A );
52
 
53
  // If we didn't get any rows, don't output anything.
54
- if ( count( $result ) < 1 ) {
55
  echo "No data in table!";
56
  exit;
57
  }
58
 
59
- if ( $headers ) {
60
  foreach ( $result[0] as $key => $col ) {
61
  $columns[] = $key;
62
  }
63
- $exporter->addRow( $columns );
64
  }
65
 
66
-
67
  while ( $more_results ) {
68
  foreach ( $result as $row ) {
69
- $exporter->addRow( $row );
70
 
71
  // Make sure we've flushed the output buffer so we don't run out of memory on large exports.
72
  ob_flush();
@@ -77,13 +87,13 @@ function wp_statistics_export_data() {
77
  $wpdb->flush();
78
 
79
  $query = $query_base . ' LIMIT ' . ( $i * 1000 ) . ',1000';
80
- $result = $wpdb->get_results( $query, ARRAY_A );
81
 
82
- if ( count( $result ) == 0 ) {
83
  $more_results = false;
84
  }
85
 
86
- $i ++;
87
  }
88
 
89
  $exporter->finalize();
@@ -92,5 +102,3 @@ function wp_statistics_export_data() {
92
  }
93
  }
94
  }
95
-
96
- ?>
1
  <?php
2
  function wp_statistics_export_data() {
3
+
4
+ if ( ! isset( $_POST['table-to-export'] ) or ! isset( $_POST['export-file-type'] ) ) {
5
+ return;
6
+ }
7
+
8
  GLOBAL $WP_Statistics, $wpdb; // this is how you get access to the database
9
 
10
+ $manage_cap = wp_statistics_validate_capability(
11
+ $WP_Statistics->get_option(
12
+ 'manage_capability',
13
+ 'manage_options'
14
+ )
15
+ );
16
 
17
+ if ( current_user_can($manage_cap) ) {
18
+ $table = $_POST['table-to-export'];
19
+ $type = $_POST['export-file-type'];
 
20
 
21
  // Validate the table name the user passed to us.
22
+ if ( ! ( $table == "useronline" ||
23
+ $table == "visit" ||
24
+ $table == "visitor" ||
25
+ $table == "exclusions" ||
26
+ $table == "pages" ||
27
+ $table == "search" )
28
+ ) {
29
  $table = false;
30
  }
31
 
35
  }
36
 
37
  if ( $table && $type ) {
38
+ require( WP_Statistics::$reg['plugin-dir'] . 'includes/github/elidickinson/php-export-data/php-export-data.class.php' );
39
+
40
+ $file_name = 'wp-statistics' . '-' . $WP_Statistics->Current_Date('Y-m-d-H-i');
 
41
 
42
  switch ( $type ) {
43
  case 'xml':
44
+ $exporter = new ExportDataExcel('browser', "{$file_name}.xml");
45
+ break;
 
46
  case 'csv':
47
+ $exporter = new ExportDataCSV('browser', "{$file_name}.csv");
48
+ break;
 
49
  case 'tsv':
50
+ $exporter = new ExportDataTSV('browser', "{$file_name}.tsv");
51
+ break;
 
52
  }
53
 
54
  $exporter->initialize();
59
 
60
  $i = 1;
61
  $more_results = true;
62
+ $result = $wpdb->get_results($query, ARRAY_A);
63
 
64
  // If we didn't get any rows, don't output anything.
65
+ if ( count($result) < 1 ) {
66
  echo "No data in table!";
67
  exit;
68
  }
69
 
70
+ if ( isset( $_POST['export-headers'] ) and $_POST['export-headers'] ) {
71
  foreach ( $result[0] as $key => $col ) {
72
  $columns[] = $key;
73
  }
74
+ $exporter->addRow($columns);
75
  }
76
 
 
77
  while ( $more_results ) {
78
  foreach ( $result as $row ) {
79
+ $exporter->addRow($row);
80
 
81
  // Make sure we've flushed the output buffer so we don't run out of memory on large exports.
82
  ob_flush();
87
  $wpdb->flush();
88
 
89
  $query = $query_base . ' LIMIT ' . ( $i * 1000 ) . ',1000';
90
+ $result = $wpdb->get_results($query, ARRAY_A);
91
 
92
+ if ( count($result) == 0 ) {
93
  $more_results = false;
94
  }
95
 
96
+ $i++;
97
  }
98
 
99
  $exporter->finalize();
102
  }
103
  }
104
  }
 
 
includes/functions/functions.php CHANGED
@@ -11,7 +11,7 @@ function wp_statistics_useronline() {
11
 
12
  global $wpdb;
13
 
14
- return $wpdb->query( "SELECT * FROM {$wpdb->prefix}statistics_useronline" );
15
  }
16
 
17
  // This function get the visit statistics for a given time frame.
@@ -24,7 +24,9 @@ function wp_statistics_visit( $time, $daily = null ) {
24
  if ( $daily == true ) {
25
 
26
  // Fetch the results from the database.
27
- $result = $wpdb->get_row( "SELECT * FROM {$wpdb->prefix}statistics_visit WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d', $time )}'" );
 
 
28
 
29
  // If we have a result, return it, otherwise force a 0 to be returned instead of the logical FALSE that would otherwise be the case.
30
  if ( $result ) {
@@ -40,33 +42,45 @@ function wp_statistics_visit( $time, $daily = null ) {
40
 
41
  switch ( $time ) {
42
  case 'today':
43
- $result = $wpdb->get_var( "SELECT SUM(visit) FROM {$wpdb->prefix}statistics_visit WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d' )}'" );
44
- break;
 
 
45
 
46
  case 'yesterday':
47
- $result = $wpdb->get_var( "SELECT SUM(visit) FROM {$wpdb->prefix}statistics_visit WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d', -1 )}'" );
48
- break;
 
 
49
 
50
  case 'week':
51
- $result = $wpdb->get_var( "SELECT SUM(visit) FROM {$wpdb->prefix}statistics_visit WHERE `last_counter` BETWEEN '{$WP_Statistics->Current_Date( 'Y-m-d', -7 )}' AND '{$WP_Statistics->Current_Date( 'Y-m-d' )}'" );
52
- break;
 
 
53
 
54
  case 'month':
55
- $result = $wpdb->get_var( "SELECT SUM(visit) FROM {$wpdb->prefix}statistics_visit WHERE `last_counter` BETWEEN '{$WP_Statistics->Current_Date( 'Y-m-d', -30 )}' AND '{$WP_Statistics->Current_Date( 'Y-m-d' )}'" );
56
- break;
 
 
57
 
58
  case 'year':
59
- $result = $wpdb->get_var( "SELECT SUM(visit) FROM {$wpdb->prefix}statistics_visit WHERE `last_counter` BETWEEN '{$WP_Statistics->Current_Date( 'Y-m-d', -365 )}' AND '{$WP_Statistics->Current_Date( 'Y-m-d' )}'" );
60
- break;
 
 
61
 
62
  case 'total':
63
- $result = $wpdb->get_var( "SELECT SUM(visit) FROM {$wpdb->prefix}statistics_visit" );
64
- $result += $WP_Statistics->Get_Historical_Data( 'visits' );
65
- break;
66
 
67
  default:
68
- $result = $wpdb->get_var( "SELECT SUM(visit) FROM {$wpdb->prefix}statistics_visit WHERE `last_counter` BETWEEN '{$WP_Statistics->Current_Date( 'Y-m-d', $time )}' AND '{$WP_Statistics->Current_Date( 'Y-m-d' )}'" );
69
- break;
 
 
70
  }
71
  }
72
 
@@ -97,7 +111,9 @@ function wp_statistics_visitor( $time, $daily = null, $countonly = false ) {
97
  if ( $daily == true ) {
98
 
99
  // Fetch the results from the database.
100
- $result = $wpdb->query( "SELECT {$select} FROM {$wpdb->prefix}statistics_visitor WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d', $time )}'" );
 
 
101
 
102
  return $result;
103
 
@@ -107,49 +123,55 @@ function wp_statistics_visitor( $time, $daily = null, $countonly = false ) {
107
  // They're pretty self explanatory.
108
  switch ( $time ) {
109
  case 'today':
110
- $sqlstatement = "SELECT {$select} FROM {$wpdb->prefix}statistics_visitor WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d' )}'";
111
- break;
 
112
 
113
  case 'yesterday':
114
- $sqlstatement = "SELECT {$select} FROM {$wpdb->prefix}statistics_visitor WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d', -1 )}'";
115
- break;
 
116
 
117
  case 'week':
118
- $sqlstatement = "SELECT {$select} FROM {$wpdb->prefix}statistics_visitor WHERE `last_counter` BETWEEN '{$WP_Statistics->Current_Date( 'Y-m-d', -7 )}' AND '{$WP_Statistics->Current_Date( 'Y-m-d' )}'";
119
- break;
 
120
 
121
  case 'month':
122
- $sqlstatement = "SELECT {$select} FROM {$wpdb->prefix}statistics_visitor WHERE `last_counter` BETWEEN '{$WP_Statistics->Current_Date( 'Y-m-d', -30 )}' AND '{$WP_Statistics->Current_Date( 'Y-m-d' )}'";
123
- break;
 
124
 
125
  case 'year':
126
- $sqlstatement = "SELECT {$select} FROM {$wpdb->prefix}statistics_visitor WHERE `last_counter` BETWEEN '{$WP_Statistics->Current_Date( 'Y-m-d', -365 )}' AND '{$WP_Statistics->Current_Date( 'Y-m-d' )}'";
127
- break;
 
128
 
129
  case 'total':
130
  $sqlstatement = "SELECT {$select} FROM {$wpdb->prefix}statistics_visitor";
131
- $history = $WP_Statistics->Get_Historical_Data( 'visitors' );
132
- break;
133
 
134
  default:
135
- $sqlstatement = "SELECT {$select} FROM {$wpdb->prefix}statistics_visitor WHERE `last_counter` BETWEEN '{$WP_Statistics->Current_Date( 'Y-m-d', $time )}' AND '{$WP_Statistics->Current_Date( 'Y-m-d' )}'";
136
- break;
 
137
  }
138
  }
139
 
140
  // Execute the SQL call, if we're only counting we can use get_var(), otherwise we use query().
141
  if ( $countonly == true ) {
142
- $result = $wpdb->get_var( $sqlstatement );
143
  $result += $history;
144
  } else {
145
- $result = $wpdb->query( $sqlstatement );
146
  }
147
 
148
  return $result;
149
  }
150
 
151
  // This function returns the statistics for a given page.
152
- function wp_statistics_pages( $time, $page_uri = '', $id = - 1, $rangestartdate = null, $rangeenddate = null ) {
153
 
154
  // We need database and the global $WP_Statistics object access.
155
  global $wpdb, $WP_Statistics;
@@ -162,14 +184,14 @@ function wp_statistics_pages( $time, $page_uri = '', $id = - 1, $rangestartdate
162
  $page_uri = wp_statistics_get_uri();
163
  }
164
 
165
- $page_uri_sql = esc_sql( $page_uri );
166
 
167
  // If a page/post ID has been passed, use it to select the rows, otherwise use the URI.
168
  // Note that a single page/post ID can have multiple URI's associated with it.
169
- if ( $id != - 1 ) {
170
- $page_sql = '`id` = ' . absint( $id );
171
  $history_key = 'page';
172
- $history_id = absint( $id );
173
  } else {
174
  $page_sql = "`URI` = '{$page_uri_sql}'";
175
  $history_key = 'uri';
@@ -180,40 +202,50 @@ function wp_statistics_pages( $time, $page_uri = '', $id = - 1, $rangestartdate
180
  // They're pretty self explanatory.
181
  switch ( $time ) {
182
  case 'today':
183
- $sqlstatement = "SELECT SUM(count) FROM {$wpdb->prefix}statistics_pages WHERE `date` = '{$WP_Statistics->Current_Date( 'Y-m-d' )}' AND {$page_sql}";
184
- break;
 
185
 
186
  case 'yesterday':
187
- $sqlstatement = "SELECT SUM(count) FROM {$wpdb->prefix}statistics_pages WHERE `date` = '{$WP_Statistics->Current_Date( 'Y-m-d', -1 )}' AND {$page_sql}";
188
- break;
 
189
 
190
  case 'week':
191
- $sqlstatement = "SELECT SUM(count) FROM {$wpdb->prefix}statistics_pages WHERE `date` BETWEEN '{$WP_Statistics->Current_Date( 'Y-m-d', -7 )}' AND '{$WP_Statistics->Current_Date( 'Y-m-d' )}' AND {$page_sql}";
192
- break;
 
193
 
194
  case 'month':
195
- $sqlstatement = "SELECT SUM(count) FROM {$wpdb->prefix}statistics_pages WHERE `date` BETWEEN '{$WP_Statistics->Current_Date( 'Y-m-d', -30 )}' AND '{$WP_Statistics->Current_Date( 'Y-m-d' )}' AND {$page_sql}";
196
- break;
 
197
 
198
  case 'year':
199
- $sqlstatement = "SELECT SUM(count) FROM {$wpdb->prefix}statistics_pages WHERE `date` BETWEEN '{$WP_Statistics->Current_Date( 'Y-m-d', -365 )}' AND '{$WP_Statistics->Current_Date( 'Y-m-d' )}' AND {$page_sql}";
200
- break;
 
201
 
202
  case 'total':
203
  $sqlstatement = "SELECT SUM(count) FROM {$wpdb->prefix}statistics_pages WHERE {$page_sql}";
204
- $history = $WP_Statistics->Get_Historical_Data( $history_key, $history_id );
205
- break;
206
  case 'range':
207
- $sqlstatement = "SELECT SUM(count) FROM {$wpdb->prefix}statistics_pages WHERE `date` BETWEEN '" . $WP_Statistics->Current_Date( 'Y-m-d', '-0', strtotime( $rangestartdate ) ) . "' AND '" . $WP_Statistics->Current_Date( 'Y-m-d', '-0', strtotime( $rangeenddate ) ) . "' AND {$page_sql}";
 
 
 
 
208
 
209
- break;
210
  default:
211
- $sqlstatement = "SELECT SUM(count) FROM {$wpdb->prefix}statistics_pages WHERE `date` = '{$WP_Statistics->Current_Date( 'Y-m-d', $time )}' AND {$page_sql}";
212
- break;
 
213
  }
214
 
215
  // Since this function only every returns a count, just use get_var().
216
- $result = $wpdb->get_var( $sqlstatement );
217
  $result += $history;
218
 
219
  // If we have an empty result, return 0 instead of a blank.
@@ -230,10 +262,13 @@ function wp_statistics_uri_to_id( $uri ) {
230
  global $wpdb;
231
 
232
  // Create the SQL query to use.
233
- $sqlstatement = $wpdb->prepare( "SELECT id FROM {$wpdb->prefix}statistics_pages WHERE `URI` = %s AND id > 0 ORDER BY date DESC", $uri );
 
 
 
234
 
235
  // Execute the query.
236
- $result = $wpdb->get_var( $sqlstatement );
237
 
238
  // If we returned a false or some other 0 equivalent value, make sure $result is set to an integer 0.
239
  if ( $result == 0 ) {
@@ -254,9 +289,16 @@ function wp_statistics_get_top_pages( $rangestartdate = null, $rangeenddate = nu
254
 
255
  // Get every unique URI from the pages database.
256
  if ( $rangestartdate != null && $rangeenddate != null ) {
257
- $result = $wpdb->get_results( $wpdb->prepare( "SELECT DISTINCT uri FROM {$wpdb->prefix}statistics_pages WHERE `date` BETWEEN %s AND %s", $rangestartdate, $rangeenddate ), ARRAY_N );
 
 
 
 
 
 
 
258
  } else {
259
- $result = $wpdb->get_results( "SELECT DISTINCT uri FROM {$wpdb->prefix}statistics_pages", ARRAY_N );
260
  }
261
 
262
  $total = 0;
@@ -265,15 +307,15 @@ function wp_statistics_get_top_pages( $rangestartdate = null, $rangeenddate = nu
265
  // Now get the total page visit count for each unique URI.
266
  foreach ( $result as $out ) {
267
  // Increment the total number of results.
268
- $total ++;
269
 
270
  // Retreive the post ID for the URI.
271
- $id = wp_statistics_uri_to_id( $out[0] );
272
 
273
  // Lookup the post title.
274
- $post = get_post( $id );
275
 
276
- if ( is_object( $post ) ) {
277
  $title = $post->post_title;
278
  } else {
279
  if ( $out[0] == '/' ) {
@@ -287,19 +329,19 @@ function wp_statistics_get_top_pages( $rangestartdate = null, $rangeenddate = nu
287
  if ( $rangestartdate != null && $rangeenddate != null ) {
288
  $uris[] = array(
289
  $out[0],
290
- wp_statistics_pages( 'range', $out[0], - 1, $rangestartdate, $rangeenddate ),
291
  $id,
292
- $title
293
  );
294
  } else {
295
- $uris[] = array( $out[0], wp_statistics_pages( 'total', $out[0] ), $id, $title );
296
  }
297
  }
298
 
299
  // If we have more than one result, let's sort them using usort.
300
- if ( count( $uris ) > 1 ) {
301
  // Sort the URI's based on their hit count.
302
- usort( $uris, 'wp_stats_compare_uri_hits' );
303
  }
304
 
305
  return array( $total, $uris );
@@ -308,12 +350,12 @@ function wp_statistics_get_top_pages( $rangestartdate = null, $rangeenddate = nu
308
  // This function gets the current page URI.
309
  function wp_statistics_get_uri() {
310
  // Get the site's path from the URL.
311
- $site_uri = parse_url( site_url(), PHP_URL_PATH );
312
- $site_uri_len = strlen( $site_uri );
313
 
314
  // Get the site's path from the URL.
315
- $home_uri = parse_url( home_url(), PHP_URL_PATH );
316
- $home_uri_len = strlen( $home_uri );
317
 
318
  // Get the current page URI.
319
  $page_uri = $_SERVER["REQUEST_URI"];
@@ -327,20 +369,20 @@ function wp_statistics_get_uri() {
327
  * we check for "/site", but in the reverse case, we need to swap the order of the check.
328
  */
329
  if ( $site_uri_len > $home_uri_len ) {
330
- if ( substr( $page_uri, 0, $site_uri_len ) == $site_uri ) {
331
- $page_uri = substr( $page_uri, $site_uri_len );
332
  }
333
 
334
- if ( substr( $page_uri, 0, $home_uri_len ) == $home_uri ) {
335
- $page_uri = substr( $page_uri, $home_uri_len );
336
  }
337
  } else {
338
- if ( substr( $page_uri, 0, $home_uri_len ) == $home_uri ) {
339
- $page_uri = substr( $page_uri, $home_uri_len );
340
  }
341
 
342
- if ( substr( $page_uri, 0, $site_uri_len ) == $site_uri ) {
343
- $page_uri = substr( $page_uri, $site_uri_len );
344
  }
345
  }
346
 
@@ -358,9 +400,16 @@ function wp_statistics_ua_list( $rangestartdate = null, $rangeenddate = null ) {
358
  global $wpdb;
359
 
360
  if ( $rangestartdate != null && $rangeenddate != null ) {
361
- $result = $wpdb->get_results( $wpdb->prepare( "SELECT DISTINCT agent FROM {$wpdb->prefix}statistics_visitor AND `last_counter` BETWEEN %s AND %s", $rangestartdate, $rangeenddate ), ARRAY_N );
 
 
 
 
 
 
 
362
  } else {
363
- $result = $wpdb->get_results( "SELECT DISTINCT agent FROM {$wpdb->prefix}statistics_visitor", ARRAY_N );
364
  }
365
 
366
  $Browers = array();
@@ -378,9 +427,18 @@ function wp_statistics_useragent( $agent, $rangestartdate = null, $rangeenddate
378
  global $wpdb;
379
 
380
  if ( $rangestartdate != null && $rangeenddate != null ) {
381
- $result = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(agent) FROM {$wpdb->prefix}statistics_visitor WHERE `agent` = %s AND `last_counter` BETWEEN %s AND %s", $agent, $rangestartdate, $rangeenddate ) );
 
 
 
 
 
 
 
382
  } else {
383
- $result = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(agent) FROM {$wpdb->prefix}statistics_visitor WHERE `agent` = %s", $agent ) );
 
 
384
  }
385
 
386
  return $result;
@@ -392,9 +450,16 @@ function wp_statistics_platform_list( $rangestartdate = null, $rangeenddate = nu
392
  global $wpdb;
393
 
394
  if ( $rangestartdate != null && $rangeenddate != null ) {
395
- $result = $wpdb->get_results( $wpdb->prepare( "SELECT DISTINCT platform FROM {$wpdb->prefix}statistics_visitor WHERE `last_counter` BETWEEN %s AND %s", $rangestartdate, $rangeenddate ), ARRAY_N );
 
 
 
 
 
 
 
396
  } else {
397
- $result = $wpdb->get_results( "SELECT DISTINCT platform FROM {$wpdb->prefix}statistics_visitor", ARRAY_N );
398
  }
399
 
400
  $Platforms = array();
@@ -412,9 +477,21 @@ function wp_statistics_platform( $platform, $rangestartdate = null, $rangeenddat
412
  global $wpdb;
413
 
414
  if ( $rangestartdate != null && $rangeenddate != null ) {
415
- $result = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(platform) FROM {$wpdb->prefix}statistics_visitor WHERE `platform` = %s AND `last_counter` BETWEEN %s AND %s", $platform, $rangestartdate, $rangeenddate ) );
 
 
 
 
 
 
 
416
  } else {
417
- $result = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(platform) FROM {$wpdb->prefix}statistics_visitor WHERE `platform` = %s", $platform ) );
 
 
 
 
 
418
  }
419
 
420
  return $result;
@@ -426,9 +503,20 @@ function wp_statistics_agent_version_list( $agent, $rangestartdate = null, $rang
426
  global $wpdb;
427
 
428
  if ( $rangestartdate != null && $rangeenddate != null ) {
429
- $result = $wpdb->get_results( $wpdb->prepare( "SELECT DISTINCT version FROM {$wpdb->prefix}statistics_visitor WHERE agent = %s AND `last_counter` BETWEEN %s AND %s", $agent, $rangestartdate, $rangeenddate ), ARRAY_N );
 
 
 
 
 
 
 
 
430
  } else {
431
- $result = $wpdb->get_results( $wpdb->prepare( "SELECT DISTINCT version FROM {$wpdb->prefix}statistics_visitor WHERE agent = %s", $agent ), ARRAY_N );
 
 
 
432
  }
433
 
434
  $Versions = array();
@@ -446,9 +534,23 @@ function wp_statistics_agent_version( $agent, $version, $rangestartdate = null,
446
  global $wpdb;
447
 
448
  if ( $rangestartdate != null && $rangeenddate != null ) {
449
- $result = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(version) FROM {$wpdb->prefix}statistics_visitor WHERE agent = %s AND version = %s AND `last_counter` BETWEEN %s AND %s", $agent, $version, $rangestartdate, $rangeenddate ) );
 
 
 
 
 
 
 
 
450
  } else {
451
- $result = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(version) FROM {$wpdb->prefix}statistics_visitor WHERE agent = %s AND version = %s", $agent, $version ) );
 
 
 
 
 
 
452
  }
453
 
454
  return $result;
@@ -473,87 +575,87 @@ function wp_statistics_searchengine_list( $all = false ) {
473
  $default = $engines = array(
474
  'ask' => array(
475
  'name' => 'Ask.com',
476
- 'translated' => __( 'Ask.com', 'wp-statistics' ),
477
  'tag' => 'ask',
478
  'sqlpattern' => '%ask.com%',
479
  'regexpattern' => 'ask\.com',
480
  'querykey' => 'q',
481
- 'image' => 'ask.png'
482
  ),
483
  'baidu' => array(
484
  'name' => 'Baidu',
485
- 'translated' => __( 'Baidu', 'wp-statistics' ),
486
  'tag' => 'baidu',
487
  'sqlpattern' => '%baidu.com%',
488
  'regexpattern' => 'baidu\.com',
489
  'querykey' => 'wd',
490
- 'image' => 'baidu.png'
491
  ),
492
  'bing' => array(
493
  'name' => 'Bing',
494
- 'translated' => __( 'Bing', 'wp-statistics' ),
495
  'tag' => 'bing',
496
  'sqlpattern' => '%bing.com%',
497
  'regexpattern' => 'bing\.com',
498
  'querykey' => 'q',
499
- 'image' => 'bing.png'
500
  ),
501
  'clearch' => array(
502
  'name' => 'clearch.org',
503
- 'translated' => __( 'clearch.org', 'wp-statistics' ),
504
  'tag' => 'clearch',
505
  'sqlpattern' => '%clearch.org%',
506
  'regexpattern' => 'clearch\.org',
507
  'querykey' => 'q',
508
- 'image' => 'clearch.png'
509
  ),
510
  'duckduckgo' => array(
511
  'name' => 'DuckDuckGo',
512
- 'translated' => __( 'DuckDuckGo', 'wp-statistics' ),
513
  'tag' => 'duckduckgo',
514
  'sqlpattern' => array( '%duckduckgo.com%', '%ddg.gg%' ),
515
  'regexpattern' => array( 'duckduckgo\.com', 'ddg\.gg' ),
516
  'querykey' => 'q',
517
- 'image' => 'duckduckgo.png'
518
  ),
519
  'google' => array(
520
  'name' => 'Google',
521
- 'translated' => __( 'Google', 'wp-statistics' ),
522
  'tag' => 'google',
523
  'sqlpattern' => '%google.%',
524
  'regexpattern' => 'google\.',
525
  'querykey' => 'q',
526
- 'image' => 'google.png'
527
  ),
528
  'yahoo' => array(
529
  'name' => 'Yahoo!',
530
- 'translated' => __( 'Yahoo!', 'wp-statistics' ),
531
  'tag' => 'yahoo',
532
  'sqlpattern' => '%yahoo.com%',
533
  'regexpattern' => 'yahoo\.com',
534
  'querykey' => 'p',
535
- 'image' => 'yahoo.png'
536
  ),
537
  'yandex' => array(
538
  'name' => 'Yandex',
539
- 'translated' => __( 'Yandex', 'wp-statistics' ),
540
  'tag' => 'yandex',
541
  'sqlpattern' => '%yandex.ru%',
542
  'regexpattern' => 'yandex\.ru',
543
  'querykey' => 'text',
544
- 'image' => 'yandex.png'
545
- )
546
  );
547
 
548
  if ( $all == false ) {
549
  foreach ( $engines as $key => $engine ) {
550
- if ( $WP_Statistics->get_option( 'disable_se_' . $engine['tag'] ) ) {
551
  unset( $engines[ $key ] );
552
  }
553
  }
554
 
555
  // If we've disabled all the search engines, reset the list back to default.
556
- if ( count( $engines ) == 0 ) {
557
  $engines = $default;
558
  }
559
  }
@@ -569,27 +671,27 @@ function wp_statistics_searchword_query( $search_engine = 'all' ) {
569
  $searchengine_list = wp_statistics_searchengine_list();
570
  $search_query = '';
571
 
572
- if ( $WP_Statistics->get_option( 'search_converted' ) ) {
573
  // Are we getting results for all search engines or a specific one?
574
- if ( strtolower( $search_engine ) == 'all' ) {
575
  // For all of them? Ok, look through the search engine list and create a SQL query string to get them all from the database.
576
  foreach ( $searchengine_list as $key => $se ) {
577
  $search_query .= "( `engine` = '{$key}' AND `words` <> '' ) OR ";
578
  }
579
 
580
  // Trim off the last ' OR ' for the loop above.
581
- $search_query = substr( $search_query, 0, strlen( $search_query ) - 4 );
582
  } else {
583
  $search_query .= "`engine` = '{$search_engine}' AND `words` <> ''";
584
  }
585
  } else {
586
  // Are we getting results for all search engines or a specific one?
587
- if ( strtolower( $search_engine ) == 'all' ) {
588
  // For all of them? Ok, look through the search engine list and create a SQL query string to get them all from the database.
589
  // NOTE: This SQL query can be *VERY* long.
590
  foreach ( $searchengine_list as $se ) {
591
  // The SQL pattern for a search engine may be an array if it has to handle multiple domains (like google.com and google.ca) or other factors.
592
- if ( is_array( $se['sqlpattern'] ) ) {
593
  foreach ( $se['sqlpattern'] as $subse ) {
594
  $search_query .= "(`referred` LIKE '{$subse}{$se['querykey']}=%' AND `referred` NOT LIKE '{$subse}{$se['querykey']}=&%' AND `referred` NOT LIKE '{$subse}{$se['querykey']}=') OR ";
595
  }
@@ -599,16 +701,16 @@ function wp_statistics_searchword_query( $search_engine = 'all' ) {
599
  }
600
 
601
  // Trim off the last ' OR ' for the loop above.
602
- $search_query = substr( $search_query, 0, strlen( $search_query ) - 4 );
603
  } else {
604
  // For just one? Ok, the SQL pattern for a search engine may be an array if it has to handle multiple domains (like google.com and google.ca) or other factors.
605
- if ( is_array( $searchengine_list[ $search_engine ]['sqlpattern'] ) ) {
606
  foreach ( $searchengine_list[ $search_engine ]['sqlpattern'] as $se ) {
607
  $search_query .= "(`referred` LIKE '{$se}{$searchengine_list[$search_engine]['querykey']}=%' AND `referred` NOT LIKE '{$se}{$searchengine_list[$search_engine]['querykey']}=&%' AND `referred` NOT LIKE '{$se}{$searchengine_list[$search_engine]['querykey']}=') OR ";
608
  }
609
 
610
  // Trim off the last ' OR ' for the loop above.
611
- $search_query = substr( $search_query, 0, strlen( $search_query ) - 4 );
612
  } else {
613
  $search_query .= "(`referred` LIKE '{$searchengine_list[$search_engine]['sqlpattern']}{$searchengine_list[$search_engine]['querykey']}=%' AND `referred` NOT LIKE '{$searchengine_list[$search_engine]['sqlpattern']}{$searchengine_list[$search_engine]['querykey']}=&%' AND `referred` NOT LIKE '{$searchengine_list[$search_engine]['sqlpattern']}{$searchengine_list[$search_engine]['querykey']}=')";
614
  }
@@ -626,54 +728,56 @@ function wp_statistics_searchengine_query( $search_engine = 'all' ) {
626
  $searchengine_list = wp_statistics_searchengine_list();
627
  $search_query = '';
628
 
629
- if ( $WP_Statistics->get_option( 'search_converted' ) ) {
630
  // Are we getting results for all search engines or a specific one?
631
- if ( strtolower( $search_engine ) == 'all' ) {
632
  // For all of them? Ok, look through the search engine list and create a SQL query string to get them all from the database.
633
  foreach ( $searchengine_list as $key => $se ) {
634
- $key = esc_sql( $key );
635
  $search_query .= "`engine` = '{$key}' OR ";
636
  }
637
 
638
  // Trim off the last ' OR ' for the loop above.
639
- $search_query = substr( $search_query, 0, strlen( $search_query ) - 4 );
640
  } else {
641
- $search_engine = esc_sql( $search_engine );
642
- $search_query .= "`engine` = '{$search_engine}'";
643
  }
644
  } else {
645
  // Are we getting results for all search engines or a specific one?
646
- if ( strtolower( $search_engine ) == 'all' ) {
647
  // For all of them? Ok, look through the search engine list and create a SQL query string to get them all from the database.
648
  // NOTE: This SQL query can be long.
649
  foreach ( $searchengine_list as $se ) {
650
  // The SQL pattern for a search engine may be an array if it has to handle multiple domains (like google.com and google.ca) or other factors.
651
- if ( is_array( $se['sqlpattern'] ) ) {
652
  foreach ( $se['sqlpattern'] as $subse ) {
653
- $subse = esc_sql( $subse );
654
  $search_query .= "`referred` LIKE '{$subse}' OR ";
655
  }
656
  } else {
657
- $se['sqlpattern'] = esc_sql( $se['sqlpattern'] );
658
- $search_query .= "`referred` LIKE '{$se['sqlpattern']}' OR ";
659
  }
660
  }
661
 
662
  // Trim off the last ' OR ' for the loop above.
663
- $search_query = substr( $search_query, 0, strlen( $search_query ) - 4 );
664
  } else {
665
  // For just one? Ok, the SQL pattern for a search engine may be an array if it has to handle multiple domains (like google.com and google.ca) or other factors.
666
- if ( is_array( $searchengine_list[ $search_engine ]['sqlpattern'] ) ) {
667
  foreach ( $searchengine_list[ $search_engine ]['sqlpattern'] as $se ) {
668
- $se = esc_sql( $se );
669
  $search_query .= "`referred` LIKE '{$se}' OR ";
670
  }
671
 
672
  // Trim off the last ' OR ' for the loop above.
673
- $search_query = substr( $search_query, 0, strlen( $search_query ) - 4 );
674
  } else {
675
- $searchengine_list[ $search_engine ]['sqlpattern'] = esc_sql( $searchengine_list[ $search_engine ]['sqlpattern'] );
676
- $search_query .= "`referred` LIKE '{$searchengine_list[$search_engine]['sqlpattern']}'";
 
 
677
  }
678
  }
679
  }
@@ -689,10 +793,10 @@ function wp_statistics_searchengine_regex( $search_engine = 'all' ) {
689
  $search_query = '';
690
 
691
  // Are we getting results for all search engines or a specific one?
692
- if ( strtolower( $search_engine ) == 'all' ) {
693
  foreach ( $searchengine_list as $se ) {
694
  // The SQL pattern for a search engine may be an array if it has to handle multiple domains (like google.com and google.ca) or other factors.
695
- if ( is_array( $se['regexpattern'] ) ) {
696
  foreach ( $se['regexpattern'] as $subse ) {
697
  $search_query .= "{$subse}|";
698
  }
@@ -702,16 +806,16 @@ function wp_statistics_searchengine_regex( $search_engine = 'all' ) {
702
  }
703
 
704
  // Trim off the last '|' for the loop above.
705
- $search_query = substr( $search_query, 0, strlen( $search_query ) - 1 );
706
  } else {
707
  // For just one? Ok, the SQL pattern for a search engine may be an array if it has to handle multiple domains (like google.com and google.ca) or other factors.
708
- if ( is_array( $searchengine_list[ $search_engine ]['regexpattern'] ) ) {
709
  foreach ( $searchengine_list[ $search_engine ]['regexpattern'] as $se ) {
710
  $search_query .= "{$se}|";
711
  }
712
 
713
  // Trim off the last '|' for the loop above.
714
- $search_query = substr( $search_query, 0, strlen( $search_query ) - 1 );
715
  } else {
716
  $search_query .= $searchengine_list[ $search_engine ]['regexpattern'];
717
  }
@@ -729,51 +833,63 @@ function wp_statistics_searchengine( $search_engine = 'all', $time = 'total' ) {
729
  // Determine if we're using the old or new method of storing search engine info and build the appropriate table name.
730
  $tablename = $wpdb->prefix . 'statistics_';
731
 
732
- if ( $WP_Statistics->get_option( 'search_converted' ) ) {
733
  $tablename .= 'search';
734
  } else {
735
  $tablename .= 'visitor';
736
  }
737
 
738
  // Get a complete list of search engines
739
- $search_query = wp_statistics_searchengine_query( $search_engine );
740
 
741
  // This function accepts several options for time parameter, each one has a unique SQL query string.
742
  // They're pretty self explanatory.
743
  switch ( $time ) {
744
  case 'today':
745
- $result = $wpdb->query( "SELECT * FROM `{$tablename}` WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d' )}' AND {$search_query}" );
746
- break;
 
 
747
 
748
  case 'yesterday':
749
- $result = $wpdb->query( "SELECT * FROM `{$tablename}` WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d', -1 )}' AND {$search_query}" );
 
 
750
 
751
- break;
752
 
753
  case 'week':
754
- $result = $wpdb->query( "SELECT * FROM `{$tablename}` WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d', -7 )}' AND {$search_query}" );
 
 
755
 
756
- break;
757
 
758
  case 'month':
759
- $result = $wpdb->query( "SELECT * FROM `{$tablename}` WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d', -30 )}' AND {$search_query}" );
 
 
760
 
761
- break;
762
 
763
  case 'year':
764
- $result = $wpdb->query( "SELECT * FROM `{$tablename}` WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d', -365 )}' AND {$search_query}" );
 
 
765
 
766
- break;
767
 
768
  case 'total':
769
- $result = $wpdb->query( "SELECT * FROM `{$tablename}` WHERE {$search_query}" );
770
 
771
- break;
772
 
773
  default:
774
- $result = $wpdb->query( "SELECT * FROM `{$tablename}` WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d', $time)}' AND {$search_query}" );
 
 
775
 
776
- break;
777
  }
778
 
779
  return $result;
@@ -787,51 +903,63 @@ function wp_statistics_searchword( $search_engine = 'all', $time = 'total' ) {
787
  // Determine if we're using the old or new method of storing search engine info and build the appropriate table name.
788
  $tablename = $wpdb->prefix . 'statistics_';
789
 
790
- if ( $WP_Statistics->get_option( 'search_converted' ) ) {
791
  $tablename .= 'search';
792
  } else {
793
  $tablename .= 'visitor';
794
  }
795
 
796
  // Get a complete list of search engines
797
- $search_query = wp_statistics_searchword_query( $search_engine );
798
 
799
  // This function accepts several options for time parameter, each one has a unique SQL query string.
800
  // They're pretty self explanatory.
801
  switch ( $time ) {
802
  case 'today':
803
- $result = $wpdb->query( "SELECT * FROM `{$tablename}` WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d' )}' AND {$search_query}" );
804
- break;
 
 
805
 
806
  case 'yesterday':
807
- $result = $wpdb->query( "SELECT * FROM `{$tablename}` WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d', -1 )}' AND {$search_query}" );
 
 
808
 
809
- break;
810
 
811
  case 'week':
812
- $result = $wpdb->query( "SELECT * FROM `{$tablename}` WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d', -7 )}' AND {$search_query}" );
 
 
813
 
814
- break;
815
 
816
  case 'month':
817
- $result = $wpdb->query( "SELECT * FROM `{$tablename}` WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d', -30 )}' AND {$search_query}" );
 
 
818
 
819
- break;
820
 
821
  case 'year':
822
- $result = $wpdb->query( "SELECT * FROM `{$tablename}` WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d', -365 )}' AND {$search_query}" );
 
 
823
 
824
- break;
825
 
826
  case 'total':
827
- $result = $wpdb->query( "SELECT * FROM `{$tablename}` WHERE {$search_query}" );
828
 
829
- break;
830
 
831
  default:
832
- $result = $wpdb->query( "SELECT * FROM `{$tablename}` WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d', $time )}' AND {$search_query}" );
 
 
833
 
834
- break;
835
  }
836
 
837
  return $result;
@@ -840,11 +968,11 @@ function wp_statistics_searchword( $search_engine = 'all', $time = 'total' ) {
840
  // This function will return the total number of posts in WordPress.
841
  function wp_statistics_countposts() {
842
 
843
- $count_posts = wp_count_posts( 'post' );
844
 
845
  $ret = 0;
846
 
847
- if ( is_object( $count_posts ) ) {
848
  $ret = $count_posts->publish;
849
  }
850
 
@@ -854,11 +982,11 @@ function wp_statistics_countposts() {
854
  // This function will return the total number of pages in WordPress.
855
  function wp_statistics_countpages() {
856
 
857
- $count_pages = wp_count_posts( 'page' );
858
 
859
  $ret = 0;
860
 
861
- if ( is_object( $count_pages ) ) {
862
  $ret = $count_pages->publish;
863
  }
864
 
@@ -870,7 +998,7 @@ function wp_statistics_countcomment() {
870
 
871
  global $wpdb;
872
 
873
- $countcomms = $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->comments} WHERE comment_approved = '1'" );
874
 
875
  return $countcomms;
876
  }
@@ -878,7 +1006,7 @@ function wp_statistics_countcomment() {
878
  // This function will return the total number of spam comments *IF* akismet is installed.
879
  function wp_statistics_countspam() {
880
 
881
- return number_format_i18n( get_option( 'akismet_spam_count' ) );
882
  }
883
 
884
  // This function will return the total number of users in WordPress.
@@ -894,11 +1022,13 @@ function wp_statistics_lastpostdate() {
894
 
895
  global $wpdb, $WP_Statistics;
896
 
897
- $db_date = $wpdb->get_var( "SELECT post_date FROM {$wpdb->posts} WHERE post_type='post' AND post_status='publish' ORDER BY post_date DESC LIMIT 1" );
 
 
898
 
899
- $date_format = get_option( 'date_format' );
900
 
901
- return $WP_Statistics->Current_Date_i18n( $date_format, $db_date, false );
902
  }
903
 
904
  // This function will return the average number of posts per day that are published on your site.
@@ -907,23 +1037,29 @@ function wp_statistics_average_post( $days = false ) {
907
 
908
  global $wpdb;
909
 
910
- $get_first_post = $wpdb->get_var( "SELECT post_date FROM {$wpdb->posts} WHERE post_status = 'publish' ORDER BY post_date LIMIT 1" );
911
- $get_total_post = $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->posts} WHERE post_status = 'publish' AND post_type = 'post'" );
 
 
 
 
912
 
913
- $days_spend = intval( ( time() - strtotime( $get_first_post ) ) / 86400 ); // 86400 = 60 * 60 * 24 = number of seconds in a day
 
 
914
 
915
  if ( $days == true ) {
916
  if ( $get_total_post == 0 ) {
917
  $get_total_post = 1;
918
  } // Avoid divide by zero errors.
919
 
920
- return round( $days_spend / $get_total_post, 0 );
921
  } else {
922
  if ( $days_spend == 0 ) {
923
  $days_spend = 1;
924
  } // Avoid divide by zero errors.
925
 
926
- return round( $get_total_post / $days_spend, 2 );
927
  }
928
  }
929
 
@@ -933,23 +1069,25 @@ function wp_statistics_average_comment( $days = false ) {
933
 
934
  global $wpdb;
935
 
936
- $get_first_comment = $wpdb->get_var( "SELECT comment_date FROM {$wpdb->comments} ORDER BY comment_date LIMIT 1" );
937
- $get_total_comment = $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->comments} WHERE comment_approved = '1'" );
938
 
939
- $days_spend = intval( ( time() - strtotime( $get_first_comment ) ) / 86400 ); // 86400 = 60 * 60 * 24 = number of seconds in a day
 
 
940
 
941
  if ( $days == true ) {
942
  if ( $get_total_comment == 0 ) {
943
  $get_total_comment = 1;
944
  } // Avoid divide by zero errors.
945
 
946
- return round( $days_spend / $get_total_comment, 0 );
947
  } else {
948
  if ( $days_spend == 0 ) {
949
  $days_spend = 1;
950
  } // Avoid divide by zero errors.
951
 
952
- return round( $get_total_comment / $days_spend, 2 );
953
  }
954
  }
955
 
@@ -959,23 +1097,25 @@ function wp_statistics_average_registeruser( $days = false ) {
959
 
960
  global $wpdb;
961
 
962
- $get_first_user = $wpdb->get_var( "SELECT user_registered FROM {$wpdb->users} ORDER BY user_registered LIMIT 1" );
963
- $get_total_user = $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->users}" );
964
 
965
- $days_spend = intval( ( time() - strtotime( $get_first_user ) ) / 86400 ); // 86400 = 60 * 60 * 24 = number of seconds in a day
 
 
966
 
967
  if ( $days == true ) {
968
  if ( $get_total_user == 0 ) {
969
  $get_total_user = 1;
970
  } // Avoid divide by zero errors.
971
 
972
- return round( $days_spend / $get_total_user, 0 );
973
  } else {
974
  if ( $days_spend == 0 ) {
975
  $days_spend = 1;
976
  } // Avoid divide by zero errors.
977
 
978
- return round( $get_total_user / $days_spend, 2 );
979
  }
980
  }
981
 
@@ -989,10 +1129,10 @@ function wp_statistics_icons( $dashicons, $icon_name = null ) {
989
  }
990
 
991
  // Since versions of WordPress before 3.8 didn't have dashicons, don't use them in those versions.
992
- if ( version_compare( $wp_version, '3.8-RC', '>=' ) || version_compare( $wp_version, '3.8', '>=' ) ) {
993
  return '<span class="dashicons ' . $dashicons . '"></span>';
994
  } else {
995
- return '<img src="' . plugins_url( 'wp-statistics/assets/images/' ) . $icon_name . '.png"/>';
996
  }
997
  }
998
 
@@ -1002,19 +1142,19 @@ function wp_statistics_geoip_supported() {
1002
  $enabled = true;
1003
 
1004
  // PHP 5.3
1005
- if ( ! version_compare( phpversion(), WP_STATISTICS_REQUIRED_GEOIP_PHP_VERSION, '>' ) ) {
1006
  $enabled = false;
1007
  }
1008
 
1009
  // PHP's cURL extension installed
1010
- if ( ! function_exists( 'curl_init' ) ) {
1011
  $enabled = false;
1012
  }
1013
 
1014
  // PHP NOT running in safe mode
1015
- if ( ini_get( 'safe_mode' ) ) {
1016
  // Double check php version, 5.4 and above don't support safe mode but the ini value may still be set after an upgrade.
1017
- if ( ! version_compare( phpversion(), '5.4', '<' ) ) {
1018
  $enabled = false;
1019
  }
1020
  }
@@ -1023,72 +1163,83 @@ function wp_statistics_geoip_supported() {
1023
  }
1024
 
1025
  // This function creates the date range selector 'widget' used in the various statistics pages.
1026
- function wp_statistics_date_range_selector( $page, $current, $range = array(), $desc = array(), $extrafields = '', $pre_extra = '', $post_extra = '' ) {
 
 
 
 
 
 
 
 
1027
  GLOBAL $WP_Statistics;
1028
 
1029
- wp_enqueue_script( 'jquery-ui-datepicker' );
1030
- wp_register_style( 'jquery-ui-smoothness-css', $WP_Statistics->plugin_url . 'assets/css/jquery-ui-smoothness.min.css' );
1031
- wp_enqueue_style( 'jquery-ui-smoothness-css' );
 
 
 
1032
 
1033
- if ( count( $range ) == 0 ) {
1034
  $range = array( 10, 20, 30, 60, 90, 180, 270, 365 );
1035
  $desc = array(
1036
- __( '10 Days', 'wp-statistics' ),
1037
- __( '20 Days', 'wp-statistics' ),
1038
- __( '30 Days', 'wp-statistics' ),
1039
- __( '2 Months', 'wp-statistics' ),
1040
- __( '3 Months', 'wp-statistics' ),
1041
- __( '6 Months', 'wp-statistics' ),
1042
- __( '9 Months', 'wp-statistics' ),
1043
- __( '1 Year', 'wp-statistics' )
1044
  );
1045
  }
1046
 
1047
- if ( count( $desc ) == 0 ) {
1048
  $desc = $range;
1049
  }
1050
 
1051
- $rcount = count( $range );
1052
 
1053
  $bold = true;
1054
 
1055
  // Check to see if there's a range in the URL, if so set it, otherwise use the default.
1056
- if ( array_key_exists( 'rangestart', $_GET ) ) {
1057
  $rangestart = $_GET['rangestart'];
1058
  } else {
1059
- $rangestart = $WP_Statistics->Current_Date( 'm/d/Y', '-' . $current );
1060
  }
1061
- if ( array_key_exists( 'rangeend', $_GET ) ) {
1062
  $rangeend = $_GET['rangeend'];
1063
  } else {
1064
- $rangeend = $WP_Statistics->Current_Date( 'm/d/Y' );
1065
  }
1066
 
1067
  // Convert the text dates to unix timestamps and do some basic sanity checking.
1068
- $rangestart_utime = $WP_Statistics->strtotimetz( $rangestart );
1069
  if ( false === $rangestart_utime ) {
1070
  $rangestart_utime = time();
1071
  }
1072
- $rangeend_utime = $WP_Statistics->strtotimetz( $rangeend );
1073
  if ( false === $rangeend_utime || $rangeend_utime < $rangestart_utime ) {
1074
  $rangeend_utime = time();
1075
  }
1076
 
1077
  // Now get the number of days in the range.
1078
  $daysToDisplay = (int) ( ( $rangeend_utime - $rangestart_utime ) / 24 / 60 / 60 );
1079
- $today = $WP_Statistics->Current_Date( 'm/d/Y' );
1080
 
1081
  // Re-create the range start/end strings from our utime's to make sure we get ride of any cruft and have them in the format we want.
1082
- $rangestart = $WP_Statistics->Local_Date( 'm/d/Y', $rangestart_utime );
1083
- $rangeend = $WP_Statistics->Local_Date( 'm/d/Y', $rangeend_utime );
1084
 
1085
  // If the rangeend isn't today OR it is but not one of the standard range values, then it's a custom selected value and we need to flag it as such.
1086
- if ( $rangeend != $today || ( $rangeend == $today && ! in_array( $current, $range ) ) ) {
1087
- $current = - 1;
1088
  } else {
1089
  // If on the other hand we are a standard range, let's reset the custom range selector to match it.
1090
- $rangestart = $WP_Statistics->Current_Date( 'm/d/Y', '-' . $current );
1091
- $rangeend = $WP_Statistics->Current_Date( 'm/d/Y' );
1092
  }
1093
 
1094
  echo '<form method="get"><ul class="subsubsub wp-statistics-sub-fullwidth">' . "\r\n";
@@ -1096,7 +1247,7 @@ function wp_statistics_date_range_selector( $page, $current, $range = array(), $
1096
  // Output any extra HTML we've been passed after the form element but before the date selector.
1097
  echo $pre_extra;
1098
 
1099
- for ( $i = 0; $i < $rcount; $i ++ ) {
1100
  echo ' <li class="all"><a ';
1101
 
1102
  if ( $current == $range[ $i ] ) {
@@ -1105,7 +1256,14 @@ function wp_statistics_date_range_selector( $page, $current, $range = array(), $
1105
  }
1106
 
1107
  // Don't bother adding he date range to the standard links as they're not needed any may confuse the custom range selector.
1108
- echo 'href="?page=' . $page . '&hitdays=' . $range[ $i ] . esc_url( $extrafields ) . '">' . $desc[ $i ] . '</a></li>';
 
 
 
 
 
 
 
1109
 
1110
  if ( $i < $rcount - 1 ) {
1111
  echo ' | ';
@@ -1118,26 +1276,40 @@ function wp_statistics_date_range_selector( $page, $current, $range = array(), $
1118
 
1119
  echo '<input type="hidden" name="hitdays" value="-1"><input type="hidden" name="page" value="' . $page . '">';
1120
 
1121
- parse_str( $extrafields, $parse );
1122
 
1123
  foreach ( $parse as $key => $value ) {
1124
- echo '<input type="hidden" name="' . $key . '" value="' . esc_url( $value ) . '">';
1125
  }
1126
 
1127
  if ( $bold ) {
1128
- echo ' <b>' . __( 'Time Frame', 'wp-statistics' ) . ':</b> ';
1129
  } else {
1130
- echo ' ' . __( 'Time Frame', 'wp-statistics' ) . ': ';
1131
  }
1132
 
1133
- echo '<input type="text" size="10" name="rangestart" id="datestartpicker" value="' . $rangestart . '" placeholder="' . __( 'MM/DD/YYYY', 'wp-statistics' ) . '"> ' . __( 'to', 'wp-statistics' ) . ' <input type="text" size="10" name="rangeend" id="dateendpicker" value="' . $rangeend . '" placeholder="' . __( 'MM/DD/YYYY', 'wp-statistics' ) . '"> <input type="submit" value="' . __( 'Go', 'wp-statistics' ) . '" class="button-primary">' . "\r\n";
 
 
 
 
 
 
 
 
 
 
 
 
 
1134
 
1135
  // Output any extra HTML we've been passed after the date selector but before the submit button.
1136
  echo $post_extra;
1137
 
1138
  echo '</form>' . "\r\n";
1139
 
1140
- echo '<script>jQuery(function() { jQuery( "#datestartpicker" ).datepicker(); jQuery( "#dateendpicker" ).datepicker(); });</script>' . "\r\n";
 
1141
  }
1142
 
1143
  // This function is used to calculate the number of days and thier respective unix timestamps.
@@ -1148,9 +1320,9 @@ function wp_statistics_date_range_calculator( $days, $start, $end ) {
1148
  $rangestart = $start;
1149
  $rangeend = $end;
1150
 
1151
- if ( $daysToDisplay == - 1 ) {
1152
- $rangestart_utime = $WP_Statistics->strtotimetz( $rangestart );
1153
- $rangeend_utime = $WP_Statistics->strtotimetz( $rangeend );
1154
  $daysToDisplay = (int) ( ( $rangeend_utime - $rangestart_utime ) / 24 / 60 / 60 );
1155
 
1156
  if ( $rangestart_utime == false || $rangeend_utime == false ) {
@@ -1171,40 +1343,102 @@ function wp_statitiscs_empty_table( $table_name = false ) {
1171
  global $wpdb;
1172
 
1173
  if ( $table_name ) {
1174
- $result = $wpdb->query( 'DELETE FROM ' . $table_name );
1175
 
1176
  if ( $result ) {
1177
- return sprintf( __( '%s table data deleted successfully.', 'wp-statistics' ), '<code>' . $table_name . '</code>' );
 
 
 
1178
  }
1179
  }
1180
 
1181
- return sprintf( __( 'Error, %s not emptied!', 'wp-statistics' ), $table_name );
1182
  }
1183
 
1184
  // This function creates a small JavaScript snipit that will load the contents of a overview or dashboard widget.
1185
  function wp_statistics_generate_widget_load_javascript( $widget, $container_id = null ) {
1186
  if ( null == $container_id ) {
1187
- $container_id = str_replace( '.', '_', $widget . '_postbox' );
1188
  }
1189
  ?>
1190
- <script type="text/javascript">
1191
- jQuery(document).ready(function () {
1192
- wp_statistics_get_widget_contents('<?php echo $widget; ?>', '<?php echo $container_id; ?>');
1193
- });
1194
- </script>
1195
  <?php
1196
  }
1197
 
1198
  /**
1199
  * Generate RGBA colors
1200
  *
1201
- * @param $num
1202
  * @param string $opacity
1203
  *
1204
  * @return string
1205
  */
1206
  function wp_statistics_generate_rgba_color( $num, $opacity = '1' ) {
1207
- $hash = md5( 'color' . $num );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1208
 
1209
- return sprintf( "'rgba(%s, %s, %s, %s)'", hexdec( substr( $hash, 0, 2 ) ), hexdec( substr( $hash, 2, 2 ) ), hexdec( substr( $hash, 4, 2 ) ), $opacity );
1210
  }
11
 
12
  global $wpdb;
13
 
14
+ return $wpdb->query("SELECT * FROM {$wpdb->prefix}statistics_useronline");
15
  }
16
 
17
  // This function get the visit statistics for a given time frame.
24
  if ( $daily == true ) {
25
 
26
  // Fetch the results from the database.
27
+ $result = $wpdb->get_row(
28
+ "SELECT * FROM {$wpdb->prefix}statistics_visit WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d', $time )}'"
29
+ );
30
 
31
  // If we have a result, return it, otherwise force a 0 to be returned instead of the logical FALSE that would otherwise be the case.
32
  if ( $result ) {
42
 
43
  switch ( $time ) {
44
  case 'today':
45
+ $result = $wpdb->get_var(
46
+ "SELECT SUM(visit) FROM {$wpdb->prefix}statistics_visit WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d' )}'"
47
+ );
48
+ break;
49
 
50
  case 'yesterday':
51
+ $result = $wpdb->get_var(
52
+ "SELECT SUM(visit) FROM {$wpdb->prefix}statistics_visit WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d', -1 )}'"
53
+ );
54
+ break;
55
 
56
  case 'week':
57
+ $result = $wpdb->get_var(
58
+ "SELECT SUM(visit) FROM {$wpdb->prefix}statistics_visit WHERE `last_counter` BETWEEN '{$WP_Statistics->Current_Date( 'Y-m-d', -7 )}' AND '{$WP_Statistics->Current_Date( 'Y-m-d' )}'"
59
+ );
60
+ break;
61
 
62
  case 'month':
63
+ $result = $wpdb->get_var(
64
+ "SELECT SUM(visit) FROM {$wpdb->prefix}statistics_visit WHERE `last_counter` BETWEEN '{$WP_Statistics->Current_Date( 'Y-m-d', -30 )}' AND '{$WP_Statistics->Current_Date( 'Y-m-d' )}'"
65
+ );
66
+ break;
67
 
68
  case 'year':
69
+ $result = $wpdb->get_var(
70
+ "SELECT SUM(visit) FROM {$wpdb->prefix}statistics_visit WHERE `last_counter` BETWEEN '{$WP_Statistics->Current_Date( 'Y-m-d', -365 )}' AND '{$WP_Statistics->Current_Date( 'Y-m-d' )}'"
71
+ );
72
+ break;
73
 
74
  case 'total':
75
+ $result = $wpdb->get_var("SELECT SUM(visit) FROM {$wpdb->prefix}statistics_visit");
76
+ $result += $WP_Statistics->Get_Historical_Data('visits');
77
+ break;
78
 
79
  default:
80
+ $result = $wpdb->get_var(
81
+ "SELECT SUM(visit) FROM {$wpdb->prefix}statistics_visit WHERE `last_counter` BETWEEN '{$WP_Statistics->Current_Date( 'Y-m-d', $time )}' AND '{$WP_Statistics->Current_Date( 'Y-m-d' )}'"
82
+ );
83
+ break;
84
  }
85
  }
86
 
111
  if ( $daily == true ) {
112
 
113
  // Fetch the results from the database.
114
+ $result = $wpdb->query(
115
+ "SELECT {$select} FROM {$wpdb->prefix}statistics_visitor WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d', $time )}'"
116
+ );
117
 
118
  return $result;
119
 
123
  // They're pretty self explanatory.
124
  switch ( $time ) {
125
  case 'today':
126
+ $sqlstatement
127
+ = "SELECT {$select} FROM {$wpdb->prefix}statistics_visitor WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d' )}'";
128
+ break;
129
 
130
  case 'yesterday':
131
+ $sqlstatement
132
+ = "SELECT {$select} FROM {$wpdb->prefix}statistics_visitor WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d', -1 )}'";
133
+ break;
134
 
135
  case 'week':
136
+ $sqlstatement
137
+ = "SELECT {$select} FROM {$wpdb->prefix}statistics_visitor WHERE `last_counter` BETWEEN '{$WP_Statistics->Current_Date( 'Y-m-d', -7 )}' AND '{$WP_Statistics->Current_Date( 'Y-m-d' )}'";
138
+ break;
139
 
140
  case 'month':
141
+ $sqlstatement
142
+ = "SELECT {$select} FROM {$wpdb->prefix}statistics_visitor WHERE `last_counter` BETWEEN '{$WP_Statistics->Current_Date( 'Y-m-d', -30 )}' AND '{$WP_Statistics->Current_Date( 'Y-m-d' )}'";
143
+ break;
144
 
145
  case 'year':
146
+ $sqlstatement
147
+ = "SELECT {$select} FROM {$wpdb->prefix}statistics_visitor WHERE `last_counter` BETWEEN '{$WP_Statistics->Current_Date( 'Y-m-d', -365 )}' AND '{$WP_Statistics->Current_Date( 'Y-m-d' )}'";
148
+ break;
149
 
150
  case 'total':
151
  $sqlstatement = "SELECT {$select} FROM {$wpdb->prefix}statistics_visitor";
152
+ $history = $WP_Statistics->Get_Historical_Data('visitors');
153
+ break;
154
 
155
  default:
156
+ $sqlstatement
157
+ = "SELECT {$select} FROM {$wpdb->prefix}statistics_visitor WHERE `last_counter` BETWEEN '{$WP_Statistics->Current_Date( 'Y-m-d', $time )}' AND '{$WP_Statistics->Current_Date( 'Y-m-d' )}'";
158
+ break;
159
  }
160
  }
161
 
162
  // Execute the SQL call, if we're only counting we can use get_var(), otherwise we use query().
163
  if ( $countonly == true ) {
164
+ $result = $wpdb->get_var($sqlstatement);
165
  $result += $history;
166
  } else {
167
+ $result = $wpdb->query($sqlstatement);
168
  }
169
 
170
  return $result;
171
  }
172
 
173
  // This function returns the statistics for a given page.
174
+ function wp_statistics_pages( $time, $page_uri = '', $id = -1, $rangestartdate = null, $rangeenddate = null ) {
175
 
176
  // We need database and the global $WP_Statistics object access.
177
  global $wpdb, $WP_Statistics;
184
  $page_uri = wp_statistics_get_uri();
185
  }
186
 
187
+ $page_uri_sql = esc_sql($page_uri);
188
 
189
  // If a page/post ID has been passed, use it to select the rows, otherwise use the URI.
190
  // Note that a single page/post ID can have multiple URI's associated with it.
191
+ if ( $id != -1 ) {
192
+ $page_sql = '`id` = ' . absint($id);
193
  $history_key = 'page';
194
+ $history_id = absint($id);
195
  } else {
196
  $page_sql = "`URI` = '{$page_uri_sql}'";
197
  $history_key = 'uri';
202
  // They're pretty self explanatory.
203
  switch ( $time ) {
204
  case 'today':
205
+ $sqlstatement
206
+ = "SELECT SUM(count) FROM {$wpdb->prefix}statistics_pages WHERE `date` = '{$WP_Statistics->Current_Date( 'Y-m-d' )}' AND {$page_sql}";
207
+ break;
208
 
209
  case 'yesterday':
210
+ $sqlstatement
211
+ = "SELECT SUM(count) FROM {$wpdb->prefix}statistics_pages WHERE `date` = '{$WP_Statistics->Current_Date( 'Y-m-d', -1 )}' AND {$page_sql}";
212
+ break;
213
 
214
  case 'week':
215
+ $sqlstatement
216
+ = "SELECT SUM(count) FROM {$wpdb->prefix}statistics_pages WHERE `date` BETWEEN '{$WP_Statistics->Current_Date( 'Y-m-d', -7 )}' AND '{$WP_Statistics->Current_Date( 'Y-m-d' )}' AND {$page_sql}";
217
+ break;
218
 
219
  case 'month':
220
+ $sqlstatement
221
+ = "SELECT SUM(count) FROM {$wpdb->prefix}statistics_pages WHERE `date` BETWEEN '{$WP_Statistics->Current_Date( 'Y-m-d', -30 )}' AND '{$WP_Statistics->Current_Date( 'Y-m-d' )}' AND {$page_sql}";
222
+ break;
223
 
224
  case 'year':
225
+ $sqlstatement
226
+ = "SELECT SUM(count) FROM {$wpdb->prefix}statistics_pages WHERE `date` BETWEEN '{$WP_Statistics->Current_Date( 'Y-m-d', -365 )}' AND '{$WP_Statistics->Current_Date( 'Y-m-d' )}' AND {$page_sql}";
227
+ break;
228
 
229
  case 'total':
230
  $sqlstatement = "SELECT SUM(count) FROM {$wpdb->prefix}statistics_pages WHERE {$page_sql}";
231
+ $history = $WP_Statistics->Get_Historical_Data($history_key, $history_id);
232
+ break;
233
  case 'range':
234
+ $sqlstatement = "SELECT SUM(count) FROM {$wpdb->prefix}statistics_pages WHERE `date` BETWEEN '" .
235
+ $WP_Statistics->Current_Date('Y-m-d', '-0', strtotime($rangestartdate)) .
236
+ "' AND '" .
237
+ $WP_Statistics->Current_Date('Y-m-d', '-0', strtotime($rangeenddate)) .
238
+ "' AND {$page_sql}";
239
 
240
+ break;
241
  default:
242
+ $sqlstatement
243
+ = "SELECT SUM(count) FROM {$wpdb->prefix}statistics_pages WHERE `date` = '{$WP_Statistics->Current_Date( 'Y-m-d', $time )}' AND {$page_sql}";
244
+ break;
245
  }
246
 
247
  // Since this function only every returns a count, just use get_var().
248
+ $result = $wpdb->get_var($sqlstatement);
249
  $result += $history;
250
 
251
  // If we have an empty result, return 0 instead of a blank.
262
  global $wpdb;
263
 
264
  // Create the SQL query to use.
265
+ $sqlstatement = $wpdb->prepare(
266
+ "SELECT id FROM {$wpdb->prefix}statistics_pages WHERE `URI` = %s AND id > 0 ORDER BY date DESC",
267
+ $uri
268
+ );
269
 
270
  // Execute the query.
271
+ $result = $wpdb->get_var($sqlstatement);
272
 
273
  // If we returned a false or some other 0 equivalent value, make sure $result is set to an integer 0.
274
  if ( $result == 0 ) {
289
 
290
  // Get every unique URI from the pages database.
291
  if ( $rangestartdate != null && $rangeenddate != null ) {
292
+ $result = $wpdb->get_results(
293
+ $wpdb->prepare(
294
+ "SELECT DISTINCT uri FROM {$wpdb->prefix}statistics_pages WHERE `date` BETWEEN %s AND %s",
295
+ $rangestartdate,
296
+ $rangeenddate
297
+ ),
298
+ ARRAY_N
299
+ );
300
  } else {
301
+ $result = $wpdb->get_results("SELECT DISTINCT uri FROM {$wpdb->prefix}statistics_pages", ARRAY_N);
302
  }
303
 
304
  $total = 0;
307
  // Now get the total page visit count for each unique URI.
308
  foreach ( $result as $out ) {
309
  // Increment the total number of results.
310
+ $total++;
311
 
312
  // Retreive the post ID for the URI.
313
+ $id = wp_statistics_uri_to_id($out[0]);
314
 
315
  // Lookup the post title.
316
+ $post = get_post($id);
317
 
318
+ if ( is_object($post) ) {
319
  $title = $post->post_title;
320
  } else {
321
  if ( $out[0] == '/' ) {
329
  if ( $rangestartdate != null && $rangeenddate != null ) {
330
  $uris[] = array(
331
  $out[0],
332
+ wp_statistics_pages('range', $out[0], -1, $rangestartdate, $rangeenddate),
333
  $id,
334
+ $title,
335
  );
336
  } else {
337
+ $uris[] = array( $out[0], wp_statistics_pages('total', $out[0]), $id, $title );
338
  }
339
  }
340
 
341
  // If we have more than one result, let's sort them using usort.
342
+ if ( count($uris) > 1 ) {
343
  // Sort the URI's based on their hit count.
344
+ usort($uris, 'wp_stats_compare_uri_hits');
345
  }
346
 
347
  return array( $total, $uris );
350
  // This function gets the current page URI.
351
  function wp_statistics_get_uri() {
352
  // Get the site's path from the URL.
353
+ $site_uri = parse_url(site_url(), PHP_URL_PATH);
354
+ $site_uri_len = strlen($site_uri);
355
 
356
  // Get the site's path from the URL.
357
+ $home_uri = parse_url(home_url(), PHP_URL_PATH);
358
+ $home_uri_len = strlen($home_uri);
359
 
360
  // Get the current page URI.
361
  $page_uri = $_SERVER["REQUEST_URI"];
369
  * we check for "/site", but in the reverse case, we need to swap the order of the check.
370
  */
371
  if ( $site_uri_len > $home_uri_len ) {
372
+ if ( substr($page_uri, 0, $site_uri_len) == $site_uri ) {
373
+ $page_uri = substr($page_uri, $site_uri_len);
374
  }
375
 
376
+ if ( substr($page_uri, 0, $home_uri_len) == $home_uri ) {
377
+ $page_uri = substr($page_uri, $home_uri_len);
378
  }
379
  } else {
380
+ if ( substr($page_uri, 0, $home_uri_len) == $home_uri ) {
381
+ $page_uri = substr($page_uri, $home_uri_len);
382
  }
383
 
384
+ if ( substr($page_uri, 0, $site_uri_len) == $site_uri ) {
385
+ $page_uri = substr($page_uri, $site_uri_len);
386
  }
387
  }
388
 
400
  global $wpdb;
401
 
402
  if ( $rangestartdate != null && $rangeenddate != null ) {
403
+ $result = $wpdb->get_results(
404
+ $wpdb->prepare(
405
+ "SELECT DISTINCT agent FROM {$wpdb->prefix}statistics_visitor AND `last_counter` BETWEEN %s AND %s",
406
+ $rangestartdate,
407
+ $rangeenddate
408
+ ),
409
+ ARRAY_N
410
+ );
411
  } else {
412
+ $result = $wpdb->get_results("SELECT DISTINCT agent FROM {$wpdb->prefix}statistics_visitor", ARRAY_N);
413
  }
414
 
415
  $Browers = array();
427
  global $wpdb;
428
 
429
  if ( $rangestartdate != null && $rangeenddate != null ) {
430
+ $result = $wpdb->get_var(
431
+ $wpdb->prepare(
432
+ "SELECT COUNT(agent) FROM {$wpdb->prefix}statistics_visitor WHERE `agent` = %s AND `last_counter` BETWEEN %s AND %s",
433
+ $agent,
434
+ $rangestartdate,
435
+ $rangeenddate
436
+ )
437
+ );
438
  } else {
439
+ $result = $wpdb->get_var(
440
+ $wpdb->prepare("SELECT COUNT(agent) FROM {$wpdb->prefix}statistics_visitor WHERE `agent` = %s", $agent)
441
+ );
442
  }
443
 
444
  return $result;
450
  global $wpdb;
451
 
452
  if ( $rangestartdate != null && $rangeenddate != null ) {
453
+ $result = $wpdb->get_results(
454
+ $wpdb->prepare(
455
+ "SELECT DISTINCT platform FROM {$wpdb->prefix}statistics_visitor WHERE `last_counter` BETWEEN %s AND %s",
456
+ $rangestartdate,
457
+ $rangeenddate
458
+ ),
459
+ ARRAY_N
460
+ );
461
  } else {
462
+ $result = $wpdb->get_results("SELECT DISTINCT platform FROM {$wpdb->prefix}statistics_visitor", ARRAY_N);
463
  }
464
 
465
  $Platforms = array();
477
  global $wpdb;
478
 
479
  if ( $rangestartdate != null && $rangeenddate != null ) {
480
+ $result = $wpdb->get_var(
481
+ $wpdb->prepare(
482
+ "SELECT COUNT(platform) FROM {$wpdb->prefix}statistics_visitor WHERE `platform` = %s AND `last_counter` BETWEEN %s AND %s",
483
+ $platform,
484
+ $rangestartdate,
485
+ $rangeenddate
486
+ )
487
+ );
488
  } else {
489
+ $result = $wpdb->get_var(
490
+ $wpdb->prepare(
491
+ "SELECT COUNT(platform) FROM {$wpdb->prefix}statistics_visitor WHERE `platform` = %s",
492
+ $platform
493
+ )
494
+ );
495
  }
496
 
497
  return $result;
503
  global $wpdb;
504
 
505
  if ( $rangestartdate != null && $rangeenddate != null ) {
506
+ $result = $wpdb->get_results(
507
+ $wpdb->prepare(
508
+ "SELECT DISTINCT version FROM {$wpdb->prefix}statistics_visitor WHERE agent = %s AND `last_counter` BETWEEN %s AND %s",
509
+ $agent,
510
+ $rangestartdate,
511
+ $rangeenddate
512
+ ),
513
+ ARRAY_N
514
+ );
515
  } else {
516
+ $result = $wpdb->get_results(
517
+ $wpdb->prepare("SELECT DISTINCT version FROM {$wpdb->prefix}statistics_visitor WHERE agent = %s", $agent),
518
+ ARRAY_N
519
+ );
520
  }
521
 
522
  $Versions = array();
534
  global $wpdb;
535
 
536
  if ( $rangestartdate != null && $rangeenddate != null ) {
537
+ $result = $wpdb->get_var(
538
+ $wpdb->prepare(
539
+ "SELECT COUNT(version) FROM {$wpdb->prefix}statistics_visitor WHERE agent = %s AND version = %s AND `last_counter` BETWEEN %s AND %s",
540
+ $agent,
541
+ $version,
542
+ $rangestartdate,
543
+ $rangeenddate
544
+ )
545
+ );
546
  } else {
547
+ $result = $wpdb->get_var(
548
+ $wpdb->prepare(
549
+ "SELECT COUNT(version) FROM {$wpdb->prefix}statistics_visitor WHERE agent = %s AND version = %s",
550
+ $agent,
551
+ $version
552
+ )
553
+ );
554
  }
555
 
556
  return $result;
575
  $default = $engines = array(
576
  'ask' => array(
577
  'name' => 'Ask.com',
578
+ 'translated' => __('Ask.com', 'wp-statistics'),
579
  'tag' => 'ask',
580
  'sqlpattern' => '%ask.com%',
581
  'regexpattern' => 'ask\.com',
582
  'querykey' => 'q',
583
+ 'image' => 'ask.png',
584
  ),
585
  'baidu' => array(
586
  'name' => 'Baidu',
587
+ 'translated' => __('Baidu', 'wp-statistics'),
588
  'tag' => 'baidu',
589
  'sqlpattern' => '%baidu.com%',
590
  'regexpattern' => 'baidu\.com',
591
  'querykey' => 'wd',
592
+ 'image' => 'baidu.png',
593
  ),
594
  'bing' => array(
595
  'name' => 'Bing',
596
+ 'translated' => __('Bing', 'wp-statistics'),
597
  'tag' => 'bing',
598
  'sqlpattern' => '%bing.com%',
599
  'regexpattern' => 'bing\.com',
600
  'querykey' => 'q',
601
+ 'image' => 'bing.png',
602
  ),
603
  'clearch' => array(
604
  'name' => 'clearch.org',
605
+ 'translated' => __('clearch.org', 'wp-statistics'),
606
  'tag' => 'clearch',
607
  'sqlpattern' => '%clearch.org%',
608
  'regexpattern' => 'clearch\.org',
609
  'querykey' => 'q',
610
+ 'image' => 'clearch.png',
611
  ),
612
  'duckduckgo' => array(
613
  'name' => 'DuckDuckGo',
614
+ 'translated' => __('DuckDuckGo', 'wp-statistics'),
615
  'tag' => 'duckduckgo',
616
  'sqlpattern' => array( '%duckduckgo.com%', '%ddg.gg%' ),
617
  'regexpattern' => array( 'duckduckgo\.com', 'ddg\.gg' ),
618
  'querykey' => 'q',
619
+ 'image' => 'duckduckgo.png',
620
  ),
621
  'google' => array(
622
  'name' => 'Google',
623
+ 'translated' => __('Google', 'wp-statistics'),
624
  'tag' => 'google',
625
  'sqlpattern' => '%google.%',
626
  'regexpattern' => 'google\.',
627
  'querykey' => 'q',
628
+ 'image' => 'google.png',
629
  ),
630
  'yahoo' => array(
631
  'name' => 'Yahoo!',
632
+ 'translated' => __('Yahoo!', 'wp-statistics'),
633
  'tag' => 'yahoo',
634
  'sqlpattern' => '%yahoo.com%',
635
  'regexpattern' => 'yahoo\.com',
636
  'querykey' => 'p',
637
+ 'image' => 'yahoo.png',
638
  ),
639
  'yandex' => array(
640
  'name' => 'Yandex',
641
+ 'translated' => __('Yandex', 'wp-statistics'),
642
  'tag' => 'yandex',
643
  'sqlpattern' => '%yandex.ru%',
644
  'regexpattern' => 'yandex\.ru',
645
  'querykey' => 'text',
646
+ 'image' => 'yandex.png',
647
+ ),
648
  );
649
 
650
  if ( $all == false ) {
651
  foreach ( $engines as $key => $engine ) {
652
+ if ( $WP_Statistics->get_option('disable_se_' . $engine['tag']) ) {
653
  unset( $engines[ $key ] );
654
  }
655
  }
656
 
657
  // If we've disabled all the search engines, reset the list back to default.
658
+ if ( count($engines) == 0 ) {
659
  $engines = $default;
660
  }
661
  }
671
  $searchengine_list = wp_statistics_searchengine_list();
672
  $search_query = '';
673
 
674
+ if ( $WP_Statistics->get_option('search_converted') ) {
675
  // Are we getting results for all search engines or a specific one?
676
+ if ( strtolower($search_engine) == 'all' ) {
677
  // For all of them? Ok, look through the search engine list and create a SQL query string to get them all from the database.
678
  foreach ( $searchengine_list as $key => $se ) {
679
  $search_query .= "( `engine` = '{$key}' AND `words` <> '' ) OR ";
680
  }
681
 
682
  // Trim off the last ' OR ' for the loop above.
683
+ $search_query = substr($search_query, 0, strlen($search_query) - 4);
684
  } else {
685
  $search_query .= "`engine` = '{$search_engine}' AND `words` <> ''";
686
  }
687
  } else {
688
  // Are we getting results for all search engines or a specific one?
689
+ if ( strtolower($search_engine) == 'all' ) {
690
  // For all of them? Ok, look through the search engine list and create a SQL query string to get them all from the database.
691
  // NOTE: This SQL query can be *VERY* long.
692
  foreach ( $searchengine_list as $se ) {
693
  // The SQL pattern for a search engine may be an array if it has to handle multiple domains (like google.com and google.ca) or other factors.
694
+ if ( is_array($se['sqlpattern']) ) {
695
  foreach ( $se['sqlpattern'] as $subse ) {
696
  $search_query .= "(`referred` LIKE '{$subse}{$se['querykey']}=%' AND `referred` NOT LIKE '{$subse}{$se['querykey']}=&%' AND `referred` NOT LIKE '{$subse}{$se['querykey']}=') OR ";
697
  }
701
  }
702
 
703
  // Trim off the last ' OR ' for the loop above.
704
+ $search_query = substr($search_query, 0, strlen($search_query) - 4);
705
  } else {
706
  // For just one? Ok, the SQL pattern for a search engine may be an array if it has to handle multiple domains (like google.com and google.ca) or other factors.
707
+ if ( is_array($searchengine_list[ $search_engine ]['sqlpattern']) ) {
708
  foreach ( $searchengine_list[ $search_engine ]['sqlpattern'] as $se ) {
709
  $search_query .= "(`referred` LIKE '{$se}{$searchengine_list[$search_engine]['querykey']}=%' AND `referred` NOT LIKE '{$se}{$searchengine_list[$search_engine]['querykey']}=&%' AND `referred` NOT LIKE '{$se}{$searchengine_list[$search_engine]['querykey']}=') OR ";
710
  }
711
 
712
  // Trim off the last ' OR ' for the loop above.
713
+ $search_query = substr($search_query, 0, strlen($search_query) - 4);
714
  } else {
715
  $search_query .= "(`referred` LIKE '{$searchengine_list[$search_engine]['sqlpattern']}{$searchengine_list[$search_engine]['querykey']}=%' AND `referred` NOT LIKE '{$searchengine_list[$search_engine]['sqlpattern']}{$searchengine_list[$search_engine]['querykey']}=&%' AND `referred` NOT LIKE '{$searchengine_list[$search_engine]['sqlpattern']}{$searchengine_list[$search_engine]['querykey']}=')";
716
  }
728
  $searchengine_list = wp_statistics_searchengine_list();
729
  $search_query = '';
730
 
731
+ if ( $WP_Statistics->get_option('search_converted') ) {
732
  // Are we getting results for all search engines or a specific one?
733
+ if ( strtolower($search_engine) == 'all' ) {
734
  // For all of them? Ok, look through the search engine list and create a SQL query string to get them all from the database.
735
  foreach ( $searchengine_list as $key => $se ) {
736
+ $key = esc_sql($key);
737
  $search_query .= "`engine` = '{$key}' OR ";
738
  }
739
 
740
  // Trim off the last ' OR ' for the loop above.
741
+ $search_query = substr($search_query, 0, strlen($search_query) - 4);
742
  } else {
743
+ $search_engine = esc_sql($search_engine);
744
+ $search_query .= "`engine` = '{$search_engine}'";
745
  }
746
  } else {
747
  // Are we getting results for all search engines or a specific one?
748
+ if ( strtolower($search_engine) == 'all' ) {
749
  // For all of them? Ok, look through the search engine list and create a SQL query string to get them all from the database.
750
  // NOTE: This SQL query can be long.
751
  foreach ( $searchengine_list as $se ) {
752
  // The SQL pattern for a search engine may be an array if it has to handle multiple domains (like google.com and google.ca) or other factors.
753
+ if ( is_array($se['sqlpattern']) ) {
754
  foreach ( $se['sqlpattern'] as $subse ) {
755
+ $subse = esc_sql($subse);
756
  $search_query .= "`referred` LIKE '{$subse}' OR ";
757
  }
758
  } else {
759
+ $se['sqlpattern'] = esc_sql($se['sqlpattern']);
760
+ $search_query .= "`referred` LIKE '{$se['sqlpattern']}' OR ";
761
  }
762
  }
763
 
764
  // Trim off the last ' OR ' for the loop above.
765
+ $search_query = substr($search_query, 0, strlen($search_query) - 4);
766
  } else {
767
  // For just one? Ok, the SQL pattern for a search engine may be an array if it has to handle multiple domains (like google.com and google.ca) or other factors.
768
+ if ( is_array($searchengine_list[ $search_engine ]['sqlpattern']) ) {
769
  foreach ( $searchengine_list[ $search_engine ]['sqlpattern'] as $se ) {
770
+ $se = esc_sql($se);
771
  $search_query .= "`referred` LIKE '{$se}' OR ";
772
  }
773
 
774
  // Trim off the last ' OR ' for the loop above.
775
+ $search_query = substr($search_query, 0, strlen($search_query) - 4);
776
  } else {
777
+ $searchengine_list[ $search_engine ]['sqlpattern'] = esc_sql(
778
+ $searchengine_list[ $search_engine ]['sqlpattern']
779
+ );
780
+ $search_query .= "`referred` LIKE '{$searchengine_list[$search_engine]['sqlpattern']}'";
781
  }
782
  }
783
  }
793
  $search_query = '';
794
 
795
  // Are we getting results for all search engines or a specific one?
796
+ if ( strtolower($search_engine) == 'all' ) {
797
  foreach ( $searchengine_list as $se ) {
798
  // The SQL pattern for a search engine may be an array if it has to handle multiple domains (like google.com and google.ca) or other factors.
799
+ if ( is_array($se['regexpattern']) ) {
800
  foreach ( $se['regexpattern'] as $subse ) {
801
  $search_query .= "{$subse}|";
802
  }
806
  }
807
 
808
  // Trim off the last '|' for the loop above.
809
+ $search_query = substr($search_query, 0, strlen($search_query) - 1);
810
  } else {
811
  // For just one? Ok, the SQL pattern for a search engine may be an array if it has to handle multiple domains (like google.com and google.ca) or other factors.
812
+ if ( is_array($searchengine_list[ $search_engine ]['regexpattern']) ) {
813
  foreach ( $searchengine_list[ $search_engine ]['regexpattern'] as $se ) {
814
  $search_query .= "{$se}|";
815
  }
816
 
817
  // Trim off the last '|' for the loop above.
818
+ $search_query = substr($search_query, 0, strlen($search_query) - 1);
819
  } else {
820
  $search_query .= $searchengine_list[ $search_engine ]['regexpattern'];
821
  }
833
  // Determine if we're using the old or new method of storing search engine info and build the appropriate table name.
834
  $tablename = $wpdb->prefix . 'statistics_';
835
 
836
+ if ( $WP_Statistics->get_option('search_converted') ) {
837
  $tablename .= 'search';
838
  } else {
839
  $tablename .= 'visitor';
840
  }
841
 
842
  // Get a complete list of search engines
843
+ $search_query = wp_statistics_searchengine_query($search_engine);
844
 
845
  // This function accepts several options for time parameter, each one has a unique SQL query string.
846
  // They're pretty self explanatory.
847
  switch ( $time ) {
848
  case 'today':
849
+ $result = $wpdb->query(
850
+ "SELECT * FROM `{$tablename}` WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d' )}' AND {$search_query}"
851
+ );
852
+ break;
853
 
854
  case 'yesterday':
855
+ $result = $wpdb->query(
856
+ "SELECT * FROM `{$tablename}` WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d', -1 )}' AND {$search_query}"
857
+ );
858
 
859
+ break;
860
 
861
  case 'week':
862
+ $result = $wpdb->query(
863
+ "SELECT * FROM `{$tablename}` WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d', -7 )}' AND {$search_query}"
864
+ );
865
 
866
+ break;
867
 
868
  case 'month':
869
+ $result = $wpdb->query(
870
+ "SELECT * FROM `{$tablename}` WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d', -30 )}' AND {$search_query}"
871
+ );
872
 
873
+ break;
874
 
875
  case 'year':
876
+ $result = $wpdb->query(
877
+ "SELECT * FROM `{$tablename}` WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d', -365 )}' AND {$search_query}"
878
+ );
879
 
880
+ break;
881
 
882
  case 'total':
883
+ $result = $wpdb->query("SELECT * FROM `{$tablename}` WHERE {$search_query}");
884
 
885
+ break;
886
 
887
  default:
888
+ $result = $wpdb->query(
889
+ "SELECT * FROM `{$tablename}` WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d', $time)}' AND {$search_query}"
890
+ );
891
 
892
+ break;
893
  }
894
 
895
  return $result;
903
  // Determine if we're using the old or new method of storing search engine info and build the appropriate table name.
904
  $tablename = $wpdb->prefix . 'statistics_';
905
 
906
+ if ( $WP_Statistics->get_option('search_converted') ) {
907
  $tablename .= 'search';
908
  } else {
909
  $tablename .= 'visitor';
910
  }
911
 
912
  // Get a complete list of search engines
913
+ $search_query = wp_statistics_searchword_query($search_engine);
914
 
915
  // This function accepts several options for time parameter, each one has a unique SQL query string.
916
  // They're pretty self explanatory.
917
  switch ( $time ) {
918
  case 'today':
919
+ $result = $wpdb->query(
920
+ "SELECT * FROM `{$tablename}` WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d' )}' AND {$search_query}"
921
+ );
922
+ break;
923
 
924
  case 'yesterday':
925
+ $result = $wpdb->query(
926
+ "SELECT * FROM `{$tablename}` WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d', -1 )}' AND {$search_query}"
927
+ );
928
 
929
+ break;
930
 
931
  case 'week':
932
+ $result = $wpdb->query(
933
+ "SELECT * FROM `{$tablename}` WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d', -7 )}' AND {$search_query}"
934
+ );
935
 
936
+ break;
937
 
938
  case 'month':
939
+ $result = $wpdb->query(
940
+ "SELECT * FROM `{$tablename}` WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d', -30 )}' AND {$search_query}"
941
+ );
942
 
943
+ break;
944
 
945
  case 'year':
946
+ $result = $wpdb->query(
947
+ "SELECT * FROM `{$tablename}` WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d', -365 )}' AND {$search_query}"
948
+ );
949
 
950
+ break;
951
 
952
  case 'total':
953
+ $result = $wpdb->query("SELECT * FROM `{$tablename}` WHERE {$search_query}");
954
 
955
+ break;
956
 
957
  default:
958
+ $result = $wpdb->query(
959
+ "SELECT * FROM `{$tablename}` WHERE `last_counter` = '{$WP_Statistics->Current_Date( 'Y-m-d', $time )}' AND {$search_query}"
960
+ );
961
 
962
+ break;
963
  }
964
 
965
  return $result;
968
  // This function will return the total number of posts in WordPress.
969
  function wp_statistics_countposts() {
970
 
971
+ $count_posts = wp_count_posts('post');
972
 
973
  $ret = 0;
974
 
975
+ if ( is_object($count_posts) ) {
976
  $ret = $count_posts->publish;
977
  }
978
 
982
  // This function will return the total number of pages in WordPress.
983
  function wp_statistics_countpages() {
984
 
985
+ $count_pages = wp_count_posts('page');
986
 
987
  $ret = 0;
988
 
989
+ if ( is_object($count_pages) ) {
990
  $ret = $count_pages->publish;
991
  }
992
 
998
 
999
  global $wpdb;
1000
 
1001
+ $countcomms = $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->comments} WHERE comment_approved = '1'");
1002
 
1003
  return $countcomms;
1004
  }
1006
  // This function will return the total number of spam comments *IF* akismet is installed.
1007
  function wp_statistics_countspam() {
1008
 
1009
+ return number_format_i18n(get_option('akismet_spam_count'));
1010
  }
1011
 
1012
  // This function will return the total number of users in WordPress.
1022
 
1023
  global $wpdb, $WP_Statistics;
1024
 
1025
+ $db_date = $wpdb->get_var(
1026
+ "SELECT post_date FROM {$wpdb->posts} WHERE post_type='post' AND post_status='publish' ORDER BY post_date DESC LIMIT 1"
1027
+ );
1028
 
1029
+ $date_format = get_option('date_format');
1030
 
1031
+ return $WP_Statistics->Current_Date_i18n($date_format, $db_date, false);
1032
  }
1033
 
1034
  // This function will return the average number of posts per day that are published on your site.
1037
 
1038
  global $wpdb;
1039
 
1040
+ $get_first_post = $wpdb->get_var(
1041
+ "SELECT post_date FROM {$wpdb->posts} WHERE post_status = 'publish' ORDER BY post_date LIMIT 1"
1042
+ );
1043
+ $get_total_post = $wpdb->get_var(
1044
+ "SELECT COUNT(*) FROM {$wpdb->posts} WHERE post_status = 'publish' AND post_type = 'post'"
1045
+ );
1046
 
1047
+ $days_spend = intval(
1048
+ ( time() - strtotime($get_first_post) ) / 86400
1049
+ ); // 86400 = 60 * 60 * 24 = number of seconds in a day
1050
 
1051
  if ( $days == true ) {
1052
  if ( $get_total_post == 0 ) {
1053
  $get_total_post = 1;
1054
  } // Avoid divide by zero errors.
1055
 
1056
+ return round($days_spend / $get_total_post, 0);
1057
  } else {
1058
  if ( $days_spend == 0 ) {
1059
  $days_spend = 1;
1060
  } // Avoid divide by zero errors.
1061
 
1062
+ return round($get_total_post / $days_spend, 2);
1063
  }
1064
  }
1065
 
1069
 
1070
  global $wpdb;
1071
 
1072
+ $get_first_comment = $wpdb->get_var("SELECT comment_date FROM {$wpdb->comments} ORDER BY comment_date LIMIT 1");
1073
+ $get_total_comment = $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->comments} WHERE comment_approved = '1'");
1074
 
1075
+ $days_spend = intval(
1076
+ ( time() - strtotime($get_first_comment) ) / 86400
1077
+ ); // 86400 = 60 * 60 * 24 = number of seconds in a day
1078
 
1079
  if ( $days == true ) {
1080
  if ( $get_total_comment == 0 ) {
1081
  $get_total_comment = 1;
1082
  } // Avoid divide by zero errors.
1083
 
1084
+ return round($days_spend / $get_total_comment, 0);
1085
  } else {
1086
  if ( $days_spend == 0 ) {
1087
  $days_spend = 1;
1088
  } // Avoid divide by zero errors.
1089
 
1090
+ return round($get_total_comment / $days_spend, 2);
1091
  }
1092
  }
1093
 
1097
 
1098
  global $wpdb;
1099
 
1100
+ $get_first_user = $wpdb->get_var("SELECT user_registered FROM {$wpdb->users} ORDER BY user_registered LIMIT 1");
1101
+ $get_total_user = $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->users}");
1102
 
1103
+ $days_spend = intval(
1104
+ ( time() - strtotime($get_first_user) ) / 86400
1105
+ ); // 86400 = 60 * 60 * 24 = number of seconds in a day
1106
 
1107
  if ( $days == true ) {
1108
  if ( $get_total_user == 0 ) {
1109
  $get_total_user = 1;
1110
  } // Avoid divide by zero errors.
1111
 
1112
+ return round($days_spend / $get_total_user, 0);
1113
  } else {
1114
  if ( $days_spend == 0 ) {
1115
  $days_spend = 1;
1116
  } // Avoid divide by zero errors.
1117
 
1118
+ return round($get_total_user / $days_spend, 2);
1119
  }
1120
  }
1121
 
1129
  }
1130
 
1131
  // Since versions of WordPress before 3.8 didn't have dashicons, don't use them in those versions.
1132
+ if ( version_compare($wp_version, '3.8-RC', '>=') || version_compare($wp_version, '3.8', '>=') ) {
1133
  return '<span class="dashicons ' . $dashicons . '"></span>';
1134
  } else {
1135
+ return '<img src="' . plugins_url('wp-statistics/assets/images/') . $icon_name . '.png"/>';
1136
  }
1137
  }
1138
 
1142
  $enabled = true;
1143
 
1144
  // PHP 5.3
1145
+ if ( ! version_compare(phpversion(), WP_Statistics::$reg['geoip-php-version'], '>') ) {
1146
  $enabled = false;
1147
  }
1148
 
1149
  // PHP's cURL extension installed
1150
+ if ( ! function_exists('curl_init') ) {
1151
  $enabled = false;
1152
  }
1153
 
1154
  // PHP NOT running in safe mode
1155
+ if ( ini_get('safe_mode') ) {
1156
  // Double check php version, 5.4 and above don't support safe mode but the ini value may still be set after an upgrade.
1157
+ if ( ! version_compare(phpversion(), '5.4', '<') ) {
1158
  $enabled = false;
1159
  }
1160
  }
1163
  }
1164
 
1165
  // This function creates the date range selector 'widget' used in the various statistics pages.
1166
+ function wp_statistics_date_range_selector(
1167
+ $page,
1168
+ $current,
1169
+ $range = array(),
1170
+ $desc = array(),
1171
+ $extrafields = '',
1172
+ $pre_extra = '',
1173
+ $post_extra = ''
1174
+ ) {
1175
  GLOBAL $WP_Statistics;
1176
 
1177
+ wp_enqueue_script('jquery-ui-datepicker');
1178
+ wp_register_style(
1179
+ 'jquery-ui-smoothness-css',
1180
+ WP_Statistics::$reg['plugin-url'] . 'assets/css/jquery-ui-smoothness.min.css'
1181
+ );
1182
+ wp_enqueue_style('jquery-ui-smoothness-css');
1183
 
1184
+ if ( count($range) == 0 ) {
1185
  $range = array( 10, 20, 30, 60, 90, 180, 270, 365 );
1186
  $desc = array(
1187
+ __('10 Days', 'wp-statistics'),
1188
+ __('20 Days', 'wp-statistics'),
1189
+ __('30 Days', 'wp-statistics'),
1190
+ __('2 Months', 'wp-statistics'),
1191
+ __('3 Months', 'wp-statistics'),
1192
+ __('6 Months', 'wp-statistics'),
1193
+ __('9 Months', 'wp-statistics'),
1194
+ __('1 Year', 'wp-statistics'),
1195
  );
1196
  }
1197
 
1198
+ if ( count($desc) == 0 ) {
1199
  $desc = $range;
1200
  }
1201
 
1202
+ $rcount = count($range);
1203
 
1204
  $bold = true;
1205
 
1206
  // Check to see if there's a range in the URL, if so set it, otherwise use the default.
1207
+ if ( array_key_exists('rangestart', $_GET) ) {
1208
  $rangestart = $_GET['rangestart'];
1209
  } else {
1210
+ $rangestart = $WP_Statistics->Current_Date('m/d/Y', '-' . $current);
1211
  }
1212
+ if ( array_key_exists('rangeend', $_GET) ) {
1213
  $rangeend = $_GET['rangeend'];
1214
  } else {
1215
+ $rangeend = $WP_Statistics->Current_Date('m/d/Y');
1216
  }
1217
 
1218
  // Convert the text dates to unix timestamps and do some basic sanity checking.
1219
+ $rangestart_utime = $WP_Statistics->strtotimetz($rangestart);
1220
  if ( false === $rangestart_utime ) {
1221
  $rangestart_utime = time();
1222
  }
1223
+ $rangeend_utime = $WP_Statistics->strtotimetz($rangeend);
1224
  if ( false === $rangeend_utime || $rangeend_utime < $rangestart_utime ) {
1225
  $rangeend_utime = time();
1226
  }
1227
 
1228
  // Now get the number of days in the range.
1229
  $daysToDisplay = (int) ( ( $rangeend_utime - $rangestart_utime ) / 24 / 60 / 60 );
1230
+ $today = $WP_Statistics->Current_Date('m/d/Y');
1231
 
1232
  // Re-create the range start/end strings from our utime's to make sure we get ride of any cruft and have them in the format we want.
1233
+ $rangestart = $WP_Statistics->Local_Date('m/d/Y', $rangestart_utime);
1234
+ $rangeend = $WP_Statistics->Local_Date('m/d/Y', $rangeend_utime);
1235
 
1236
  // If the rangeend isn't today OR it is but not one of the standard range values, then it's a custom selected value and we need to flag it as such.
1237
+ if ( $rangeend != $today || ( $rangeend == $today && ! in_array($current, $range) ) ) {
1238
+ $current = -1;
1239
  } else {
1240
  // If on the other hand we are a standard range, let's reset the custom range selector to match it.
1241
+ $rangestart = $WP_Statistics->Current_Date('m/d/Y', '-' . $current);
1242
+ $rangeend = $WP_Statistics->Current_Date('m/d/Y');
1243
  }
1244
 
1245
  echo '<form method="get"><ul class="subsubsub wp-statistics-sub-fullwidth">' . "\r\n";
1247
  // Output any extra HTML we've been passed after the form element but before the date selector.
1248
  echo $pre_extra;
1249
 
1250
+ for ( $i = 0; $i < $rcount; $i++ ) {
1251
  echo ' <li class="all"><a ';
1252
 
1253
  if ( $current == $range[ $i ] ) {
1256
  }
1257
 
1258
  // Don't bother adding he date range to the standard links as they're not needed any may confuse the custom range selector.
1259
+ echo 'href="?page=' .
1260
+ $page .
1261
+ '&hitdays=' .
1262
+ $range[ $i ] .
1263
+ esc_url($extrafields) .
1264
+ '">' .
1265
+ $desc[ $i ] .
1266
+ '</a></li>';
1267
 
1268
  if ( $i < $rcount - 1 ) {
1269
  echo ' | ';
1276
 
1277
  echo '<input type="hidden" name="hitdays" value="-1"><input type="hidden" name="page" value="' . $page . '">';
1278
 
1279
+ parse_str($extrafields, $parse);
1280
 
1281
  foreach ( $parse as $key => $value ) {
1282
+ echo '<input type="hidden" name="' . $key . '" value="' . esc_url($value) . '">';
1283
  }
1284
 
1285
  if ( $bold ) {
1286
+ echo ' <b>' . __('Time Frame', 'wp-statistics') . ':</b> ';
1287
  } else {
1288
+ echo ' ' . __('Time Frame', 'wp-statistics') . ': ';
1289
  }
1290
 
1291
+ echo '<input type="text" size="10" name="rangestart" id="datestartpicker" value="' .
1292
+ $rangestart .
1293
+ '" placeholder="' .
1294
+ __('MM/DD/YYYY', 'wp-statistics') .
1295
+ '"> ' .
1296
+ __('to', 'wp-statistics') .
1297
+ ' <input type="text" size="10" name="rangeend" id="dateendpicker" value="' .
1298
+ $rangeend .
1299
+ '" placeholder="' .
1300
+ __('MM/DD/YYYY', 'wp-statistics') .
1301
+ '"> <input type="submit" value="' .
1302
+ __('Go', 'wp-statistics') .
1303
+ '" class="button-primary">' .
1304
+ "\r\n";
1305
 
1306
  // Output any extra HTML we've been passed after the date selector but before the submit button.
1307
  echo $post_extra;
1308
 
1309
  echo '</form>' . "\r\n";
1310
 
1311
+ echo '<script>jQuery(function() { jQuery( "#datestartpicker" ).datepicker(); jQuery( "#dateendpicker" ).datepicker(); });</script>' .
1312
+ "\r\n";
1313
  }
1314
 
1315
  // This function is used to calculate the number of days and thier respective unix timestamps.
1320
  $rangestart = $start;
1321
  $rangeend = $end;
1322
 
1323
+ if ( $daysToDisplay == -1 ) {
1324
+ $rangestart_utime = $WP_Statistics->strtotimetz($rangestart);
1325
+ $rangeend_utime = $WP_Statistics->strtotimetz($rangeend);
1326
  $daysToDisplay = (int) ( ( $rangeend_utime - $rangestart_utime ) / 24 / 60 / 60 );
1327
 
1328
  if ( $rangestart_utime == false || $rangeend_utime == false ) {
1343
  global $wpdb;
1344
 
1345
  if ( $table_name ) {
1346
+ $result = $wpdb->query('DELETE FROM ' . $table_name);
1347
 
1348
  if ( $result ) {
1349
+ return sprintf(
1350
+ __('%s table data deleted successfully.', 'wp-statistics'),
1351
+ '<code>' . $table_name . '</code>'
1352
+ );
1353
  }
1354
  }
1355
 
1356
+ return sprintf(__('Error, %s not emptied!', 'wp-statistics'), $table_name);
1357
  }
1358
 
1359
  // This function creates a small JavaScript snipit that will load the contents of a overview or dashboard widget.
1360
  function wp_statistics_generate_widget_load_javascript( $widget, $container_id = null ) {
1361
  if ( null == $container_id ) {
1362
+ $container_id = str_replace('.', '_', $widget . '_postbox');
1363
  }
1364
  ?>
1365
+ <script type="text/javascript">
1366
+ jQuery(document).ready(function () {
1367
+ wp_statistics_get_widget_contents('<?php echo $widget; ?>', '<?php echo $container_id; ?>');
1368
+ });
1369
+ </script>
1370
  <?php
1371
  }
1372
 
1373
  /**
1374
  * Generate RGBA colors
1375
  *
1376
+ * @param $num
1377
  * @param string $opacity
1378
  *
1379
  * @return string
1380
  */
1381
  function wp_statistics_generate_rgba_color( $num, $opacity = '1' ) {
1382
+ $hash = md5('color' . $num);
1383
+
1384
+ return sprintf(
1385
+ "'rgba(%s, %s, %s, %s)'",
1386
+ hexdec(substr($hash, 0, 2)),
1387
+ hexdec(substr($hash, 2, 2)),
1388
+ hexdec(substr($hash, 4, 2)),
1389
+ $opacity
1390
+ );
1391
+ }
1392
+
1393
+ /**
1394
+ * This function will validate that a capability exists,
1395
+ * if not it will default to returning the 'manage_options' capability.
1396
+ *
1397
+ * @param string $capability Capability
1398
+ *
1399
+ * @return string 'manage_options'
1400
+ */
1401
+ function wp_statistics_validate_capability( $capability ) {
1402
+
1403
+ global $wp_roles;
1404
+
1405
+ $role_list = $wp_roles->get_names();
1406
+
1407
+ if ( ! is_object($wp_roles) || ! is_array($wp_roles->roles) ) {
1408
+ return 'manage_options';
1409
+ }
1410
+
1411
+ foreach ( $wp_roles->roles as $role ) {
1412
+
1413
+ $cap_list = $role['capabilities'];
1414
+
1415
+ foreach ( $cap_list as $key => $cap ) {
1416
+ if ( $capability == $key ) {
1417
+ return $capability;
1418
+ }
1419
+ }
1420
+ }
1421
+
1422
+ return 'manage_options';
1423
+ }
1424
+
1425
+ /**
1426
+ * Notices displayed near the top of admin pages.
1427
+ *
1428
+ * @param $type
1429
+ * @param $message
1430
+ */
1431
+ function wp_statistics_admin_notice_result( $type, $message ) {
1432
+
1433
+ switch ( $type ) {
1434
+ case 'error':
1435
+ $class = 'notice notice-error';
1436
+ break;
1437
+
1438
+ case 'success':
1439
+ $class = 'notice notice-success';
1440
+ break;
1441
+ }
1442
 
1443
+ printf( '<div class="%1$s"><p>%2$s</p></div>', esc_attr( $class ), esc_html( $message ) );
1444
  }
includes/functions/geoip-populate.php DELETED
@@ -1,53 +0,0 @@
1
- <?php
2
- /*
3
- This file contains the code required to populate GeoIP infomration in to the database.
4
-
5
- It is used in two different parts of the plugin; when a user manual requests the update to happen and after a new GeoIP database has been download (if the option is selected).
6
- */
7
-
8
- // Include the MaxMind library and use it.
9
- include_once( plugin_dir_path( __FILE__ ) . '../../vendor/autoload.php' );
10
- use GeoIp2\Database\Reader;
11
-
12
- // This function does all the work.
13
- function wp_statistics_populate_geoip_info() {
14
- global $wpdb;
15
-
16
- // Find all rows in the table that currently don't have GeoIP info or have an unknown ('000') location.
17
- $result = $wpdb->get_results( "SELECT id,ip FROM `{$wpdb->prefix}statistics_visitor` WHERE location = '' or location = '000' or location IS NULL" );
18
-
19
- // Try create a new reader instance.
20
- try {
21
- $upload_dir = wp_upload_dir();
22
- $reader = new Reader( $upload_dir['basedir'] . '/wp-statistics/GeoLite2-Country.mmdb' );
23
- } catch ( Exception $e ) {
24
- return "<div class='updated settings-error'><p><strong>" . __( 'Unable to load the GeoIP database, make sure you have downloaded it in the settings page.', 'wp-statistics' ) . "</strong></p></div>";
25
- }
26
-
27
- $count = 0;
28
-
29
- // Loop through all the missing rows and update them if we find a locaiton for them.
30
- foreach ( $result as $item ) {
31
- $count ++;
32
-
33
- // If the IP address is only a hash, don't bother updating the record.
34
- if ( substr( $item->ip, 0, 6 ) != '#hash#' ) {
35
- try {
36
- $record = $reader->country( $item->ip );
37
- $location = $record->country->isoCode;
38
- if ( $location == "" ) {
39
- $location = "000";
40
- }
41
- } catch ( Exception $e ) {
42
- $location = "000";
43
- }
44
-
45
- // Update the row in the database.
46
- $wpdb->update( $wpdb->prefix . "statistics_visitor", array( 'location' => $location ), array( 'id' => $item->id ) );
47
- }
48
- }
49
-
50
- return "<div class='updated settings-error'><p><strong>" . sprintf( __( 'Updated %s GeoIP records in the visitors database.', 'wp-statistics' ), $count ) . "</strong></p></div>";
51
- }
52
-
53
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/functions/purge-hits.php CHANGED
@@ -5,7 +5,9 @@ function wp_statistics_purge_visitor_hits( $purge_hits ) {
5
  // If it's less than 10 hits, don't do anything.
6
  if ( $purge_hits > 9 ) {
7
  // Purge the visitor's with more than the defined hits.
8
- $result = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}statistics_visitor WHERE `hits` > %s", $purge_hits ) );
 
 
9
 
10
  $to_delete = array();
11
 
@@ -14,38 +16,52 @@ function wp_statistics_purge_visitor_hits( $purge_hits ) {
14
  foreach ( $result as $row ) {
15
  $to_delete[] = array( $row->ID, $row->last_counter, $row->hits );
16
  }
17
- if ( count( $to_delete ) > 0 ) {
18
  foreach ( $to_delete as $item ) {
19
  // First update the daily hit count.
20
- $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->prefix}statistics_visit SET `visit` = `visit` - %d WHERE `last_counter` = %s;", $item[2], $item[1] ) );
 
 
 
 
 
 
21
  // Next remove the visitor. Note we can't do both in a single query, looks like $wpdb doesn't like executing them together.
22
- $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}statistics_visitor WHERE `id` = %s;", $item[0] ) );
 
 
23
  }
24
 
25
- $result_string = sprintf( __( '%s records purged successfully.', 'wp-statistics' ), '<code>' . count( $to_delete ) . '</code>' );
 
 
 
26
  } else {
27
- $result_string = __( 'No visitors found to purge.', 'wp-statistics' );
28
  }
29
  } else {
30
- $result_string = __( 'Number of hits must be greater than or equal to 10!', 'wp-statistics' );
31
  }
32
 
33
- if ( $WP_Statistics->get_option( 'prune_report' ) == true ) {
34
- $blogname = get_bloginfo( 'name' );
35
- $blogemail = get_bloginfo( 'admin_email' );
36
 
37
  $headers[] = "From: $blogname <$blogemail>";
38
  $headers[] = "MIME-Version: 1.0";
39
  $headers[] = "Content-type: text/html; charset=utf-8";
40
 
41
- if ( $WP_Statistics->get_option( 'email_list' ) == '' ) {
42
- $WP_Statistics->update_option( 'email_list', $blogemail );
43
  }
44
 
45
- wp_mail( $WP_Statistics->get_option( 'email_list' ), __( 'Database pruned on', 'wp-statistics' ) . ' ' . $blogname, $result_string, $headers );
 
 
 
 
 
46
  }
47
 
48
  return $result_string;
49
  }
50
-
51
- ?>
5
  // If it's less than 10 hits, don't do anything.
6
  if ( $purge_hits > 9 ) {
7
  // Purge the visitor's with more than the defined hits.
8
+ $result = $wpdb->get_results(
9
+ $wpdb->prepare("SELECT * FROM {$wpdb->prefix}statistics_visitor WHERE `hits` > %s", $purge_hits)
10
+ );
11
 
12
  $to_delete = array();
13
 
16
  foreach ( $result as $row ) {
17
  $to_delete[] = array( $row->ID, $row->last_counter, $row->hits );
18
  }
19
+ if ( count($to_delete) > 0 ) {
20
  foreach ( $to_delete as $item ) {
21
  // First update the daily hit count.
22
+ $wpdb->query(
23
+ $wpdb->prepare(
24
+ "UPDATE {$wpdb->prefix}statistics_visit SET `visit` = `visit` - %d WHERE `last_counter` = %s;",
25
+ $item[2],
26
+ $item[1]
27
+ )
28
+ );
29
  // Next remove the visitor. Note we can't do both in a single query, looks like $wpdb doesn't like executing them together.
30
+ $wpdb->query(
31
+ $wpdb->prepare("DELETE FROM {$wpdb->prefix}statistics_visitor WHERE `id` = %s;", $item[0])
32
+ );
33
  }
34
 
35
+ $result_string = sprintf(
36
+ __('%s records purged successfully.', 'wp-statistics'),
37
+ '<code>' . count($to_delete) . '</code>'
38
+ );
39
  } else {
40
+ $result_string = __('No visitors found to purge.', 'wp-statistics');
41
  }
42
  } else {
43
+ $result_string = __('Number of hits must be greater than or equal to 10!', 'wp-statistics');
44
  }
45
 
46
+ if ( $WP_Statistics->get_option('prune_report') == true ) {
47
+ $blogname = get_bloginfo('name');
48
+ $blogemail = get_bloginfo('admin_email');
49
 
50
  $headers[] = "From: $blogname <$blogemail>";
51
  $headers[] = "MIME-Version: 1.0";
52
  $headers[] = "Content-type: text/html; charset=utf-8";
53
 
54
+ if ( $WP_Statistics->get_option('email_list') == '' ) {
55
+ $WP_Statistics->update_option('email_list', $blogemail);
56
  }
57
 
58
+ wp_mail(
59
+ $WP_Statistics->get_option('email_list'),
60
+ __('Database pruned on', 'wp-statistics') . ' ' . $blogname,
61
+ $result_string,
62
+ $headers
63
+ );
64
  }
65
 
66
  return $result_string;
67
  }
 
 
includes/functions/purge.php CHANGED
@@ -6,69 +6,121 @@ function wp_statistics_purge_data( $purge_days ) {
6
  if ( $purge_days > 30 ) {
7
  // Purge the visit data.
8
  $table_name = $wpdb->prefix . 'statistics_visit';
9
- $date_string = $WP_Statistics->current_date( 'Y-m-d', '-' . $purge_days );
10
 
11
- $result = $wpdb->query( $wpdb->prepare( "DELETE FROM {$table_name} WHERE `last_counter` < %s", $date_string ) );
12
 
13
  if ( $result ) {
14
  // Update the historical count with what we purged.
15
- $historical_result = $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->prefix}statistics_historical SET value = value + %d WHERE `category` = 'visits'", $result ) );
 
 
 
 
 
16
 
17
  if ( $historical_result == 0 ) {
18
- $wpdb->insert( $wpdb->prefix . "statistics_historical", array( 'value' => $result,
19
- 'category' => 'visits',
20
- 'page_id' => - 2,
21
- 'uri' => '-2'
22
- ) );
 
 
 
 
23
  }
24
 
25
- $result_string = sprintf( __( '%s data older than %s days purged successfully.', 'wp-statistics' ), '<code>' . $table_name . '</code>', '<code>' . $purge_days . '</code>' );
 
 
 
 
26
  } else {
27
- $result_string = sprintf( __( 'No records found to purge from %s!', 'wp-statistics' ), '<code>' . $table_name . '</code>' );
 
 
 
28
  }
29
 
30
  // Purge the visitors data.
31
  $table_name = $wpdb->prefix . 'statistics_visitor';
32
 
33
- $result = $wpdb->query( $wpdb->prepare( "DELETE FROM {$table_name} WHERE `last_counter` < %s", $date_string ) );
34
 
35
  if ( $result ) {
36
  // Update the historical count with what we purged.
37
- $historical_result = $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->prefix}statistics_historical SET value = value + %d WHERE `category` = 'visitors'", $result ) );
 
 
 
 
 
38
 
39
  if ( $historical_result == 0 ) {
40
- $wpdb->insert( $wpdb->prefix . "statistics_historical", array( 'value' => $result,
41
- 'category' => 'visitors',
42
- 'page_id' => - 1,
43
- 'uri' => '-1'
44
- ) );
 
 
 
 
45
  }
46
 
47
- $result_string .= '<br>' . sprintf( __( '%s data older than %s days purged successfully.', 'wp-statistics' ), '<code>' . $table_name . '</code>', '<code>' . $purge_days . '</code>' );
 
 
 
 
 
48
  } else {
49
- $result_string .= '<br>' . sprintf( __( 'No records found to purge from %s!', 'wp-statistics' ), '<code>' . $table_name . '</code>' );
 
 
 
 
50
  }
51
 
52
  // Purge the exclusions data.
53
  $table_name = $wpdb->prefix . 'statistics_exclusions';
54
 
55
- $result = $wpdb->query( $wpdb->prepare( "DELETE FROM {$table_name} WHERE `date` < %s", $date_string ) );
56
 
57
  if ( $result ) {
58
- $result_string .= '<br>' . sprintf( __( '%s data older than %s days purged successfully.', 'wp-statistics' ), '<code>' . $table_name . '</code>', '<code>' . $purge_days . '</code>' );
 
 
 
 
 
59
  } else {
60
- $result_string .= '<br>' . sprintf( __( 'No records found to purge from %s!', 'wp-statistics' ), '<code>' . $table_name . '</code>' );
 
 
 
 
61
  }
62
 
63
  // Purge the search data.
64
  $table_name = $wpdb->prefix . 'statistics_search';
65
 
66
- $result = $wpdb->query( $wpdb->prepare( "DELETE FROM {$table_name} WHERE `last_counter` < %s", $date_string ) );
67
 
68
  if ( $result ) {
69
- $result_string .= '<br>' . sprintf( __( '%s data older than %s days purged successfully.', 'wp-statistics' ), '<code>' . $table_name . '</code>', '<code>' . $purge_days . '</code>' );
 
 
 
 
 
70
  } else {
71
- $result_string .= '<br>' . sprintf( __( 'No records found to purge from %s!', 'wp-statistics' ), '<code>' . $table_name . '</code>' );
 
 
 
 
72
  }
73
 
74
  // Purge the pages data, this is more complex as we want to save the historical data per page.
@@ -76,57 +128,88 @@ function wp_statistics_purge_data( $purge_days ) {
76
  $historical = 0;
77
 
78
  // The first thing we need to do is update the historical data by finding all the unique pages.
79
- $result = $wpdb->get_results( $wpdb->prepare( "SELECT DISTINCT uri FROM {$table_name} WHERE `date` < %s", $date_string ) );
 
 
80
 
81
  // If we have a result, let's store the historical data.
82
  if ( $result ) {
83
  // Loop through all the unique rows that were returned.
84
  foreach ( $result as $row ) {
85
  // Use the unique rows to get a total count from the database of all the data from the given URIs/Pageids that we're going to delete later.
86
- $historical = $wpdb->get_var( $wpdb->prepare( "SELECT sum(count) FROM {$table_name} WHERE `uri` = %s AND `date` < %s", $row->uri, $date_string ) );
 
 
 
 
 
 
87
 
88
  // Do an update of the historical data.
89
- $uresult = $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->prefix}statistics_historical SET `value` = value + %d WHERE `uri` = %s AND `category` = 'uri'", $historical, $row->uri, $date_string ) );
 
 
 
 
 
 
 
90
 
91
  // If we failed it's because this is the first time we've seen this URI/pageid so let's create a historical row for it.
92
  if ( $uresult == 0 ) {
93
- $wpdb->insert( $wpdb->prefix . "statistics_historical", array( 'value' => $historical,
94
- 'category' => 'uri',
95
- 'uri' => $row->uri,
96
- 'page_id' => wp_statistics_uri_to_id( $row->uri )
97
- ) );
 
 
 
 
98
  }
99
  }
100
  }
101
 
102
  // Now that we've done all of the required historical data storage, we can actually delete the data from the database.
103
- $result = $wpdb->query( $wpdb->prepare( "DELETE FROM {$table_name} WHERE `date` < %s", $date_string ) );
104
 
105
  if ( $result ) {
106
- $result_string .= '<br>' . sprintf( __( '%s data older than %s days purged successfully.', 'wp-statistics' ), '<code>' . $table_name . '</code>', '<code>' . $purge_days . '</code>' );
 
 
 
 
 
107
  } else {
108
- $result_string .= '<br>' . sprintf( __( 'No records found to purge from %s!', 'wp-statistics' ), '<code>' . $table_name . '</code>' );
 
 
 
 
109
  }
110
 
111
- if ( $WP_Statistics->get_option( 'prune_report' ) == true ) {
112
- $blogname = get_bloginfo( 'name' );
113
- $blogemail = get_bloginfo( 'admin_email' );
114
 
115
  $headers[] = "From: $blogname <$blogemail>";
116
  $headers[] = "MIME-Version: 1.0";
117
  $headers[] = "Content-type: text/html; charset=utf-8";
118
 
119
- if ( $WP_Statistics->get_option( 'email_list' ) == '' ) {
120
- $WP_Statistics->update_option( 'email_list', $blogemail );
121
  }
122
 
123
- wp_mail( $WP_Statistics->get_option( 'email_list' ), __( 'Database pruned on', 'wp-statistics' ) . ' ' . $blogname, $result_string, $headers );
 
 
 
 
 
124
  }
125
 
126
  return $result_string;
127
  } else {
128
- return __( 'Please select a value over 30 days.', 'wp-statistics' );
129
  }
130
  }
131
-
132
- ?>
6
  if ( $purge_days > 30 ) {
7
  // Purge the visit data.
8
  $table_name = $wpdb->prefix . 'statistics_visit';
9
+ $date_string = $WP_Statistics->current_date('Y-m-d', '-' . $purge_days);
10
 
11
+ $result = $wpdb->query($wpdb->prepare("DELETE FROM {$table_name} WHERE `last_counter` < %s", $date_string));
12
 
13
  if ( $result ) {
14
  // Update the historical count with what we purged.
15
+ $historical_result = $wpdb->query(
16
+ $wpdb->prepare(
17
+ "UPDATE {$wpdb->prefix}statistics_historical SET value = value + %d WHERE `category` = 'visits'",
18
+ $result
19
+ )
20
+ );
21
 
22
  if ( $historical_result == 0 ) {
23
+ $wpdb->insert(
24
+ $wpdb->prefix . "statistics_historical",
25
+ array(
26
+ 'value' => $result,
27
+ 'category' => 'visits',
28
+ 'page_id' => -2,
29
+ 'uri' => '-2',
30
+ )
31
+ );
32
  }
33
 
34
+ $result_string = sprintf(
35
+ __('%s data older than %s days purged successfully.', 'wp-statistics'),
36
+ '<code>' . $table_name . '</code>',
37
+ '<code>' . $purge_days . '</code>'
38
+ );
39
  } else {
40
+ $result_string = sprintf(
41
+ __('No records found to purge from %s!', 'wp-statistics'),
42
+ '<code>' . $table_name . '</code>'
43
+ );
44
  }
45
 
46
  // Purge the visitors data.
47
  $table_name = $wpdb->prefix . 'statistics_visitor';
48
 
49
+ $result = $wpdb->query($wpdb->prepare("DELETE FROM {$table_name} WHERE `last_counter` < %s", $date_string));
50
 
51
  if ( $result ) {
52
  // Update the historical count with what we purged.
53
+ $historical_result = $wpdb->query(
54
+ $wpdb->prepare(
55
+ "UPDATE {$wpdb->prefix}statistics_historical SET value = value + %d WHERE `category` = 'visitors'",
56
+ $result
57
+ )
58
+ );
59
 
60
  if ( $historical_result == 0 ) {
61
+ $wpdb->insert(
62
+ $wpdb->prefix . "statistics_historical",
63
+ array(
64
+ 'value' => $result,
65
+ 'category' => 'visitors',
66
+ 'page_id' => -1,
67
+ 'uri' => '-1',
68
+ )
69
+ );
70
  }
71
 
72
+ $result_string .= '<br>' .
73
+ sprintf(
74
+ __('%s data older than %s days purged successfully.', 'wp-statistics'),
75
+ '<code>' . $table_name . '</code>',
76
+ '<code>' . $purge_days . '</code>'
77
+ );
78
  } else {
79
+ $result_string .= '<br>' .
80
+ sprintf(
81
+ __('No records found to purge from %s!', 'wp-statistics'),
82
+ '<code>' . $table_name . '</code>'
83
+ );
84
  }
85
 
86
  // Purge the exclusions data.
87
  $table_name = $wpdb->prefix . 'statistics_exclusions';
88
 
89
+ $result = $wpdb->query($wpdb->prepare("DELETE FROM {$table_name} WHERE `date` < %s", $date_string));
90
 
91
  if ( $result ) {
92
+ $result_string .= '<br>' .
93
+ sprintf(
94
+ __('%s data older than %s days purged successfully.', 'wp-statistics'),
95
+ '<code>' . $table_name . '</code>',
96
+ '<code>' . $purge_days . '</code>'
97
+ );
98
  } else {
99
+ $result_string .= '<br>' .
100
+ sprintf(
101
+ __('No records found to purge from %s!', 'wp-statistics'),
102
+ '<code>' . $table_name . '</code>'
103
+ );
104
  }
105
 
106
  // Purge the search data.
107
  $table_name = $wpdb->prefix . 'statistics_search';
108
 
109
+ $result = $wpdb->query($wpdb->prepare("DELETE FROM {$table_name} WHERE `last_counter` < %s", $date_string));
110
 
111
  if ( $result ) {
112
+ $result_string .= '<br>' .
113
+ sprintf(
114
+ __('%s data older than %s days purged successfully.', 'wp-statistics'),
115
+ '<code>' . $table_name . '</code>',
116
+ '<code>' . $purge_days . '</code>'
117
+ );
118
  } else {
119
+ $result_string .= '<br>' .
120
+ sprintf(
121
+ __('No records found to purge from %s!', 'wp-statistics'),
122
+ '<code>' . $table_name . '</code>'
123
+ );
124
  }
125
 
126
  // Purge the pages data, this is more complex as we want to save the historical data per page.
128
  $historical = 0;
129
 
130
  // The first thing we need to do is update the historical data by finding all the unique pages.
131
+ $result = $wpdb->get_results(
132
+ $wpdb->prepare("SELECT DISTINCT uri FROM {$table_name} WHERE `date` < %s", $date_string)
133
+ );
134
 
135
  // If we have a result, let's store the historical data.
136
  if ( $result ) {
137
  // Loop through all the unique rows that were returned.
138
  foreach ( $result as $row ) {
139
  // Use the unique rows to get a total count from the database of all the data from the given URIs/Pageids that we're going to delete later.
140
+ $historical = $wpdb->get_var(
141
+ $wpdb->prepare(
142
+ "SELECT sum(count) FROM {$table_name} WHERE `uri` = %s AND `date` < %s",
143
+ $row->uri,
144
+ $date_string
145
+ )
146
+ );
147
 
148
  // Do an update of the historical data.
149
+ $uresult = $wpdb->query(
150
+ $wpdb->prepare(
151
+ "UPDATE {$wpdb->prefix}statistics_historical SET `value` = value + %d WHERE `uri` = %s AND `category` = 'uri'",
152
+ $historical,
153
+ $row->uri,
154
+ $date_string
155
+ )
156
+ );
157
 
158
  // If we failed it's because this is the first time we've seen this URI/pageid so let's create a historical row for it.
159
  if ( $uresult == 0 ) {
160
+ $wpdb->insert(
161
+ $wpdb->prefix . "statistics_historical",
162
+ array(
163
+ 'value' => $historical,
164
+ 'category' => 'uri',
165
+ 'uri' => $row->uri,
166
+ 'page_id' => wp_statistics_uri_to_id($row->uri),
167
+ )
168
+ );
169
  }
170
  }
171
  }
172
 
173
  // Now that we've done all of the required historical data storage, we can actually delete the data from the database.
174
+ $result = $wpdb->query($wpdb->prepare("DELETE FROM {$table_name} WHERE `date` < %s", $date_string));
175
 
176
  if ( $result ) {
177
+ $result_string .= '<br>' .
178
+ sprintf(
179
+ __('%s data older than %s days purged successfully.', 'wp-statistics'),
180
+ '<code>' . $table_name . '</code>',
181
+ '<code>' . $purge_days . '</code>'
182
+ );
183
  } else {
184
+ $result_string .= '<br>' .
185
+ sprintf(
186
+ __('No records found to purge from %s!', 'wp-statistics'),
187
+ '<code>' . $table_name . '</code>'
188
+ );
189
  }
190
 
191
+ if ( $WP_Statistics->get_option('prune_report') == true ) {
192
+ $blogname = get_bloginfo('name');
193
+ $blogemail = get_bloginfo('admin_email');
194
 
195
  $headers[] = "From: $blogname <$blogemail>";
196
  $headers[] = "MIME-Version: 1.0";
197
  $headers[] = "Content-type: text/html; charset=utf-8";
198
 
199
+ if ( $WP_Statistics->get_option('email_list') == '' ) {
200
+ $WP_Statistics->update_option('email_list', $blogemail);
201
  }
202
 
203
+ wp_mail(
204
+ $WP_Statistics->get_option('email_list'),
205
+ __('Database pruned on', 'wp-statistics') . ' ' . $blogname,
206
+ $result_string,
207
+ $headers
208
+ );
209
  }
210
 
211
  return $result_string;
212
  } else {
213
+ return __('Please select a value over 30 days.', 'wp-statistics');
214
  }
215
  }
 
 
includes/{classes → github/elidickinson/php-export-data}/php-export-data.class.php RENAMED
@@ -1,6 +1,5 @@
1
  <?php
2
  // php-export-data by Eli Dickinson, http://github.com/elidickinson/php-export-data
3
-
4
  /**
5
  * ExportData is the base class for exporters to specific file formats. See other
6
  * classes below.
@@ -10,20 +9,18 @@ abstract class ExportData {
10
  protected $stringData; // stringData so far, used if export string mode
11
  protected $tempFile; // handle to temp file (for export file mode)
12
  protected $tempFilename; // temp file name and path (for export file mode)
13
-
14
  public $filename; // file mode: the output file name; browser mode: file name for download; string mode: not used
15
-
16
- public function __construct( $exportTo = "browser", $filename = "exportdata" ) {
17
- if ( ! in_array( $exportTo, array( 'browser', 'file', 'string' ) ) ) {
18
- throw new Exception( "$exportTo is not a valid ExportData export type" );
19
  }
20
  $this->exportTo = $exportTo;
21
  $this->filename = $filename;
22
  }
23
-
24
  public function initialize() {
25
-
26
- switch ( $this->exportTo ) {
27
  case 'browser':
28
  $this->sendHttpHeaders();
29
  break;
@@ -31,23 +28,23 @@ abstract class ExportData {
31
  $this->stringData = '';
32
  break;
33
  case 'file':
34
- $this->tempFilename = tempnam( sys_get_temp_dir(), 'exportdata' );
35
- $this->tempFile = fopen( $this->tempFilename, "w" );
36
  break;
37
  }
38
-
39
- $this->write( $this->generateHeader() );
40
  }
41
-
42
- public function addRow( $row ) {
43
- $this->write( $this->generateRow( $row ) );
44
  }
45
-
46
  public function finalize() {
47
-
48
- $this->write( $this->generateFooter() );
49
-
50
- switch ( $this->exportTo ) {
51
  case 'browser':
52
  flush();
53
  break;
@@ -56,20 +53,20 @@ abstract class ExportData {
56
  break;
57
  case 'file':
58
  // close temp file and move it to correct location
59
- fclose( $this->tempFile );
60
- rename( $this->tempFilename, $this->filename );
61
  break;
62
  }
63
  }
64
-
65
  public function getString() {
66
  return $this->stringData;
67
  }
68
-
69
  abstract public function sendHttpHeaders();
70
-
71
- protected function write( $data ) {
72
- switch ( $this->exportTo ) {
73
  case 'browser':
74
  echo $data;
75
  break;
@@ -77,137 +74,130 @@ abstract class ExportData {
77
  $this->stringData .= $data;
78
  break;
79
  case 'file':
80
- fwrite( $this->tempFile, $data );
81
  break;
82
  }
83
  }
84
-
85
  protected function generateHeader() {
86
  // can be overridden by subclass to return any data that goes at the top of the exported file
87
  }
88
-
89
  protected function generateFooter() {
90
  // can be overridden by subclass to return any data that goes at the bottom of the exported file
91
  }
92
-
93
  // In subclasses generateRow will take $row array and return string of it formatted for export type
94
- abstract protected function generateRow( $row );
95
-
96
  }
97
-
98
  /**
99
  * ExportDataTSV - Exports to TSV (tab separated value) format.
100
  */
101
  class ExportDataTSV extends ExportData {
102
-
103
- function generateRow( $row ) {
104
- foreach ( $row as $key => $value ) {
105
  // Escape inner quotes and wrap all contents in new quotes.
106
  // Note that we are using \" to escape double quote not ""
107
- $row[ $key ] = '"' . str_replace( '"', '\"', $value ) . '"';
108
  }
109
-
110
- return implode( "\t", $row ) . "\n";
111
  }
112
-
113
  function sendHttpHeaders() {
114
- header( "Content-type: text/tab-separated-values" );
115
- header( "Content-Disposition: attachment; filename=" . basename( $this->filename ) );
116
  }
117
  }
118
-
119
  /**
120
  * ExportDataCSV - Exports to CSV (comma separated value) format.
121
  */
122
  class ExportDataCSV extends ExportData {
123
-
124
- function generateRow( $row ) {
125
- foreach ( $row as $key => $value ) {
126
  // Escape inner quotes and wrap all contents in new quotes.
127
  // Note that we are using \" to escape double quote not ""
128
- $row[ $key ] = '"' . str_replace( '"', '\"', $value ) . '"';
129
  }
130
-
131
- return implode( ",", $row ) . "\n";
132
  }
133
-
134
  function sendHttpHeaders() {
135
- header( "Content-type: text/csv" );
136
- header( "Content-Disposition: attachment; filename=" . basename( $this->filename ) );
137
  }
138
  }
139
-
140
-
141
  /**
142
- * ExportDataExcel exports data into an XML format (spreadsheetML) that can be
143
  * read by MS Excel 2003 and newer as well as OpenOffice
144
- *
145
  * Creates a workbook with a single worksheet (title specified by
146
  * $title).
147
- *
148
  * Note that using .XML is the "correct" file extension for these files, but it
149
  * generally isn't associated with Excel. Using .XLS is tempting, but Excel 2007 will
150
  * throw a scary warning that the extension doesn't match the file type.
151
- *
152
  * Based on Excel XML code from Excel_XML (http://github.com/oliverschwarz/php-excel)
153
  * by Oliver Schwarz
154
  */
155
  class ExportDataExcel extends ExportData {
156
-
157
  const XmlHeader = "<?xml version=\"1.0\" encoding=\"%s\"?\>\n<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\" xmlns:x=\"urn:schemas-microsoft-com:office:excel\" xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\" xmlns:html=\"http://www.w3.org/TR/REC-html40\">";
158
  const XmlFooter = "</Workbook>";
159
-
160
  public $encoding = 'UTF-8'; // encoding type to specify in file.
161
  // Note that you're on your own for making sure your data is actually encoded to this encoding
162
-
163
  public $title = 'Sheet1'; // title for Worksheet
164
-
165
  function generateHeader() {
166
-
167
  // workbook header
168
- $output = stripslashes( sprintf( self::XmlHeader, $this->encoding ) ) . "\n";
169
-
170
  // Set up styles
171
  $output .= "<Styles>\n";
172
  $output .= "<Style ss:ID=\"sDT\"><NumberFormat ss:Format=\"Short Date\"/></Style>\n";
173
  $output .= "</Styles>\n";
174
-
175
  // worksheet header
176
- $output .= sprintf( "<Worksheet ss:Name=\"%s\">\n <Table>\n", htmlentities( $this->title ) );
177
-
178
  return $output;
179
  }
180
-
181
  function generateFooter() {
182
  $output = '';
183
-
184
  // worksheet footer
185
  $output .= " </Table>\n</Worksheet>\n";
186
-
187
  // workbook footer
188
  $output .= self::XmlFooter;
189
-
190
  return $output;
191
  }
192
-
193
- function generateRow( $row ) {
194
  $output = '';
195
  $output .= " <Row>\n";
196
- foreach ( $row as $k => $v ) {
197
- $output .= $this->generateCell( $v );
198
  }
199
  $output .= " </Row>\n";
200
-
201
  return $output;
202
  }
203
-
204
- private function generateCell( $item ) {
205
  $output = '';
206
- $style = '';
207
-
208
  // Tell Excel to treat as a number. Note that Excel only stores roughly 15 digits, so keep
209
  // as text if number is longer than that.
210
- if ( preg_match( "/^-?\d+(?:[.,]\d+)?$/", $item ) && ( strlen( $item ) < 15 ) ) {
211
  $type = 'Number';
212
  }
213
  // Sniff for valid dates; should look something like 2010-07-14 or 7/14/2010 etc. Can
@@ -216,30 +206,30 @@ class ExportDataExcel extends ExportData {
216
  // Note we want to be very strict in what we consider a date. There is the possibility
217
  // of really screwing up the data if we try to reformat a string that was not actually
218
  // intended to represent a date.
219
- elseif ( preg_match( "/^(\d{1,2}|\d{4})[\/\-]\d{1,2}[\/\-](\d{1,2}|\d{4})([^\d].+)?$/", $item ) &&
220
- ( $timestamp = strtotime( $item ) ) &&
221
- ( $timestamp > 0 ) &&
222
- ( $timestamp < strtotime( '+500 years' ) )
223
- ) {
224
- $type = 'DateTime';
225
- $item = strftime( "%Y-%m-%dT%H:%M:%S", $timestamp );
226
  $style = 'sDT'; // defined in header; tells excel to format date for display
227
- } else {
 
228
  $type = 'String';
229
  }
230
-
231
- $item = str_replace( '&#039;', '&apos;', htmlspecialchars( $item, ENT_QUOTES ) );
232
  $output .= " ";
233
  $output .= $style ? "<Cell ss:StyleID=\"$style\">" : "<Cell>";
234
- $output .= sprintf( "<Data ss:Type=\"%s\">%s</Data>", $type, $item );
235
  $output .= "</Cell>\n";
236
-
237
  return $output;
238
  }
239
-
240
  function sendHttpHeaders() {
241
- header( "Content-Type: application/vnd.ms-excel; charset=" . $this->encoding );
242
- header( "Content-Disposition: inline; filename=\"" . basename( $this->filename ) . "\"" );
243
  }
244
-
245
- }
1
  <?php
2
  // php-export-data by Eli Dickinson, http://github.com/elidickinson/php-export-data
 
3
  /**
4
  * ExportData is the base class for exporters to specific file formats. See other
5
  * classes below.
9
  protected $stringData; // stringData so far, used if export string mode
10
  protected $tempFile; // handle to temp file (for export file mode)
11
  protected $tempFilename; // temp file name and path (for export file mode)
 
12
  public $filename; // file mode: the output file name; browser mode: file name for download; string mode: not used
13
+ public function __construct($exportTo = "browser", $filename = "exportdata") {
14
+ if(!in_array($exportTo, array('browser','file','string') )) {
15
+ throw new Exception("$exportTo is not a valid ExportData export type");
 
16
  }
17
  $this->exportTo = $exportTo;
18
  $this->filename = $filename;
19
  }
20
+
21
  public function initialize() {
22
+
23
+ switch($this->exportTo) {
24
  case 'browser':
25
  $this->sendHttpHeaders();
26
  break;
28
  $this->stringData = '';
29
  break;
30
  case 'file':
31
+ $this->tempFilename = tempnam(sys_get_temp_dir(), 'exportdata');
32
+ $this->tempFile = fopen($this->tempFilename, "w");
33
  break;
34
  }
35
+
36
+ $this->write($this->generateHeader());
37
  }
38
+
39
+ public function addRow($row) {
40
+ $this->write($this->generateRow($row));
41
  }
42
+
43
  public function finalize() {
44
+
45
+ $this->write($this->generateFooter());
46
+
47
+ switch($this->exportTo) {
48
  case 'browser':
49
  flush();
50
  break;
53
  break;
54
  case 'file':
55
  // close temp file and move it to correct location
56
+ fclose($this->tempFile);
57
+ rename($this->tempFilename, $this->filename);
58
  break;
59
  }
60
  }
61
+
62
  public function getString() {
63
  return $this->stringData;
64
  }
65
+
66
  abstract public function sendHttpHeaders();
67
+
68
+ protected function write($data) {
69
+ switch($this->exportTo) {
70
  case 'browser':
71
  echo $data;
72
  break;
74
  $this->stringData .= $data;
75
  break;
76
  case 'file':
77
+ fwrite($this->tempFile, $data);
78
  break;
79
  }
80
  }
81
+
82
  protected function generateHeader() {
83
  // can be overridden by subclass to return any data that goes at the top of the exported file
84
  }
85
+
86
  protected function generateFooter() {
87
  // can be overridden by subclass to return any data that goes at the bottom of the exported file
88
  }
89
+
90
  // In subclasses generateRow will take $row array and return string of it formatted for export type
91
+ abstract protected function generateRow($row);
92
+
93
  }
 
94
  /**
95
  * ExportDataTSV - Exports to TSV (tab separated value) format.
96
  */
97
  class ExportDataTSV extends ExportData {
98
+
99
+ function generateRow($row) {
100
+ foreach ($row as $key => $value) {
101
  // Escape inner quotes and wrap all contents in new quotes.
102
  // Note that we are using \" to escape double quote not ""
103
+ $row[$key] = '"'. str_replace('"', '\"', $value) .'"';
104
  }
105
+ return implode("\t", $row) . "\n";
 
106
  }
107
+
108
  function sendHttpHeaders() {
109
+ header("Content-type: text/tab-separated-values");
110
+ header("Content-Disposition: attachment; filename=".basename($this->filename));
111
  }
112
  }
 
113
  /**
114
  * ExportDataCSV - Exports to CSV (comma separated value) format.
115
  */
116
  class ExportDataCSV extends ExportData {
117
+
118
+ function generateRow($row) {
119
+ foreach ($row as $key => $value) {
120
  // Escape inner quotes and wrap all contents in new quotes.
121
  // Note that we are using \" to escape double quote not ""
122
+ $row[$key] = '"'. str_replace('"', '\"', $value) .'"';
123
  }
124
+ return implode(",", $row) . "\n";
 
125
  }
126
+
127
  function sendHttpHeaders() {
128
+ header("Content-type: text/csv");
129
+ header("Content-Disposition: attachment; filename=".basename($this->filename));
130
  }
131
  }
 
 
132
  /**
133
+ * ExportDataExcel exports data into an XML format (spreadsheetML) that can be
134
  * read by MS Excel 2003 and newer as well as OpenOffice
135
+ *
136
  * Creates a workbook with a single worksheet (title specified by
137
  * $title).
138
+ *
139
  * Note that using .XML is the "correct" file extension for these files, but it
140
  * generally isn't associated with Excel. Using .XLS is tempting, but Excel 2007 will
141
  * throw a scary warning that the extension doesn't match the file type.
142
+ *
143
  * Based on Excel XML code from Excel_XML (http://github.com/oliverschwarz/php-excel)
144
  * by Oliver Schwarz
145
  */
146
  class ExportDataExcel extends ExportData {
147
+
148
  const XmlHeader = "<?xml version=\"1.0\" encoding=\"%s\"?\>\n<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\" xmlns:x=\"urn:schemas-microsoft-com:office:excel\" xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\" xmlns:html=\"http://www.w3.org/TR/REC-html40\">";
149
  const XmlFooter = "</Workbook>";
150
+
151
  public $encoding = 'UTF-8'; // encoding type to specify in file.
152
  // Note that you're on your own for making sure your data is actually encoded to this encoding
153
+
154
  public $title = 'Sheet1'; // title for Worksheet
155
+
156
  function generateHeader() {
157
+
158
  // workbook header
159
+ $output = stripslashes(sprintf(self::XmlHeader, $this->encoding)) . "\n";
160
+
161
  // Set up styles
162
  $output .= "<Styles>\n";
163
  $output .= "<Style ss:ID=\"sDT\"><NumberFormat ss:Format=\"Short Date\"/></Style>\n";
164
  $output .= "</Styles>\n";
165
+
166
  // worksheet header
167
+ $output .= sprintf("<Worksheet ss:Name=\"%s\">\n <Table>\n", htmlentities($this->title));
168
+
169
  return $output;
170
  }
171
+
172
  function generateFooter() {
173
  $output = '';
174
+
175
  // worksheet footer
176
  $output .= " </Table>\n</Worksheet>\n";
177
+
178
  // workbook footer
179
  $output .= self::XmlFooter;
180
+
181
  return $output;
182
  }
183
+
184
+ function generateRow($row) {
185
  $output = '';
186
  $output .= " <Row>\n";
187
+ foreach ($row as $k => $v) {
188
+ $output .= $this->generateCell($v);
189
  }
190
  $output .= " </Row>\n";
 
191
  return $output;
192
  }
193
+
194
+ private function generateCell($item) {
195
  $output = '';
196
+ $style = '';
197
+
198
  // Tell Excel to treat as a number. Note that Excel only stores roughly 15 digits, so keep
199
  // as text if number is longer than that.
200
+ if(preg_match("/^-?\d+(?:[.,]\d+)?$/",$item) && (strlen($item) < 15)) {
201
  $type = 'Number';
202
  }
203
  // Sniff for valid dates; should look something like 2010-07-14 or 7/14/2010 etc. Can
206
  // Note we want to be very strict in what we consider a date. There is the possibility
207
  // of really screwing up the data if we try to reformat a string that was not actually
208
  // intended to represent a date.
209
+ elseif(preg_match("/^(\d{1,2}|\d{4})[\/\-]\d{1,2}[\/\-](\d{1,2}|\d{4})([^\d].+)?$/",$item) &&
210
+ ($timestamp = strtotime($item)) &&
211
+ ($timestamp > 0) &&
212
+ ($timestamp < strtotime('+500 years'))) {
213
+ $type = 'DateTime';
214
+ $item = strftime("%Y-%m-%dT%H:%M:%S",$timestamp);
 
215
  $style = 'sDT'; // defined in header; tells excel to format date for display
216
+ }
217
+ else {
218
  $type = 'String';
219
  }
220
+
221
+ $item = str_replace('&#039;', '&apos;', htmlspecialchars($item, ENT_QUOTES));
222
  $output .= " ";
223
  $output .= $style ? "<Cell ss:StyleID=\"$style\">" : "<Cell>";
224
+ $output .= sprintf("<Data ss:Type=\"%s\">%s</Data>", $type, $item);
225
  $output .= "</Cell>\n";
226
+
227
  return $output;
228
  }
229
+
230
  function sendHttpHeaders() {
231
+ header("Content-Type: application/vnd.ms-excel; charset=" . $this->encoding);
232
+ header("Content-Disposition: inline; filename=\"" . basename($this->filename) . "\"");
233
  }
234
+
235
+ }
includes/log/all-browsers.php CHANGED
@@ -1,296 +1,314 @@
1
  <script type="text/javascript">
2
- jQuery(document).ready(function () {
3
- postboxes.add_postbox_toggles(pagenow);
4
- });
5
  </script>
6
  <?php
7
  $daysToDisplay = 20;
8
- if ( array_key_exists( 'hitdays', $_GET ) ) {
9
- $daysToDisplay = intval( $_GET['hitdays'] );
10
  }
11
 
12
- if ( array_key_exists( 'rangestart', $_GET ) ) {
13
  $rangestart = $_GET['rangestart'];
14
  } else {
15
  $rangestart = '';
16
  }
17
- if ( array_key_exists( 'rangeend', $_GET ) ) {
18
  $rangeend = $_GET['rangeend'];
19
  } else {
20
  $rangeend = '';
21
  }
22
 
23
- list( $daysToDisplay, $rangestart_utime, $rangeend_utime ) = wp_statistics_date_range_calculator( $daysToDisplay, $rangestart, $rangeend );
 
 
 
 
24
 
25
- $rangestartdate = $WP_Statistics->real_current_date( 'Y-m-d', '-0', $rangestart_utime );
26
- $rangeenddate = $WP_Statistics->real_current_date( 'Y-m-d', '-0', $rangeend_utime );
27
 
28
  // Browsers
29
  $Browsers = wp_statistics_ua_list();
30
- if ( ! is_array( $Browsers ) ) {
31
  $Browsers = array();
32
  }
33
 
34
- natcasesort( $Browsers );
35
  $BrowserVisits = array();
36
  foreach ( $Browsers as $Browser ) {
37
- $BrowserVisits[ $Browser ] = wp_statistics_useragent( $Browser, $rangestartdate, $rangeenddate );
38
  }
39
 
 
40
  $i = 0;
41
  $browser_value = array();
42
  $browser_color = array();
43
 
44
  foreach ( $BrowserVisits as $key => $value ) {
45
  if ( $value > 10 and $key ) {
46
- $i ++;
47
  $browser_name[] = "'" . $key . "'";
48
  $browser_value[] = $value;
49
- $browser_color[] = wp_statistics_generate_rgba_color( $i, '0.4' );
50
  }
51
  }
52
 
53
  // Platforms
54
- $Platforms = wp_statistics_platform_list( null, $rangestartdate, $rangeenddate );
55
- if ( ! is_array( $Platforms ) ) {
56
  $Platforms = array();
57
  }
58
 
59
- natcasesort( $Platforms );
60
  $PlatformVisits = array();
61
  foreach ( $Platforms as $Platform ) {
62
- $PlatformVisits[ $Platform ] = wp_statistics_platform( $Platform );
63
  }
64
 
65
  $i = 0;
66
  foreach ( $PlatformVisits as $key => $value ) {
67
- $i ++;
68
  $platform_name[] = "'" . $key . "'";
69
  $platform_value[] = $value;
70
- $platform_color[] = wp_statistics_generate_rgba_color( $i, '0.4' );
71
  }
72
  ?>
73
  <div class="wrap">
74
- <h2><?php _e( 'Browser Statistics', 'wp-statistics' ); ?></h2>
75
- <div><?php wp_statistics_date_range_selector( WP_STATISTICS_BROWSERS_PAGE, $daysToDisplay ); ?></div>
76
- <div class="postbox-container" style="width: 48%; float: left; margin-right:20px">
77
- <div class="metabox-holder">
78
- <div class="meta-box-sortables">
79
- <div class="postbox">
80
- <?php $paneltitle = __( 'Browsers', 'wp-statistics' ); ?>
81
- <button class="handlediv" type="button" aria-expanded="true">
82
- <span class="screen-reader-text"><?php printf( __( 'Toggle panel: %s', 'wp-statistics' ), $paneltitle ); ?></span>
83
- <span class="toggle-indicator" aria-hidden="true"></span>
84
- </button>
85
- <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
86
- <div class="inside">
87
- <canvas id="browsers-log" height="200"></canvas>
88
- <script>
89
- var ctx = document.getElementById("browsers-log").getContext('2d');
90
- var ChartJs = new Chart(ctx, {
91
- type: 'pie',
92
- data: {
93
- labels: [<?php echo implode( ', ', $browser_name ); ?>],
94
- datasets: [{
95
- label: '<?php _e( 'Browsers', 'wp-statistics' ); ?>',
96
- data: [<?php echo implode( ', ', $browser_value ); ?>],
97
- backgroundColor: [<?php echo implode( ', ', $browser_color ); ?>],
98
- }]
99
- },
100
- options: {
101
- responsive: true,
102
- legend: {
103
- position: 'bottom',
104
- },
105
- tooltips: {
106
- callbacks: {
107
- label: function (tooltipItem, data) {
108
- var dataset = data.datasets[tooltipItem.datasetIndex];
109
- var total = dataset.data.reduce(function (previousValue, currentValue, currentIndex, array) {
110
- return previousValue + currentValue;
111
- });
112
- var currentValue = dataset.data[tooltipItem.index];
113
- var precentage = Math.floor(((currentValue / total) * 100) + 0.5);
114
- return precentage + "% - " + data.labels[tooltipItem.index];
115
- }
116
- }
117
- }
118
- }
119
- });
120
- </script>
121
- </div>
122
- </div>
123
- </div>
124
- </div>
125
- </div>
126
 
127
- <div class="postbox-container" style="width: 48%; float: left; margin-right:20px">
128
- <div class="metabox-holder">
129
- <div class="meta-box-sortables">
130
- <div class="postbox">
131
- <?php $paneltitle = __( 'Platform', 'wp-statistics' ); ?>
132
- <button class="handlediv" type="button" aria-expanded="true">
133
- <span class="screen-reader-text"><?php printf( __( 'Toggle panel: %s', 'wp-statistics' ), $paneltitle ); ?></span>
134
- <span class="toggle-indicator" aria-hidden="true"></span>
135
- </button>
136
- <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
137
- <div class="inside">
138
- <canvas id="platforms-log" height="200"></canvas>
139
- <script>
140
- var ctx = document.getElementById("platforms-log").getContext('2d');
141
- var ChartJs = new Chart(ctx, {
142
- type: 'pie',
143
- data: {
144
- labels: [<?php echo implode( ', ', $platform_name ); ?>],
145
- datasets: [{
146
- label: '<?php _e( 'Platforms', 'wp-statistics' ); ?>',
147
- data: [<?php echo implode( ', ', $platform_value ); ?>],
148
- backgroundColor: [<?php echo implode( ', ', $platform_color ); ?>],
149
- }]
150
- },
151
- options: {
152
- responsive: true,
153
- legend: {
154
- position: 'bottom',
155
- },
156
- tooltips: {
157
- callbacks: {
158
- label: function (tooltipItem, data) {
159
- var dataset = data.datasets[tooltipItem.datasetIndex];
160
- var total = dataset.data.reduce(function (previousValue, currentValue, currentIndex, array) {
161
- return previousValue + currentValue;
162
- });
163
- var currentValue = dataset.data[tooltipItem.index];
164
- var precentage = Math.floor(((currentValue / total) * 100) + 0.5);
165
- return precentage + "% - " + data.labels[tooltipItem.index];
166
- }
167
- }
168
- }
169
- }
170
- });
171
- </script>
172
- </div>
173
- </div>
174
- </div>
175
- </div>
176
- </div>
177
 
178
- <div style="width: 100%; clear: both;">
179
- <hr/>
180
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181
 
182
- <div class="postbox-container" style="width: 30%; float: left; margin-right: 20px;">
183
- <div class="metabox-holder">
184
- <div class="meta-box-sortables">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185
  <?php
186
- for ( $BrowserCount = 0; $BrowserCount < count( $Browsers ); $BrowserCount ++ ) {
187
  if ( $BrowserCount % 3 == 0 ) {
188
- wp_statistics_browser_version_stats( $Browsers[ $BrowserCount ], $rangestartdate, $rangeenddate );
189
  }
190
  }
191
  ?>
192
- </div>
193
- </div>
194
- </div>
195
 
196
- <div class="postbox-container" style="width: 30%; float: left; margin-right: 20px;">
197
- <div class="metabox-holder">
198
- <div class="meta-box-sortables">
199
  <?php
200
- for ( $BrowserCount = 0; $BrowserCount < count( $Browsers ); $BrowserCount ++ ) {
201
  if ( $BrowserCount % 3 == 1 ) {
202
- wp_statistics_browser_version_stats( $Browsers[ $BrowserCount ], $rangestartdate, $rangeenddate );
203
  }
204
  }
205
  ?>
206
- </div>
207
- </div>
208
- </div>
209
 
210
- <div class="postbox-container" style="width: 30%; float: left">
211
- <div class="metabox-holder">
212
- <div class="meta-box-sortables">
213
  <?php
214
- for ( $BrowserCount = 0; $BrowserCount < count( $Browsers ); $BrowserCount ++ ) {
215
  if ( $BrowserCount % 3 == 2 ) {
216
- wp_statistics_browser_version_stats( $Browsers[ $BrowserCount ], $rangestartdate, $rangeenddate );
217
  }
218
  }
219
  ?>
220
- </div>
221
- </div>
222
- </div>
223
  </div>
224
 
225
  <?php
226
  function wp_statistics_browser_version_stats( $Browser, $rangestartdate, $rangeenddate ) {
227
  $id = 'browser-stats-' . $Browser;
228
- $browser_tag = strtolower( preg_replace( '/[^a-zA-Z]/', '', $Browser ) );
229
- $versions = wp_statistics_agent_version_list( $Browser, $rangestartdate, $rangeenddate );
230
  $version_name = array();
231
  $version_value = array();
232
  $browser_color = array();
233
  $i = 0;
234
 
235
- if ( count( $versions ) < 10 ) {
236
  return;
237
  }
238
 
239
  foreach ( $versions as $key => $value ) {
240
- $i ++;
241
- $version_value[ $value ] = wp_statistics_agent_version( $Browser, $value, $rangestartdate, $rangeenddate );
242
- $version_color[] = wp_statistics_generate_rgba_color( $i, '0.4' );
243
  }
244
 
245
- natcasesort( $version_value );
246
- $version_value = array_slice( $version_value, - 20 );
247
 
248
  foreach ( $version_value as $key => $value ) {
249
  $version_name[] = "'" . $key . "'";
250
  }
251
  ?>
252
- <div class="postbox">
253
- <?php $paneltitle = sprintf( __( '%s Version', 'wp-statistics' ), $Browser ); ?>
254
- <button class="handlediv" type="button" aria-expanded="true">
255
- <span class="screen-reader-text"><?php printf( __( 'Toggle panel: %s', 'wp-statistics' ), $paneltitle ); ?></span>
256
- <span class="toggle-indicator" aria-hidden="true"></span>
257
- </button>
258
- <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
259
- <div class="inside">
260
- <canvas id="<?php echo $id; ?>" height="250"></canvas>
261
- <script>
262
- var ctx = document.getElementById("<?php echo $id; ?>").getContext('2d');
263
- var ChartJs = new Chart(ctx, {
264
- type: 'doughnut',
265
- data: {
266
- labels: [<?php echo implode( ', ', $version_name ); ?>],
267
- datasets: [{
268
- label: '<?php _e( 'Platforms', 'wp-statistics' ); ?>',
269
- data: [<?php echo implode( ', ', $version_value ); ?>],
270
- backgroundColor: [<?php echo implode( ', ', $version_color ); ?>],
271
- }]
272
- },
273
- options: {
274
- responsive: true,
275
- legend: {
276
- display: false,
277
- },
278
- tooltips: {
279
- callbacks: {
280
- label: function (tooltipItem, data) {
281
- var dataset = data.datasets[tooltipItem.datasetIndex];
282
- var total = dataset.data.reduce(function (previousValue, currentValue, currentIndex, array) {
283
- return previousValue + currentValue;
284
- });
285
- var currentValue = dataset.data[tooltipItem.index];
286
- var precentage = Math.floor(((currentValue / total) * 100) + 0.5);
287
- return precentage + "% - " + data.labels[tooltipItem.index];
288
- }
289
- }
290
- }
291
- }
292
- });
293
- </script>
294
- </div>
295
- </div>
296
- <?php } ?>
 
 
 
 
1
  <script type="text/javascript">
2
+ jQuery(document).ready(function () {
3
+ postboxes.add_postbox_toggles(pagenow);
4
+ });
5
  </script>
6
  <?php
7
  $daysToDisplay = 20;
8
+ if ( array_key_exists('hitdays', $_GET) ) {
9
+ $daysToDisplay = intval($_GET['hitdays']);
10
  }
11
 
12
+ if ( array_key_exists('rangestart', $_GET) ) {
13
  $rangestart = $_GET['rangestart'];
14
  } else {
15
  $rangestart = '';
16
  }
17
+ if ( array_key_exists('rangeend', $_GET) ) {
18
  $rangeend = $_GET['rangeend'];
19
  } else {
20
  $rangeend = '';
21
  }
22
 
23
+ list( $daysToDisplay, $rangestart_utime, $rangeend_utime ) = wp_statistics_date_range_calculator(
24
+ $daysToDisplay,
25
+ $rangestart,
26
+ $rangeend
27
+ );
28
 
29
+ $rangestartdate = $WP_Statistics->real_current_date('Y-m-d', '-0', $rangestart_utime);
30
+ $rangeenddate = $WP_Statistics->real_current_date('Y-m-d', '-0', $rangeend_utime);
31
 
32
  // Browsers
33
  $Browsers = wp_statistics_ua_list();
34
+ if ( ! is_array($Browsers) ) {
35
  $Browsers = array();
36
  }
37
 
38
+ natcasesort($Browsers);
39
  $BrowserVisits = array();
40
  foreach ( $Browsers as $Browser ) {
41
+ $BrowserVisits[ $Browser ] = wp_statistics_useragent($Browser, $rangestartdate, $rangeenddate);
42
  }
43
 
44
+ $browser_name = array();
45
  $i = 0;
46
  $browser_value = array();
47
  $browser_color = array();
48
 
49
  foreach ( $BrowserVisits as $key => $value ) {
50
  if ( $value > 10 and $key ) {
51
+ $i++;
52
  $browser_name[] = "'" . $key . "'";
53
  $browser_value[] = $value;
54
+ $browser_color[] = wp_statistics_generate_rgba_color($i, '0.4');
55
  }
56
  }
57
 
58
  // Platforms
59
+ $Platforms = wp_statistics_platform_list(null, $rangestartdate, $rangeenddate);
60
+ if ( ! is_array($Platforms) ) {
61
  $Platforms = array();
62
  }
63
 
64
+ natcasesort($Platforms);
65
  $PlatformVisits = array();
66
  foreach ( $Platforms as $Platform ) {
67
+ $PlatformVisits[ $Platform ] = wp_statistics_platform($Platform);
68
  }
69
 
70
  $i = 0;
71
  foreach ( $PlatformVisits as $key => $value ) {
72
+ $i++;
73
  $platform_name[] = "'" . $key . "'";
74
  $platform_value[] = $value;
75
+ $platform_color[] = wp_statistics_generate_rgba_color($i, '0.4');
76
  }
77
  ?>
78
  <div class="wrap">
79
+ <h2><?php _e('Browser Statistics', 'wp-statistics'); ?></h2>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
 
81
+ <div><?php wp_statistics_date_range_selector(WP_Statistics::$page['browser'], $daysToDisplay); ?></div>
82
+ <div class="postbox-container" style="width: 48%; float: left; margin-right:20px">
83
+ <div class="metabox-holder">
84
+ <div class="meta-box-sortables">
85
+ <div class="postbox">
86
+ <?php $paneltitle = __('Browsers', 'wp-statistics'); ?>
87
+ <button class="handlediv" type="button" aria-expanded="true">
88
+ <span class="screen-reader-text"><?php printf(
89
+ __('Toggle panel: %s', 'wp-statistics'),
90
+ $paneltitle
91
+ ); ?></span>
92
+ <span class="toggle-indicator" aria-hidden="true"></span>
93
+ </button>
94
+ <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
 
96
+ <div class="inside">
97
+ <canvas id="browsers-log" height="200"></canvas>
98
+ <script>
99
+ var ctx = document.getElementById("browsers-log").getContext('2d');
100
+ var ChartJs = new Chart(ctx, {
101
+ type: 'pie',
102
+ data: {
103
+ labels: [<?php echo implode( ', ', $browser_name ); ?>],
104
+ datasets: [{
105
+ label: '<?php _e( 'Browsers', 'wp-statistics' ); ?>',
106
+ data: [<?php echo implode( ', ', $browser_value ); ?>],
107
+ backgroundColor: [<?php echo implode( ', ', $browser_color ); ?>],
108
+ }]
109
+ },
110
+ options: {
111
+ responsive: true,
112
+ legend: {
113
+ position: 'bottom',
114
+ },
115
+ tooltips: {
116
+ callbacks: {
117
+ label: function (tooltipItem, data) {
118
+ var dataset = data.datasets[tooltipItem.datasetIndex];
119
+ var total = dataset.data.reduce(function (previousValue, currentValue, currentIndex, array) {
120
+ return previousValue + currentValue;
121
+ });
122
+ var currentValue = dataset.data[tooltipItem.index];
123
+ var precentage = Math.floor(((currentValue / total) * 100) + 0.5);
124
+ return precentage + "% - " + data.labels[tooltipItem.index];
125
+ }
126
+ }
127
+ }
128
+ }
129
+ });
130
+ </script>
131
+ </div>
132
+ </div>
133
+ </div>
134
+ </div>
135
+ </div>
136
 
137
+ <div class="postbox-container" style="width: 48%; float: left; margin-right:20px">
138
+ <div class="metabox-holder">
139
+ <div class="meta-box-sortables">
140
+ <div class="postbox">
141
+ <?php $paneltitle = __('Platform', 'wp-statistics'); ?>
142
+ <button class="handlediv" type="button" aria-expanded="true">
143
+ <span class="screen-reader-text"><?php printf(
144
+ __('Toggle panel: %s', 'wp-statistics'),
145
+ $paneltitle
146
+ ); ?></span>
147
+ <span class="toggle-indicator" aria-hidden="true"></span>
148
+ </button>
149
+ <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
150
+
151
+ <div class="inside">
152
+ <canvas id="platforms-log" height="200"></canvas>
153
+ <script>
154
+ var ctx = document.getElementById("platforms-log").getContext('2d');
155
+ var ChartJs = new Chart(ctx, {
156
+ type: 'pie',
157
+ data: {
158
+ labels: [<?php echo implode( ', ', $platform_name ); ?>],
159
+ datasets: [{
160
+ label: '<?php _e( 'Platforms', 'wp-statistics' ); ?>',
161
+ data: [<?php echo implode( ', ', $platform_value ); ?>],
162
+ backgroundColor: [<?php echo implode( ', ', $platform_color ); ?>],
163
+ }]
164
+ },
165
+ options: {
166
+ responsive: true,
167
+ legend: {
168
+ position: 'bottom',
169
+ },
170
+ tooltips: {
171
+ callbacks: {
172
+ label: function (tooltipItem, data) {
173
+ var dataset = data.datasets[tooltipItem.datasetIndex];
174
+ var total = dataset.data.reduce(function (previousValue, currentValue, currentIndex, array) {
175
+ return previousValue + currentValue;
176
+ });
177
+ var currentValue = dataset.data[tooltipItem.index];
178
+ var precentage = Math.floor(((currentValue / total) * 100) + 0.5);
179
+ return precentage + "% - " + data.labels[tooltipItem.index];
180
+ }
181
+ }
182
+ }
183
+ }
184
+ });
185
+ </script>
186
+ </div>
187
+ </div>
188
+ </div>
189
+ </div>
190
+ </div>
191
+
192
+ <div style="width: 100%; clear: both;">
193
+ <hr/>
194
+ </div>
195
+
196
+ <div class="postbox-container" style="width: 30%; float: left; margin-right: 20px;">
197
+ <div class="metabox-holder">
198
+ <div class="meta-box-sortables">
199
  <?php
200
+ for ( $BrowserCount = 0; $BrowserCount < count($Browsers); $BrowserCount++ ) {
201
  if ( $BrowserCount % 3 == 0 ) {
202
+ wp_statistics_browser_version_stats($Browsers[ $BrowserCount ], $rangestartdate, $rangeenddate);
203
  }
204
  }
205
  ?>
206
+ </div>
207
+ </div>
208
+ </div>
209
 
210
+ <div class="postbox-container" style="width: 30%; float: left; margin-right: 20px;">
211
+ <div class="metabox-holder">
212
+ <div class="meta-box-sortables">
213
  <?php
214
+ for ( $BrowserCount = 0; $BrowserCount < count($Browsers); $BrowserCount++ ) {
215
  if ( $BrowserCount % 3 == 1 ) {
216
+ wp_statistics_browser_version_stats($Browsers[ $BrowserCount ], $rangestartdate, $rangeenddate);
217
  }
218
  }
219
  ?>
220
+ </div>
221
+ </div>
222
+ </div>
223
 
224
+ <div class="postbox-container" style="width: 30%; float: left">
225
+ <div class="metabox-holder">
226
+ <div class="meta-box-sortables">
227
  <?php
228
+ for ( $BrowserCount = 0; $BrowserCount < count($Browsers); $BrowserCount++ ) {
229
  if ( $BrowserCount % 3 == 2 ) {
230
+ wp_statistics_browser_version_stats($Browsers[ $BrowserCount ], $rangestartdate, $rangeenddate);
231
  }
232
  }
233
  ?>
234
+ </div>
235
+ </div>
236
+ </div>
237
  </div>
238
 
239
  <?php
240
  function wp_statistics_browser_version_stats( $Browser, $rangestartdate, $rangeenddate ) {
241
  $id = 'browser-stats-' . $Browser;
242
+ $browser_tag = strtolower(preg_replace('/[^a-zA-Z]/', '', $Browser));
243
+ $versions = wp_statistics_agent_version_list($Browser, $rangestartdate, $rangeenddate);
244
  $version_name = array();
245
  $version_value = array();
246
  $browser_color = array();
247
  $i = 0;
248
 
249
+ if ( count($versions) < 10 ) {
250
  return;
251
  }
252
 
253
  foreach ( $versions as $key => $value ) {
254
+ $i++;
255
+ $version_value[ $value ] = wp_statistics_agent_version($Browser, $value, $rangestartdate, $rangeenddate);
256
+ $version_color[] = wp_statistics_generate_rgba_color($i, '0.4');
257
  }
258
 
259
+ natcasesort($version_value);
260
+ $version_value = array_slice($version_value, -20);
261
 
262
  foreach ( $version_value as $key => $value ) {
263
  $version_name[] = "'" . $key . "'";
264
  }
265
  ?>
266
+ <div class="postbox">
267
+ <?php $paneltitle = sprintf(__('%s Version', 'wp-statistics'), $Browser); ?>
268
+ <button class="handlediv" type="button" aria-expanded="true">
269
+ <span class="screen-reader-text"><?php printf(
270
+ __('Toggle panel: %s', 'wp-statistics'),
271
+ $paneltitle
272
+ ); ?></span>
273
+ <span class="toggle-indicator" aria-hidden="true"></span>
274
+ </button>
275
+ <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
276
+
277
+ <div class="inside">
278
+ <canvas id="<?php echo $id; ?>" height="250"></canvas>
279
+ <script>
280
+ var ctx = document.getElementById("<?php echo $id; ?>").getContext('2d');
281
+ var ChartJs = new Chart(ctx, {
282
+ type: 'doughnut',
283
+ data: {
284
+ labels: [<?php echo implode( ', ', $version_name ); ?>],
285
+ datasets: [{
286
+ label: '<?php _e( 'Platforms', 'wp-statistics' ); ?>',
287
+ data: [<?php echo implode( ', ', $version_value ); ?>],
288
+ backgroundColor: [<?php echo implode( ', ', $version_color ); ?>],
289
+ }]
290
+ },
291
+ options: {
292
+ responsive: true,
293
+ legend: {
294
+ display: false,
295
+ },
296
+ tooltips: {
297
+ callbacks: {
298
+ label: function (tooltipItem, data) {
299
+ var dataset = data.datasets[tooltipItem.datasetIndex];
300
+ var total = dataset.data.reduce(function (previousValue, currentValue, currentIndex, array) {
301
+ return previousValue + currentValue;
302
+ });
303
+ var currentValue = dataset.data[tooltipItem.index];
304
+ var precentage = Math.floor(((currentValue / total) * 100) + 0.5);
305
+ return precentage + "% - " + data.labels[tooltipItem.index];
306
+ }
307
+ }
308
+ }
309
+ }
310
+ });
311
+ </script>
312
+ </div>
313
+ </div>
314
+ <?php }
includes/log/authors.php CHANGED
@@ -1,45 +1,47 @@
1
  <script type="text/javascript">
2
- jQuery(document).ready(function () {
3
- postboxes.add_postbox_toggles(pagenow);
4
- });
5
  </script>
6
  <div class="wrap">
7
- <h2><?php _e( 'Author Statistics', 'wp-statistics' ); ?></h2>
8
  <?php
9
  $daysToDisplay = 20;
10
- if ( array_key_exists( 'hitdays', $_GET ) ) {
11
- $daysToDisplay = intval( $_GET['hitdays'] );
12
  }
13
 
14
- if ( array_key_exists( 'rangestart', $_GET ) ) {
15
  $rangestart = $_GET['rangestart'];
16
  } else {
17
  $rangestart = '';
18
  }
19
- if ( array_key_exists( 'rangeend', $_GET ) ) {
20
  $rangeend = $_GET['rangeend'];
21
  } else {
22
  $rangeend = '';
23
  }
24
- if ( array_key_exists( 'author', $_GET ) ) {
25
- $author = intval( $_GET['author'] );
26
  } else {
27
- if ( array_key_exists( 'preauthor', $_GET ) ) {
28
- $author = intval( $_GET['preauthor'] );
29
  } else {
30
  $author = 0;
31
  }
32
  }
33
 
34
- $html = __( 'Select Author', 'wp-statistics' ) . ': ';
35
  $html .= '<select name="author" id="author">';
36
 
37
- $authors_list = wp_list_authors( 'html=0&style=none&echo=0&exclude_admin=0&optioncount=0&show_fullname=1&hide_empty=1&orderby=name&order=ASC' );
 
 
38
 
39
- $authors_array = explode( ',', $authors_list );
40
 
41
  foreach ( $authors_array as $value ) {
42
- $author_obj = get_user_by( 'slug', $value );
43
 
44
  if ( $author_obj !== false ) {
45
  // Check to see if this tag is the one that is currently selected.
@@ -55,170 +57,193 @@
55
 
56
  $html .= '</select>';
57
 
58
- $html .= ' <input type="submit" value="' . __( 'Select', 'wp-statistics' ) . '" class="button-primary">';
59
  $html .= '<br>';
60
 
61
- list( $daysToDisplay, $rangestart_utime, $rangeend_utime ) = wp_statistics_date_range_calculator( $daysToDisplay, $rangestart, $rangeend );
 
 
 
 
62
 
63
- wp_statistics_date_range_selector( WP_STATISTICS_AUTHORS_PAGE, $daysToDisplay, null, null, '&preauthor=' . $author, $html );
 
 
 
 
 
 
 
64
 
65
  $args = array(
66
  'author' => $author,
67
  );
68
 
69
- $posts = get_posts( $args );
70
 
71
- $visit_total = 0;
72
  $daysInThePast = (int) ( ( time() - $rangeend_utime ) / 86400 );
73
- $posts_stats = array();
74
- $visits = array();
75
 
76
  // Setup the array, otherwise PHP may throw an error.
77
  foreach ( $posts as $post ) {
78
  $posts_stats[ $post->ID ] = 0;
79
  }
80
 
81
- for ( $i = $daysToDisplay; $i >= 0; $i -- ) {
82
- $date[] = "'" . $WP_Statistics->Real_Current_Date( 'M j', '-' . ( $i + $daysInThePast ), $rangeend_utime ) . "'";
83
 
84
  $stat = 0;
85
  foreach ( $posts as $post ) {
86
- $temp_stat = wp_statistics_pages( '-' . (int) ( $i + $daysInThePast ), null, $post->ID );
87
  $posts_stats[ $post->ID ] += $temp_stat;
88
- $stat = $temp_stat;
89
  }
90
 
91
- $visits[] = $stat;
92
  $visit_total += $stat;
93
  }
94
  ?>
95
- <div class="postbox-container" id="last-log">
96
- <div class="metabox-holder">
97
- <div class="meta-box-sortables">
98
- <div class="postbox">
99
- <?php $paneltitle = __( 'Author Statistics Chart', 'wp-statistics' ); ?>
100
- <button class="handlediv" type="button" aria-expanded="true">
101
- <span class="screen-reader-text"><?php printf( __( 'Toggle panel: %s', 'wp-statistics' ), $paneltitle ); ?></span>
102
- <span class="toggle-indicator" aria-hidden="true"></span>
103
- </button>
104
- <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
105
- <div class="inside">
106
- <canvas id="hit-stats" height="80"></canvas>
107
- <script>
108
- var ctx = document.getElementById("hit-stats").getContext('2d');
109
- var ChartJs = new Chart(ctx, {
110
- type: 'line',
111
- data: {
112
- labels: [<?php echo implode( ', ', $date ); ?>],
113
- datasets: [
114
- {
115
- label: '<?php _e( 'Visits', 'wp-statistics' ); ?>',
116
- data: [<?php echo implode( ',', $visits ); ?>],
117
- backgroundColor: 'rgba(54, 162, 235, 0.2)',
118
- borderColor: 'rgba(54, 162, 235, 1)',
119
- borderWidth: 1,
120
- fill: true,
121
- },
122
- ]
123
- },
124
- options: {
125
- responsive: true,
126
- legend: {
127
- position: 'bottom',
128
- },
129
- title: {
130
- display: true,
131
- text: '<?php echo sprintf( __( 'Hits in the last %s days', 'wp-statistics' ), $daysToDisplay ); ?>'
132
- },
133
- tooltips: {
134
- mode: 'index',
135
- intersect: false,
136
- },
137
- scales: {
138
- yAxes: [{
139
- ticks: {
140
- beginAtZero: true
141
- }
142
- }]
143
- }
144
- }
145
- });
146
- </script>
147
- </div>
148
- </div>
149
- </div>
150
- </div>
151
- </div>
152
-
153
- <div class="postbox-container" style="width: 100%; float: left; margin-right:20px">
154
- <div class="metabox-holder">
155
- <div class="meta-box-sortables">
156
- <div class="postbox">
157
- <?php $paneltitle = __( 'Author Statistics Summary', 'wp-statistics' ); ?>
158
- <button class="handlediv" type="button" aria-expanded="true">
159
- <span class="screen-reader-text"><?php printf( __( 'Toggle panel: %s', 'wp-statistics' ), $paneltitle ); ?></span>
160
- <span class="toggle-indicator" aria-hidden="true"></span>
161
- </button>
162
- <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
163
- <div class="inside">
164
- <table width="auto" class="widefat table-stats" id="summary-stats">
165
- <tbody>
166
- <tr>
167
- <th></th>
168
- <th class="th-center"><?php _e( 'Count', 'wp-statistics' ); ?></th>
169
- </tr>
170
-
171
- <tr>
172
- <th><?php _e( 'Number of posts by author', 'wp-statistics' ); ?>:</th>
173
- <th class="th-center"><span><?php echo number_format_i18n( count( $posts ) ); ?></span>
174
- </th>
175
- </tr>
176
-
177
- <tr>
178
- <th><?php _e( 'Chart Visits Total', 'wp-statistics' ); ?>:</th>
179
- <th class="th-center"><span><?php echo number_format_i18n( $visit_total ); ?></span>
180
- </th>
181
- </tr>
182
-
183
- <tr>
184
- <th><?php _e( 'All Time Visits Total', 'wp-statistics' ); ?>:</th>
185
- <th class="th-center"><span><?php
 
 
 
 
 
 
 
 
186
 
187
  $stat = 0;
188
  foreach ( $posts as $post ) {
189
- $stat += wp_statistics_pages( 'total', null, $post->ID );
190
  }
191
 
192
- echo number_format_i18n( $stat ); ?></span></th>
193
- </tr>
194
- </tbody>
195
- </table>
196
- </div>
197
- </div>
198
- </div>
199
- </div>
200
- </div>
201
-
202
- <div class="postbox-container" style="width: 100%; float: left; margin-right:20px">
203
- <div class="metabox-holder">
204
- <div class="meta-box-sortables">
205
- <div class="postbox">
206
- <?php $paneltitle = __( 'Author Posts Sorted by Hits', 'wp-statistics' ); ?>
207
- <button class="handlediv" type="button" aria-expanded="true">
208
- <span class="screen-reader-text"><?php printf( __( 'Toggle panel: %s', 'wp-statistics' ), $paneltitle ); ?></span>
209
- <span class="toggle-indicator" aria-hidden="true"></span>
210
- </button>
211
- <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
212
- <div class="inside">
213
- <table width="auto" class="widefat table-stats" id="post-stats">
214
- <tbody>
215
- <tr>
216
- <th><?php _e( 'Post Title', 'wp-statistics' ); ?></th>
217
- <th class="th-center"><?php _e( 'Hits', 'wp-statistics' ); ?></th>
218
- </tr>
 
 
 
 
219
 
220
  <?php
221
- arsort( $posts_stats );
222
 
223
  $posts_by_id = array();
224
 
@@ -230,22 +255,24 @@
230
  $post_obj = $posts_by_id[ $post_id ];
231
 
232
  ?>
233
- <tr>
234
- <th>
235
- <a href="<?php echo get_permalink( $post_obj ); ?>"><?php echo $post_obj->post_title; ?></a>
236
- </th>
237
- <th class="th-center"><span><?php echo number_format_i18n( $post_stat ); ?></span>
238
- </th>
239
- </tr>
 
 
240
  <?php
241
  }
242
  ?>
243
- </tbody>
244
- </table>
245
- </div>
246
- </div>
247
- </div>
248
- </div>
249
- </div>
250
 
251
  </div>
1
  <script type="text/javascript">
2
+ jQuery(document).ready(function () {
3
+ postboxes.add_postbox_toggles(pagenow);
4
+ });
5
  </script>
6
  <div class="wrap">
7
+ <h2><?php _e('Author Statistics', 'wp-statistics'); ?></h2>
8
  <?php
9
  $daysToDisplay = 20;
10
+ if ( array_key_exists('hitdays', $_GET) ) {
11
+ $daysToDisplay = intval($_GET['hitdays']);
12
  }
13
 
14
+ if ( array_key_exists('rangestart', $_GET) ) {
15
  $rangestart = $_GET['rangestart'];
16
  } else {
17
  $rangestart = '';
18
  }
19
+ if ( array_key_exists('rangeend', $_GET) ) {
20
  $rangeend = $_GET['rangeend'];
21
  } else {
22
  $rangeend = '';
23
  }
24
+ if ( array_key_exists('author', $_GET) ) {
25
+ $author = intval($_GET['author']);
26
  } else {
27
+ if ( array_key_exists('preauthor', $_GET) ) {
28
+ $author = intval($_GET['preauthor']);
29
  } else {
30
  $author = 0;
31
  }
32
  }
33
 
34
+ $html = __('Select Author', 'wp-statistics') . ': ';
35
  $html .= '<select name="author" id="author">';
36
 
37
+ $authors_list = wp_list_authors(
38
+ 'html=0&style=none&echo=0&exclude_admin=0&optioncount=0&show_fullname=1&hide_empty=1&orderby=name&order=ASC'
39
+ );
40
 
41
+ $authors_array = explode(',', $authors_list);
42
 
43
  foreach ( $authors_array as $value ) {
44
+ $author_obj = get_user_by('slug', $value);
45
 
46
  if ( $author_obj !== false ) {
47
  // Check to see if this tag is the one that is currently selected.
57
 
58
  $html .= '</select>';
59
 
60
+ $html .= ' <input type="submit" value="' . __('Select', 'wp-statistics') . '" class="button-primary">';
61
  $html .= '<br>';
62
 
63
+ list( $daysToDisplay, $rangestart_utime, $rangeend_utime ) = wp_statistics_date_range_calculator(
64
+ $daysToDisplay,
65
+ $rangestart,
66
+ $rangeend
67
+ );
68
 
69
+ wp_statistics_date_range_selector(
70
+ WP_Statistics::$page['authors'],
71
+ $daysToDisplay,
72
+ null,
73
+ null,
74
+ '&preauthor=' . $author,
75
+ $html
76
+ );
77
 
78
  $args = array(
79
  'author' => $author,
80
  );
81
 
82
+ $posts = get_posts($args);
83
 
84
+ $visit_total = 0;
85
  $daysInThePast = (int) ( ( time() - $rangeend_utime ) / 86400 );
86
+ $posts_stats = array();
87
+ $visits = array();
88
 
89
  // Setup the array, otherwise PHP may throw an error.
90
  foreach ( $posts as $post ) {
91
  $posts_stats[ $post->ID ] = 0;
92
  }
93
 
94
+ for ( $i = $daysToDisplay; $i >= 0; $i-- ) {
95
+ $date[] = "'" . $WP_Statistics->Real_Current_Date('M j', '-' . ( $i + $daysInThePast ), $rangeend_utime) . "'";
96
 
97
  $stat = 0;
98
  foreach ( $posts as $post ) {
99
+ $temp_stat = wp_statistics_pages('-' . (int) ( $i + $daysInThePast ), null, $post->ID);
100
  $posts_stats[ $post->ID ] += $temp_stat;
101
+ $stat = $temp_stat;
102
  }
103
 
104
+ $visits[] = $stat;
105
  $visit_total += $stat;
106
  }
107
  ?>
108
+ <div class="postbox-container" id="last-log">
109
+ <div class="metabox-holder">
110
+ <div class="meta-box-sortables">
111
+ <div class="postbox">
112
+ <?php $paneltitle = __('Author Statistics Chart', 'wp-statistics'); ?>
113
+ <button class="handlediv" type="button" aria-expanded="true">
114
+ <span class="screen-reader-text"><?php printf(
115
+ __('Toggle panel: %s', 'wp-statistics'),
116
+ $paneltitle
117
+ ); ?></span>
118
+ <span class="toggle-indicator" aria-hidden="true"></span>
119
+ </button>
120
+ <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
121
+
122
+ <div class="inside">
123
+ <canvas id="hit-stats" height="80"></canvas>
124
+ <script>
125
+ var ctx = document.getElementById("hit-stats").getContext('2d');
126
+ var ChartJs = new Chart(ctx, {
127
+ type: 'line',
128
+ data: {
129
+ labels: [<?php echo implode( ', ', $date ); ?>],
130
+ datasets: [
131
+ {
132
+ label: '<?php _e( 'Visits', 'wp-statistics' ); ?>',
133
+ data: [<?php echo implode( ',', $visits ); ?>],
134
+ backgroundColor: 'rgba(54, 162, 235, 0.2)',
135
+ borderColor: 'rgba(54, 162, 235, 1)',
136
+ borderWidth: 1,
137
+ fill: true,
138
+ },
139
+ ]
140
+ },
141
+ options: {
142
+ responsive: true,
143
+ legend: {
144
+ position: 'bottom',
145
+ },
146
+ title: {
147
+ display: true,
148
+ text: '<?php echo sprintf( __( 'Hits in the last %s days', 'wp-statistics' ), $daysToDisplay ); ?>'
149
+ },
150
+ tooltips: {
151
+ mode: 'index',
152
+ intersect: false,
153
+ },
154
+ scales: {
155
+ yAxes: [{
156
+ ticks: {
157
+ beginAtZero: true
158
+ }
159
+ }]
160
+ }
161
+ }
162
+ });
163
+ </script>
164
+ </div>
165
+ </div>
166
+ </div>
167
+ </div>
168
+ </div>
169
+
170
+ <div class="postbox-container" style="width: 100%; float: left; margin-right:20px">
171
+ <div class="metabox-holder">
172
+ <div class="meta-box-sortables">
173
+ <div class="postbox">
174
+ <?php $paneltitle = __('Author Statistics Summary', 'wp-statistics'); ?>
175
+ <button class="handlediv" type="button" aria-expanded="true">
176
+ <span class="screen-reader-text"><?php printf(
177
+ __('Toggle panel: %s', 'wp-statistics'),
178
+ $paneltitle
179
+ ); ?></span>
180
+ <span class="toggle-indicator" aria-hidden="true"></span>
181
+ </button>
182
+ <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
183
+
184
+ <div class="inside">
185
+ <table width="auto" class="widefat table-stats" id="summary-stats">
186
+ <tbody>
187
+ <tr>
188
+ <th></th>
189
+ <th class="th-center"><?php _e('Count', 'wp-statistics'); ?></th>
190
+ </tr>
191
+
192
+ <tr>
193
+ <th><?php _e('Number of posts by author', 'wp-statistics'); ?>:</th>
194
+ <th class="th-center"><span><?php echo number_format_i18n(count($posts)); ?></span>
195
+ </th>
196
+ </tr>
197
+
198
+ <tr>
199
+ <th><?php _e('Chart Visits Total', 'wp-statistics'); ?>:</th>
200
+ <th class="th-center"><span><?php echo number_format_i18n($visit_total); ?></span>
201
+ </th>
202
+ </tr>
203
+
204
+ <tr>
205
+ <th><?php _e('All Time Visits Total', 'wp-statistics'); ?>:</th>
206
+ <th class="th-center"><span><?php
207
 
208
  $stat = 0;
209
  foreach ( $posts as $post ) {
210
+ $stat += wp_statistics_pages('total', null, $post->ID);
211
  }
212
 
213
+ echo number_format_i18n($stat); ?></span></th>
214
+ </tr>
215
+ </tbody>
216
+ </table>
217
+ </div>
218
+ </div>
219
+ </div>
220
+ </div>
221
+ </div>
222
+
223
+ <div class="postbox-container" style="width: 100%; float: left; margin-right:20px">
224
+ <div class="metabox-holder">
225
+ <div class="meta-box-sortables">
226
+ <div class="postbox">
227
+ <?php $paneltitle = __('Author Posts Sorted by Hits', 'wp-statistics'); ?>
228
+ <button class="handlediv" type="button" aria-expanded="true">
229
+ <span class="screen-reader-text"><?php printf(
230
+ __('Toggle panel: %s', 'wp-statistics'),
231
+ $paneltitle
232
+ ); ?></span>
233
+ <span class="toggle-indicator" aria-hidden="true"></span>
234
+ </button>
235
+ <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
236
+
237
+ <div class="inside">
238
+ <table width="auto" class="widefat table-stats" id="post-stats">
239
+ <tbody>
240
+ <tr>
241
+ <th><?php _e('Post Title', 'wp-statistics'); ?></th>
242
+ <th class="th-center"><?php _e('Hits', 'wp-statistics'); ?></th>
243
+ </tr>
244
 
245
  <?php
246
+ arsort($posts_stats);
247
 
248
  $posts_by_id = array();
249
 
255
  $post_obj = $posts_by_id[ $post_id ];
256
 
257
  ?>
258
+ <tr>
259
+ <th>
260
+ <a href="<?php echo get_permalink(
261
+ $post_obj
262
+ ); ?>"><?php echo $post_obj->post_title; ?></a>
263
+ </th>
264
+ <th class="th-center"><span><?php echo number_format_i18n($post_stat); ?></span>
265
+ </th>
266
+ </tr>
267
  <?php
268
  }
269
  ?>
270
+ </tbody>
271
+ </table>
272
+ </div>
273
+ </div>
274
+ </div>
275
+ </div>
276
+ </div>
277
 
278
  </div>
includes/log/categories.php CHANGED
@@ -1,209 +1,232 @@
1
  <script type="text/javascript">
2
- jQuery(document).ready(function () {
3
- postboxes.add_postbox_toggles(pagenow);
4
- });
5
  </script>
6
  <div class="wrap">
7
- <h2><?php _e( 'Category Statistics', 'wp-statistics' ); ?></h2>
8
 
9
  <?php
10
  $daysToDisplay = 20;
11
- if ( array_key_exists( 'hitdays', $_GET ) ) {
12
- $daysToDisplay = intval( $_GET['hitdays'] );
13
  }
14
 
15
- if ( array_key_exists( 'rangestart', $_GET ) ) {
16
  $rangestart = $_GET['rangestart'];
17
  } else {
18
  $rangestart = '';
19
  }
20
- if ( array_key_exists( 'rangeend', $_GET ) ) {
21
  $rangeend = $_GET['rangeend'];
22
  } else {
23
  $rangeend = '';
24
  }
25
- if ( array_key_exists( 'cat', $_GET ) ) {
26
- $category = intval( $_GET['cat'] );
27
  } else {
28
- if ( array_key_exists( 'precat', $_GET ) ) {
29
- $category = intval( $_GET['precat'] );
30
  } else {
31
  $category = 0;
32
  }
33
  }
34
 
35
- $html = __( 'Select Category', 'wp-statistics' ) . ': ';
36
 
37
  $args = array(
38
  'selected' => $category,
39
  'echo' => 0,
40
  );
41
 
42
- $html .= wp_dropdown_categories( $args );
43
- $html .= '<input type="submit" value="' . __( 'Select', 'wp-statistics' ) . '" class="button-primary">';
44
  $html .= '<br>';
45
 
46
- list( $daysToDisplay, $rangestart_utime, $rangeend_utime ) = wp_statistics_date_range_calculator( $daysToDisplay, $rangestart, $rangeend );
 
 
 
 
47
 
48
- wp_statistics_date_range_selector( WP_STATISTICS_CATEGORIES_PAGE, $daysToDisplay, null, null, '&precat=' . $category, $html );
 
 
 
 
 
 
 
49
 
50
  $args = array(
51
  'category' => $category,
52
  );
53
 
54
- $posts = get_posts( $args );
55
 
56
- $visit_total = 0;
57
  $daysInThePast = (int) ( ( time() - $rangeend_utime ) / 86400 );
58
- $posts_stats = array();
59
- $visits = array();
60
 
61
  // Setup the array, otherwise PHP may throw an error.
62
  foreach ( $posts as $post ) {
63
  $posts_stats[ $post->ID ] = 0;
64
  }
65
 
66
- for ( $i = $daysToDisplay; $i >= 0; $i -- ) {
67
- $date[] = "'" . $WP_Statistics->Real_Current_Date( 'M j', '-' . ( $i + $daysInThePast ), $rangeend_utime ) . "'";
68
 
69
  $stat = 0;
70
  foreach ( $posts as $post ) {
71
- $temp_stat = wp_statistics_pages( '-' . (int) ( $i + $daysInThePast ), null, $post->ID );
72
  $posts_stats[ $post->ID ] += $temp_stat;
73
- $stat = $temp_stat;
74
  }
75
 
76
- $visits[] = $stat;
77
  $visit_total += $stat;
78
  }
79
  ?>
80
- <div class="postbox-container" id="last-log">
81
- <div class="metabox-holder">
82
- <div class="meta-box-sortables">
83
- <div class="postbox">
84
- <?php $paneltitle = __( 'Category Statistics Chart', 'wp-statistics' ); ?>
85
- <button class="handlediv" type="button" aria-expanded="true">
86
- <span class="screen-reader-text"><?php printf( __( 'Toggle panel: %s', 'wp-statistics' ), $paneltitle ); ?></span>
87
- <span class="toggle-indicator" aria-hidden="true"></span>
88
- </button>
89
- <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
90
- <div class="inside">
91
- <canvas id="hit-stats" height="80"></canvas>
92
- <script>
93
- var ctx = document.getElementById("hit-stats").getContext('2d');
94
- var ChartJs = new Chart(ctx, {
95
- type: 'line',
96
- data: {
97
- labels: [<?php echo implode( ', ', $date ); ?>],
98
- datasets: [
99
- {
100
- label: '<?php _e( 'Visits', 'wp-statistics' ); ?>',
101
- data: [<?php echo implode( ',', $visits ); ?>],
102
- backgroundColor: 'rgba(54, 162, 235, 0.2)',
103
- borderColor: 'rgba(54, 162, 235, 1)',
104
- borderWidth: 1,
105
- fill: true,
106
- },
107
- ]
108
- },
109
- options: {
110
- responsive: true,
111
- legend: {
112
- position: 'bottom',
113
- },
114
- title: {
115
- display: true,
116
- text: '<?php echo sprintf( __( 'Hits in the last %s days', 'wp-statistics' ), $daysToDisplay ); ?>'
117
- },
118
- tooltips: {
119
- mode: 'index',
120
- intersect: false,
121
- },
122
- scales: {
123
- yAxes: [{
124
- ticks: {
125
- beginAtZero: true
126
- }
127
- }]
128
- }
129
- }
130
- });
131
- </script>
132
- </div>
133
- </div>
134
- </div>
135
- </div>
136
- </div>
137
-
138
- <div class="postbox-container" style="width: 100%; float: left; margin-right:20px">
139
- <div class="metabox-holder">
140
- <div class="meta-box-sortables">
141
- <div class="postbox">
142
- <?php $paneltitle = __( 'Category Statistics Summary', 'wp-statistics' ); ?>
143
- <button class="handlediv" type="button" aria-expanded="true">
144
- <span class="screen-reader-text"><?php printf( __( 'Toggle panel: %s', 'wp-statistics' ), $paneltitle ); ?></span>
145
- <span class="toggle-indicator" aria-hidden="true"></span>
146
- </button>
147
- <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
148
- <div class="inside">
149
- <table width="auto" class="widefat table-stats" id="summary-stats">
150
- <tbody>
151
- <tr>
152
- <th></th>
153
- <th class="th-center"><?php _e( 'Count', 'wp-statistics' ); ?></th>
154
- </tr>
155
-
156
- <tr>
157
- <th><?php _e( 'Number of posts in category', 'wp-statistics' ); ?>:</th>
158
- <th class="th-center"><span><?php echo number_format_i18n( count( $posts ) ); ?></span>
159
- </th>
160
- </tr>
161
-
162
- <tr>
163
- <th><?php _e( 'Chart Visits Total', 'wp-statistics' ); ?>:</th>
164
- <th class="th-center"><span><?php echo number_format_i18n( $visit_total ); ?></span>
165
- </th>
166
- </tr>
167
-
168
- <tr>
169
- <th><?php _e( 'All Time Visits Total', 'wp-statistics' ); ?>:</th>
170
- <th class="th-center"><span><?php
 
 
 
 
 
 
 
 
171
 
172
  $stat = 0;
173
  foreach ( $posts as $post ) {
174
- $stat += wp_statistics_pages( 'total', null, $post->ID );
175
  }
176
 
177
- echo number_format_i18n( $stat ); ?></span></th>
178
- </tr>
179
- </tbody>
180
- </table>
181
- </div>
182
- </div>
183
- </div>
184
- </div>
185
- </div>
186
-
187
- <div class="postbox-container" style="width: 100%; float: left; margin-right:20px">
188
- <div class="metabox-holder">
189
- <div class="meta-box-sortables">
190
- <div class="postbox">
191
- <?php $paneltitle = __( 'Category Posts Sorted by Hits', 'wp-statistics' ); ?>
192
- <button class="handlediv" type="button" aria-expanded="true">
193
- <span class="screen-reader-text"><?php printf( __( 'Toggle panel: %s', 'wp-statistics' ), $paneltitle ); ?></span>
194
- <span class="toggle-indicator" aria-hidden="true"></span>
195
- </button>
196
- <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
197
- <div class="inside">
198
- <table width="auto" class="widefat table-stats" id="post-stats">
199
- <tbody>
200
- <tr>
201
- <th><?php _e( 'Post Title', 'wp-statistics' ); ?></th>
202
- <th class="th-center"><?php _e( 'Hits', 'wp-statistics' ); ?></th>
203
- </tr>
 
 
 
 
204
 
205
  <?php
206
- arsort( $posts_stats );
207
 
208
  $posts_by_id = array();
209
 
@@ -215,22 +238,24 @@
215
  $post_obj = $posts_by_id[ $post_id ];
216
 
217
  ?>
218
- <tr>
219
- <th>
220
- <a href="<?php echo get_permalink( $post_obj ); ?>"><?php echo $post_obj->post_title; ?></a>
221
- </th>
222
- <th class="th-center"><span><?php echo number_format_i18n( $post_stat ); ?></span>
223
- </th>
224
- </tr>
 
 
225
  <?php
226
  }
227
  ?>
228
- </tbody>
229
- </table>
230
- </div>
231
- </div>
232
- </div>
233
- </div>
234
- </div>
235
 
236
  </div>
1
  <script type="text/javascript">
2
+ jQuery(document).ready(function () {
3
+ postboxes.add_postbox_toggles(pagenow);
4
+ });
5
  </script>
6
  <div class="wrap">
7
+ <h2><?php _e('Category Statistics', 'wp-statistics'); ?></h2>
8
 
9
  <?php
10
  $daysToDisplay = 20;
11
+ if ( array_key_exists('hitdays', $_GET) ) {
12
+ $daysToDisplay = intval($_GET['hitdays']);
13
  }
14
 
15
+ if ( array_key_exists('rangestart', $_GET) ) {
16
  $rangestart = $_GET['rangestart'];
17
  } else {
18
  $rangestart = '';
19
  }
20
+ if ( array_key_exists('rangeend', $_GET) ) {
21
  $rangeend = $_GET['rangeend'];
22
  } else {
23
  $rangeend = '';
24
  }
25
+ if ( array_key_exists('cat', $_GET) ) {
26
+ $category = intval($_GET['cat']);
27
  } else {
28
+ if ( array_key_exists('precat', $_GET) ) {
29
+ $category = intval($_GET['precat']);
30
  } else {
31
  $category = 0;
32
  }
33
  }
34
 
35
+ $html = __('Select Category', 'wp-statistics') . ': ';
36
 
37
  $args = array(
38
  'selected' => $category,
39
  'echo' => 0,
40
  );
41
 
42
+ $html .= wp_dropdown_categories($args);
43
+ $html .= '<input type="submit" value="' . __('Select', 'wp-statistics') . '" class="button-primary">';
44
  $html .= '<br>';
45
 
46
+ list( $daysToDisplay, $rangestart_utime, $rangeend_utime ) = wp_statistics_date_range_calculator(
47
+ $daysToDisplay,
48
+ $rangestart,
49
+ $rangeend
50
+ );
51
 
52
+ wp_statistics_date_range_selector(
53
+ WP_Statistics::$page['categories'],
54
+ $daysToDisplay,
55
+ null,
56
+ null,
57
+ '&precat=' . $category,
58
+ $html
59
+ );
60
 
61
  $args = array(
62
  'category' => $category,
63
  );
64
 
65
+ $posts = get_posts($args);
66
 
67
+ $visit_total = 0;
68
  $daysInThePast = (int) ( ( time() - $rangeend_utime ) / 86400 );
69
+ $posts_stats = array();
70
+ $visits = array();
71
 
72
  // Setup the array, otherwise PHP may throw an error.
73
  foreach ( $posts as $post ) {
74
  $posts_stats[ $post->ID ] = 0;
75
  }
76
 
77
+ for ( $i = $daysToDisplay; $i >= 0; $i-- ) {
78
+ $date[] = "'" . $WP_Statistics->Real_Current_Date('M j', '-' . ( $i + $daysInThePast ), $rangeend_utime) . "'";
79
 
80
  $stat = 0;
81
  foreach ( $posts as $post ) {
82
+ $temp_stat = wp_statistics_pages('-' . (int) ( $i + $daysInThePast ), null, $post->ID);
83
  $posts_stats[ $post->ID ] += $temp_stat;
84
+ $stat = $temp_stat;
85
  }
86
 
87
+ $visits[] = $stat;
88
  $visit_total += $stat;
89
  }
90
  ?>
91
+ <div class="postbox-container" id="last-log">
92
+ <div class="metabox-holder">
93
+ <div class="meta-box-sortables">
94
+ <div class="postbox">
95
+ <?php $paneltitle = __('Category Statistics Chart', 'wp-statistics'); ?>
96
+ <button class="handlediv" type="button" aria-expanded="true">
97
+ <span class="screen-reader-text"><?php printf(
98
+ __('Toggle panel: %s', 'wp-statistics'),
99
+ $paneltitle
100
+ ); ?></span>
101
+ <span class="toggle-indicator" aria-hidden="true"></span>
102
+ </button>
103
+ <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
104
+
105
+ <div class="inside">
106
+ <canvas id="hit-stats" height="80"></canvas>
107
+ <script>
108
+ var ctx = document.getElementById("hit-stats").getContext('2d');
109
+ var ChartJs = new Chart(ctx, {
110
+ type: 'line',
111
+ data: {
112
+ labels: [<?php echo implode( ', ', $date ); ?>],
113
+ datasets: [
114
+ {
115
+ label: '<?php _e( 'Visits', 'wp-statistics' ); ?>',
116
+ data: [<?php echo implode( ',', $visits ); ?>],
117
+ backgroundColor: 'rgba(54, 162, 235, 0.2)',
118
+ borderColor: 'rgba(54, 162, 235, 1)',
119
+ borderWidth: 1,
120
+ fill: true,
121
+ },
122
+ ]
123
+ },
124
+ options: {
125
+ responsive: true,
126
+ legend: {
127
+ position: 'bottom',
128
+ },
129
+ title: {
130
+ display: true,
131
+ text: '<?php echo sprintf( __( 'Hits in the last %s days', 'wp-statistics' ), $daysToDisplay ); ?>'
132
+ },
133
+ tooltips: {
134
+ mode: 'index',
135
+ intersect: false,
136
+ },
137
+ scales: {
138
+ yAxes: [{
139
+ ticks: {
140
+ beginAtZero: true
141
+ }
142
+ }]
143
+ }
144
+ }
145
+ });
146
+ </script>
147
+ </div>
148
+ </div>
149
+ </div>
150
+ </div>
151
+ </div>
152
+
153
+ <div class="postbox-container" style="width: 100%; float: left; margin-right:20px">
154
+ <div class="metabox-holder">
155
+ <div class="meta-box-sortables">
156
+ <div class="postbox">
157
+ <?php $paneltitle = __('Category Statistics Summary', 'wp-statistics'); ?>
158
+ <button class="handlediv" type="button" aria-expanded="true">
159
+ <span class="screen-reader-text"><?php printf(
160
+ __('Toggle panel: %s', 'wp-statistics'),
161
+ $paneltitle
162
+ ); ?></span>
163
+ <span class="toggle-indicator" aria-hidden="true"></span>
164
+ </button>
165
+ <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
166
+
167
+ <div class="inside">
168
+ <table width="auto" class="widefat table-stats" id="summary-stats">
169
+ <tbody>
170
+ <tr>
171
+ <th></th>
172
+ <th class="th-center"><?php _e('Count', 'wp-statistics'); ?></th>
173
+ </tr>
174
+
175
+ <tr>
176
+ <th><?php _e('Number of posts in category', 'wp-statistics'); ?>:</th>
177
+ <th class="th-center"><span><?php echo number_format_i18n(count($posts)); ?></span>
178
+ </th>
179
+ </tr>
180
+
181
+ <tr>
182
+ <th><?php _e('Chart Visits Total', 'wp-statistics'); ?>:</th>
183
+ <th class="th-center"><span><?php echo number_format_i18n($visit_total); ?></span>
184
+ </th>
185
+ </tr>
186
+
187
+ <tr>
188
+ <th><?php _e('All Time Visits Total', 'wp-statistics'); ?>:</th>
189
+ <th class="th-center"><span><?php
190
 
191
  $stat = 0;
192
  foreach ( $posts as $post ) {
193
+ $stat += wp_statistics_pages('total', null, $post->ID);
194
  }
195
 
196
+ echo number_format_i18n($stat); ?></span></th>
197
+ </tr>
198
+ </tbody>
199
+ </table>
200
+ </div>
201
+ </div>
202
+ </div>
203
+ </div>
204
+ </div>
205
+
206
+ <div class="postbox-container" style="width: 100%; float: left; margin-right:20px">
207
+ <div class="metabox-holder">
208
+ <div class="meta-box-sortables">
209
+ <div class="postbox">
210
+ <?php $paneltitle = __('Category Posts Sorted by Hits', 'wp-statistics'); ?>
211
+ <button class="handlediv" type="button" aria-expanded="true">
212
+ <span class="screen-reader-text"><?php printf(
213
+ __('Toggle panel: %s', 'wp-statistics'),
214
+ $paneltitle
215
+ ); ?></span>
216
+ <span class="toggle-indicator" aria-hidden="true"></span>
217
+ </button>
218
+ <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
219
+
220
+ <div class="inside">
221
+ <table width="auto" class="widefat table-stats" id="post-stats">
222
+ <tbody>
223
+ <tr>
224
+ <th><?php _e('Post Title', 'wp-statistics'); ?></th>
225
+ <th class="th-center"><?php _e('Hits', 'wp-statistics'); ?></th>
226
+ </tr>
227
 
228
  <?php
229
+ arsort($posts_stats);
230
 
231
  $posts_by_id = array();
232
 
238
  $post_obj = $posts_by_id[ $post_id ];
239
 
240
  ?>
241
+ <tr>
242
+ <th>
243
+ <a href="<?php echo get_permalink(
244
+ $post_obj
245
+ ); ?>"><?php echo $post_obj->post_title; ?></a>
246
+ </th>
247
+ <th class="th-center"><span><?php echo number_format_i18n($post_stat); ?></span>
248
+ </th>
249
+ </tr>
250
  <?php
251
  }
252
  ?>
253
+ </tbody>
254
+ </table>
255
+ </div>
256
+ </div>
257
+ </div>
258
+ </div>
259
+ </div>
260
 
261
  </div>
includes/log/exclusions.php CHANGED
@@ -1,31 +1,40 @@
1
  <script type="text/javascript">
2
- jQuery(document).ready(function () {
3
- postboxes.add_postbox_toggles(pagenow);
4
- });
5
  </script>
6
  <?php
7
- if ( $WP_Statistics->get_option( 'record_exclusions' ) != 1 ) {
8
- echo "<div class='updated settings-error'><p><strong>" . __( 'Attention: Exclusion are not currently set to be recorded, the results below may not reflect current statistics!', 'wp-statistics' ) . "</strong></p></div>";
 
 
 
 
 
9
  }
10
 
11
  $daysToDisplay = 20;
12
- if ( array_key_exists( 'hitdays', $_GET ) ) {
13
- $daysToDisplay = intval( $_GET['hitdays'] );
14
  }
15
 
16
- if ( array_key_exists( 'rangestart', $_GET ) ) {
17
  $rangestart = $_GET['rangestart'];
18
  } else {
19
  $rangestart = '';
20
  }
21
- if ( array_key_exists( 'rangeend', $_GET ) ) {
22
  $rangeend = $_GET['rangeend'];
23
  } else {
24
  $rangeend = '';
25
  }
26
 
27
- list( $daysToDisplay, $rangestart_utime, $rangeend_utime ) = wp_statistics_date_range_calculator( $daysToDisplay, $rangestart, $rangeend );
28
- $total_stats = $WP_Statistics->get_option( 'chart_totals' );
 
 
 
 
29
 
30
  $excluded_reasons = array(
31
  'Robot',
@@ -43,7 +52,7 @@ $excluded_reasons = array(
43
  'Excluded URL',
44
  '404 Pages',
45
  'Referrer Spam',
46
- 'AJAX Request'
47
  );
48
  $excluded_reason_tags = array(
49
  'Robot' => 'robot',
@@ -62,7 +71,7 @@ $excluded_reason_tags = array(
62
  'Excluded URL' => 'excluded_url',
63
  '404 Pages' => 'excluded_404s',
64
  'Referrer Spam' => 'referrer_spam',
65
- 'AJAX Request' => 'ajax'
66
  );
67
  $excluded_reason_db = array(
68
  'Robot' => 'robot',
@@ -81,26 +90,26 @@ $excluded_reason_db = array(
81
  'Excluded URL' => 'excluded url',
82
  '404 Pages' => '404',
83
  'Referrer Spam' => 'referrer_spam',
84
- 'AJAX Request' => 'ajax'
85
  );
86
  $excluded_reason_translate = array(
87
- 'Robot' => json_encode( __( 'Robot', 'wp-statistics' ) ),
88
- 'Browscap' => json_encode( __( 'Browscap', 'wp-statistics' ) ),
89
- 'IP Match' => json_encode( __( 'IP Match', 'wp-statistics' ) ),
90
- 'Self Referral' => json_encode( __( 'Self Referral', 'wp-statistics' ) ),
91
- 'Login Page' => json_encode( __( 'Login Page', 'wp-statistics' ) ),
92
- 'Admin Page' => json_encode( __( 'Admin Page', 'wp-statistics' ) ),
93
- 'User Role' => json_encode( __( 'User Role', 'wp-statistics' ) ),
94
- 'Total' => json_encode( __( 'Total', 'wp-statistics' ) ),
95
- 'GeoIP' => json_encode( __( 'GeoIP', 'wp-statistics' ) ),
96
- 'Hostname' => json_encode( __( 'Hostname', 'wp-statistics' ) ),
97
- 'Robot Threshold' => json_encode( __( 'Robot Threshold', 'wp-statistics' ) ),
98
- 'Honey Pot' => json_encode( __( 'Honey Pot', 'wp-statistics' ) ),
99
- 'Feeds' => json_encode( __( 'Feeds', 'wp-statistics' ) ),
100
- 'Excluded URL' => json_encode( __( 'Excluded URL', 'wp-statistics' ) ),
101
- '404 Pages' => json_encode( __( '404 Pages', 'wp-statistics' ) ),
102
- 'Referrer Spam' => json_encode( __( 'Referrer Spam', 'wp-statistics' ) ),
103
- 'AJAX Request' => json_encode( __( 'AJAX Request', 'wp-statistics' ) )
104
  );
105
  $excluded_results = array( 'Total' => array() );
106
  $excluded_total = 0;
@@ -110,16 +119,20 @@ foreach ( $excluded_reasons as $reason ) {
110
  // is created with mixed case so it looks nice to the user. Therefore we have to convert it to lower case here.
111
  $thisreason = $excluded_reason_db[ $reason ];
112
 
113
- for ( $i = $daysToDisplay; $i >= 0; $i -- ) {
114
 
115
  // We're looping through the days backwards, so let's fine out what date we want to look at.
116
- $thisdate = $WP_Statistics->real_current_date( 'Y-m-d', '-' . $i, $rangeend_utime );
117
 
118
  // Create the SQL query string to get the data.
119
- $query = $wpdb->prepare( "SELECT count FROM {$wpdb->prefix}statistics_exclusions WHERE reason = %s AND date = %s", $thisreason, $thisdate );
 
 
 
 
120
 
121
  // Execute the query.
122
- $excluded_results[ $reason ][ $i ] = $wpdb->get_var( $query );
123
 
124
  // If we're returned an error or a FALSE value, then let's make sure it's set to a numerical 0.
125
  if ( $excluded_results[ $reason ][ $i ] < 1 ) {
@@ -127,135 +140,144 @@ foreach ( $excluded_reasons as $reason ) {
127
  }
128
 
129
  // Make sure to initialize the results so we don't get warnings when WP_DEBUG is enabled.
130
- if ( ! array_key_exists( $i, $excluded_results['Total'] ) ) {
131
  $excluded_results['Total'][ $i ] = 0;
132
  }
133
 
134
  // We're totalling things up here for use later.
135
  $excluded_results['Total'][ $i ] += $excluded_results[ $reason ][ $i ];
136
- $excluded_total += $excluded_results[ $reason ][ $i ];
137
  }
138
  }
139
 
140
- $excuded_all_time = $wpdb->get_var( "SELECT SUM(count) FROM {$wpdb->prefix}statistics_exclusions" );
141
 
142
  // If the chart totals is enabled, cheat a little and just add another reason category to the list so it gets generated later.
143
  if ( $total_stats == 1 ) {
144
  $excluded_reasons[] = 'Total';
145
  }
146
 
147
- for ( $i = $daysToDisplay; $i >= 0; $i -- ) {
148
- $date[] = "'" . $WP_Statistics->Current_Date( 'M j', '-' . $i ) . "'";
149
  }
150
 
151
  $stats = array();
152
  foreach ( $excluded_reasons as $reason ) {
153
- for ( $i = $daysToDisplay; $i >= 0; $i -- ) {
154
  $stats[ $reason ][] = $excluded_results[ $reason ][ $i ];
155
  }
156
  }
157
  ?>
158
  <div class="wrap">
159
- <h2><?php _e( 'Exclusions Statistics', 'wp-statistics' ); ?></h2>
160
- <?php wp_statistics_date_range_selector( WP_STATISTICS_EXCLUSIONS_PAGE, $daysToDisplay ); ?>
161
- <div class="postbox-container" id="last-log">
162
- <div class="metabox-holder">
163
- <div class="meta-box-sortables">
164
- <div class="postbox">
165
- <?php $paneltitle = __( 'Exclusions Statistical Chart', 'wp-statistics' ); ?>
166
- <button class="handlediv" type="button" aria-expanded="true">
167
- <span class="screen-reader-text"><?php printf( __( 'Toggle panel: %s', 'wp-statistics' ), $paneltitle ); ?></span>
168
- <span class="toggle-indicator" aria-hidden="true"></span>
169
- </button>
170
- <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
171
- <div class="inside">
172
- <div class="inside">
173
- <canvas id="hit-stats" height="80"></canvas>
174
- <script type='text/javascript' src='<?php echo WP_STATISTICS_PLUGIN_DIR; ?>/assets/js/Chart.bundle.min.js'></script>
175
- <script>
176
- var ctx = document.getElementById("hit-stats").getContext('2d');
177
- var ChartJs = new Chart(ctx, {
178
- type: 'line',
179
- data: {
180
- labels: [<?php echo implode( ', ', $date ); ?>],
181
- datasets: [
 
 
 
 
 
182
  <?php foreach ($stats as $key => $value) : $i ++; ?>
183
- {
184
- label: '<?php echo $key; ?>',
185
- data: [<?php echo implode( ',', $value ); ?>],
186
- backgroundColor: <?php echo wp_statistics_generate_rgba_color( $i, '0.2' ); ?>,
187
- borderColor: <?php echo wp_statistics_generate_rgba_color( $i, '1' ); ?>,
188
- borderWidth: 1,
189
- fill: true,
190
- },
191
  <?php endforeach; ?>
192
- ]
193
- },
194
- options: {
195
- responsive: true,
196
- legend: {
197
- position: 'bottom',
198
- },
199
- title: {
200
- display: true,
201
- text: '<?php echo sprintf( __( 'Hits in the last %s days', 'wp-statistics' ), $daysToDisplay ); ?>'
202
- },
203
- tooltips: {
204
- mode: 'index',
205
- intersect: false,
206
- },
207
- scales: {
208
- yAxes: [{
209
- ticks: {
210
- beginAtZero: true
211
- }
212
- }]
213
- }
214
- }
215
- });
216
- </script>
217
- </div>
218
- </div>
219
- </div>
220
- </div>
221
- </div>
222
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
223
 
224
- <div class="postbox-container" style="width: 100%; float: left; margin-right:20px">
225
- <div class="metabox-holder">
226
- <div class="meta-box-sortables">
227
- <div class="postbox">
228
- <?php $paneltitle = __( 'Hits Statistics Summary', 'wp-statistics' ); ?>
229
- <button class="handlediv" type="button" aria-expanded="true">
230
- <span class="screen-reader-text"><?php printf( __( 'Toggle panel: %s', 'wp-statistics' ), $paneltitle ); ?></span>
231
- <span class="toggle-indicator" aria-hidden="true"></span>
232
- </button>
233
- <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
234
- <div class="inside">
235
- <table width="auto" class="widefat table-stats" id="summary-stats">
236
- <tbody>
237
- <tr>
238
- <th></th>
239
- <th class="th-center"><?php _e( 'Exclusions', 'wp-statistics' ); ?></th>
240
- </tr>
241
 
242
- <tr>
243
- <th><?php _e( 'Chart Total', 'wp-statistics' ); ?>:</th>
244
- <th class="th-center"><span><?php echo number_format_i18n( $excluded_total ); ?></span>
245
- </th>
246
- </tr>
247
 
248
- <tr>
249
- <th><?php _e( 'All Time Total', 'wp-statistics' ); ?>:</th>
250
- <th class="th-center">
251
- <span><?php echo number_format_i18n( $excuded_all_time ); ?></span>
252
- </th>
253
- </tr>
254
- </tbody>
255
- </table>
256
- </div>
257
- </div>
258
- </div>
259
- </div>
260
- </div>
261
  </div>
1
  <script type="text/javascript">
2
+ jQuery(document).ready(function () {
3
+ postboxes.add_postbox_toggles(pagenow);
4
+ });
5
  </script>
6
  <?php
7
+ if ( $WP_Statistics->get_option('record_exclusions') != 1 ) {
8
+ echo "<div class='updated settings-error'><p><strong>" .
9
+ __(
10
+ 'Attention: Exclusion are not currently set to be recorded, the results below may not reflect current statistics!',
11
+ 'wp-statistics'
12
+ ) .
13
+ "</strong></p></div>";
14
  }
15
 
16
  $daysToDisplay = 20;
17
+ if ( array_key_exists('hitdays', $_GET) ) {
18
+ $daysToDisplay = intval($_GET['hitdays']);
19
  }
20
 
21
+ if ( array_key_exists('rangestart', $_GET) ) {
22
  $rangestart = $_GET['rangestart'];
23
  } else {
24
  $rangestart = '';
25
  }
26
+ if ( array_key_exists('rangeend', $_GET) ) {
27
  $rangeend = $_GET['rangeend'];
28
  } else {
29
  $rangeend = '';
30
  }
31
 
32
+ list( $daysToDisplay, $rangestart_utime, $rangeend_utime ) = wp_statistics_date_range_calculator(
33
+ $daysToDisplay,
34
+ $rangestart,
35
+ $rangeend
36
+ );
37
+ $total_stats = $WP_Statistics->get_option('chart_totals');
38
 
39
  $excluded_reasons = array(
40
  'Robot',
52
  'Excluded URL',
53
  '404 Pages',
54
  'Referrer Spam',
55
+ 'AJAX Request',
56
  );
57
  $excluded_reason_tags = array(
58
  'Robot' => 'robot',
71
  'Excluded URL' => 'excluded_url',
72
  '404 Pages' => 'excluded_404s',
73
  'Referrer Spam' => 'referrer_spam',
74
+ 'AJAX Request' => 'ajax',
75
  );
76
  $excluded_reason_db = array(
77
  'Robot' => 'robot',
90
  'Excluded URL' => 'excluded url',
91
  '404 Pages' => '404',
92
  'Referrer Spam' => 'referrer_spam',
93
+ 'AJAX Request' => 'ajax',
94
  );
95
  $excluded_reason_translate = array(
96
+ 'Robot' => json_encode(__('Robot', 'wp-statistics')),
97
+ 'Browscap' => json_encode(__('Browscap', 'wp-statistics')),
98
+ 'IP Match' => json_encode(__('IP Match', 'wp-statistics')),
99
+ 'Self Referral' => json_encode(__('Self Referral', 'wp-statistics')),
100
+ 'Login Page' => json_encode(__('Login Page', 'wp-statistics')),
101
+ 'Admin Page' => json_encode(__('Admin Page', 'wp-statistics')),
102
+ 'User Role' => json_encode(__('User Role', 'wp-statistics')),
103
+ 'Total' => json_encode(__('Total', 'wp-statistics')),
104
+ 'GeoIP' => json_encode(__('GeoIP', 'wp-statistics')),
105
+ 'Hostname' => json_encode(__('Hostname', 'wp-statistics')),
106
+ 'Robot Threshold' => json_encode(__('Robot Threshold', 'wp-statistics')),
107
+ 'Honey Pot' => json_encode(__('Honey Pot', 'wp-statistics')),
108
+ 'Feeds' => json_encode(__('Feeds', 'wp-statistics')),
109
+ 'Excluded URL' => json_encode(__('Excluded URL', 'wp-statistics')),
110
+ '404 Pages' => json_encode(__('404 Pages', 'wp-statistics')),
111
+ 'Referrer Spam' => json_encode(__('Referrer Spam', 'wp-statistics')),
112
+ 'AJAX Request' => json_encode(__('AJAX Request', 'wp-statistics')),
113
  );
114
  $excluded_results = array( 'Total' => array() );
115
  $excluded_total = 0;
119
  // is created with mixed case so it looks nice to the user. Therefore we have to convert it to lower case here.
120
  $thisreason = $excluded_reason_db[ $reason ];
121
 
122
+ for ( $i = $daysToDisplay; $i >= 0; $i-- ) {
123
 
124
  // We're looping through the days backwards, so let's fine out what date we want to look at.
125
+ $thisdate = $WP_Statistics->real_current_date('Y-m-d', '-' . $i, $rangeend_utime);
126
 
127
  // Create the SQL query string to get the data.
128
+ $query = $wpdb->prepare(
129
+ "SELECT count FROM {$wpdb->prefix}statistics_exclusions WHERE reason = %s AND date = %s",
130
+ $thisreason,
131
+ $thisdate
132
+ );
133
 
134
  // Execute the query.
135
+ $excluded_results[ $reason ][ $i ] = $wpdb->get_var($query);
136
 
137
  // If we're returned an error or a FALSE value, then let's make sure it's set to a numerical 0.
138
  if ( $excluded_results[ $reason ][ $i ] < 1 ) {
140
  }
141
 
142
  // Make sure to initialize the results so we don't get warnings when WP_DEBUG is enabled.
143
+ if ( ! array_key_exists($i, $excluded_results['Total']) ) {
144
  $excluded_results['Total'][ $i ] = 0;
145
  }
146
 
147
  // We're totalling things up here for use later.
148
  $excluded_results['Total'][ $i ] += $excluded_results[ $reason ][ $i ];
149
+ $excluded_total += $excluded_results[ $reason ][ $i ];
150
  }
151
  }
152
 
153
+ $excuded_all_time = $wpdb->get_var("SELECT SUM(count) FROM {$wpdb->prefix}statistics_exclusions");
154
 
155
  // If the chart totals is enabled, cheat a little and just add another reason category to the list so it gets generated later.
156
  if ( $total_stats == 1 ) {
157
  $excluded_reasons[] = 'Total';
158
  }
159
 
160
+ for ( $i = $daysToDisplay; $i >= 0; $i-- ) {
161
+ $date[] = "'" . $WP_Statistics->Current_Date('M j', '-' . $i) . "'";
162
  }
163
 
164
  $stats = array();
165
  foreach ( $excluded_reasons as $reason ) {
166
+ for ( $i = $daysToDisplay; $i >= 0; $i-- ) {
167
  $stats[ $reason ][] = $excluded_results[ $reason ][ $i ];
168
  }
169
  }
170
  ?>
171
  <div class="wrap">
172
+ <h2><?php _e('Exclusions Statistics', 'wp-statistics'); ?></h2>
173
+ <?php wp_statistics_date_range_selector(WP_Statistics::$page['exclusions'], $daysToDisplay); ?>
174
+ <div class="postbox-container" id="last-log">
175
+ <div class="metabox-holder">
176
+ <div class="meta-box-sortables">
177
+ <div class="postbox">
178
+ <?php $paneltitle = __('Exclusions Statistical Chart', 'wp-statistics'); ?>
179
+ <button class="handlediv" type="button" aria-expanded="true">
180
+ <span class="screen-reader-text"><?php printf(
181
+ __('Toggle panel: %s', 'wp-statistics'),
182
+ $paneltitle
183
+ ); ?></span>
184
+ <span class="toggle-indicator" aria-hidden="true"></span>
185
+ </button>
186
+ <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
187
+
188
+ <div class="inside">
189
+ <div class="inside">
190
+ <canvas id="hit-stats" height="80"></canvas>
191
+ <script type='text/javascript'
192
+ src='<?php echo WP_Statistics::$reg['plugin-url']; ?>assets/js/Chart.bundle.min.js'></script>
193
+ <script>
194
+ var ctx = document.getElementById("hit-stats").getContext('2d');
195
+ var ChartJs = new Chart(ctx, {
196
+ type: 'line',
197
+ data: {
198
+ labels: [<?php echo implode( ', ', $date ); ?>],
199
+ datasets: [
200
  <?php foreach ($stats as $key => $value) : $i ++; ?>
201
+ {
202
+ label: '<?php echo $key; ?>',
203
+ data: [<?php echo implode( ',', $value ); ?>],
204
+ backgroundColor: <?php echo wp_statistics_generate_rgba_color( $i, '0.2' ); ?>,
205
+ borderColor: <?php echo wp_statistics_generate_rgba_color( $i, '1' ); ?>,
206
+ borderWidth: 1,
207
+ fill: true,
208
+ },
209
  <?php endforeach; ?>
210
+ ]
211
+ },
212
+ options: {
213
+ responsive: true,
214
+ legend: {
215
+ position: 'bottom',
216
+ },
217
+ title: {
218
+ display: true,
219
+ text: '<?php echo sprintf( __( 'Hits in the last %s days', 'wp-statistics' ), $daysToDisplay ); ?>'
220
+ },
221
+ tooltips: {
222
+ mode: 'index',
223
+ intersect: false,
224
+ },
225
+ scales: {
226
+ yAxes: [{
227
+ ticks: {
228
+ beginAtZero: true
229
+ }
230
+ }]
231
+ }
232
+ }
233
+ });
234
+ </script>
235
+ </div>
236
+ </div>
237
+ </div>
238
+ </div>
239
+ </div>
240
+ </div>
241
+
242
+ <div class="postbox-container" style="width: 100%; float: left; margin-right:20px">
243
+ <div class="metabox-holder">
244
+ <div class="meta-box-sortables">
245
+ <div class="postbox">
246
+ <?php $paneltitle = __('Hits Statistics Summary', 'wp-statistics'); ?>
247
+ <button class="handlediv" type="button" aria-expanded="true">
248
+ <span class="screen-reader-text"><?php printf(
249
+ __('Toggle panel: %s', 'wp-statistics'),
250
+ $paneltitle
251
+ ); ?></span>
252
+ <span class="toggle-indicator" aria-hidden="true"></span>
253
+ </button>
254
+ <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
255
 
256
+ <div class="inside">
257
+ <table width="auto" class="widefat table-stats" id="summary-stats">
258
+ <tbody>
259
+ <tr>
260
+ <th></th>
261
+ <th class="th-center"><?php _e('Exclusions', 'wp-statistics'); ?></th>
262
+ </tr>
 
 
 
 
 
 
 
 
 
 
263
 
264
+ <tr>
265
+ <th><?php _e('Chart Total', 'wp-statistics'); ?>:</th>
266
+ <th class="th-center"><span><?php echo number_format_i18n($excluded_total); ?></span>
267
+ </th>
268
+ </tr>
269
 
270
+ <tr>
271
+ <th><?php _e('All Time Total', 'wp-statistics'); ?>:</th>
272
+ <th class="th-center">
273
+ <span><?php echo number_format_i18n($excuded_all_time); ?></span>
274
+ </th>
275
+ </tr>
276
+ </tbody>
277
+ </table>
278
+ </div>
279
+ </div>
280
+ </div>
281
+ </div>
282
+ </div>
283
  </div>
includes/log/hit-statistics.php CHANGED
@@ -1,164 +1,178 @@
1
  <script type="text/javascript">
2
- jQuery(document).ready(function () {
3
- postboxes.add_postbox_toggles(pagenow);
4
- });
5
  </script>
6
  <div class="wrap">
7
- <h2><?php _e( 'Hit Statistics', 'wp-statistics' ); ?></h2>
8
  <?php
9
  $daysToDisplay = 20;
10
- if ( array_key_exists( 'hitdays', $_GET ) ) {
11
- $daysToDisplay = intval( $_GET['hitdays'] );
12
  }
13
 
14
- if ( array_key_exists( 'rangestart', $_GET ) ) {
15
  $rangestart = $_GET['rangestart'];
16
  } else {
17
  $rangestart = '';
18
  }
19
- if ( array_key_exists( 'rangeend', $_GET ) ) {
20
  $rangeend = $_GET['rangeend'];
21
  } else {
22
  $rangeend = '';
23
  }
24
 
25
- list( $daysToDisplay, $rangestart_utime, $rangeend_utime ) = wp_statistics_date_range_calculator( $daysToDisplay, $rangestart, $rangeend );
26
- wp_statistics_date_range_selector( WP_STATISTICS_HITS_PAGE, $daysToDisplay );
 
 
 
 
27
 
28
- $visit_total = 0;
29
  $visitor_total = 0;
30
  $daysInThePast = (int) ( ( time() - $rangeend_utime ) / 86400 );
31
- $visitors = array();
32
- $visits = array();
33
 
34
- for ( $i = $daysToDisplay; $i >= 0; $i -- ) {
35
- $stat = wp_statistics_visit( '-' . (int) ( $i + $daysInThePast ), true );
36
  $visit_total += $stat;
37
- $visits[] = $stat;
38
  }
39
 
40
- for ( $i = $daysToDisplay; $i >= 0; $i -- ) {
41
- $stat = wp_statistics_visitor( '-' . (int) ( $i + $daysInThePast ), true );
42
  $visitor_total += $stat;
43
- $visitors[] = $stat;
44
  }
45
 
46
- for ( $i = $daysToDisplay; $i >= 0; $i -- ) {
47
- $date[] = "'" . $WP_Statistics->Current_Date( 'M j', '-' . $i ) . "'";
48
  }
49
  ?>
50
- <div class="postbox-container" id="last-log">
51
- <div class="metabox-holder">
52
- <div class="meta-box-sortables">
53
- <div class="postbox">
54
- <?php $paneltitle = __( 'Hits Statistics Chart', 'wp-statistics' ); ?>
55
- <button class="handlediv" type="button" aria-expanded="true">
56
- <span class="screen-reader-text"><?php printf( __( 'Toggle panel: %s', 'wp-statistics' ), $paneltitle ); ?></span>
57
- <span class="toggle-indicator" aria-hidden="true"></span>
58
- </button>
59
- <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
60
- <div class="inside">
61
- <canvas id="hit-stats" height="80"></canvas>
62
- <script>
63
- var ctx = document.getElementById("hit-stats").getContext('2d');
64
- var ChartJs = new Chart(ctx, {
65
- type: 'line',
66
- data: {
67
- labels: [<?php echo implode( ', ', $date ); ?>],
68
- datasets: [
 
 
 
 
69
  <?php if ( $WP_Statistics->get_option( 'visitors' ) ) { ?>
70
- {
71
- label: '<?php _e( 'Visitors', 'wp-statistics' ); ?>',
72
- data: [<?php echo implode( ',', $visitors ); ?>],
73
- backgroundColor: 'rgba(255, 99, 132, 0.2)',
74
- borderColor: 'rgba(255, 99, 132, 1)',
75
- borderWidth: 1,
76
- fill: true,
77
- },
78
  <?php } ?>
79
  <?php if ( $WP_Statistics->get_option( 'visits' ) ) { ?>
80
- {
81
- label: '<?php _e( 'Visits', 'wp-statistics' ); ?>',
82
- data: [<?php echo implode( ',', $visits ); ?>],
83
- backgroundColor: 'rgba(54, 162, 235, 0.2)',
84
- borderColor: 'rgba(54, 162, 235, 1)',
85
- borderWidth: 1,
86
- fill: true,
87
- },
88
  <?php } ?>
89
- ]
90
- },
91
- options: {
92
- responsive: true,
93
- legend: {
94
- position: 'bottom',
95
- },
96
- title: {
97
- display: true,
98
- text: '<?php echo sprintf( __( 'Hits in the last %s days', 'wp-statistics' ), $daysToDisplay ); ?>'
99
- },
100
- tooltips: {
101
- mode: 'index',
102
- intersect: false,
103
- },
104
- scales: {
105
- yAxes: [{
106
- ticks: {
107
- beginAtZero: true
108
- }
109
- }]
110
- }
111
- }
112
- });
113
- </script>
114
- </div>
115
- </div>
116
- </div>
117
- </div>
118
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
 
120
- <div class="postbox-container" style="width: 100%; float: left; margin-right:20px">
121
- <div class="metabox-holder">
122
- <div class="meta-box-sortables">
123
- <div class="postbox">
124
- <?php $paneltitle = __( 'Hits Statistics Summary', 'wp-statistics' ); ?>
125
- <button class="handlediv" type="button" aria-expanded="true">
126
- <span class="screen-reader-text"><?php printf( __( 'Toggle panel: %s', 'wp-statistics' ), $paneltitle ); ?></span>
127
- <span class="toggle-indicator" aria-hidden="true"></span>
128
- </button>
129
- <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
130
- <div class="inside">
131
- <table width="auto" class="widefat table-stats" id="summary-stats">
132
- <tbody>
133
- <tr>
134
- <th></th>
135
- <th class="th-center"><?php _e( 'Visits', 'wp-statistics' ); ?></th>
136
- <th class="th-center"><?php _e( 'Visitors', 'wp-statistics' ); ?></th>
137
- </tr>
138
 
139
- <tr>
140
- <th><?php _e( 'Chart Total', 'wp-statistics' ); ?>:</th>
141
- <th class="th-center"><span><?php echo number_format_i18n( $visit_total ); ?></span>
142
- </th>
143
- <th class="th-center"><span><?php echo number_format_i18n( $visitor_total ); ?></span>
144
- </th>
145
- </tr>
146
 
147
- <tr>
148
- <th><?php _e( 'All Time Total', 'wp-statistics' ); ?>:</th>
149
- <th class="th-center">
150
- <span><?php echo number_format_i18n( wp_statistics_visit( 'total' ) ); ?></span>
151
- </th>
152
- <th class="th-center">
153
- <span><?php echo number_format_i18n( wp_statistics_visitor( 'total', null, true ) ); ?></span>
154
- </th>
155
- </tr>
156
- </tbody>
157
- </table>
158
- </div>
159
- </div>
160
- </div>
161
- </div>
162
- </div>
 
 
163
 
164
  </div>
1
  <script type="text/javascript">
2
+ jQuery(document).ready(function () {
3
+ postboxes.add_postbox_toggles(pagenow);
4
+ });
5
  </script>
6
  <div class="wrap">
7
+ <h2><?php _e('Hit Statistics', 'wp-statistics'); ?></h2>
8
  <?php
9
  $daysToDisplay = 20;
10
+ if ( array_key_exists('hitdays', $_GET) ) {
11
+ $daysToDisplay = intval($_GET['hitdays']);
12
  }
13
 
14
+ if ( array_key_exists('rangestart', $_GET) ) {
15
  $rangestart = $_GET['rangestart'];
16
  } else {
17
  $rangestart = '';
18
  }
19
+ if ( array_key_exists('rangeend', $_GET) ) {
20
  $rangeend = $_GET['rangeend'];
21
  } else {
22
  $rangeend = '';
23
  }
24
 
25
+ list( $daysToDisplay, $rangestart_utime, $rangeend_utime ) = wp_statistics_date_range_calculator(
26
+ $daysToDisplay,
27
+ $rangestart,
28
+ $rangeend
29
+ );
30
+ wp_statistics_date_range_selector(WP_Statistics::$page['hits'], $daysToDisplay);
31
 
32
+ $visit_total = 0;
33
  $visitor_total = 0;
34
  $daysInThePast = (int) ( ( time() - $rangeend_utime ) / 86400 );
35
+ $visitors = array();
36
+ $visits = array();
37
 
38
+ for ( $i = $daysToDisplay; $i >= 0; $i-- ) {
39
+ $stat = wp_statistics_visit('-' . (int) ( $i + $daysInThePast ), true);
40
  $visit_total += $stat;
41
+ $visits[] = $stat;
42
  }
43
 
44
+ for ( $i = $daysToDisplay; $i >= 0; $i-- ) {
45
+ $stat = wp_statistics_visitor('-' . (int) ( $i + $daysInThePast ), true);
46
  $visitor_total += $stat;
47
+ $visitors[] = $stat;
48
  }
49
 
50
+ for ( $i = $daysToDisplay; $i >= 0; $i-- ) {
51
+ $date[] = "'" . $WP_Statistics->Current_Date('M j', '-' . $i) . "'";
52
  }
53
  ?>
54
+ <div class="postbox-container" id="last-log">
55
+ <div class="metabox-holder">
56
+ <div class="meta-box-sortables">
57
+ <div class="postbox">
58
+ <?php $paneltitle = __('Hits Statistics Chart', 'wp-statistics'); ?>
59
+ <button class="handlediv" type="button" aria-expanded="true">
60
+ <span class="screen-reader-text"><?php printf(
61
+ __('Toggle panel: %s', 'wp-statistics'),
62
+ $paneltitle
63
+ ); ?></span>
64
+ <span class="toggle-indicator" aria-hidden="true"></span>
65
+ </button>
66
+ <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
67
+
68
+ <div class="inside">
69
+ <canvas id="hit-stats" height="80"></canvas>
70
+ <script>
71
+ var ctx = document.getElementById("hit-stats").getContext('2d');
72
+ var ChartJs = new Chart(ctx, {
73
+ type: 'line',
74
+ data: {
75
+ labels: [<?php echo implode( ', ', $date ); ?>],
76
+ datasets: [
77
  <?php if ( $WP_Statistics->get_option( 'visitors' ) ) { ?>
78
+ {
79
+ label: '<?php _e( 'Visitors', 'wp-statistics' ); ?>',
80
+ data: [<?php echo implode( ',', $visitors ); ?>],
81
+ backgroundColor: 'rgba(255, 99, 132, 0.2)',
82
+ borderColor: 'rgba(255, 99, 132, 1)',
83
+ borderWidth: 1,
84
+ fill: true,
85
+ },
86
  <?php } ?>
87
  <?php if ( $WP_Statistics->get_option( 'visits' ) ) { ?>
88
+ {
89
+ label: '<?php _e( 'Visits', 'wp-statistics' ); ?>',
90
+ data: [<?php echo implode( ',', $visits ); ?>],
91
+ backgroundColor: 'rgba(54, 162, 235, 0.2)',
92
+ borderColor: 'rgba(54, 162, 235, 1)',
93
+ borderWidth: 1,
94
+ fill: true,
95
+ },
96
  <?php } ?>
97
+ ]
98
+ },
99
+ options: {
100
+ responsive: true,
101
+ legend: {
102
+ position: 'bottom',
103
+ },
104
+ title: {
105
+ display: true,
106
+ text: '<?php echo sprintf( __( 'Hits in the last %s days', 'wp-statistics' ), $daysToDisplay ); ?>'
107
+ },
108
+ tooltips: {
109
+ mode: 'index',
110
+ intersect: false,
111
+ },
112
+ scales: {
113
+ yAxes: [{
114
+ ticks: {
115
+ beginAtZero: true
116
+ }
117
+ }]
118
+ }
119
+ }
120
+ });
121
+ </script>
122
+ </div>
123
+ </div>
124
+ </div>
125
+ </div>
126
+ </div>
127
+
128
+ <div class="postbox-container" style="width: 100%; float: left; margin-right:20px">
129
+ <div class="metabox-holder">
130
+ <div class="meta-box-sortables">
131
+ <div class="postbox">
132
+ <?php $paneltitle = __('Hits Statistics Summary', 'wp-statistics'); ?>
133
+ <button class="handlediv" type="button" aria-expanded="true">
134
+ <span class="screen-reader-text"><?php printf(
135
+ __('Toggle panel: %s', 'wp-statistics'),
136
+ $paneltitle
137
+ ); ?></span>
138
+ <span class="toggle-indicator" aria-hidden="true"></span>
139
+ </button>
140
+ <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
141
 
142
+ <div class="inside">
143
+ <table width="auto" class="widefat table-stats" id="summary-stats">
144
+ <tbody>
145
+ <tr>
146
+ <th></th>
147
+ <th class="th-center"><?php _e('Visits', 'wp-statistics'); ?></th>
148
+ <th class="th-center"><?php _e('Visitors', 'wp-statistics'); ?></th>
149
+ </tr>
 
 
 
 
 
 
 
 
 
 
150
 
151
+ <tr>
152
+ <th><?php _e('Chart Total', 'wp-statistics'); ?>:</th>
153
+ <th class="th-center"><span><?php echo number_format_i18n($visit_total); ?></span>
154
+ </th>
155
+ <th class="th-center"><span><?php echo number_format_i18n($visitor_total); ?></span>
156
+ </th>
157
+ </tr>
158
 
159
+ <tr>
160
+ <th><?php _e('All Time Total', 'wp-statistics'); ?>:</th>
161
+ <th class="th-center">
162
+ <span><?php echo number_format_i18n(wp_statistics_visit('total')); ?></span>
163
+ </th>
164
+ <th class="th-center">
165
+ <span><?php echo number_format_i18n(
166
+ wp_statistics_visitor('total', null, true)
167
+ ); ?></span>
168
+ </th>
169
+ </tr>
170
+ </tbody>
171
+ </table>
172
+ </div>
173
+ </div>
174
+ </div>
175
+ </div>
176
+ </div>
177
 
178
  </div>
includes/log/last-search.php CHANGED
@@ -1,18 +1,18 @@
1
  <script type="text/javascript">
2
- jQuery(document).ready(function () {
3
- postboxes.add_postbox_toggles(pagenow);
4
- });
5
  </script>
6
  <?php
7
  $search_engines = wp_statistics_searchengine_list();
8
 
9
- $search_result['All'] = wp_statistics_searchword( 'all', 'total' );
10
 
11
  foreach ( $search_engines as $key => $se ) {
12
- $search_result[ $key ] = wp_statistics_searchword( $key, 'total' );
13
  }
14
 
15
- if ( array_key_exists( 'referred', $_GET ) ) {
16
  if ( $_GET['referred'] != '' ) {
17
  $referred = $_GET['referred'];
18
  } else {
@@ -25,15 +25,15 @@ if ( array_key_exists( 'referred', $_GET ) ) {
25
  $total = $search_result[ $referred ];
26
  ?>
27
  <div class="wrap">
28
- <h2><?php _e( 'Latest Search Words', 'wp-statistics' ); ?></h2>
29
- <ul class="subsubsub">
30
  <?php
31
- $search_result_count = count( $search_result );
32
  $i = 0;
33
  $separator = ' | ';
34
 
35
  foreach ( $search_result as $key => $value ) {
36
- $i ++;
37
 
38
  if ( $i == $search_result_count ) {
39
  $separator = '';
@@ -42,29 +42,37 @@ $total = $search_result[ $referred ];
42
  if ( $key == 'All' ) {
43
  $tag = '';
44
  $name = 'All';
45
- $translate = __( 'All', 'wp-statistics' );
46
  } else {
47
  $tag = $search_engines[ $key ]['tag'];
48
  $name = $search_engines[ $key ]['name'];
49
  $translate = $search_engines[ $key ]['translated'];
50
  }
51
 
52
- echo "<li><a href='?page=" . WP_STATISTICS_WORDS_PAGE . "&referred={$tag}'>" . $translate . " <span class='count'>({$value})</span></a></li>{$separator}";
 
 
 
 
53
  }
54
  ?>
55
- </ul>
56
- <div class="postbox-container" id="last-log">
57
- <div class="metabox-holder">
58
- <div class="meta-box-sortables">
59
- <div class="postbox">
60
- <?php $paneltitle = __( 'Latest Search Word Statistics', 'wp-statistics' ); ?>
61
- <button class="handlediv" type="button" aria-expanded="true">
62
- <span class="screen-reader-text"><?php printf( __( 'Toggle panel: %s', 'wp-statistics' ), $paneltitle ); ?></span>
63
- <span class="toggle-indicator" aria-hidden="true"></span>
64
- </button>
65
- <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
66
- <div class="inside">
67
- <div class='log-latest'>
 
 
 
 
68
  <?php
69
  if ( $total > 0 ) {
70
  // Instantiate pagination object with appropriate arguments
@@ -75,84 +83,125 @@ $total = $search_result[ $referred ];
75
  $styleErrors = "paginationErrors";
76
  $styleSelect = "paginationSelect";
77
 
78
- $Pagination = new WP_Statistics_Pagination( $total, $pagesPerSection, $options, false, $stylePageOff, $stylePageOn, $styleErrors, $styleSelect );
 
 
 
 
 
 
 
 
 
79
 
80
  $start = $Pagination->getEntryStart();
81
  $end = $Pagination->getEntryEnd();
82
 
83
  // Retrieve MySQL data
84
  if ( $referred && $referred != '' ) {
85
- $search_query = wp_statistics_searchword_query( $referred );
86
  } else {
87
- $search_query = wp_statistics_searchword_query( 'all' );
88
  }
89
 
90
  // Determine if we're using the old or new method of storing search engine info and build the appropriate table name.
91
  $tablename = $wpdb->prefix . 'statistics_';
92
 
93
- if ( $WP_Statistics->get_option( 'search_converted' ) ) {
94
- $tabletwo = $tablename . 'visitor';
95
  $tablename .= 'search';
96
- $result = $wpdb->get_results( "SELECT * FROM `{$tablename}` INNER JOIN `{$tabletwo}` on {$tablename}.`visitor` = {$tabletwo}.`ID` WHERE {$search_query} ORDER BY `{$tablename}`.`ID` DESC LIMIT {$start}, {$end}" );
 
 
97
  } else {
98
  $tablename .= 'visitor';
99
- $result = $wpdb->get_results( "SELECT * FROM `{$tablename}` WHERE {$search_query} ORDER BY `{$tablename}`.`ID` DESC LIMIT {$start}, {$end}" );
 
 
100
  }
101
 
102
  $ISOCountryCode = $WP_Statistics->get_country_codes();
103
 
104
- $dash_icon = wp_statistics_icons( 'dashicons-location-alt', 'map' );
105
 
106
  foreach ( $result as $items ) {
107
- if ( ! $WP_Statistics->Search_Engine_QueryString( $items->referred ) ) {
108
  continue;
109
  }
110
 
111
- if ( substr( $items->ip, 0, 6 ) == '#hash#' ) {
112
- $ip_string = __( '#hash#', 'wp-statistics' );
113
  $map_string = "";
114
  } else {
115
- $ip_string = "<a href='http://www.geoiptool.com/en/?IP={$items->ip}' target='_blank'>{$items->ip}</a>";
116
- $map_string = "<a class='show-map' href='http://www.geoiptool.com/en/?IP={$items->ip}' target='_blank' title='" . __( 'Map', 'wp-statistics' ) . "'>{$dash_icon}</a>";
 
 
 
 
117
  }
118
 
119
- if ( $WP_Statistics->get_option( 'search_converted' ) ) {
120
- $this_search_engine = $WP_Statistics->Search_Engine_Info_By_Engine( $items->engine );
 
 
121
  $words = $items->words;
122
  } else {
123
- $this_search_engine = $WP_Statistics->Search_Engine_Info( $items->referred );
124
- $words = $WP_Statistics->Search_Engine_QueryString( $items->referred );
 
 
125
  }
126
 
127
  echo "<div class='log-item'>";
128
  echo "<div class='log-referred'>" . $words . "</div>";
129
- echo "<div class='log-ip'>" . date( get_option( 'date_format' ), strtotime( $items->last_counter ) ) . " - {$ip_string}</div>";
 
 
130
  echo "<div class='clear'></div>";
131
  echo "<div class='log-url'>";
132
  echo $map_string;
133
 
134
- if ( $WP_Statistics->get_option( 'geoip' ) ) {
135
- echo "<img src='" . plugins_url( 'wp-statistics/assets/images/flags/' . $items->location . '.png' ) . "' title='{$ISOCountryCode[$items->location]}' class='log-tools'/>";
 
 
 
 
136
  }
137
 
138
- echo "<a href='?page=" . WP_STATISTICS_OVERVIEW_PAGE . "&type=last-all-search&referred={$this_search_engine['tag']}'><img src='" . plugins_url( 'wp-statistics/assets/images/' . $this_search_engine['image'] ) . "' class='log-tools' title='" . __( $this_search_engine['name'], 'wp-statistics' ) . "'/></a>";
139
-
140
- if ( array_search( strtolower( $items->agent ), array(
141
- "chrome",
142
- "firefox",
143
- "msie",
144
- "opera",
145
- "safari"
146
- ) ) !== false
 
 
 
 
 
 
 
 
 
147
  ) {
148
- $agent = "<img src='" . plugins_url( 'wp-statistics/assets/images/' ) . $items->agent . ".png' class='log-tools' title='{$items->agent}'/>";
 
 
 
149
  } else {
150
- $agent = wp_statistics_icons( 'dashicons-editor-help', 'unknown' );
151
  }
152
 
153
- echo "<a href='?page=" . WP_STATISTICS_OVERVIEW_PAGE . "&type=last-all-visitor&agent={$items->agent}'>{$agent}</a>";
 
 
154
 
155
- echo $WP_Statistics->get_referrer_link( $items->referred );
156
 
157
  echo "</div>";
158
  echo "</div>";
@@ -161,16 +210,20 @@ $total = $search_result[ $referred ];
161
 
162
  echo "</div>";
163
  ?>
164
- </div>
165
- </div>
166
 
167
- <div class="pagination-log">
168
  <?php if ( $total > 0 ) {
169
  echo $Pagination->display(); ?>
170
- <p id="result-log"><?php printf( __( 'Page %1$s of %2$s', 'wp-statistics' ), $Pagination->getCurrentPage(), $Pagination->getTotalPages() ); ?></p>
 
 
 
 
171
  <?php } ?>
172
- </div>
173
- </div>
174
- </div>
175
- </div>
176
- </div>
1
  <script type="text/javascript">
2
+ jQuery(document).ready(function () {
3
+ postboxes.add_postbox_toggles(pagenow);
4
+ });
5
  </script>
6
  <?php
7
  $search_engines = wp_statistics_searchengine_list();
8
 
9
+ $search_result['All'] = wp_statistics_searchword('all', 'total');
10
 
11
  foreach ( $search_engines as $key => $se ) {
12
+ $search_result[ $key ] = wp_statistics_searchword($key, 'total');
13
  }
14
 
15
+ if ( array_key_exists('referred', $_GET) ) {
16
  if ( $_GET['referred'] != '' ) {
17
  $referred = $_GET['referred'];
18
  } else {
25
  $total = $search_result[ $referred ];
26
  ?>
27
  <div class="wrap">
28
+ <h2><?php _e('Latest Search Words', 'wp-statistics'); ?></h2>
29
+ <ul class="subsubsub">
30
  <?php
31
+ $search_result_count = count($search_result);
32
  $i = 0;
33
  $separator = ' | ';
34
 
35
  foreach ( $search_result as $key => $value ) {
36
+ $i++;
37
 
38
  if ( $i == $search_result_count ) {
39
  $separator = '';
42
  if ( $key == 'All' ) {
43
  $tag = '';
44
  $name = 'All';
45
+ $translate = __('All', 'wp-statistics');
46
  } else {
47
  $tag = $search_engines[ $key ]['tag'];
48
  $name = $search_engines[ $key ]['name'];
49
  $translate = $search_engines[ $key ]['translated'];
50
  }
51
 
52
+ echo "<li><a href='?page=" .
53
+ WP_Statistics::$page['words'] .
54
+ "&referred={$tag}'>" .
55
+ $translate .
56
+ " <span class='count'>({$value})</span></a></li>{$separator}";
57
  }
58
  ?>
59
+ </ul>
60
+ <div class="postbox-container" id="last-log">
61
+ <div class="metabox-holder">
62
+ <div class="meta-box-sortables">
63
+ <div class="postbox">
64
+ <?php $paneltitle = __('Latest Search Word Statistics', 'wp-statistics'); ?>
65
+ <button class="handlediv" type="button" aria-expanded="true">
66
+ <span class="screen-reader-text"><?php printf(
67
+ __('Toggle panel: %s', 'wp-statistics'),
68
+ $paneltitle
69
+ ); ?></span>
70
+ <span class="toggle-indicator" aria-hidden="true"></span>
71
+ </button>
72
+ <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
73
+
74
+ <div class="inside">
75
+ <div class='log-latest'>
76
  <?php
77
  if ( $total > 0 ) {
78
  // Instantiate pagination object with appropriate arguments
83
  $styleErrors = "paginationErrors";
84
  $styleSelect = "paginationSelect";
85
 
86
+ $Pagination = new WP_Statistics_Pagination(
87
+ $total,
88
+ $pagesPerSection,
89
+ $options,
90
+ false,
91
+ $stylePageOff,
92
+ $stylePageOn,
93
+ $styleErrors,
94
+ $styleSelect
95
+ );
96
 
97
  $start = $Pagination->getEntryStart();
98
  $end = $Pagination->getEntryEnd();
99
 
100
  // Retrieve MySQL data
101
  if ( $referred && $referred != '' ) {
102
+ $search_query = wp_statistics_searchword_query($referred);
103
  } else {
104
+ $search_query = wp_statistics_searchword_query('all');
105
  }
106
 
107
  // Determine if we're using the old or new method of storing search engine info and build the appropriate table name.
108
  $tablename = $wpdb->prefix . 'statistics_';
109
 
110
+ if ( $WP_Statistics->get_option('search_converted') ) {
111
+ $tabletwo = $tablename . 'visitor';
112
  $tablename .= 'search';
113
+ $result = $wpdb->get_results(
114
+ "SELECT * FROM `{$tablename}` INNER JOIN `{$tabletwo}` on {$tablename}.`visitor` = {$tabletwo}.`ID` WHERE {$search_query} ORDER BY `{$tablename}`.`ID` DESC LIMIT {$start}, {$end}"
115
+ );
116
  } else {
117
  $tablename .= 'visitor';
118
+ $result = $wpdb->get_results(
119
+ "SELECT * FROM `{$tablename}` WHERE {$search_query} ORDER BY `{$tablename}`.`ID` DESC LIMIT {$start}, {$end}"
120
+ );
121
  }
122
 
123
  $ISOCountryCode = $WP_Statistics->get_country_codes();
124
 
125
+ $dash_icon = wp_statistics_icons('dashicons-location-alt', 'map');
126
 
127
  foreach ( $result as $items ) {
128
+ if ( ! $WP_Statistics->Search_Engine_QueryString($items->referred) ) {
129
  continue;
130
  }
131
 
132
+ if ( substr($items->ip, 0, 6) == '#hash#' ) {
133
+ $ip_string = __('#hash#', 'wp-statistics');
134
  $map_string = "";
135
  } else {
136
+ $ip_string
137
+ = "<a href='http://www.geoiptool.com/en/?IP={$items->ip}' target='_blank'>{$items->ip}</a>";
138
+ $map_string
139
+ = "<a class='show-map' href='http://www.geoiptool.com/en/?IP={$items->ip}' target='_blank' title='" .
140
+ __('Map', 'wp-statistics') .
141
+ "'>{$dash_icon}</a>";
142
  }
143
 
144
+ if ( $WP_Statistics->get_option('search_converted') ) {
145
+ $this_search_engine = $WP_Statistics->Search_Engine_Info_By_Engine(
146
+ $items->engine
147
+ );
148
  $words = $items->words;
149
  } else {
150
+ $this_search_engine = $WP_Statistics->Search_Engine_Info($items->referred);
151
+ $words = $WP_Statistics->Search_Engine_QueryString(
152
+ $items->referred
153
+ );
154
  }
155
 
156
  echo "<div class='log-item'>";
157
  echo "<div class='log-referred'>" . $words . "</div>";
158
+ echo "<div class='log-ip'>" .
159
+ date(get_option('date_format'), strtotime($items->last_counter)) .
160
+ " - {$ip_string}</div>";
161
  echo "<div class='clear'></div>";
162
  echo "<div class='log-url'>";
163
  echo $map_string;
164
 
165
+ if ( $WP_Statistics->get_option('geoip') ) {
166
+ echo "<img src='" .
167
+ plugins_url(
168
+ 'wp-statistics/assets/images/flags/' . $items->location . '.png'
169
+ ) .
170
+ "' title='{$ISOCountryCode[$items->location]}' class='log-tools'/>";
171
  }
172
 
173
+ echo "<a href='?page=" .
174
+ WP_Statistics::$page['overview'] .
175
+ "&type=last-all-search&referred={$this_search_engine['tag']}'><img src='" .
176
+ plugins_url('wp-statistics/assets/images/' . $this_search_engine['image']) .
177
+ "' class='log-tools' title='" .
178
+ __($this_search_engine['name'], 'wp-statistics') .
179
+ "'/></a>";
180
+
181
+ if ( array_search(
182
+ strtolower($items->agent),
183
+ array(
184
+ "chrome",
185
+ "firefox",
186
+ "msie",
187
+ "opera",
188
+ "safari",
189
+ )
190
+ ) !== false
191
  ) {
192
+ $agent = "<img src='" .
193
+ plugins_url('wp-statistics/assets/images/') .
194
+ $items->agent .
195
+ ".png' class='log-tools' title='{$items->agent}'/>";
196
  } else {
197
+ $agent = wp_statistics_icons('dashicons-editor-help', 'unknown');
198
  }
199
 
200
+ echo "<a href='?page=" .
201
+ WP_Statistics::$page['overview'] .
202
+ "&type=last-all-visitor&agent={$items->agent}'>{$agent}</a>";
203
 
204
+ echo $WP_Statistics->get_referrer_link($items->referred);
205
 
206
  echo "</div>";
207
  echo "</div>";
210
 
211
  echo "</div>";
212
  ?>
213
+ </div>
214
+ </div>
215
 
216
+ <div class="pagination-log">
217
  <?php if ( $total > 0 ) {
218
  echo $Pagination->display(); ?>
219
+ <p id="result-log"><?php printf(
220
+ __('Page %1$s of %2$s', 'wp-statistics'),
221
+ $Pagination->getCurrentPage(),
222
+ $Pagination->getTotalPages()
223
+ ); ?></p>
224
  <?php } ?>
225
+ </div>
226
+ </div>
227
+ </div>
228
+ </div>
229
+ </div>
includes/log/last-visitor.php CHANGED
@@ -1,7 +1,7 @@
1
  <script type="text/javascript">
2
- jQuery(document).ready(function () {
3
- postboxes.add_postbox_toggles(pagenow);
4
- });
5
  </script>
6
  <?php
7
  $ISOCountryCode = $WP_Statistics->get_country_codes();
@@ -10,35 +10,37 @@ $_var = 'agent';
10
  $_get = '%';
11
  $title = 'All';
12
 
13
- if ( array_key_exists( 'agent', $_GET ) ) {
14
  $_var = 'agent';
15
  $_get = '%' . $_GET['agent'] . '%';
16
- $title = htmlentities( $_GET['agent'], ENT_QUOTES );
17
  }
18
 
19
- if ( array_key_exists( 'ip', $_GET ) ) {
20
  $_var = 'ip';
21
  $_get = '%' . $_GET['ip'] . '%';
22
- $title = htmlentities( $_GET['ip'], ENT_QUOTES );
23
  }
24
 
25
- $_get = esc_attr($_get);
26
- $total_visitor = $wpdb->get_var( "SELECT COUNT(*) FROM `{$wpdb->prefix}statistics_visitor`" );
27
 
28
  if ( $_get != '%' ) {
29
- $total = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM `{$wpdb->prefix}statistics_visitor` WHERE `{$_var}` LIKE %s", $_get ) );
 
 
30
  } else {
31
  $total = $total_visitor;
32
  }
33
 
34
  ?>
35
  <div class="wrap">
36
- <h2><?php _e( 'Recent Visitors', 'wp-statistics' ); ?></h2>
37
- <ul class="subsubsub">
38
- <li class="all"><a <?php if ( $_get == '%' ) {
39
  echo 'class="current"';
40
- } ?>href="?page=<?php echo WP_STATISTICS_VISITORS_PAGE; ?>"><?php _e( 'All', 'wp-statistics' ); ?>
41
- <span class="count">(<?php echo $total_visitor; ?>)</span></a></li>
42
  <?php
43
  if ( isset( $_var ) ) {
44
  $spacer = " | ";
@@ -46,14 +48,14 @@ if ( $_get != '%' ) {
46
  if ( $_var == 'agent' ) {
47
  $Browsers = wp_statistics_ua_list();
48
  $i = 0;
49
- $Total = count( $Browsers );
50
 
51
  foreach ( $Browsers as $Browser ) {
52
  if ( $Browser == null ) {
53
  continue;
54
  }
55
 
56
- $i ++;
57
  if ( $title == $Browser ) {
58
  $current = 'class="current" ';
59
  } else {
@@ -62,7 +64,18 @@ if ( $_get != '%' ) {
62
  if ( $i == $Total ) {
63
  $spacer = "";
64
  }
65
- echo $spacer . "<li><a " . $current . "href='?page=" . WP_STATISTICS_VISITORS_PAGE . "&agent=" . $Browser . "'> " . __( $Browser, 'wp-statistics' ) . " <span class='count'>(" . number_format_i18n( wp_statistics_useragent( $Browser ) ) . ")</span></a></li>";
 
 
 
 
 
 
 
 
 
 
 
66
  }
67
  } else {
68
  if ( $_get != '%' ) {
@@ -70,25 +83,32 @@ if ( $_get != '%' ) {
70
  } else {
71
  $current = "";
72
  }
73
- echo $spacer . "<li><a {$current} href='?page=" . WP_STATISTICS_VISITORS_PAGE . "&{$_var}={$_get}'>{$title} <span class='count'>({$total})</span></a></li>";
 
 
 
74
  }
75
  }
76
  ?>
77
- </ul>
78
- <div class="postbox-container" id="last-log">
79
- <div class="metabox-holder">
80
- <div class="meta-box-sortables">
81
- <div class="postbox">
82
- <?php $paneltitle = __( 'Recent Visitor Statistics', 'wp-statistics' );
83
- if ( $_get != '%' ) {
84
- $paneltitle = $paneltitle . ' [' . __( 'Filtered by', 'wp-statistics' ) . ': ' . $title . ']';
85
- } ?>
86
- <button class="handlediv" type="button" aria-expanded="true">
87
- <span class="screen-reader-text"><?php printf( __( 'Toggle panel: %s', 'wp-statistics' ), $paneltitle ); ?></span>
88
- <span class="toggle-indicator" aria-hidden="true"></span>
89
- </button>
90
- <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
91
- <div class="inside">
 
 
 
 
92
  <?php
93
  // Instantiate pagination object with appropriate arguments
94
  $pagesPerSection = 10;
@@ -98,61 +118,96 @@ if ( $_get != '%' ) {
98
  $styleErrors = "paginationErrors";
99
  $styleSelect = "paginationSelect";
100
 
101
- $Pagination = new WP_Statistics_Pagination( $total, $pagesPerSection, $options, false, $stylePageOff, $stylePageOn, $styleErrors, $styleSelect );
 
 
 
 
 
 
 
 
 
102
 
103
  $start = $Pagination->getEntryStart();
104
  $end = $Pagination->getEntryEnd();
105
 
106
  // Retrieve MySQL data
107
  if ( $_get != '%' ) {
108
- $result = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM `{$wpdb->prefix}statistics_visitor` WHERE `{$_var}` LIKE %s ORDER BY `{$wpdb->prefix}statistics_visitor`.`ID` DESC LIMIT {$start}, {$end}", $_get ) );
 
 
 
 
 
109
  } else {
110
- $result = $wpdb->get_results( "SELECT * FROM `{$wpdb->prefix}statistics_visitor` ORDER BY `{$wpdb->prefix}statistics_visitor`.`ID` DESC LIMIT {$start}, {$end}" );
 
 
111
  }
112
 
113
  // Check to see if User Agent logging is enabled.
114
- $DisplayUA = $WP_Statistics->get_option( "store_ua" );
115
 
116
  echo "<div class='log-latest'>";
117
 
118
- $dash_icon = wp_statistics_icons( 'dashicons-visibility', 'visibility' );
119
 
120
  foreach ( $result as $items ) {
121
- if ( substr( $items->ip, 0, 6 ) == '#hash#' ) {
122
- $ip_string = __( '#hash#', 'wp-statistics' );
123
  $map_string = "";
124
  } else {
125
- $ip_string = "<a href='?page=" . WP_STATISTICS_VISITORS_PAGE . "&ip={$items->ip}'>{$dash_icon}{$items->ip}</a>";
126
- $map_string = "<a class='show-map' href='http://www.geoiptool.com/en/?IP={$items->ip}' target='_blank' title='" . __( 'Map', 'wp-statistics' ) . "'>" . wp_statistics_icons( 'dashicons-location-alt', 'map' ) . "</a>";
 
 
 
 
 
 
 
127
  }
128
 
129
  echo "<div class='log-item'>";
130
  echo "<div class='log-referred'>{$ip_string}</div>";
131
- echo "<div class='log-ip'>" . date( get_option( 'date_format' ), strtotime( $items->last_counter ) ) . "</div>";
 
 
132
  echo "<div class='clear'></div>";
133
  echo "<div class='log-url'>";
134
  echo $map_string;
135
 
136
- if ( $WP_Statistics->get_option( 'geoip' ) ) {
137
- echo "<img src='" . plugins_url( 'wp-statistics/assets/images/flags/' . $items->location . '.png' ) . "' title='{$ISOCountryCode[$items->location]}' class='log-tools'/>";
 
 
138
  }
139
 
140
- if ( array_search( strtolower( $items->agent ), array(
141
- "chrome",
142
- "firefox",
143
- "msie",
144
- "opera",
145
- "safari"
146
- ) ) !== false
 
 
 
147
  ) {
148
- $agent = "<img src='" . plugins_url( 'wp-statistics/assets/images/' ) . $items->agent . ".png' class='log-tools' title='{$items->agent}'/>";
 
 
 
149
  } else {
150
- $agent = wp_statistics_icons( 'dashicons-editor-help', 'unknown' );
151
  }
152
 
153
- echo "<a href='?page=" . WP_STATISTICS_VISITORS_PAGE . "&agent={$items->agent}'>{$agent}</a>";
 
 
154
 
155
- echo $WP_Statistics->get_referrer_link( $items->referred );
156
 
157
  echo "</div>";
158
  echo "</div>";
@@ -160,14 +215,18 @@ if ( $_get != '%' ) {
160
 
161
  echo "</div>";
162
  ?>
163
- </div>
164
- </div>
165
 
166
- <div class="pagination-log">
167
  <?php echo $Pagination->display(); ?>
168
- <p id="result-log"><?php printf( __( 'Page %1$s of %2$s', 'wp-statistics' ), $Pagination->getCurrentPage(), $Pagination->getTotalPages() ); ?></p>
169
- </div>
170
- </div>
171
- </div>
172
- </div>
 
 
 
 
173
  </div>
1
  <script type="text/javascript">
2
+ jQuery(document).ready(function () {
3
+ postboxes.add_postbox_toggles(pagenow);
4
+ });
5
  </script>
6
  <?php
7
  $ISOCountryCode = $WP_Statistics->get_country_codes();
10
  $_get = '%';
11
  $title = 'All';
12
 
13
+ if ( array_key_exists('agent', $_GET) ) {
14
  $_var = 'agent';
15
  $_get = '%' . $_GET['agent'] . '%';
16
+ $title = htmlentities($_GET['agent'], ENT_QUOTES);
17
  }
18
 
19
+ if ( array_key_exists('ip', $_GET) ) {
20
  $_var = 'ip';
21
  $_get = '%' . $_GET['ip'] . '%';
22
+ $title = htmlentities($_GET['ip'], ENT_QUOTES);
23
  }
24
 
25
+ $_get = esc_attr($_get);
26
+ $total_visitor = $wpdb->get_var("SELECT COUNT(*) FROM `{$wpdb->prefix}statistics_visitor`");
27
 
28
  if ( $_get != '%' ) {
29
+ $total = $wpdb->get_var(
30
+ $wpdb->prepare("SELECT COUNT(*) FROM `{$wpdb->prefix}statistics_visitor` WHERE `{$_var}` LIKE %s", $_get)
31
+ );
32
  } else {
33
  $total = $total_visitor;
34
  }
35
 
36
  ?>
37
  <div class="wrap">
38
+ <h2><?php _e('Recent Visitors', 'wp-statistics'); ?></h2>
39
+ <ul class="subsubsub">
40
+ <li class="all"><a <?php if ( $_get == '%' ) {
41
  echo 'class="current"';
42
+ } ?>href="?page=<?php echo WP_Statistics::$page['visitors']; ?>"><?php _e('All', 'wp-statistics'); ?>
43
+ <span class="count">(<?php echo $total_visitor; ?>)</span></a></li>
44
  <?php
45
  if ( isset( $_var ) ) {
46
  $spacer = " | ";
48
  if ( $_var == 'agent' ) {
49
  $Browsers = wp_statistics_ua_list();
50
  $i = 0;
51
+ $Total = count($Browsers);
52
 
53
  foreach ( $Browsers as $Browser ) {
54
  if ( $Browser == null ) {
55
  continue;
56
  }
57
 
58
+ $i++;
59
  if ( $title == $Browser ) {
60
  $current = 'class="current" ';
61
  } else {
64
  if ( $i == $Total ) {
65
  $spacer = "";
66
  }
67
+ echo $spacer .
68
+ "<li><a " .
69
+ $current .
70
+ "href='?page=" .
71
+ WP_Statistics::$page['visitors'] .
72
+ "&agent=" .
73
+ $Browser .
74
+ "'> " .
75
+ __($Browser, 'wp-statistics') .
76
+ " <span class='count'>(" .
77
+ number_format_i18n(wp_statistics_useragent($Browser)) .
78
+ ")</span></a></li>";
79
  }
80
  } else {
81
  if ( $_get != '%' ) {
83
  } else {
84
  $current = "";
85
  }
86
+ echo $spacer .
87
+ "<li><a {$current} href='?page=" .
88
+ WP_Statistics::$page['visitors'] .
89
+ "&{$_var}={$_get}'>{$title} <span class='count'>({$total})</span></a></li>";
90
  }
91
  }
92
  ?>
93
+ </ul>
94
+ <div class="postbox-container" id="last-log">
95
+ <div class="metabox-holder">
96
+ <div class="meta-box-sortables">
97
+ <div class="postbox">
98
+ <?php $paneltitle = __('Recent Visitor Statistics', 'wp-statistics');
99
+ if ( $_get != '%' ) {
100
+ $paneltitle = $paneltitle . ' [' . __('Filtered by', 'wp-statistics') . ': ' . $title . ']';
101
+ } ?>
102
+ <button class="handlediv" type="button" aria-expanded="true">
103
+ <span class="screen-reader-text"><?php printf(
104
+ __('Toggle panel: %s', 'wp-statistics'),
105
+ $paneltitle
106
+ ); ?></span>
107
+ <span class="toggle-indicator" aria-hidden="true"></span>
108
+ </button>
109
+ <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
110
+
111
+ <div class="inside">
112
  <?php
113
  // Instantiate pagination object with appropriate arguments
114
  $pagesPerSection = 10;
118
  $styleErrors = "paginationErrors";
119
  $styleSelect = "paginationSelect";
120
 
121
+ $Pagination = new WP_Statistics_Pagination(
122
+ $total,
123
+ $pagesPerSection,
124
+ $options,
125
+ false,
126
+ $stylePageOff,
127
+ $stylePageOn,
128
+ $styleErrors,
129
+ $styleSelect
130
+ );
131
 
132
  $start = $Pagination->getEntryStart();
133
  $end = $Pagination->getEntryEnd();
134
 
135
  // Retrieve MySQL data
136
  if ( $_get != '%' ) {
137
+ $result = $wpdb->get_results(
138
+ $wpdb->prepare(
139
+ "SELECT * FROM `{$wpdb->prefix}statistics_visitor` WHERE `{$_var}` LIKE %s ORDER BY `{$wpdb->prefix}statistics_visitor`.`ID` DESC LIMIT {$start}, {$end}",
140
+ $_get
141
+ )
142
+ );
143
  } else {
144
+ $result = $wpdb->get_results(
145
+ "SELECT * FROM `{$wpdb->prefix}statistics_visitor` ORDER BY `{$wpdb->prefix}statistics_visitor`.`ID` DESC LIMIT {$start}, {$end}"
146
+ );
147
  }
148
 
149
  // Check to see if User Agent logging is enabled.
150
+ $DisplayUA = $WP_Statistics->get_option("store_ua");
151
 
152
  echo "<div class='log-latest'>";
153
 
154
+ $dash_icon = wp_statistics_icons('dashicons-visibility', 'visibility');
155
 
156
  foreach ( $result as $items ) {
157
+ if ( substr($items->ip, 0, 6) == '#hash#' ) {
158
+ $ip_string = __('#hash#', 'wp-statistics');
159
  $map_string = "";
160
  } else {
161
+ $ip_string = "<a href='?page=" .
162
+ WP_Statistics::$page['visitors'] .
163
+ "&ip={$items->ip}'>{$dash_icon}{$items->ip}</a>";
164
+ $map_string
165
+ = "<a class='show-map' href='http://www.geoiptool.com/en/?IP={$items->ip}' target='_blank' title='" .
166
+ __('Map', 'wp-statistics') .
167
+ "'>" .
168
+ wp_statistics_icons('dashicons-location-alt', 'map') .
169
+ "</a>";
170
  }
171
 
172
  echo "<div class='log-item'>";
173
  echo "<div class='log-referred'>{$ip_string}</div>";
174
+ echo "<div class='log-ip'>" .
175
+ date(get_option('date_format'), strtotime($items->last_counter)) .
176
+ "</div>";
177
  echo "<div class='clear'></div>";
178
  echo "<div class='log-url'>";
179
  echo $map_string;
180
 
181
+ if ( $WP_Statistics->get_option('geoip') ) {
182
+ echo "<img src='" .
183
+ plugins_url('wp-statistics/assets/images/flags/' . $items->location . '.png') .
184
+ "' title='{$ISOCountryCode[$items->location]}' class='log-tools'/>";
185
  }
186
 
187
+ if ( array_search(
188
+ strtolower($items->agent),
189
+ array(
190
+ "chrome",
191
+ "firefox",
192
+ "msie",
193
+ "opera",
194
+ "safari",
195
+ )
196
+ ) !== false
197
  ) {
198
+ $agent = "<img src='" .
199
+ plugins_url('wp-statistics/assets/images/') .
200
+ $items->agent .
201
+ ".png' class='log-tools' title='{$items->agent}'/>";
202
  } else {
203
+ $agent = wp_statistics_icons('dashicons-editor-help', 'unknown');
204
  }
205
 
206
+ echo "<a href='?page=" .
207
+ WP_Statistics::$page['visitors'] .
208
+ "&agent={$items->agent}'>{$agent}</a>";
209
 
210
+ echo $WP_Statistics->get_referrer_link($items->referred);
211
 
212
  echo "</div>";
213
  echo "</div>";
215
 
216
  echo "</div>";
217
  ?>
218
+ </div>
219
+ </div>
220
 
221
+ <div class="pagination-log">
222
  <?php echo $Pagination->display(); ?>
223
+ <p id="result-log"><?php printf(
224
+ __('Page %1$s of %2$s', 'wp-statistics'),
225
+ $Pagination->getCurrentPage(),
226
+ $Pagination->getTotalPages()
227
+ ); ?></p>
228
+ </div>
229
+ </div>
230
+ </div>
231
+ </div>
232
  </div>
includes/log/log.php CHANGED
@@ -1,123 +1,169 @@
1
  <?php
2
- $loading_img = '<div style="width: 100%; text-align: center;"><img src=" ' . plugins_url( 'wp-statistics/assets/images/' ) . 'ajax-loading.gif" alt="' . __( 'Reloading...', 'wp-statistics' ) . '"></div>';
 
 
 
 
3
 
4
  $nag_html = '';
5
- if ( ! $WP_Statistics->get_option( 'disable_donation_nag', false ) ) {
6
- $nag_html = '<div id="wps_nag" class="update-nag" style="width: 90%;"><div id="donate-text"><p>' . __( 'Have you thought about donating to WP Statistics?', 'wp-statistics' ) . ' <a href="http://wp-statistics.com/donate/" target="_blank">' . __( 'Donate Now!', 'wp-statistics' ) . '</a></p></div><div id="donate-button"><a class="button-primary" id="wps_close_nag">' . __( 'Close', 'wp-statistics' ) . '</a></div></div>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  }
8
 
9
  // WP Statistics 10.0 had a bug which could corrupt the metabox display if the user re-ordered the widgets. Check to see if the meta data is corrupt and if so delete it.
10
- $widget_order = get_user_meta( $WP_Statistics->user_id, 'meta-box-order_toplevel_page_wps_overview_page', true );
11
 
12
- if ( is_array( $widget_order ) && count( $widget_order ) > 2 ) {
13
- delete_user_meta( $WP_Statistics->user_id, 'meta-box-order_toplevel_page_wps_overview_page' );
14
  }
15
 
16
  // Add the about box here as metaboxes added on the actual page load cannot be closed.
17
- add_meta_box( 'wps_about_postbox', sprintf( __( 'About WP Statistics Version %s', 'wp-statistics' ), WP_STATISTICS_VERSION ), 'wp_statistics_generate_overview_postbox_contents', $WP_Statistics->menu_slugs['overview'], 'side', null, array( 'widget' => 'about' ) );
 
 
 
 
 
 
 
 
18
 
19
  function wp_statistics_generate_overview_postbox_contents( $post, $args ) {
20
- $loading_img = '<div style="width: 100%; text-align: center;"><img src=" ' . plugins_url( 'wp-statistics/assets/images/' ) . 'ajax-loading.gif" alt="' . __( 'Loading...', 'wp-statistics' ) . '"></div>';
 
 
 
 
21
  $widget = $args['args']['widget'];
22
- $container_id = str_replace( '.', '_', $widget . '_postbox' );
23
 
24
  echo '<div id="' . $container_id . '">' . $loading_img . '</div>';
25
- wp_statistics_generate_widget_load_javascript( $widget, $container_id );
26
  }
27
 
28
  ?>
29
  <div class="wrap">
30
  <?php echo $nag_html; ?>
31
- <h2><?php echo get_admin_page_title(); ?></h2>
32
- <?php wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false ); ?>
33
- <?php wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false ); ?>
34
-
35
- <div class="metabox-holder" id="overview-widgets">
36
- <div class="postbox-container" id="wps-postbox-container-1">
37
- <?php do_meta_boxes( $WP_Statistics->menu_slugs['overview'], 'side', '' ); ?>
38
- </div>
39
-
40
- <div class="postbox-container" id="wps-postbox-container-2">
41
- <?php do_meta_boxes( $WP_Statistics->menu_slugs['overview'], 'normal', '' ); ?>
42
- </div>
43
- </div>
44
  </div>
45
  <?php
46
- $new_buttons = '</button><button class="handlediv button-link wps-refresh" type="button" id="{{refreshid}}">' . wp_statistics_icons( 'dashicons-update' ) . '<span class="screen-reader-text">' . __( 'Reload', 'wp-statistics' ) . '</span></button><button class="handlediv button-link wps-more" type="button" id="{{moreid}}">' . wp_statistics_icons( 'dashicons-migrate' ) . '<span class="screen-reader-text">' . __( 'More Details', 'wp-statistics' ) . '</span></button>';
47
- $new_button = '</button><button class="handlediv button-link wps-refresh" type="button" id="{{refreshid}}">' . wp_statistics_icons( 'dashicons-update' ) . '<span class="screen-reader-text">' . __( 'Reload', 'wp-statistics' ) . '</span></button>';
 
 
 
 
 
 
 
 
 
 
 
 
48
 
49
  $admin_url = get_admin_url() . "admin.php?page=";
50
 
51
  $page_urls = array();
52
 
53
- $page_urls['wps_browsers_more_button'] = $admin_url . WP_STATISTICS_BROWSERS_PAGE;
54
- $page_urls['wps_countries_more_button'] = $admin_url . WP_STATISTICS_COUNTRIES_PAGE;
55
- $page_urls['wps_exclusions_more_button'] = $admin_url . WP_STATISTICS_EXCLUSIONS_PAGE;
56
- $page_urls['wps_hits_more_button'] = $admin_url . WP_STATISTICS_HITS_PAGE;
57
- $page_urls['wps_online_more_button'] = $admin_url . WP_STATISTICS_ONLINE_PAGE;
58
- $page_urls['wps_pages_more_button'] = $admin_url . WP_STATISTICS_PAGES_PAGE;
59
- $page_urls['wps_referring_more_button'] = $admin_url . WP_STATISTICS_REFERRERS_PAGE;
60
- $page_urls['wps_search_more_button'] = $admin_url . WP_STATISTICS_SEARCHES_PAGE;
61
- $page_urls['wps_words_more_button'] = $admin_url . WP_STATISTICS_WORDS_PAGE;
62
- $page_urls['wps_top_visitors_more_button'] = $admin_url . WP_STATISTICS_TOP_VISITORS_PAGE;
63
- $page_urls['wps_recent_more_button'] = $admin_url . WP_STATISTICS_VISITORS_PAGE;
 
64
 
65
  ?>
66
  <script type="text/javascript">
67
- var wp_statistics_destinations = <?php echo json_encode( $page_urls ); ?>;
68
- var wp_statistics_loading_image = '<?php echo $loading_img; ?>'
69
-
70
- jQuery(document).ready(function () {
71
-
72
- // Add the "more" and "refresh" buttons.
73
- jQuery('.postbox').each(function () {
74
- var temp = jQuery(this);
75
- var temp_id = temp.attr('id');
76
- var temp_html = temp.html();
77
- if (temp_id == 'wps_summary_postbox' || temp_id == 'wps_map_postbox' || temp_id == 'wps_about_postbox') {
78
- if (temp_id != 'wps_about_postbox') {
79
- new_text = '<?php echo $new_button;?>';
80
- new_text = new_text.replace('{{refreshid}}', temp_id.replace('_postbox', '_refresh_button'));
81
-
82
- temp_html = temp_html.replace('</button>', new_text);
83
- }
84
- } else {
85
- new_text = '<?php echo $new_buttons;?>';
86
- new_text = new_text.replace('{{refreshid}}', temp_id.replace('_postbox', '_refresh_button'));
87
- new_text = new_text.replace('{{moreid}}', temp_id.replace('_postbox', '_more_button'));
88
-
89
- temp_html = temp_html.replace('</button>', new_text);
90
- }
91
-
92
- temp.html(temp_html);
93
- });
94
-
95
- // close postboxes that should be closed
96
- jQuery('.if-js-closed').removeClass('if-js-closed').addClass('closed');
97
-
98
- // postboxes setup
99
- postboxes.add_postbox_toggles('<?php echo $WP_Statistics->menu_slugs['overview']; ?>');
100
-
101
- jQuery('.wps-refresh').unbind('click').on('click', wp_statistics_refresh_widget);
102
- jQuery('.wps-more').unbind('click').on('click', wp_statistics_goto_more);
103
-
104
- jQuery('.hide-postbox-tog').on('click', wp_statistics_refresh_on_toggle_widget);
105
-
106
- jQuery('#wps_close_nag').click(function () {
107
- var data = {
108
- 'action': 'wp_statistics_close_donation_nag',
109
- 'query': '',
110
- };
111
-
112
- jQuery.ajax({
113
- url: ajaxurl,
114
- type: 'get',
115
- data: data,
116
- datatype: 'json',
117
- });
118
-
119
- jQuery('#wps_nag').hide();
120
- });
121
-
122
- });
123
  </script>
1
  <?php
2
+ $loading_img = '<div style="width: 100%; text-align: center;"><img src=" ' .
3
+ plugins_url('wp-statistics/assets/images/') .
4
+ 'ajax-loading.gif" alt="' .
5
+ __('Reloading...', 'wp-statistics') .
6
+ '"></div>';
7
 
8
  $nag_html = '';
9
+ if ( ! $WP_Statistics->get_option('geoip') ) {
10
+ $nag_html .= sprintf(
11
+ __(
12
+ '<div class="update-nag" style="%s">GeoIP collection is not enabled. Please go to <a href="%s">setting page</a> to enable GeoIP for getting more information and location (country) from the visitor.</div>',
13
+ 'wp-statistics'
14
+ ),
15
+ 'width: 90%;',
16
+ admin_url('admin.php?page=wps_settings_page&tab=externals-settings')
17
+ );
18
+ }
19
+
20
+ if ( ! $WP_Statistics->get_option('disable_donation_nag', false) ) {
21
+ $nag_html .= '<div id="wps_nag" class="update-nag" style="width: 90%;"><div id="donate-text">' .
22
+ __('Have you thought about donating to WP Statistics?', 'wp-statistics') .
23
+ ' <a href="http://wp-statistics.com/donate/" target="_blank">' .
24
+ __('Donate Now!', 'wp-statistics') .
25
+ '</a></div><div id="donate-button"><a class="button-primary" id="wps_close_nag">' .
26
+ __('Close', 'wp-statistics') .
27
+ '</a></div></div>';
28
  }
29
 
30
  // WP Statistics 10.0 had a bug which could corrupt the metabox display if the user re-ordered the widgets. Check to see if the meta data is corrupt and if so delete it.
31
+ $widget_order = get_user_meta($WP_Statistics->user_id, 'meta-box-order_toplevel_page_wps_overview_page', true);
32
 
33
+ if ( is_array($widget_order) && count($widget_order) > 2 ) {
34
+ delete_user_meta($WP_Statistics->user_id, 'meta-box-order_toplevel_page_wps_overview_page');
35
  }
36
 
37
  // Add the about box here as metaboxes added on the actual page load cannot be closed.
38
+ add_meta_box(
39
+ 'wps_about_postbox',
40
+ sprintf(__('About WP Statistics Version %s', 'wp-statistics'), WP_Statistics::$reg['version']),
41
+ 'wp_statistics_generate_overview_postbox_contents',
42
+ $WP_Statistics->menu_slugs['overview'],
43
+ 'side',
44
+ null,
45
+ array( 'widget' => 'about' )
46
+ );
47
 
48
  function wp_statistics_generate_overview_postbox_contents( $post, $args ) {
49
+ $loading_img = '<div style="width: 100%; text-align: center;"><img src=" ' .
50
+ plugins_url('wp-statistics/assets/images/') .
51
+ 'ajax-loading.gif" alt="' .
52
+ __('Loading...', 'wp-statistics') .
53
+ '"></div>';
54
  $widget = $args['args']['widget'];
55
+ $container_id = str_replace('.', '_', $widget . '_postbox');
56
 
57
  echo '<div id="' . $container_id . '">' . $loading_img . '</div>';
58
+ wp_statistics_generate_widget_load_javascript($widget, $container_id);
59
  }
60
 
61
  ?>
62
  <div class="wrap">
63
  <?php echo $nag_html; ?>
64
+ <h2><?php echo get_admin_page_title(); ?></h2>
65
+ <?php wp_nonce_field('closedpostboxes', 'closedpostboxesnonce', false); ?>
66
+ <?php wp_nonce_field('meta-box-order', 'meta-box-order-nonce', false); ?>
67
+
68
+ <div class="metabox-holder" id="overview-widgets">
69
+ <div class="postbox-container" id="wps-postbox-container-1">
70
+ <?php do_meta_boxes($WP_Statistics->menu_slugs['overview'], 'side', ''); ?>
71
+ </div>
72
+
73
+ <div class="postbox-container" id="wps-postbox-container-2">
74
+ <?php do_meta_boxes($WP_Statistics->menu_slugs['overview'], 'normal', ''); ?>
75
+ </div>
76
+ </div>
77
  </div>
78
  <?php
79
+ $new_buttons = '</button><button class="handlediv button-link wps-refresh" type="button" id="{{refreshid}}">' .
80
+ wp_statistics_icons('dashicons-update') .
81
+ '<span class="screen-reader-text">' .
82
+ __('Reload', 'wp-statistics') .
83
+ '</span></button><button class="handlediv button-link wps-more" type="button" id="{{moreid}}">' .
84
+ wp_statistics_icons('dashicons-migrate') .
85
+ '<span class="screen-reader-text">' .
86
+ __('More Details', 'wp-statistics') .
87
+ '</span></button>';
88
+ $new_button = '</button><button class="handlediv button-link wps-refresh" type="button" id="{{refreshid}}">' .
89
+ wp_statistics_icons('dashicons-update') .
90
+ '<span class="screen-reader-text">' .
91
+ __('Reload', 'wp-statistics') .
92
+ '</span></button>';
93
 
94
  $admin_url = get_admin_url() . "admin.php?page=";
95
 
96
  $page_urls = array();
97
 
98
+ $page_urls['wps_browsers_more_button'] = $admin_url . WP_Statistics::$page['browser'];
99
+ $page_urls['wps_countries_more_button'] = $admin_url . WP_Statistics::$page['countries'];
100
+ $page_urls['wps_exclusions_more_button'] = $admin_url . WP_Statistics::$page['exclusions'];
101
+ $page_urls['wps_hits_more_button'] = $admin_url . WP_Statistics::$page['hits'];
102
+ $page_urls['wps_online_more_button'] = $admin_url . WP_Statistics::$page['online'];
103
+ $page_urls['wps_pages_more_button'] = $admin_url . WP_Statistics::$page['pages'];
104
+ $page_urls['wps_referring_more_button'] = $admin_url . WP_Statistics::$page['referrers'];
105
+ $page_urls['wps_searched_phrases_more_button'] = $admin_url . WP_Statistics::$page['searched-phrases'];
106
+ $page_urls['wps_search_more_button'] = $admin_url . WP_Statistics::$page['searches'];
107
+ $page_urls['wps_words_more_button'] = $admin_url . WP_Statistics::$page['words'];
108
+ $page_urls['wps_top_visitors_more_button'] = $admin_url . WP_Statistics::$page['top-visitors'];
109
+ $page_urls['wps_recent_more_button'] = $admin_url . WP_Statistics::$page['visitors'];
110
 
111
  ?>
112
  <script type="text/javascript">
113
+ var wp_statistics_destinations = <?php echo json_encode( $page_urls ); ?>;
114
+ var wp_statistics_loading_image = '<?php echo $loading_img; ?>'
115
+
116
+ jQuery(document).ready(function () {
117
+
118
+ // Add the "more" and "refresh" buttons.
119
+ jQuery('.postbox').each(function () {
120
+ var temp = jQuery(this);
121
+ var temp_id = temp.attr('id');
122
+ var temp_html = temp.html();
123
+ if (temp_id == 'wps_summary_postbox' || temp_id == 'wps_map_postbox' || temp_id == 'wps_about_postbox') {
124
+ if (temp_id != 'wps_about_postbox') {
125
+ new_text = '<?php echo $new_button;?>';
126
+ new_text = new_text.replace('{{refreshid}}', temp_id.replace('_postbox', '_refresh_button'));
127
+
128
+ temp_html = temp_html.replace('</button>', new_text);
129
+ }
130
+ } else {
131
+ new_text = '<?php echo $new_buttons;?>';
132
+ new_text = new_text.replace('{{refreshid}}', temp_id.replace('_postbox', '_refresh_button'));
133
+ new_text = new_text.replace('{{moreid}}', temp_id.replace('_postbox', '_more_button'));
134
+
135
+ temp_html = temp_html.replace('</button>', new_text);
136
+ }
137
+
138
+ temp.html(temp_html);
139
+ });
140
+
141
+ // close postboxes that should be closed
142
+ jQuery('.if-js-closed').removeClass('if-js-closed').addClass('closed');
143
+
144
+ // postboxes setup
145
+ postboxes.add_postbox_toggles('<?php echo $WP_Statistics->menu_slugs['overview']; ?>');
146
+
147
+ jQuery('.wps-refresh').unbind('click').on('click', wp_statistics_refresh_widget);
148
+ jQuery('.wps-more').unbind('click').on('click', wp_statistics_goto_more);
149
+
150
+ jQuery('.hide-postbox-tog').on('click', wp_statistics_refresh_on_toggle_widget);
151
+
152
+ jQuery('#wps_close_nag').click(function () {
153
+ var data = {
154
+ 'action': 'wp_statistics_close_donation_nag',
155
+ 'query': '',
156
+ };
157
+
158
+ jQuery.ajax({
159
+ url: ajaxurl,
160
+ type: 'get',
161
+ data: data,
162
+ datatype: 'json',
163
+ });
164
+
165
+ jQuery('#wps_nag').hide();
166
+ });
167
+
168
+ });
169
  </script>
includes/log/online.php CHANGED
@@ -1,30 +1,35 @@
1
  <script type="text/javascript">
2
- jQuery(document).ready(function () {
3
- postboxes.add_postbox_toggles(pagenow);
4
- });
5
  </script>
6
  <?php
7
 
8
  ?>
9
  <div class="wrap">
10
- <h2><?php _e( 'Online Users', 'wp-statistics' ); ?></h2>
11
- <div class="postbox-container" id="last-log">
12
- <div class="metabox-holder">
13
- <div class="meta-box-sortables">
14
-
15
- <div class="postbox">
16
- <?php $paneltitle = __( 'Online Users', 'wp-statistics' ); ?>
17
- <button class="handlediv" type="button" aria-expanded="true">
18
- <span class="screen-reader-text"><?php printf( __( 'Toggle panel: %s', 'wp-statistics' ), $paneltitle ); ?></span>
19
- <span class="toggle-indicator" aria-hidden="true"></span>
20
- </button>
21
- <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
22
- <div class="inside">
 
 
 
 
 
23
  <?php
24
  $ISOCountryCode = $WP_Statistics->get_country_codes();
25
 
26
- $result = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}statistics_useronline;" );
27
- $total = count( $result );
28
 
29
  if ( $total > 0 ) {
30
  // Instantiate pagination object with appropriate arguments
@@ -35,7 +40,16 @@
35
  $styleErrors = "paginationErrors";
36
  $styleSelect = "paginationSelect";
37
 
38
- $Pagination = new WP_Statistics_Pagination( $total, $pagesPerSection, $options, false, $stylePageOff, $stylePageOn, $styleErrors, $styleSelect );
 
 
 
 
 
 
 
 
 
39
 
40
  $start = $Pagination->getEntryStart();
41
  $end = $Pagination->getEntryEnd();
@@ -43,55 +57,74 @@
43
  echo "<div class='log-latest'>";
44
  $count = 0;
45
 
46
- $dash_icon = wp_statistics_icons( 'dashicons-visibility', 'visibility' );
47
 
48
  foreach ( $result as $items ) {
49
- $count ++;
50
 
51
  if ( $count >= $start ) {
52
- if ( substr( $items->ip, 0, 6 ) == '#hash#' ) {
53
- $ip_string = __( '#hash#', 'wp-statistics' );
54
  $map_string = "";
55
  } else {
56
- $ip_string = "<a href='?page=" . WP_STATISTICS_OVERVIEW_PAGE . "&type=last-all-visitor&ip={$items->ip}'>{$dash_icon}{$items->ip}</a>";
57
- $map_string = "<a class='show-map' href='http://www.geoiptool.com/en/?IP={$items->ip}' target='_blank' title='" . __( 'Map', 'wp-statistics' ) . "'>" . wp_statistics_icons( 'dashicons-location-alt', 'map' ) . "</a>";
 
 
 
 
 
 
 
58
  }
59
 
60
  echo "<div class='log-item'>";
61
  echo "<div class='log-url'>";
62
  echo $map_string;
63
 
64
- if ( $WP_Statistics->get_option( 'geoip' ) ) {
65
- echo "<img src='" . plugins_url( 'wp-statistics/assets/images/flags/' . $items->location . '.png' ) . "' title='{$ISOCountryCode[$items->location]}' class='log-tools'/>";
 
 
 
 
66
  }
67
 
68
- if ( array_search( strtolower( $items->agent ), array(
69
- "chrome",
70
- "firefox",
71
- "msie",
72
- "opera",
73
- "safari"
74
- ) ) !== false
 
 
 
75
  ) {
76
- $agent = "<img src='" . plugins_url( 'wp-statistics/assets/images/' ) . $items->agent . ".png' class='log-tools' title='{$items->agent}'/>";
 
 
 
77
  } else {
78
- $agent = wp_statistics_icons( 'dashicons-editor-help', 'unknown' );
79
  }
80
 
81
- echo "<a href='?page=" . WP_STATISTICS_OVERVIEW_PAGE . "&type=last-all-visitor&agent={$items->agent}'>{$agent}</a> {$items->ip}";
 
 
82
  echo "<br>";
83
 
84
  $timediff = ( $items->timestamp - $items->created );
85
 
86
  if ( $timediff > 3600 ) {
87
- $onlinefor = date( "H:i:s", ( $items->timestamp - $items->created ) );
88
  } else if ( $timediff > 60 ) {
89
- $onlinefor = "00:" . date( "i:s", ( $items->timestamp - $items->created ) );
90
  } else {
91
- $onlinefor = "00:00:" . date( "s", ( $items->timestamp - $items->created ) );
92
  }
93
 
94
- echo sprintf( __( 'Online for %s (HH:MM:SS)', 'wp-statistics' ), $onlinefor );
95
 
96
  echo "</div>";
97
  echo "</div>";
@@ -105,19 +138,25 @@
105
 
106
  echo "</div>";
107
  } else {
108
- echo "<div class='wps-center'>" . __( 'Currently there are no users online in the site.', 'wp-statistics' ) . "</div>";
 
 
109
  }
110
  ?>
111
- </div>
112
- </div>
113
 
114
  <?php if ( $total > 0 ) { ?>
115
- <div class="pagination-log">
116
  <?php echo $Pagination->display(); ?>
117
- <p id="result-log"><?php printf( __( 'Page %1$s of %2$s', 'wp-statistics' ), $Pagination->getCurrentPage(), $Pagination->getTotalPages() ); ?></p>
118
- </div>
 
 
 
 
119
  <?php } ?>
120
- </div>
121
- </div>
122
- </div>
123
  </div>
1
  <script type="text/javascript">
2
+ jQuery(document).ready(function () {
3
+ postboxes.add_postbox_toggles(pagenow);
4
+ });
5
  </script>
6
  <?php
7
 
8
  ?>
9
  <div class="wrap">
10
+ <h2><?php _e('Online Users', 'wp-statistics'); ?></h2>
11
+
12
+ <div class="postbox-container" id="last-log">
13
+ <div class="metabox-holder">
14
+ <div class="meta-box-sortables">
15
+
16
+ <div class="postbox">
17
+ <?php $paneltitle = __('Online Users', 'wp-statistics'); ?>
18
+ <button class="handlediv" type="button" aria-expanded="true">
19
+ <span class="screen-reader-text"><?php printf(
20
+ __('Toggle panel: %s', 'wp-statistics'),
21
+ $paneltitle
22
+ ); ?></span>
23
+ <span class="toggle-indicator" aria-hidden="true"></span>
24
+ </button>
25
+ <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
26
+
27
+ <div class="inside">
28
  <?php
29
  $ISOCountryCode = $WP_Statistics->get_country_codes();
30
 
31
+ $result = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}statistics_useronline;");
32
+ $total = count($result);
33
 
34
  if ( $total > 0 ) {
35
  // Instantiate pagination object with appropriate arguments
40
  $styleErrors = "paginationErrors";
41
  $styleSelect = "paginationSelect";
42
 
43
+ $Pagination = new WP_Statistics_Pagination(
44
+ $total,
45
+ $pagesPerSection,
46
+ $options,
47
+ false,
48
+ $stylePageOff,
49
+ $stylePageOn,
50
+ $styleErrors,
51
+ $styleSelect
52
+ );
53
 
54
  $start = $Pagination->getEntryStart();
55
  $end = $Pagination->getEntryEnd();
57
  echo "<div class='log-latest'>";
58
  $count = 0;
59
 
60
+ $dash_icon = wp_statistics_icons('dashicons-visibility', 'visibility');
61
 
62
  foreach ( $result as $items ) {
63
+ $count++;
64
 
65
  if ( $count >= $start ) {
66
+ if ( substr($items->ip, 0, 6) == '#hash#' ) {
67
+ $ip_string = __('#hash#', 'wp-statistics');
68
  $map_string = "";
69
  } else {
70
+ $ip_string = "<a href='?page=" .
71
+ WP_Statistics::$page['overview'] .
72
+ "&type=last-all-visitor&ip={$items->ip}'>{$dash_icon}{$items->ip}</a>";
73
+ $map_string
74
+ = "<a class='show-map' href='http://www.geoiptool.com/en/?IP={$items->ip}' target='_blank' title='" .
75
+ __('Map', 'wp-statistics') .
76
+ "'>" .
77
+ wp_statistics_icons('dashicons-location-alt', 'map') .
78
+ "</a>";
79
  }
80
 
81
  echo "<div class='log-item'>";
82
  echo "<div class='log-url'>";
83
  echo $map_string;
84
 
85
+ if ( $WP_Statistics->get_option('geoip') ) {
86
+ echo "<img src='" .
87
+ plugins_url(
88
+ 'wp-statistics/assets/images/flags/' . $items->location . '.png'
89
+ ) .
90
+ "' title='{$ISOCountryCode[$items->location]}' class='log-tools'/>";
91
  }
92
 
93
+ if ( array_search(
94
+ strtolower($items->agent),
95
+ array(
96
+ "chrome",
97
+ "firefox",
98
+ "msie",
99
+ "opera",
100
+ "safari",
101
+ )
102
+ ) !== false
103
  ) {
104
+ $agent = "<img src='" .
105
+ plugins_url('wp-statistics/assets/images/') .
106
+ $items->agent .
107
+ ".png' class='log-tools' title='{$items->agent}'/>";
108
  } else {
109
+ $agent = wp_statistics_icons('dashicons-editor-help', 'unknown');
110
  }
111
 
112
+ echo "<a href='?page=" .
113
+ WP_Statistics::$page['overview'] .
114
+ "&type=last-all-visitor&agent={$items->agent}'>{$agent}</a> {$items->ip}";
115
  echo "<br>";
116
 
117
  $timediff = ( $items->timestamp - $items->created );
118
 
119
  if ( $timediff > 3600 ) {
120
+ $onlinefor = date("H:i:s", ( $items->timestamp - $items->created ));
121
  } else if ( $timediff > 60 ) {
122
+ $onlinefor = "00:" . date("i:s", ( $items->timestamp - $items->created ));
123
  } else {
124
+ $onlinefor = "00:00:" . date("s", ( $items->timestamp - $items->created ));
125
  }
126
 
127
+ echo sprintf(__('Online for %s (HH:MM:SS)', 'wp-statistics'), $onlinefor);
128
 
129
  echo "</div>";
130
  echo "</div>";
138
 
139
  echo "</div>";
140
  } else {
141
+ echo "<div class='wps-center'>" .
142
+ __('Currently there are no users online in the site.', 'wp-statistics') .
143
+ "</div>";
144
  }
145
  ?>
146
+ </div>
147
+ </div>
148
 
149
  <?php if ( $total > 0 ) { ?>
150
+ <div class="pagination-log">
151
  <?php echo $Pagination->display(); ?>
152
+ <p id="result-log"><?php printf(
153
+ __('Page %1$s of %2$s', 'wp-statistics'),
154
+ $Pagination->getCurrentPage(),
155
+ $Pagination->getTotalPages()
156
+ ); ?></p>
157
+ </div>
158
  <?php } ?>
159
+ </div>
160
+ </div>
161
+ </div>
162
  </div>
includes/log/page-statistics.php CHANGED
@@ -1,26 +1,26 @@
1
  <script type="text/javascript">
2
- jQuery(document).ready(function () {
3
- postboxes.add_postbox_toggles(pagenow);
4
- });
5
  </script>
6
  <?php
7
- if ( array_key_exists( 'page-uri', $_GET ) ) {
8
  $pageuri = $_GET['page-uri'];
9
  } else {
10
  $pageuri = null;
11
  }
12
- if ( array_key_exists( 'page-id', $_GET ) ) {
13
  $pageid = (int) $_GET['page-id'];
14
  } else {
15
  $pageid = null;
16
  }
17
 
18
  if ( $pageuri && ! $pageid ) {
19
- $pageid = wp_statistics_uri_to_id( $pageuri );
20
  }
21
 
22
- $post = get_post( $pageid );
23
- if ( is_object( $post ) ) {
24
  $title = $post->post_title;
25
  } else {
26
  $title = "";
@@ -32,40 +32,52 @@ if ( $pageuri ) {
32
  }
33
 
34
  $daysToDisplay = 20;
35
- if ( array_key_exists( 'hitdays', $_GET ) ) {
36
- $daysToDisplay = intval( $_GET['hitdays'] );
37
  }
38
 
39
- if ( array_key_exists( 'rangestart', $_GET ) ) {
40
  $rangestart = $_GET['rangestart'];
41
  } else {
42
  $rangestart = '';
43
  }
44
- if ( array_key_exists( 'rangeend', $_GET ) ) {
45
  $rangeend = $_GET['rangeend'];
46
  } else {
47
  $rangeend = '';
48
  }
49
  ?>
50
  <div class="wrap">
51
- <h2><?php echo __( 'Page Trend for Post ID', 'wp-statistics' ) . ' ' . $pageid . ' - ' . $title; ?></h2>
52
- <?php wp_statistics_date_range_selector( WP_STATISTICS_PAGES_PAGE, $daysToDisplay, null, null, $urlfields ); ?>
53
- <div class="postbox-container" id="last-log">
54
- <div class="metabox-holder">
55
- <div class="meta-box-sortables">
56
- <div class="postbox">
57
- <?php $paneltitle = __( 'Page Trend', 'wp-statistics' ); ?>
58
- <button class="handlediv" type="button" aria-expanded="true">
59
- <span class="screen-reader-text"><?php printf( __( 'Toggle panel: %s', 'wp-statistics' ), $paneltitle ); ?></span>
60
- <span class="toggle-indicator" aria-hidden="true"></span>
61
- </button>
62
- <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
63
- <div class="inside">
64
- <?php include_once( dirname( __FILE__ ) . '/widgets/page.php' );
65
- wp_statistics_generate_page_postbox_content( $pageuri, $pageid, $daysToDisplay, null, $rangestart, $rangeend ); ?>
66
- </div>
67
- </div>
68
- </div>
69
- </div>
70
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
71
  </div>
1
  <script type="text/javascript">
2
+ jQuery(document).ready(function () {
3
+ postboxes.add_postbox_toggles(pagenow);
4
+ });
5
  </script>
6
  <?php
7
+ if ( array_key_exists('page-uri', $_GET) ) {
8
  $pageuri = $_GET['page-uri'];
9
  } else {
10
  $pageuri = null;
11
  }
12
+ if ( array_key_exists('page-id', $_GET) ) {
13
  $pageid = (int) $_GET['page-id'];
14
  } else {
15
  $pageid = null;
16
  }
17
 
18
  if ( $pageuri && ! $pageid ) {
19
+ $pageid = wp_statistics_uri_to_id($pageuri);
20
  }
21
 
22
+ $post = get_post($pageid);
23
+ if ( is_object($post) ) {
24
  $title = $post->post_title;
25
  } else {
26
  $title = "";
32
  }
33
 
34
  $daysToDisplay = 20;
35
+ if ( array_key_exists('hitdays', $_GET) ) {
36
+ $daysToDisplay = intval($_GET['hitdays']);
37
  }
38
 
39
+ if ( array_key_exists('rangestart', $_GET) ) {
40
  $rangestart = $_GET['rangestart'];
41
  } else {
42
  $rangestart = '';
43
  }
44
+ if ( array_key_exists('rangeend', $_GET) ) {
45
  $rangeend = $_GET['rangeend'];
46
  } else {
47
  $rangeend = '';
48
  }
49
  ?>
50
  <div class="wrap">
51
+ <h2><?php echo sprintf(__('Page Trend for Post ID %s', 'wp-statistics'), $pageid) . ' - ' . $title; ?></h2>
52
+ <?php wp_statistics_date_range_selector(WP_Statistics::$page['pages'], $daysToDisplay, null, null, $urlfields); ?>
53
+ <div class="postbox-container" id="last-log">
54
+ <div class="metabox-holder">
55
+ <div class="meta-box-sortables">
56
+ <div class="postbox">
57
+ <?php $paneltitle = __('Page Trend', 'wp-statistics'); ?>
58
+ <button class="handlediv" type="button" aria-expanded="true">
59
+ <span class="screen-reader-text"><?php printf(
60
+ __('Toggle panel: %s', 'wp-statistics'),
61
+ $paneltitle
62
+ ); ?></span>
63
+ <span class="toggle-indicator" aria-hidden="true"></span>
64
+ </button>
65
+ <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
66
+
67
+ <div class="inside">
68
+ <?php
69
+ include( WP_Statistics::$reg['plugin-dir'] . 'includes/log/widgets/page.php' );
70
+ wp_statistics_generate_page_postbox_content(
71
+ $pageuri,
72
+ $pageid,
73
+ $daysToDisplay,
74
+ null,
75
+ $rangestart,
76
+ $rangeend
77
+ ); ?>
78
+ </div>
79
+ </div>
80
+ </div>
81
+ </div>
82
+ </div>
83
  </div>
includes/log/search-statistics.php CHANGED
@@ -1,131 +1,139 @@
1
  <script type="text/javascript">
2
- jQuery(document).ready(function () {
3
- postboxes.add_postbox_toggles(pagenow);
4
- });
5
  </script>
6
  <?php
7
  $search_engines = wp_statistics_searchengine_list();
8
 
9
  $daysToDisplay = 20;
10
- if ( array_key_exists( 'hitdays', $_GET ) ) {
11
- $daysToDisplay = intval( $_GET['hitdays'] );
12
  }
13
 
14
- if ( array_key_exists( 'rangestart', $_GET ) ) {
15
  $rangestart = $_GET['rangestart'];
16
  } else {
17
  $rangestart = '';
18
  }
19
- if ( array_key_exists( 'rangeend', $_GET ) ) {
20
  $rangeend = $_GET['rangeend'];
21
  } else {
22
  $rangeend = '';
23
  }
24
 
25
- list( $daysToDisplay, $rangestart_utime, $rangeend_utime ) = wp_statistics_date_range_calculator( $daysToDisplay, $rangestart, $rangeend );
26
- $daysInThePast = round( ( time() - $rangeend_utime ) / 86400, 0 );
 
 
 
 
27
 
28
- $total_stats = $WP_Statistics->get_option( 'chart_totals' );
29
  $date = array();
30
  $stats = array();
31
  $total_daily = array();
32
 
33
  foreach ( $search_engines as $se ) {
34
- for ( $i = $daysToDisplay; $i >= 0; $i -- ) {
35
- if ( ! array_key_exists( $i, $total_daily ) ) {
36
  $total_daily[ $i ] = 0;
37
  }
38
 
39
- $stat = wp_statistics_searchengine( $se['tag'], '-' . ( $i + $daysInThePast ) );
40
  $stats[ $se['name'] ][] = $stat;
41
- $total_daily[ $i ] += $stat;
42
  }
43
  }
44
 
45
- for ( $i = $daysToDisplay; $i >= 0; $i -- ) {
46
- $date[] = "'" . $WP_Statistics->Real_Current_Date( 'M j', '-' . ( $i + $daysInThePast ), $rangeend_utime ) . "'";
47
  }
48
  ?>
49
  <div class="wrap">
50
- <h2><?php _e( 'Search Engine Referral Statistics', 'wp-statistics' ); ?></h2>
51
- <?php wp_statistics_date_range_selector( WP_STATISTICS_SEARCHES_PAGE, $daysToDisplay ); ?>
52
- <div class="postbox-container" id="last-log">
53
- <div class="metabox-holder">
54
- <div class="meta-box-sortables">
55
- <div class="postbox">
56
- <?php $paneltitle = __( 'Search Engine Referral Statistics', 'wp-statistics' ); ?>
57
- <button class="handlediv" type="button" aria-expanded="true">
58
- <span class="screen-reader-text"><?php printf( __( 'Toggle panel: %s', 'wp-statistics' ), $paneltitle ); ?></span>
59
- <span class="toggle-indicator" aria-hidden="true"></span>
60
- </button>
61
- <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
62
- <div class="inside">
63
- <canvas id="search-stats" height="80"></canvas>
64
- <script>
65
- var colors = [];
66
- colors['baidu'] = ['rgba(35, 25, 220, 0.2)', 'rgba(35, 25, 220, 1)'];
67
- colors['bing'] = ['rgba(12, 132, 132, 0.2)', 'rgba(12, 132, 132, 1)'];
68
- colors['duckduckgo'] = ['rgba(222, 88, 51, 0.2)', 'rgba(222, 88, 51, 1)'];
69
- colors['google'] = ['rgba(23, 107, 239, 0.2)', 'rgba(23, 107, 239, 1)'];
70
- colors['yahoo'] = ['rgba(64, 0, 144, 0.2)', 'rgba(64, 0, 144, 1)'];
71
- colors['yandex'] = ['rgba(255, 219, 77, 0.2)', 'rgba(255, 219, 77, 1)'];
72
- colors['ask'] = ['rgba(205, 0, 0, 0.2)', 'rgba(205, 0, 0, 1)'];
73
- colors['clearch'] = ['rgba(13, 0, 76, 0.2)', 'rgba(13, 0, 76, 1)'];
74
 
75
- var ctx = document.getElementById("search-stats").getContext('2d');
76
- var ChartJs = new Chart(ctx, {
77
- type: 'line',
78
- data: {
79
- labels: [<?php echo implode( ', ', $date ); ?>],
80
- datasets: [
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  <?php foreach ( $search_engines as $se ): ?>
82
- {
83
- label: '<?php echo $se['name']; ?>',
84
- data: [<?php echo implode( ',', $stats[ $se['name'] ] ); ?>],
85
- backgroundColor: colors['<?php echo $se['tag']; ?>'][0],
86
- borderColor: colors['<?php echo $se['tag']; ?>'][1],
87
- borderWidth: 1,
88
- fill: true,
89
- },
90
  <?php endforeach; ?>
91
  <?php if ( $total_stats == 1 ) : ?>
92
- {
93
- label: '<?php _e( 'Total', 'wp-statistics' ); ?>',
94
- data: [<?php echo implode( ',', $total_daily ); ?>],
95
- backgroundColor: 'rgba(180, 180, 180, 0.2)',
96
- borderColor: 'rgba(180, 180, 180, 1)',
97
- borderWidth: 1,
98
- fill: false,
99
- },
100
  <?php endif;?>
101
- ]
102
- },
103
- options: {
104
- responsive: true,
105
- legend: {
106
- position: 'bottom',
107
- },
108
- title: {
109
- display: true,
110
- text: '<?php echo sprintf( __( 'Search engine referrals in the last %s days', 'wp-statistics' ), $daysToDisplay ); ?>'
111
- },
112
- tooltips: {
113
- mode: 'index',
114
- intersect: false,
115
- },
116
- scales: {
117
- yAxes: [{
118
- ticks: {
119
- beginAtZero: true
120
- }
121
- }]
122
- }
123
- }
124
- });
125
- </script>
126
- </div>
127
- </div>
128
- </div>
129
- </div>
130
- </div>
131
  </div>
1
  <script type="text/javascript">
2
+ jQuery(document).ready(function () {
3
+ postboxes.add_postbox_toggles(pagenow);
4
+ });
5
  </script>
6
  <?php
7
  $search_engines = wp_statistics_searchengine_list();
8
 
9
  $daysToDisplay = 20;
10
+ if ( array_key_exists('hitdays', $_GET) ) {
11
+ $daysToDisplay = intval($_GET['hitdays']);
12
  }
13
 
14
+ if ( array_key_exists('rangestart', $_GET) ) {
15
  $rangestart = $_GET['rangestart'];
16
  } else {
17
  $rangestart = '';
18
  }
19
+ if ( array_key_exists('rangeend', $_GET) ) {
20
  $rangeend = $_GET['rangeend'];
21
  } else {
22
  $rangeend = '';
23
  }
24
 
25
+ list( $daysToDisplay, $rangestart_utime, $rangeend_utime ) = wp_statistics_date_range_calculator(
26
+ $daysToDisplay,
27
+ $rangestart,
28
+ $rangeend
29
+ );
30
+ $daysInThePast = round(( time() - $rangeend_utime ) / 86400, 0);
31
 
32
+ $total_stats = $WP_Statistics->get_option('chart_totals');
33
  $date = array();
34
  $stats = array();
35
  $total_daily = array();
36
 
37
  foreach ( $search_engines as $se ) {
38
+ for ( $i = $daysToDisplay; $i >= 0; $i-- ) {
39
+ if ( ! array_key_exists($i, $total_daily) ) {
40
  $total_daily[ $i ] = 0;
41
  }
42
 
43
+ $stat = wp_statistics_searchengine($se['tag'], '-' . ( $i + $daysInThePast ));
44
  $stats[ $se['name'] ][] = $stat;
45
+ $total_daily[ $i ] += $stat;
46
  }
47
  }
48
 
49
+ for ( $i = $daysToDisplay; $i >= 0; $i-- ) {
50
+ $date[] = "'" . $WP_Statistics->Real_Current_Date('M j', '-' . ( $i + $daysInThePast ), $rangeend_utime) . "'";
51
  }
52
  ?>
53
  <div class="wrap">
54
+ <h2><?php _e('Search Engine Referral Statistics', 'wp-statistics'); ?></h2>
55
+ <?php wp_statistics_date_range_selector(WP_Statistics::$page['searches'], $daysToDisplay); ?>
56
+ <div class="postbox-container" id="last-log">
57
+ <div class="metabox-holder">
58
+ <div class="meta-box-sortables">
59
+ <div class="postbox">
60
+ <?php $paneltitle = __('Search Engine Referral Statistics', 'wp-statistics'); ?>
61
+ <button class="handlediv" type="button" aria-expanded="true">
62
+ <span class="screen-reader-text"><?php printf(
63
+ __('Toggle panel: %s', 'wp-statistics'),
64
+ $paneltitle
65
+ ); ?></span>
66
+ <span class="toggle-indicator" aria-hidden="true"></span>
67
+ </button>
68
+ <h2 class="hndle"><span><?php echo $paneltitle; ?></span></h2>
 
 
 
 
 
 
 
 
 
69
 
70
+ <div class="inside">
71
+ <canvas id="search-stats" height="80"></canvas>
72
+ <script>
73
+ var colors = [];
74
+ colors['baidu'] = ['rgba(35, 25, 220, 0.2)', 'rgba(35, 25, 220, 1)'];
75
+ colors['bing'] = ['rgba(12, 132, 132, 0.2)', 'rgba(12, 132, 132, 1)'];
76
+ colors['duckduckgo'] = ['rgba(222, 88, 51, 0.2)', 'rgba(222, 88, 51, 1)'];
77
+ colors['google'] = ['rgba(23, 107, 239, 0.2)', 'rgba(23, 107, 239, 1)'];
78
+ colors['yahoo'] = ['rgba(64, 0, 144, 0.2)', 'rgba(64, 0, 144, 1)'];
79
+ colors['yandex'] = ['rgba(255, 219, 77, 0.2)', 'rgba(255, 219, 77, 1)'];
80
+ colors['ask'] = ['rgba(205, 0, 0, 0.2)', 'rgba(205, 0, 0, 1)'];
81
+ colors['clearch'] = ['rgba(13, 0, 76, 0.2)', 'rgba(13, 0, 76, 1)'];
82
+
83
+ var ctx = document.getElementById("search-stats").getContext('2d');
84
+ var ChartJs = new Chart(ctx, {
85
+ type: 'line',
86
+ data: {
87
+ labels: [<?php echo implode( ', ', $date ); ?>],
88
+ datasets: [
89
  <?php foreach ( $search_engines as $se ): ?>
90
+ {
91
+ label: '<?php echo $se['name']; ?>',
92
+ data: [<?php echo implode( ',', $stats[ $se['name'] ] ); ?>],
93
+ backgroundColor: colors['<?php echo $se['tag']; ?>'][0],
94
+ borderColor: colors['<?php echo $se['tag']; ?>'][1],
95
+ borderWidth: 1,
96
+ fill: true,
97
+ },
98
  <?php endforeach; ?>
99
  <?php if ( $total_stats == 1 ) : ?>
100
+ {
101
+ label: '<?php _e( 'Total', 'wp-statistics' ); ?>',
102
+ data: [<?php echo implode( ',', $total_daily ); ?>],
103
+ backgroundColor: 'rgba(180, 180, 180, 0.2)',
104
+ borderColor: 'rgba(180, 180, 180, 1)',
105
+ borderWidth: 1,
106
+ fill: false,
107
+ },
108
  <?php endif;?>
109
+ ]
110
+ },
111
+ options: {
112
+ responsive: true,
113
+ legend: {
114
+ position: 'bottom',
115
+ },
116
+ title: {
117
+ display: true,
118
+ text: '<?php echo sprintf( __( 'Search engine referrals in the last %s days', 'wp-statistics' ), $daysToDisplay ); ?>'
119
+ },
120
+ tooltips: {
121
+ mode: 'index',
122
+ intersect: false,
123
+ },
124
+ scales: {
125
+ yAxes: [{
126
+ ticks: {
127
+ beginAtZero: true
128
+ }
129
+ }]
130
+ }
131
+ }
132
+ });
133
+ </script>
134
+ </div>
135
+ </div>
136
+ </div>
137
+ </div>
138
+ </div>
139
  </div>
includes/log/searched-phrases.php ADDED
@@ -0,0 +1,191 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script type="text/javascript">
2
+ jQuery(document).ready(function () {
3
+ jQuery('.show-map').click(function () {
4
+ alert('<?php _e( 'To be added soon', 'wp-statistics' ); ?>');
5
+ });
6
+
7
+ postboxes.add_postbox_toggles(pagenow);
8
+ });
9
+ </script>
10
+ <?php
11
+ $date_args = '';
12
+ $daysToDisplay = 20;
13
+ if ( array_key_exists('hitdays', $_GET) ) {
14
+ $daysToDisplay = intval(esc_attr($_GET['hitdays']));
15
+ $date_args .= '&hitdays=' . $daysToDisplay;
16
+ }
17
+
18
+ if ( array_key_exists('rangestart', $_GET) ) {
19
+ $rangestart = esc_attr($_GET['rangestart']);
20
+ $date_args .= '&rangestart=' . $rangestart;
21
+ } else {
22
+ $rangestart = '';
23
+ }
24
+
25
+ if ( array_key_exists('rangeend', $_GET) ) {
26
+ $rangeend = esc_attr($_GET['rangeend']);
27
+ $date_args .= '&rangeend=' . $rangeend;
28
+ } else {
29
+ $rangeend = '';
30
+ }
31
+
32
+ list( $daysToDisplay, $rangestart_utime, $rangeend_utime ) = wp_statistics_date_range_calculator(
33
+ $daysToDisplay,
34
+ $rangestart,
35
+ $rangeend
36
+ );
37
+
38
+ $rangestartdate = $WP_Statistics->real_current_date('Y-m-d', '-0', $rangestart_utime);
39
+ $rangeenddate = $WP_Statistics->real_current_date('Y-m-d', '-0', $rangeend_utime);
40
+
41
+ if ( array_key_exists('phrase', $_GET) ) {
42
+ $phrase = $_GET['phrase'];
43
+ $title = $_GET['phrase'];
44
+ $referr_field = '&phrase=' . $phrase;
45
+ } else {
46
+ $phrase = '';
47
+ $phrase_field = null;
48
+ }
49
+
50
+ $get_urls = array();
51
+ $total = 0;
52
+
53
+ if ( $phrase ) {
54
+ $q_string = $wpdb->prepare(
55
+ "SELECT `words` , count(`words`) as `count` FROM `{$wpdb->prefix}statistics_search` WHERE `words` LIKE %s AND `words` <> '' AND `last_counter` BETWEEN %s AND %s GROUP BY `words` order by `count` DESC",
56
+ '%' . $phrase . '%',
57
+ $rangestartdate,
58
+ $rangeenddate
59
+ );
60
+ $result = $wpdb->get_results($q_string);
61
+ $total = count($result);
62
+ } else {
63
+ $q_string = $wpdb->prepare(
64
+ "SELECT `words` , count(`words`) as `count` FROM `{$wpdb->prefix}statistics_search` WHERE `words` <> '' AND `last_counter` BETWEEN %s AND %s GROUP BY `words` order by `count` DESC",
65
+ $rangestartdate,
66
+ $rangeenddate
67
+ );
68
+ $result = $wpdb->get_results($q_string);
69
+ $total = count($result);
70
+ }
71
+
72
+ ?>
73
+ <div class="wrap">
74
+ <h2><?php _e('Top Searched Phrases', 'wp-statistics'); ?></h2>
75
+
76
+ <div><?php wp_statistics_date_range_selector(
77
+ WP_Statistics::$page['searched-phrases'],
78
+ $daysToDisplay,
79
+ null,
80
+ null,
81
+ $phrase_field
82
+ ); ?></div>
83
+
84
+ <div class="clear"/>
85
+
86
+ <ul class="subsubsub">
87
+ <?php if ( $phrase ) { ?>
88
+ <li class="all"><a <?php if ( ! $phrase ) {
89
+ echo 'class="current"';
90
+ } ?>href="?page=<?php echo WP_Statistics::$page['searched-phrases'] . $date_args; ?>"><?php _e(
91
+ 'All',
92
+ 'wp-statistics'
93
+ ); ?></a>
94
+ </li>
95
+ |
96
+ <li>
97
+ <a class="current"
98
+ href="?page=<?php echo WP_Statistics::$page['searched-phrases']; ?>&referr=<?php echo esc_html($phrase) .
99
+ $date_args; ?>"> <?php echo htmlentities(
100
+ $title,
101
+ ENT_QUOTES
102
+ ); ?>
103
+ <span class="count">(<?php echo $total; ?>)</span></a></li>
104
+ <?php } else { ?>
105
+ <li class="all"><a <?php if ( ! $phrase ) {
106
+ echo 'class="current"';
107
+ } ?>href="?page=<?php echo WP_Statistics::$page['searched-phrases'] . $date_args; ?>"><?php _e(
108
+ 'All',
109
+ 'wp-statistics'
110
+ ); ?>
111
+ <span class="count">(<?php echo $total; ?>)</span></a></li>
112
+ <?php } ?>
113
+ </ul>
114
+ <div class="postbox-container" id="last-log">
115
+ <div class="metabox-holder">
116
+ <div class="meta-box-sortables">
117
+ <div class="postbox">
118
+ <?php if ( $phrase ) {
119
+ $paneltitle = sprintf(__('Searched Phrase: %s', 'wp-statistics'), esc_html($phrase));
120
+ } else {
121
+ $paneltitle = __('Top Searched Phrases', 'wp-statistics');
122
+ }; ?>
123
+ <button class="handlediv" type="button" aria-expanded="true">
124
+ <span class="screen-reader-text"><?php printf(
125
+ __('Toggle panel: %s', 'wp-statistics'),
126
+ $paneltitle
127
+ ); ?></span>
128
+ <span class="toggle-indicator" aria-hidden="true"></span>
129
+ </button>
130
+ <h2 class="hndle"><span><?php echo $paneltitle; ?></h2>
131
+
132
+ <div class="inside">
133
+ <div class="log-latest">
134
+ <?php
135
+
136
+ if ( $total > 0 ) {
137
+ // Initiate pagination object with appropriate arguments
138
+ $pagesPerSection = 10;
139
+ $options = array( 25, "All" );
140
+ $stylePageOff = "pageOff";
141
+ $stylePageOn = "pageOn";
142
+ $styleErrors = "paginationErrors";
143
+ $styleSelect = "paginationSelect";
144
+
145
+ $Pagination = new WP_Statistics_Pagination(
146
+ $total,
147
+ $pagesPerSection,
148
+ $options,
149
+ false,
150
+ $stylePageOff,
151
+ $stylePageOn,
152
+ $styleErrors,
153
+ $styleSelect
154
+ );
155
+
156
+ $start = $Pagination->getEntryStart();
157
+ $end = $Pagination->getEntryEnd();
158
+
159
+ if ( $result ) {
160
+ $result = array_slice($result, $start, $end);
161
+ $i = $start;
162
+ foreach ( $result as $item ) {
163
+ $i++;
164
+ echo "<div class='log-item'>";
165
+ echo "<div class='log-referred'>{$i} - {$item->words}</div>";
166
+ echo "<div class='clear'></div>";
167
+ echo "<div class='log-url'>{$item->count}</div>";
168
+ echo "</div>";
169
+ }
170
+ }
171
+ }
172
+
173
+ ?>
174
+ </div>
175
+ </div>
176
+ </div>
177
+
178
+ <div class="pagination-log">
179
+ <?php if ( $total > 0 ) {
180
+ echo $Pagination->display(); ?>
181
+ <p id="result-log"><?php printf(
182
+ __('Page %1$s of %2$s', 'wp-statistics'),
183
+ $Pagination->getCurrentPage(),
184
+ $Pagination->getTotalPages()
185
+ ); ?></p>
186
+ <?php } ?>
187
+ </div>
188
+ </div>
189
+ </div>
190
+ </div>
191
+ </div>
includes/log/tags.php CHANGED
@@ -1,37 +1,37 @@
1
  <script type="text/javascript">
2
- jQuery(document).ready(function () {
3
- postboxes.add_postbox_toggles(pagenow);
4
- });
5
  </script>
6
  <div class="wrap">
7
- <h2><?php _e( 'Tag Statistics', 'wp-statistics' ); ?></h2>
8
  <?php
9
  $daysToDisplay = 20;
10
- if ( array_key_exists( 'hitdays', $_GET ) ) {
11
- $daysToDisplay = intval( $_GET['hitdays'] );
12
  }
13
 
14
- if ( array_key_exists( 'rangestart', $_GET ) ) {
15
  $rangestart = $_GET['rangestart'];
16
  } else {
17
  $rangestart = '';
18
  }
19
- if ( array_key_exists( 'rangeend', $_GET ) ) {
20
  $rangeend = $_GET['rangeend'];
21
  } else {
22
  $rangeend = '';
23
  }
24
- if ( array_key_exists( 'tag', $_GET ) ) {
25
  $tag = $_GET['tag'];
26
  } else {
27
- if ( array_key_exists( 'pretag', $_GET ) ) {
28
  $tag = $_GET['pretag'];
29
  } else {
30
  $tag = '';
31
  }
32
  }
33
 
34
- $html = __( 'Select Tag', 'wp-statistics' ) . ': ';
35
 
36
  $tags = get_tags();
37
 
@@ -54,176 +54,192 @@
54
  }
55
 
56
  $html .= '</select>';
57
- $html .= ' <input type="submit" value="' . __( 'Select', 'wp-statistics' ) . '" class="button-primary">';
58
  $html .= '<br>';
59
 
60
- list( $daysToDisplay, $rangestart_utime, $rangeend_utime ) = wp_statistics_date_range_calculator( $daysToDisplay, $rangestart, $rangeend );
 
 
 
 
61
 
62
- wp_statistics_date_range_selector( WP_STATISTICS_TAGS_PAGE, $daysToDisplay, null, null, '&pretag=' . $tag, $html );
63
 
64
  $args = array(
65
  'tax_query' => array(
66
  array(
67
  'taxonomy' => 'post_tag',
68
  'field' => 'slug',
69
- 'terms' => sanitize_title( $tag ),
70
- )
71
  ),
72
  );
73
 
74
- $posts = get_posts( $args );
75
 
76
- $visit_total = 0;
77
  $daysInThePast = (int) ( ( time() - $rangeend_utime ) / 86400 );
78
- $posts_stats = array();
79
- $visits = array();
80
 
81
  // Setup the array, otherwise PHP may throw an error.
82
  foreach ( $posts as $post ) {
83
  $posts_stats[ $post->ID ] = 0;
84
  }
85
 
86
- for ( $i = $daysToDisplay; $i >= 0; $i -- ) {
87
- $date[] = "'" . $WP_Statistics->Real_Current_Date( 'M j', '-' . ( $i + $daysInThePast ), $rangeend_utime ) . "'";
88
 
89
  $stat = 0;
90
  foreach ( $posts as $post ) {
91
- $temp_stat = wp_statistics_pages( '-' . (int) ( $i + $daysInThePast ), null, $post->ID );
92
  $posts_stats[ $post->ID ] += $temp_stat;
93
- $stat = $temp_stat;
94
  }
95
 
96
- $visits[] = $stat;
97
  $visit_total += $stat;
98
  }
99
  ?>
100
- <div class="postbox-container" id="last-log">
101
- <div class="metabox-holder">
102
- <div class="meta-box-sortables">
103
- <div class="postbox">
104
- <?php $paneltitle = __( 'Tag Statistics Chart', 'wp-statistics' ); ?>
105
- <button class="handlediv" type="button" aria-expanded="true">
106
- <span class="screen-reader-text"><?php printf( __( 'Toggle panel: %s', 'wp-statistics' ), $paneltitle ); ?></span>
107
- <span class="toggle-indicator" aria-hidden="true"></span>
108
- </button>
109
- <h2 class="hndle"><span><?php echo $paneltitle; ?></h2>
110
- <div class="inside">
111
- <canvas id="hit-stats" height="80"></canvas>
112
- <script>
113
- var ctx = document.getElementById("hit-stats").getContext('2d');
114
- var ChartJs = new Chart(ctx, {
115
- type: 'line',
116
- data: {
117
- labels: [<?php echo implode( ', ', $date ); ?>],
118
- datasets: [
119
- {
120
- label: '<?php _e( 'Visits', 'wp-statistics' ); ?>',
121
- data: [<?php echo implode( ',', $visits ); ?>],
122
- backgroundColor: 'rgba(54, 162, 235, 0.2)',
123
- borderColor: 'rgba(54, 162, 235, 1)',
124
- borderWidth: 1,
125
- fill: true,
126
- },
127
- ]
128
- },
129
- options: {
130
- responsive: true,
131
- legend: {
132
- position: 'bottom',
133
- },
134
- title: {
135
- display: true,
136
- text: '<?php echo sprintf( __( 'Hits in the last %s days', 'wp-statistics' ), $daysToDisplay ); ?>'
137
- },
138
- tooltips: {
139
- mode: 'index',
140
- intersect: false,
141
- },
142
- scales: {
143
- yAxes: [{
144
- ticks: {
145
- beginAtZero: true
146
- }
147
- }]
148
- }
149
- }
150
- });
151
- </script>
152
- </div>
153
- </div>
154
- </div>
155
- </div>
156
- </div>
157
-
158
- <div class="postbox-container" style="width: 100%; float: left; margin-right:20px">
159
- <div class="metabox-holder">
160
- <div class="meta-box-sortables">
161
- <div class="postbox">
162
- <?php $paneltitle = __( 'Tag Statistics Summary', 'wp-statistics' ); ?>
163
- <button class="handlediv" type="button" aria-expanded="true">
164
- <span class="screen-reader-text"><?php printf( __( 'Toggle panel: %s', 'wp-statistics' ), $paneltitle ); ?></span>
165
- <span class="toggle-indicator" aria-hidden="true"></span>
166
- </button>
167
- <h2 class="hndle"><span><?php echo $paneltitle; ?></h2>
168
- <div class="inside">
169
- <table width="auto" class="widefat table-stats" id="summary-stats">
170
- <tbody>
171
- <tr>
172
- <th></th>
173
- <th class="th-center"><?php _e( 'Count', 'wp-statistics' ); ?></th>
174
- </tr>
175
-
176
- <tr>
177
- <th><?php _e( 'Number of posts in tag', 'wp-statistics' ); ?>:</th>
178
- <th class="th-center"><span><?php echo number_format_i18n( count( $posts ) ); ?></span>
179
- </th>
180
- </tr>
181
-
182
- <tr>
183
- <th><?php _e( 'Chart Visits Total', 'wp-statistics' ); ?>:</th>
184
- <th class="th-center"><span><?php echo number_format_i18n( $visit_total ); ?></span>
185
- </th>
186
- </tr>
187
-
188
- <tr>
189
- <th><?php _e( 'All Time Visits Total', 'wp-statistics' ); ?>:</th>
190
- <th class="th-center"><span><?php
 
 
 
 
 
 
 
 
191
 
192
  $stat = 0;
193
  foreach ( $posts as $post ) {
194
- $stat += wp_statistics_pages( 'total', null, $post->ID );
195
  }
196
 
197
- echo number_format_i18n( $stat ); ?></span></th>
198
- </tr>
199
- </tbody>
200
- </table>
201
- </div>
202
- </div>
203
- </div>
204
- </div>
205
- </div>
206
-
207
- <div class="postbox-container" style="width: 100%; float: left; margin-right:20px">
208
- <div class="metabox-holder">
209
- <div class="meta-box-sortables">
210
- <div class="postbox">
211
- <?php $paneltitle = __( 'Tag Posts Sorted by Hits', 'wp-statistics' ); ?>
212
- <button class="handlediv" type="button" aria-expanded="true">
213
- <span class="screen-reader-text"><?php printf( __( 'Toggle panel: %s', 'wp-statistics' ), $paneltitle ); ?></span>
214
- <span class="toggle-indicator" aria-hidden="true"></span>
215
- </button>
216
- <h2 class="hndle"><span><?php echo $paneltitle; ?></h2>
217
- <div class="inside">
218
- <table width="auto" class="widefat table-stats" id="post-stats">
219
- <tbody>
220
- <tr>
221
- <th><?php _e( 'Post Title', 'wp-statistics' ); ?></th>
222
- <th class="th-center"><?php _e( 'Hits', 'wp-statistics' ); ?></th>
223
- </tr>
 
 
 
 
224
 
225
  <?php
226
- arsort( $posts_stats );
227
 
228
  $posts_by_id = array();
229
 
@@ -235,22 +251,24 @@
235
  $post_obj = $posts_by_id[ $post_id ];
236
 
237
  ?>
238
- <tr>
239
- <th>
240
- <a href="<?php echo get_permalink( $post_obj ); ?>"><?php echo $post_obj->post_title; ?></a>
241
- </th>
242
- <th class="th-center"><span><?php echo number_format_i18n( $post_stat ); ?></span>
243
- </th>
244
- </tr>
 
 
245
  <?php
246
  }
247
  ?>
248
- </tbody>
249
- </table>
250
- </div>
251
- </div>
252
- </div>
253
- </div>
254
- </div>
255
 
256
  </div>
1
  <script type="text/javascript">
2
+ jQuery(document).ready(function () {
3
+ postboxes.add_postbox_toggles(pagenow);
4
+ });
5
  </script>
6
  <div class="wrap">
7
+ <h2><?php _e('Tag Statistics', 'wp-statistics'); ?></h2>
8
  <?php
9
  $daysToDisplay = 20;
10
+ if ( array_key_exists('hitdays', $_GET) ) {
11
+ $daysToDisplay = intval($_GET['hitdays']);
12
  }
13
 
14
+ if ( array_key_exists('rangestart', $_GET) ) {
15
  $rangestart = $_GET['rangestart'];
16
  } else {
17
  $rangestart = '';
18
  }
19
+ if ( array_key_exists('rangeend', $_GET) ) {
20
  $rangeend = $_GET['rangeend'];
21
  } else {
22
  $rangeend = '';
23
  }
24
+ if ( array_key_exists('tag', $_GET) ) {
25
  $tag = $_GET['tag'];
26
  } else {
27
+ if ( array_key_exists('pretag', $_GET) ) {
28
  $tag = $_GET['pretag'];
29
  } else {
30
  $tag = '';
31
  }
32
  }
33
 
34
+ $html = __('Select Tag', 'wp-statistics') . ': ';
35
 
36
  $tags = get_tags();
37
 
54
  }
55
 
56
  $html .= '</select>';
57
+ $html .= ' <input type="submit" value="' . __('Select', 'wp-statistics') . '" class="button-primary">';
58
  $html .= '<br>';
59
 
60
+ list( $daysToDisplay, $rangestart_utime, $rangeend_utime ) = wp_statistics_date_range_calculator(
61
+ $daysToDisplay,
62
+ $rangestart,
63
+ $rangeend
64
+ );
65
 
66
+ wp_statistics_date_range_selector(WP_Statistics::$page['tags'], $daysToDisplay, null, null, '&pretag=' . $tag, $html);
67
 
68
  $args = array(
69
  'tax_query' => array(
70
  array(
71
  'taxonomy' => 'post_tag',
72
  'field' => 'slug',
73
+ 'terms' => sanitize_title($tag),
74
+ ),
75
  ),
76
  );
77
 
78
+ $posts = get_posts($args);
79
 
80
+ $visit_total = 0;
81
  $daysInThePast = (int) ( ( time() - $rangeend_utime ) / 86400 );
82
+ $posts_stats = array();
83
+ $visits = array();
84
 
85
  // Setup the array, otherwise PHP may throw an error.
86
  foreach ( $posts as $post ) {
87
  $posts_stats[ $post->ID ] = 0;
88
  }
89
 
90
+ for ( $i = $daysToDisplay; $i >= 0; $i-- ) {
91
+ $date[] = "'" . $WP_Statistics->Real_Current_Date('M j', '-' . ( $i + $daysInThePast ), $rangeend_utime) . "'";
92
 
93
  $stat = 0;
94
  foreach ( $posts as $post ) {
95
+ $temp_stat = wp_statistics_pages('-' . (int) ( $i + $daysInThePast ), null, $post->ID);
96
  $posts_stats[ $post->ID ] += $temp_stat;
97
+ $stat = $temp_stat;
98
  }
99
 
100
+ $visits[] = $stat;
101
  $visit_total += $stat;
102
  }
103
  ?>
104
+ <div class="postbox-container" id="last-log">
105
+ <div class="metabox-holder">
106
+ <div class="meta-box-sortables">
107
+ <div class="postbox">
108
+ <?php $paneltitle = __('Tag Statistics Chart', 'wp-statistics'); ?>
109
+ <button class="handlediv" type="button" aria-expanded="true">
110
+ <span class="screen-reader-text"><?php printf(
111
+ __('Toggle panel: %s', 'wp-statistics'),
112
+ $paneltitle
113
+ ); ?></span>
114
+ <span class="toggle-indicator" aria-hidden="true"></span>
115
+ </button>
116
+ <h2 class="hndle"><span><?php echo $paneltitle; ?></h2>
117
+
118
+ <div class="inside">
119
+ <canvas id="hit-stats" height="80"></canvas>
120
+ <script>
121
+ var ctx = document.getElementById("hit-stats").getContext('2d');
122
+ var ChartJs = new Chart(ctx, {
123
+ type: 'line',
124
+ data: {
125
+ labels: [<?php echo implode( ', ', $date ); ?>],
126
+ datasets: [
127
+ {
128
+ label: '<?php _e( 'Visits', 'wp-statistics' ); ?>',
129
+ data: [<?php echo implode( ',', $visits ); ?>],
130
+ backgroundColor: 'rgba(54, 162, 235, 0.2)',
131
+ borderColor: 'rgba(54, 162, 235, 1)',
132
+ borderWidth: 1,
133
+ fill: true,
134
+ },
135
+ ]
136
+ },
137
+ options: {
138
+ responsive: true,
139
+ legend: {
140
+ position: 'bottom',
141
+ },
142
+ title: {
143
+ display: true,
144
+ text: '<?php echo sprintf( __( 'Hits in the last %s days', 'wp-statistics' ), $daysToDisplay ); ?>'
145
+ },
146
+ tooltips: {
147
+ mode: 'index',
148
+ intersect: false,
149
+ },
150
+ scales: {
151
+ yAxes: [{
152
+ ticks: {
153
+ beginAtZero: true
154
+ }
155
+ }]
156
+ }
157
+ }
158
+ });
159
+ </script>
160
+ </div>
161
+ </div>
162
+ </div>
163
+ </div>
164
+ </div>
165
+
166
+ <div class="postbox-container" style="width: 100%; float: left; margin-right:20px">
167
+ <div class="metabox-holder">
168
+ <div class="meta-box-sortables">
169
+ <div class="postbox">
170
+ <?php $paneltitle = __('Tag Statistics Summary', 'wp-statistics'); ?>
171
+ <button class="handlediv" type="button" aria-expanded="true">
172
+ <span class="screen-reader-text"><?php printf(
173
+ __('Toggle panel: %s', 'wp-statistics'),
174
+ $paneltitle
175
+ ); ?></span>
176
+ <span class="toggle-indicator" aria-hidden="true"></span>
177
+ </button>
178
+ <h2 class="hndle"><span><?php echo $paneltitle; ?></h2>
179
+
180
+ <div class="inside">
181
+ <table width="auto" class="widefat table-stats" id="summary-stats">
182
+ <tbody>
183
+ <tr>
184
+ <th></th>
185
+ <th class="th-center"><?php _e('Count', 'wp-statistics'); ?></th>
186
+ </tr>
187
+
188
+ <tr>
189
+ <th><?php _e('Number of posts in tag', 'wp-statistics'); ?>:</th>
190
+ <th class="th-center"><span><?php echo number_format_i18n(count($posts)); ?></span>
191
+ </th>
192
+ </tr>
193
+
194
+ <tr>
195
+ <th><?php _e('Chart Visits Total', 'wp-statistics'); ?>:</th>
196
+ <th class="th-center"><span><?php echo number_format_i18n($visit_total); ?></span>
197
+ </th>
198
+ </tr>
199
+
200
+ <tr>
201
+ <th><?php _e('All Time Visits Total', 'wp-statistics'); ?>:</th>
202
+ <th class="th-center"><span><?php
203
 
204
  $stat = 0;
205
  foreach ( $posts as $post ) {
206
+ $stat += wp_statistics_pages('total', null, $post->ID);
207
  }
208
 
209
+ echo number_format_i18n($stat); ?></span></th>
210
+ </tr>
211
+ </tbody>
212
+ </table>
213
+ </div>
214
+ </div>
215
+ </div>
216
+ </div>
217
+ </div>
218
+
219
+ <div class="postbox-container" style="width: 100%; float: left; margin-right:20px">
220
+ <div class="metabox-holder">
221
+ <div class="meta-box-sortables">
222
+ <div class="postbox">
223
+ <?php $paneltitle = __('Tag Posts Sorted by Hits', 'wp-statistics'); ?>
224
+ <button class="handlediv" type="button" aria-expanded="true">
225
+ <span class="screen-reader-text"><?php printf(
226
+ __('Toggle panel: %s', 'wp-statistics'),
227
+ $paneltitle
228
+ ); ?></span>
229
+ <span class="toggle-indicator" aria-hidden="true"></span>
230
+ </button>
231
+ <h2 class="hndle"><span><?php echo $paneltitle; ?></h2>
232
+
233
+ <div class="inside">
234
+ <table width="auto" class="widefat table-stats" id="post-stats">
235
+ <tbody>
236
+ <tr>
237
+ <th><?php _e('Post Title', 'wp-statistics'); ?></th>
238
+ <th class="th-center"><?php _e('Hits', 'wp-statistics'); ?></th>
239
+ </tr>
240
 
241
  <?php
242
+ arsort($posts_stats);
243
 
244
  $posts_by_id = array();
245
 
251
  $post_obj = $posts_by_id[ $post_id ];
252
 
253
  ?>
254
+ <tr>
255
+ <th>
256
+ <a href="<?php echo get_permalink(
257
+ $post_obj
258
+ ); ?>"><?php echo $post_obj->post_title; ?></a>
259
+ </th>
260
+ <th class="th-center"><span><?php echo number_format_i18n($post_stat); ?></span>
261
+ </th>
262
+ </tr>
263
  <?php
264
  }
265
  ?>
266
+ </tbody>
267
+ </table>
268
+ </div>
269
+ </div>
270
+ </div>
271
+ </div>
272
+ </div>
273
 
274
  </div>
includes/log/top-countries.php CHANGED
@@ -1,81 +1,100 @@
1
  <script type="text/javascript">
2
- jQuery(document).ready(function () {
3
- postboxes.add_postbox_toggles(pagenow);
4
- });
5
  </script>
6
  <?php
7
  $daysToDisplay = 20;
8
- if ( array_key_exists( 'hitdays', $_GET ) ) {
9
- $daysToDisplay = intval( $_GET['hitdays'] );
10
  }
11
 
12
- if ( array_key_exists( 'rangestart', $_GET ) ) {
13
  $rangestart = $_GET['rangestart'];
14
  } else {
15
  $rangestart = '';
16
  }
17
- if ( array_key_exists( 'rangeend', $_GET ) ) {
18
  $rangeend = $_GET['rangeend'];
19
  } else {
20
  $rangeend = '';
21
  }
22
 
23
- list( $daysToDisplay, $rangestart_utime, $rangeend_utime ) = wp_statistics_date_range_calculator( $daysToDisplay, $rangestart, $rangeend );
 
 
 
 
24
 
25
  ?>
26
  <div class="wrap">
27
- <h2><?php _e( 'Top Countries', 'wp-statistics' ); ?></h2>
28
- <?php wp_statistics_date_range_selector( WP_STATISTICS_COUNTRIES_PAGE, $daysToDisplay ); ?>
29
- <div class="postbox-container" id="last-log">
30
- <div class="metabox-holder">
31
- <div class="meta-box-sortables">
32
- <div class="postbox">
33
- <?php $paneltitle = __( 'Top Countries', 'wp-statistics' ); ?>
34
- <button class="handlediv" type="button" aria-expanded="true">
35
- <span class="screen-reader-text"><?php printf( __( 'Toggle panel: %s', 'wp-statistics' ), $paneltitle ); ?></span>
36
- <span class="toggle-indicator" aria-hidden="true"></span>
37
- </button>
38
- <h2 class="hndle"><span><?php echo $paneltitle; ?></h2>
39
- <div class="inside">
40
- <table class="widefat table-stats" id="last-referrer" style="width: 100%;">
41
- <tr>
42
- <td><?php _e( 'Rank', 'wp-statistics' ); ?></td>
43
- <td><?php _e( 'Flag', 'wp-statistics' ); ?></td>
44
- <td><?php _e( 'Country', 'wp-statistics' ); ?></td>
45
- <td><?php _e( 'Visitor Count', 'wp-statistics' ); ?></td>
46
- </tr>
 
 
 
 
47
 
48
  <?php
49
  $ISOCountryCode = $WP_Statistics->get_country_codes();
50
 
51
- $result = $wpdb->get_results( "SELECT DISTINCT `location` FROM `{$wpdb->prefix}statistics_visitor`" );
 
 
52
 
53
- $rangestartdate = $WP_Statistics->real_current_date( 'Y-m-d', '-0', $rangestart_utime );
54
- $rangeenddate = $WP_Statistics->real_current_date( 'Y-m-d', '-0', $rangeend_utime );
55
 
56
  foreach ( $result as $item ) {
57
- $Countries[ $item->location ] = $wpdb->get_var( $wpdb->prepare( "SELECT count(location) FROM `{$wpdb->prefix}statistics_visitor` WHERE location=%s AND `last_counter` BETWEEN %s AND %s", $item->location, $rangestartdate, $rangeenddate ) );
 
 
 
 
 
 
 
58
  }
59
 
60
- arsort( $Countries );
61
  $i = 0;
62
 
63
  foreach ( $Countries as $item => $value ) {
64
- $i ++;
65
- $item = strtoupper( $item );
66
 
67
  echo "<tr>";
68
  echo "<td>$i</td>";
69
- echo "<td><img src='" . plugins_url( 'wp-statistics/assets/images/flags/' . $item . '.png' ) . "' title='{$ISOCountryCode[$item]}'/></td>";
 
 
70
  echo "<td style='direction: ltr;'>{$ISOCountryCode[$item]}</td>";
71
- echo "<td>" . number_format_i18n( $value ) . "</td>";
72
  echo "</tr>";
73
  }
74
  ?>
75
- </table>
76
- </div>
77
- </div>
78
- </div>
79
- </div>
80
- </div>
81
  </div>
1
  <script type="text/javascript">
2
+ jQuery(document).ready(function () {
3
+ postboxes.add_postbox_toggles(pagenow);
4
+ });
5
  </script>
6
  <?php
7
  $daysToDisplay = 20;
8
+ if ( array_key_exists('hitdays', $_GET) ) {
9
+ $daysToDisplay = intval($_GET['hitdays']);
10
  }
11
 
12
+ if ( array_key_exists('rangestart', $_GET) ) {
13
  $rangestart = $_GET['rangestart'];
14
  } else {
15
  $rangestart = '';
16
  }
17
+ if ( array_key_exists('rangeend', $_GET) ) {
18
  $rangeend = $_GET['rangeend'];
19
  } else {
20
  $rangeend = '';
21
  }
22
 
23
+ list( $daysToDisplay, $rangestart_utime, $rangeend_utime ) = wp_statistics_date_range_calculator(
24
+ $daysToDisplay,
25
+ $rangestart,
26
+ $rangeend
27
+ );
28
 
29
  ?>
30
  <div class="wrap">
31
+ <h2><?php _e('Top Countries', 'wp-statistics'); ?></h2>
32
+ <?php wp_statistics_date_range_selector(WP_Statistics::$page['countries'], $daysToDisplay); ?>
33
+ <div class="postbox-container" id="last-log">
34
+ <div class="metabox-holder">
35
+ <div class="meta-box-sortables">
36
+ <div class="postbox">
37
+ <?php $paneltitle = __('Top Countries', 'wp-statistics'); ?>
38
+ <button class="handlediv" type="button" aria-expanded="true">
39
+ <span class="screen-reader-text"><?php printf(
40
+ __('Toggle panel: %s', 'wp-statistics'),
41
+ $paneltitle
42
+ ); ?></span>
43
+ <span class="toggle-indicator" aria-hidden="true"></span>
44
+ </button>
45
+ <h2 class="hndle"><span><?php echo $paneltitle; ?></h2>
46
+
47
+ <div class="inside">
48
+ <table class="widefat table-stats" id="last-referrer" style="width: 100%;">
49
+ <tr>
50
+ <td><?php _e('Rank', 'wp-statistics'); ?></td>
51
+ <td><?php _e('Flag', 'wp-statistics'); ?></td>
52
+ <td><?php _e('Country', 'wp-statistics'); ?></td>
53
+ <td><?php _e('Visitor Count', 'wp-statistics'); ?></td>
54
+ </tr>
55
 
56
  <?php
57
  $ISOCountryCode = $WP_Statistics->get_country_codes();
58
 
59
+ $result = $wpdb->get_results(
60
+ "SELECT DISTINCT `location` FROM `{$wpdb->prefix}statistics_visitor`"
61
+ );
62
 
63
+ $rangestartdate = $WP_Statistics->real_current_date('Y-m-d', '-0', $rangestart_utime);
64
+ $rangeenddate = $WP_Statistics->real_current_date('Y-m-d', '-0', $rangeend_utime);
65
 
66
  foreach ( $result as $item ) {
67
+ $Countries[ $item->location ] = $wpdb->get_var(
68
+ $wpdb->prepare(
69
+ "SELECT count(location) FROM `{$wpdb->prefix}statistics_visitor` WHERE location=%s AND `last_counter` BETWEEN %s AND %s",
70
+ $item->location,
71
+ $rangestartdate,
72
+ $rangeenddate
73
+ )
74
+ );
75
  }
76
 
77
+ arsort($Countries);
78
  $i = 0;
79
 
80
  foreach ( $Countries as $item => $value ) {
81
+ $i++;
82
+ $item = strtoupper($item);
83
 
84
  echo "<tr>";
85
  echo "<td>$i</td>";
86
+ echo "<td><img src='" .
87
+ plugins_url('wp-statistics/assets/images/flags/' . $item . '.png') .
88
+ "' title='{$ISOCountryCode[$item]}'/></td>";
89
  echo "<td style='direction: ltr;'>{$ISOCountryCode[$item]}</td>";
90
+ echo "<td>" . number_format_i18n($value) . "</td>";
91
  echo "</tr>";
92
  }
93
  ?>
94
+ </table>
95
+ </div>
96
+ </div>
97
+ </div>
98
+ </div>
99
+ </div>
100
  </div>
includes/log/top-pages.php CHANGED
@@ -1,36 +1,43 @@
1
  <script type="text/javascript">
2
- jQuery(document).ready(function () {
3
- postboxes.add_postbox_toggles(pagenow);
4
- });
5
  </script>
6
  <?php
7
  $daysToDisplay = 20;
8
- if ( array_key_exists( 'hitdays', $_GET ) ) {
9
- $daysToDisplay = intval( $_GET['hitdays'] );
10
  }
11
 
12
- if ( array_key_exists( 'rangestart', $_GET ) ) {
13
  $rangestart = $_GET['rangestart'];
14
  } else {
15
  $rangestart = '';
16
  }
17
- if ( array_key_exists( 'rangeend', $_GET ) ) {
18
  $rangeend = $_GET['rangeend'];
19
  } else {
20
  $rangeend = '';
21
  }
22
 
23
- list( $daysToDisplay, $rangestart_utime, $rangeend_utime ) = wp_statistics_date_range_calculator( $daysToDisplay, $rangestart, $rangeend );
24
- $daysInThePast = round( ( time() - $rangeend_utime ) / 86400, 0 );
25
-
26
- list( $total, $uris ) = wp_statistics_get_top_pages( $WP_Statistics->Real_Current_Date( 'Y-m-d', '-0', $rangestart_utime ), $WP_Statistics->Real_Current_Date( 'Y-m-d', '-0', $rangeend_utime ) );
 
 
 
 
 
 
 
27
  $count = 0;
28
 
29
  foreach ( $uris as $uri ) {
30
- $count ++;
31
 
32
- for ( $i = $daysToDisplay; $i >= 0; $i -- ) {
33
- $stats[ $uri[0] ][] = wp_statistics_pages( '-' . ( $i + $daysInThePast ), $uri[0] );
34
  }
35
 
36
  if ( $count > 4 ) {
@@ -38,85 +45,93 @@ foreach ( $uris as $uri ) {
38
  }
39
  }
40
 
41
- for ( $i = $daysToDisplay; $i >= 0; $i -- ) {
42
- $date[] = "'" . $WP_Statistics->Current_Date( 'M j', '-' . $i ) . "'";
43
  }
44
  ?>
45
  <div class="wrap">
46
- <h2><?php _e( 'Top Pages', 'wp-statistics' ); ?></h2>
47
- <?php wp_statistics_date_range_selector( WP_STATISTICS_PAGES_PAGE, $daysToDisplay ); ?>
48
- <div class="postbox-container" id="last-log">
49
- <div class="metabox-holder">
50
- <div class="meta-box-sortables">
51
- <div class="postbox">
52
- <?php $paneltitle = __( 'Top 5 Pages Trends', 'wp-statistics' ); ?>
53
- <button class="handlediv" type="button" aria-expanded="true">
54
- <span class="screen-reader-text"><?php printf( __( 'Toggle panel: %s', 'wp-statistics' ), $paneltitle ); ?></span>
55
- <span class="toggle-indicator" aria-hidden="true"></span>
56
- </button>
57
- <h2 class="hndle"><span><?php echo $paneltitle; ?></h2>
58
- <div class="inside">
59
- <canvas id="hit-stats" height="80"></canvas>
60
- <script>
61
- var colors = [];
62
- colors[0] = ['rgba(12, 132, 132, 0.2)', 'rgba(12, 132, 132, 1)'];
63
- colors[1] = ['rgba(23, 107, 239, 0.2)', 'rgba(23, 107, 239, 1)'];
64
- colors[2] = ['rgba(222, 88, 51, 0.2)', 'rgba(222, 88, 51, 1)'];
65
- colors[3] = ['rgba(255, 99, 132, 0.2)', 'rgba(255, 99, 132, 1)'];
66
- colors[4] = ['rgba(54, 162, 235, 0.2)', 'rgba(54, 162, 235, 1)'];
67
-
68
- var ctx = document.getElementById("hit-stats").getContext('2d');
69
- var ChartJs = new Chart(ctx, {
70
- type: 'line',
71
- data: {
72
- labels: [<?php echo implode( ', ', $date ); ?>],
73
- datasets: [
 
 
 
 
74
  <?php foreach ($stats as $key => $value) : $i++; ?>
75
- {
76
- label: '<?php echo $key; ?>',
77
- data: [<?php echo implode( ',', $value ); ?>],
78
- backgroundColor: colors[<?php echo $i; ?>][0],
79
- borderColor: colors[<?php echo $i; ?>][1],
80
- fill: true,
81
- borderWidth: 1,
82
- },
83
  <?php endforeach; ?>
84
- ]
85
- },
86
- options: {
87
- responsive: true,
88
- legend: {
89
- position: 'bottom',
90
- },
91
- title: {
92
- display: true,
93
- text: '<?php echo htmlentities( __( 'Top 5 Page Trending Stats', 'wp-statistics' ), ENT_QUOTES ); ?>'
94
- },
95
- tooltips: {
96
- mode: 'index',
97
- intersect: false,
98
- },
99
- scales: {
100
- yAxes: [{
101
- ticks: {
102
- beginAtZero: true
103
- }
104
- }]
105
- }
106
- }
107
- });
108
- </script>
109
- </div>
110
- </div>
111
-
112
- <div class="postbox">
113
- <?php $paneltitle = __( 'Top Pages', 'wp-statistics' ); ?>
114
- <button class="handlediv" type="button" aria-expanded="true">
115
- <span class="screen-reader-text"><?php printf( __( 'Toggle panel: %s', 'wp-statistics' ), $paneltitle ); ?></span>
116
- <span class="toggle-indicator" aria-hidden="true"></span>
117
- </button>
118
- <h2 class="hndle"><span><?php echo $paneltitle; ?></h2>
119
- <div class="inside">
 
 
 
 
120
  <?php
121
  if ( $total > 0 ) {
122
  // Instantiate pagination object with appropriate arguments
@@ -127,7 +142,16 @@ for ( $i = $daysToDisplay; $i >= 0; $i -- ) {
127
  $styleErrors = "paginationErrors";
128
  $styleSelect = "paginationSelect";
129
 
130
- $Pagination = new WP_Statistics_Pagination( $total, $pagesPerSection, $options, false, $stylePageOff, $stylePageOn, $styleErrors, $styleSelect );
 
 
 
 
 
 
 
 
 
131
 
132
  $start = $Pagination->getEntryStart();
133
  $end = $Pagination->getEntryEnd();
@@ -138,18 +162,32 @@ for ( $i = $daysToDisplay; $i >= 0; $i -- ) {
138
  $count = 0;
139
 
140
  foreach ( $uris as $uri ) {
141
- $count ++;
142
 
143
  if ( $count >= $start ) {
144
  echo "<div class='log-item'>";
145
 
146
  if ( $uri[3] == '' ) {
147
- $uri[3] = '[' . htmlentities( __( 'No page title found', 'wp-statistics' ), ENT_QUOTES ) . ']';
 
 
148
  }
149
 
150
  echo "<div class='log-page-title'>{$count} - {$uri[3]}</div>";
151
- echo "<div class='right-div'>" . __( 'Visits', 'wp-statistics' ) . ": <a href='?page=" . WP_STATISTICS_PAGES_PAGE . '&page-uri=' . htmlentities( $uri[0], ENT_QUOTES ) . "'>" . number_format_i18n( $uri[1] ) . "</a></div>";
152
- echo "<div class='left-div'><a dir='ltr' href='" . htmlentities( $site_url . $uri[0], ENT_QUOTES ) . "'>" . htmlentities( urldecode( $uri[0] ), ENT_QUOTES ) . "</a></div>";
 
 
 
 
 
 
 
 
 
 
 
 
153
  echo "</div>";
154
  }
155
 
@@ -162,16 +200,20 @@ for ( $i = $daysToDisplay; $i >= 0; $i -- ) {
162
  echo "</div>";
163
  }
164
  ?>
165
- </div>
166
- </div>
167
 
168
  <?php if ( $total > 0 ) { ?>
169
- <div class="pagination-log">
170
  <?php echo $Pagination->display(); ?>
171
- <p id="result-log"><?php printf( __( 'Page %1$s of %2$s', 'wp-statistics' ), $Pagination->getCurrentPage(), $Pagination->getTotalPages() ); ?></p>
172
- </div>
 
 
 
 
173
  <?php } ?>
174
- </div>
175
- </div>
176
- </div>
177
  </div>
1
  <script type="text/javascript">
2
+ jQuery(document).ready(function () {
3
+ postboxes.add_postbox_toggles(pagenow);
4
+ });
5
  </script>
6
  <?php
7
  $daysToDisplay = 20;
8
+ if ( array_key_exists('hitdays', $_GET) ) {
9
+ $daysToDisplay = intval($_GET['hitdays']);
10
  }
11
 
12
+ if ( array_key_exists('rangestart', $_GET) ) {
13
  $rangestart = $_GET['rangestart'];
14
  } else {
15
  $rangestart = '';
16
  }
17
+ if ( array_key_exists('rangeend', $_GET) ) {
18
  $rangeend = $_GET['rangeend'];
19
  } else {
20
  $rangeend = '';
21
  }
22
 
23
+ list( $daysToDisplay, $rangestart_utime, $rangeend_utime ) = wp_statistics_date_range_calculator(
24
+ $daysToDisplay,
25
+ $rangestart,
26
+ $rangeend
27
+ );
28
+ $daysInThePast = round(( time() - $rangeend_utime ) / 86400, 0);
29
+
30
+ list( $total, $uris ) = wp_statistics_get_top_pages(
31
+ $WP_Statistics->Real_Current_Date('Y-m-d', '-0', $rangestart_utime),
32
+ $WP_Statistics->Real_Current_Date('Y-m-d', '-0', $rangeend_utime)
33
+ );
34
  $count = 0;
35
 
36
  foreach ( $uris as $uri ) {
37
+ $count++;
38
 
39
+ for ( $i = $daysToDisplay; $i >= 0; $i-- ) {
40
+ $stats[ $uri[0] ][] = wp_statistics_pages('-' . ( $i + $daysInThePast ), $uri[0]);
41
  }
42
 
43
  if ( $count > 4 ) {
45
  }
46
  }
47
 
48
+ for ( $i = $daysToDisplay; $i >= 0; $i-- ) {
49
+ $date[] = "'" . $WP_Statistics->Current_Date('M j', '-' . $i) . "'";
50
  }
51
  ?>
52
  <div class="wrap">
53
+ <h2><?php _e('Top Pages', 'wp-statistics'); ?></h2>
54
+ <?php wp_statistics_date_range_selector(WP_Statistics::$page['pages'], $daysToDisplay); ?>
55
+ <div class="postbox-container" id="last-log">
56
+ <div class="metabox-holder">
57
+ <div class="meta-box-sortables">
58
+ <div class="postbox">
59
+ <?php $paneltitle = __('Top 5 Pages Trends', 'wp-statistics'); ?>
60
+ <button class="handlediv" type="button" aria-expanded="true">
61
+ <span class="screen-reader-text"><?php printf(
62
+ __('Toggle panel: %s', 'wp-statistics'),
63
+ $paneltitle
64
+ ); ?></span>
65
+ <span class="toggle-indicator" aria-hidden="true"></span>
66
+ </button>
67
+ <h2 class="hndle"><span><?php echo $paneltitle; ?></h2>
68
+
69
+ <div class="inside">
70
+ <canvas id="hit-stats" height="80"></canvas>
71
+ <script>
72
+ var colors = [];
73
+ colors[0] = ['rgba(12, 132, 132, 0.2)', 'rgba(12, 132, 132, 1)'];
74
+ colors[1] = ['rgba(23, 107, 239, 0.2)', 'rgba(23, 107, 239, 1)'];
75
+ colors[2] = ['rgba(222, 88, 51, 0.2)', 'rgba(222, 88, 51, 1)'];
76
+ colors[3] = ['rgba(255, 99, 132, 0.2)', 'rgba(255, 99, 132, 1)'];
77
+ colors[4] = ['rgba(54, 162, 235, 0.2)', 'rgba(54, 162, 235, 1)'];
78
+
79
+ var ctx = document.getElementById("hit-stats").getContext('2d');
80
+ var ChartJs = new Chart(ctx, {
81
+ type: 'line',
82
+ data: {
83
+ labels: [<?php echo implode( ', ', $date ); ?>],
84
+ datasets: [
85
  <?php foreach ($stats as $key => $value) : $i++; ?>
86
+ {
87
+ label: '<?php echo $key; ?>',
88
+ data: [<?php echo implode( ',', $value ); ?>],
89
+ backgroundColor: colors[<?php echo $i; ?>][0],
90
+ borderColor: colors[<?php echo $i; ?>][1],
91
+ fill: true,
92
+ borderWidth: 1,
93
+ },
94
  <?php endforeach; ?>
95
+ ]
96
+ },
97
+ options: {
98
+ responsive: true,
99
+ legend: {
100
+ position: 'bottom',
101
+ },
102
+ title: {
103
+ display: true,
104
+ text: '<?php echo htmlentities( __( 'Top 5 Page Trending Stats', 'wp-statistics' ), ENT_QUOTES ); ?>'
105
+ },
106
+ tooltips: {
107
+ mode: 'index',
108
+ intersect: false,
109
+ },
110
+ scales: {
111
+ yAxes: [{
112
+ ticks: {
113
+ beginAtZero: true
114
+ }
115
+ }]
116
+ }
117
+ }
118
+ });
119
+ </script>
120
+ </div>
121
+ </div>
122
+
123
+ <div class="postbox">
124
+ <?php $paneltitle = __('Top Pages', 'wp-statistics'); ?>
125
+ <button class="handlediv" type="button" aria-expanded="true">
126
+ <span class="screen-reader-text"><?php printf(
127
+ __('Toggle panel: %s', 'wp-statistics'),
128
+ $paneltitle
129
+ ); ?></span>
130
+ <span class="toggle-indicator" aria-hidden="true"></span>
131
+ </button>
132
+ <h2 class="hndle"><span><?php echo $paneltitle; ?></h2>
133
+
134
+ <div class="inside">
135
  <?php
136
  if ( $total > 0 ) {
137
  // Instantiate pagination object with appropriate arguments
142
  $styleErrors = "paginationErrors";
143
  $styleSelect = "paginationSelect";
144
 
145
+ $Pagination = new WP_Statistics_Pagination(
146
+ $total,
147
+ $pagesPerSection,
148
+ $options,
149
+ false,
150
+ $stylePageOff,
151
+ $stylePageOn,
152
+ $styleErrors,
153
+ $styleSelect
154
+ );
155
 
156
  $start = $Pagination->getEntryStart();
157
  $end = $Pagination->getEntryEnd();
162
  $count = 0;
163
 
164
  foreach ( $uris as $uri ) {
165
+ $count++;
166
 
167
  if ( $count >= $start ) {
168
  echo "<div class='log-item'>";
169
 
170
  if ( $uri[3] == '' ) {
171
+ $uri[3] = '[' .
172
+ htmlentities(__('No page title found', 'wp-statistics'), ENT_QUOTES) .
173
+ ']';
174
  }
175
 
176
  echo "<div class='log-page-title'>{$count} - {$uri[3]}</div>";
177
+ echo "<div class='right-div'>" .
178
+ __('Visits', 'wp-statistics') .
179
+ ": <a href='?page=" .
180
+ WP_Statistics::$page['pages'] .
181
+ '&page-uri=' .
182
+ htmlentities($uri[0], ENT_QUOTES) .
183
+ "'>" .
184
+ number_format_i18n($uri[1]) .
185
+ "</a></div>";
186
+ echo "<div class='left-div'><a dir='ltr' href='" .
187
+ htmlentities($site_url . $uri[0], ENT_QUOTES) .
188
+ "'>" .
189
+ htmlentities(urldecode($uri[0]), ENT_QUOTES) .
190
+ "</a></div>";
191
  echo "</div>";
192
  }
193
 
200
  echo "</div>";
201
  }
202
  ?>
203
+ </div>
204
+ </div>
205
 
206
  <?php if ( $total > 0 ) { ?>
207
+ <div class="pagination-log">
208
  <?php echo $Pagination->display(); ?>
209
+ <p id="result-log"><?php printf(
210
+ __('Page %1$s of %2$s', 'wp-statistics'),
211
+ $Pagination->getCurrentPage(),
212
+ $Pagination->getTotalPages()
213
+ ); ?></p>
214
+ </div>
215
  <?php } ?>
216
+ </div>
217
+ </div>
218
+ </div>
219
  </div>
includes/log/top-referring.php CHANGED
@@ -1,40 +1,44 @@
1
  <script type="text/javascript">
2
- jQuery(document).ready(function () {
3
- jQuery('.show-map').click(function () {
4
- alert('<?php _e( 'To be added soon', 'wp-statistics' ); ?>');
5
- });
6
 
7
- postboxes.add_postbox_toggles(pagenow);
8
- });
9
  </script>
10
  <?php
11
  $date_args = '';
12
  $daysToDisplay = 20;
13
- if ( array_key_exists( 'hitdays', $_GET ) ) {
14
- $daysToDisplay = intval( esc_attr($_GET['hitdays']) );
15
- $date_args .= '&hitdays=' . $daysToDisplay;
16
  }
17
 
18
- if ( array_key_exists( 'rangestart', $_GET ) ) {
19
  $rangestart = esc_attr($_GET['rangestart']);
20
- $date_args .= '&rangestart=' . $rangestart;
21
  } else {
22
  $rangestart = '';
23
  }
24
 
25
- if ( array_key_exists( 'rangeend', $_GET ) ) {
26
- $rangeend = esc_attr($_GET['rangeend']);
27
  $date_args .= '&rangeend=' . $rangeend;
28
  } else {
29
  $rangeend = '';
30
  }
31
 
32
- list( $daysToDisplay, $rangestart_utime, $rangeend_utime ) = wp_statistics_date_range_calculator( $daysToDisplay, $rangestart, $rangeend );
 
 
 
 
33
 
34
- $rangestartdate = $WP_Statistics->real_current_date( 'Y-m-d', '-0', $rangestart_utime );
35
- $rangeenddate = $WP_Statistics->real_current_date( 'Y-m-d', '-0', $rangeend_utime );
36
 
37
- if ( array_key_exists( 'referr', $_GET ) ) {
38
  $referr = $_GET['referr'];
39
  $title = $_GET['referr'];
40
  $referr_field = '&referr=' . $referr;
@@ -47,69 +51,104 @@ $get_urls = array();
47
  $total = 0;
48
 
49
  if ( $referr ) {
50
- $result = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM `{$wpdb->prefix}statistics_visitor` WHERE `referred` LIKE %s AND referred <> '' AND `last_counter` BETWEEN %s AND %s ORDER BY `{$wpdb->prefix}statistics_visitor`.`ID` DESC", '%' . $referr . '%', $rangestartdate, $rangeenddate ) );
 
 
 
 
 
 
 
51
 
52
- $total = count( $result );
53
  } else {
54
- $result = $wpdb->get_results( $wpdb->prepare( "SELECT referred FROM {$wpdb->prefix}statistics_visitor WHERE referred <> '' AND `last_counter` BETWEEN %s AND %s", $rangestartdate, $rangeenddate ) );
 
 
 
 
 
 
55
 
56
  $urls = array();
57
  foreach ( $result as $item ) {
58
 
59
- $url = parse_url( $item->referred );
60
 
61
- if ( empty( $url['host'] ) || stristr( get_bloginfo( 'url' ), $url['host'] ) ) {
62
  continue;
63
  }
64
 
65
  $urls[] = $url['scheme'] . '://' . $url['host'];
66
  }
67
 
68
- $get_urls = array_count_values( $urls );
69
 
70
- $total = count( $get_urls );
71
  }
72
 
73
  ?>
74
  <div class="wrap">
75
- <h2><?php _e( 'Top Referring Sites', 'wp-statistics' ); ?></h2>
76
 
77
- <div><?php wp_statistics_date_range_selector( WP_STATISTICS_REFERRERS_PAGE, $daysToDisplay, null, null, $referr_field ); ?></div>
 
 
 
 
 
 
78
 
79
- <div class="clear"/>
80
 
81
- <ul class="subsubsub">
82
  <?php if ( $referr ) { ?>
83
- <li class="all"><a <?php if ( ! $referr ) {
84
  echo 'class="current"';
85
- } ?>href="?page=<?php echo WP_STATISTICS_REFERRERS_PAGE . $date_args; ?>"><?php _e( 'All', 'wp-statistics' ); ?></a>
86
- </li>
87
- |
88
- <li>
89
- <a class="current" href="?page=<?php echo WP_STATISTICS_REFERRERS_PAGE; ?>&referr=<?php echo $WP_Statistics->html_sanitize_referrer( $referr ) . $date_args; ?>"> <?php echo htmlentities( $title, ENT_QUOTES ); ?>
90
- <span class="count">(<?php echo $total; ?>)</span></a></li>
 
 
 
 
 
 
91
  <?php } else { ?>
92
- <li class="all"><a <?php if ( ! $referr ) {
93
  echo 'class="current"';
94
- } ?>href="?page=<?php echo WP_STATISTICS_REFERRERS_PAGE . $date_args; ?>"><?php _e( 'All', 'wp-statistics' ); ?>
95
- <span class="count">(<?php echo $total; ?>)</span></a></li>
 
 
 
96
  <?php } ?>
97
- </ul>
98
- <div class="postbox-container" id="last-log">
99
- <div class="metabox-holder">
100
- <div class="meta-box-sortables">
101
- <div class="postbox">
102
- <?php if ( $referr ) {
103
- $paneltitle = sprintf( __( 'Referring site: %s', 'wp-statistics' ), $WP_Statistics->html_sanitize_referrer( $referr ) );
104
- } else {
105
- $paneltitle = __( 'Top Referring Sites', 'wp-statistics' );
106
- }; ?>
107
- <button class="handlediv" type="button" aria-expanded="true">
108
- <span class="screen-reader-text"><?php printf( __( 'Toggle panel: %s', 'wp-statistics' ), $paneltitle ); ?></span>
109
- <span class="toggle-indicator" aria-hidden="true"></span>
110
- </button>
111
- <h2 class="hndle"><span><?php echo $paneltitle; ?></h2>
112
- <div class="inside">
 
 
 
 
 
 
 
113
  <?php
114
  echo "<div class='log-latest'>";
115
 
@@ -122,54 +161,101 @@ if ( $referr ) {
122
  $styleErrors = "paginationErrors";
123
  $styleSelect = "paginationSelect";
124
 
125
- $Pagination = new WP_Statistics_Pagination( $total, $pagesPerSection, $options, false, $stylePageOff, $stylePageOn, $styleErrors, $styleSelect );
 
 
 
 
 
 
 
 
 
126
 
127
  $start = $Pagination->getEntryStart();
128
  $end = $Pagination->getEntryEnd();
129
 
130
  if ( $referr ) {
131
- if ( $WP_Statistics->get_option( 'search_converted' ) ) {
132
- $result = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM `{$wpdb->prefix}statistics_search` INNER JOIN `{$wpdb->prefix}statistics_visitor` on {$wpdb->prefix}statistics_search.`visitor` = {$wpdb->prefix}statistics_visitor.`ID` WHERE `host` = %s AND {$wpdb->prefix}statistics_visitor.`last_counter` BETWEEN %s AND %s ORDER BY `{$wpdb->prefix}statistics_search`.`ID` DESC LIMIT %d, %d", $referr, $rangestartdate, $rangeenddate, $start, $end ) );
 
 
 
 
 
 
 
 
 
133
  }
134
 
135
  foreach ( $result as $item ) {
136
  echo "<div class='log-item'>";
137
- echo "<div class='log-referred'><a href='?page=" . WP_STATISTICS_OVERVIEW_PAGE . "&type=last-all-visitor&ip={$item->ip}'>" . wp_statistics_icons( 'dashicons-visibility', 'visibility' ) . "{$item->ip}</a></div>";
138
- echo "<div class='log-ip'>" . date( get_option( 'date_format' ), strtotime( $item->last_counter ) ) . " - <a href='http://www.geoiptool.com/en/?IP={$item->ip}' target='_blank'>{$item->ip}</a></div>";
 
 
 
 
 
 
139
  echo "<div class='clear'></div>";
140
- echo "<a class='show-map' title='" . __( 'Map', 'wp-statistics' ) . "'><div class='dashicons dashicons-location-alt'></div></a>";
141
-
142
- if ( array_search( strtolower( $item->agent ), array(
143
- 'chrome',
144
- 'firefox',
145
- 'msie',
146
- 'opera',
147
- 'safari'
148
- ) ) !== false
 
 
 
 
 
149
  ) {
150
- $agent = "<img src='" . plugins_url( 'wp-statistics/assets/images/' ) . $item->agent . ".png' class='log-tools' title='{$item->agent}'/>";
 
 
 
151
  } else {
152
  $agent = "<div class='dashicons dashicons-editor-help'></div>";
153
  }
154
 
155
- echo "<div class='log-agent'><a href='?page=" . WP_STATISTICS_OVERVIEW_PAGE . "&type=last-all-visitor&agent={$item->agent}'>{$agent}</a>";
156
- echo $WP_Statistics->get_referrer_link( $item->referred, 100 ) . '</div>';
 
 
157
  echo "</div>";
158
  }
159
  } else {
160
- arsort( $get_urls );
161
- $get_urls = array_slice( $get_urls, $start, $end );
162
 
163
  $i = $start;
164
  foreach ( $get_urls as $items => $value ) {
165
- $i ++;
166
- $referrer_html = $WP_Statistics->html_sanitize_referrer( $items );
167
  $referrer_html = parse_url($referrer_html)['host'];
168
  echo "<div class='log-item'>";
169
- echo "<div class='log-referred'>{$i} - <a href='?page=" . WP_STATISTICS_REFERRERS_PAGE . "&referr=" . $referrer_html . $date_args . "'>" . $referrer_html . "</a></div>";
170
- echo "<div class='log-ip'>" . __( 'References', 'wp-statistics' ) . ': ' . number_format_i18n( $value ) . '</div>';
 
 
 
 
 
 
 
 
 
 
 
171
  echo "<div class='clear'></div>";
172
- echo "<div class='log-url'>" . $WP_Statistics->get_referrer_link( $items, 100 ) . '</div>';
 
 
173
  echo "</div>";
174
  }
175
  }
@@ -177,16 +263,20 @@ if ( $referr ) {
177
 
178
  echo '</div>';
179
  ?>
180
- </div>
181
- </div>
182
 
183
- <div class="pagination-log">
184
  <?php if ( $total > 0 ) {
185
  echo $Pagination->display(); ?>
186
- <p id="result-log"><?php printf( __( 'Page %1$s of %2$s', 'wp-statistics' ), $Pagination->getCurrentPage(), $Pagination->getTotalPages() ); ?></p>
 
 
 
 
187
  <?php } ?>
188
- </div>
189
- </div>
190
- </div>
191
- </div>
192
- </div>
1
  <script type="text/javascript">
2
+ jQuery(document).ready(function () {
3
+ jQuery('.show-map').click(function () {
4
+ alert('<?php _e( 'To be added soon', 'wp-statistics' ); ?>');
5
+ });
6
 
7
+ postboxes.add_postbox_toggles(pagenow);
8
+ });
9
  </script>
10
  <?php
11
  $date_args = '';
12
  $daysToDisplay = 20;
13
+ if ( array_key_exists('hitdays', $_GET) ) {
14
+ $daysToDisplay = intval(esc_attr($_GET['hitdays']));
15
+ $date_args .= '&hitdays=' . $daysToDisplay;
16
  }
17
 
18
+ if ( array_key_exists('rangestart', $_GET) ) {
19
  $rangestart = esc_attr($_GET['rangestart']);
20
+ $date_args .= '&rangestart=' . $rangestart;
21
  } else {
22
  $rangestart = '';
23
  }
24
 
25
+ if ( array_key_exists('rangeend', $_GET) ) {
26
+ $rangeend = esc_attr($_GET['rangeend']);
27
  $date_args .= '&rangeend=' . $rangeend;
28
  } else {
29
  $rangeend = '';
30
  }
31
 
32
+ list( $daysToDisplay, $rangestart_utime, $rangeend_utime ) = wp_statistics_date_range_calculator(
33
+ $daysToDisplay,
34
+ $rangestart,
35
+ $rangeend
36
+ );
37
 
38
+ $rangestartdate = $WP_Statistics->real_current_date('Y-m-d', '-0', $rangestart_utime);
39
+ $rangeenddate = $WP_Statistics->real_current_date('Y-m-d', '-0', $rangeend_utime);
40
 
41
+ if ( array_key_exists('referr', $_GET) ) {
42
  $referr = $_GET['referr'];
43
  $title = $_GET['referr'];
44
  $referr_field = '&referr=' . $referr;
51
  $total = 0;
52
 
53
  if ( $referr ) {
54
+ $result = $wpdb->get_results(
55
+ $wpdb->prepare(
56
+ "SELECT * FROM `{$wpdb->prefix}statistics_visitor` WHERE `referred` LIKE %s AND referred <> '' AND `last_counter` BETWEEN %s AND %s ORDER BY `{$wpdb->prefix}statistics_visitor`.`ID` DESC",
57
+ '%' . $referr . '%',
58
+ $rangestartdate,
59
+ $rangeenddate
60
+ )
61
+ );
62
 
63
+ $total = count($result);
64
  } else {
65
+ $result = $wpdb->get_results(
66
+ $wpdb->prepare(
67
+ "SELECT referred FROM {$wpdb->prefix}statistics_visitor WHERE referred <> '' AND `last_counter` BETWEEN %s AND %s",
68
+ $rangestartdate,
69
+ $rangeenddate
70
+ )
71
+ );
72
 
73
  $urls = array();
74
  foreach ( $result as $item ) {
75
 
76
+ $url = parse_url($item->referred);
77
 
78
+ if ( empty( $url['host'] ) || stristr(get_bloginfo('url'), $url['host']) ) {
79
  continue;
80
  }
81
 
82
  $urls[] = $url['scheme'] . '://' . $url['host'];
83
  }
84
 
85
+ $get_urls = array_count_values($urls);
86
 
87
+ $total = count($get_urls);
88
  }
89
 
90
  ?>
91
  <div class="wrap">
92
+ <h2><?php _e('Top Referring Sites', 'wp-statistics'); ?></h2>
93
 
94
+ <div><?php wp_statistics_date_range_selector(
95
+ WP_Statistics::$page['referrers'],
96
+ $daysToDisplay,
97
+ null,
98
+ null,
99
+ $referr_field
100
+ ); ?></div>
101
 
102
+ <div class="clear"/>
103
 
104
+ <ul class="subsubsub">
105
  <?php if ( $referr ) { ?>
106
+ <li class="all"><a <?php if ( ! $referr ) {
107
  echo 'class="current"';
108
+ } ?>href="?page=<?php echo WP_Statistics::$page['referrers'] . $date_args; ?>"><?php _e(
109
+ 'All',
110
+ 'wp-statistics'
111
+ ); ?></a>
112
+ </li>
113
+ |
114
+ <li>
115
+ <a class="current"
116
+ href="?page=<?php echo WP_Statistics::$page['referrers']; ?>&referr=<?php echo $WP_Statistics->html_sanitize_referrer(
117
+ $referr
118
+ ) . $date_args; ?>"> <?php echo htmlentities($title, ENT_QUOTES); ?>
119
+ <span class="count">(<?php echo $total; ?>)</span></a></li>
120
  <?php } else { ?>
121
+ <li class="all"><a <?php if ( ! $referr ) {
122
  echo 'class="current"';
123
+ } ?>href="?page=<?php echo WP_Statistics::$page['referrers'] . $date_args; ?>"><?php _e(
124
+ 'All',
125
+ 'wp-statistics'
126
+ ); ?>
127
+ <span class="count">(<?php echo $total; ?>)</span></a></li>
128
  <?php } ?>
129
+ </ul>
130
+ <div class="postbox-container" id="last-log">
131
+ <div class="metabox-holder">
132
+ <div class="meta-box-sortables">
133
+ <div class="postbox">
134
+ <?php if ( $referr ) {
135
+ $paneltitle = sprintf(
136
+ __('Referring site: %s', 'wp-statistics'),
137
+ $WP_Statistics->html_sanitize_referrer($referr)
138
+ );
139
+ } else {
140
+ $paneltitle = __('Top Referring Sites', 'wp-statistics');
141
+ }; ?>
142
+ <button class="handlediv" type="button" aria-expanded="true">
143
+ <span class="screen-reader-text"><?php printf(
144
+ __('Toggle panel: %s', 'wp-statistics'),
145
+ $paneltitle
146
+ ); ?></span>
147
+ <span class="toggle-indicator" aria-hidden="true"></span>
148
+ </button>
149
+ <h2 class="hndle"><span><?php echo $paneltitle; ?></h2>
150
+
151
+ <div class="inside">
152
  <?php
153
  echo "<div class='log-latest'>";
154
 
161
  $styleErrors = "paginationErrors";
162
  $styleSelect = "paginationSelect";
163
 
164
+ $Pagination = new WP_Statistics_Pagination(
165
+ $total,
166
+ $pagesPerSection,
167
+ $options,
168
+ false,
169
+ $stylePageOff,
170
+ $stylePageOn,
171
+ $styleErrors,
172
+ $styleSelect
173
+ );
174
 
175
  $start = $Pagination->getEntryStart();
176
  $end = $Pagination->getEntryEnd();
177
 
178
  if ( $referr ) {
179
+ if ( $WP_Statistics->get_option('search_converted') ) {
180
+ $result = $wpdb->get_results(
181
+ $wpdb->prepare(
182
+ "SELECT * FROM `{$wpdb->prefix}statistics_search` INNER JOIN `{$wpdb->prefix}statistics_visitor` on {$wpdb->prefix}statistics_search.`visitor` = {$wpdb->prefix}statistics_visitor.`ID` WHERE `host` = %s AND {$wpdb->prefix}statistics_visitor.`last_counter` BETWEEN %s AND %s ORDER BY `{$wpdb->prefix}statistics_search`.`ID` DESC LIMIT %d, %d",
183
+ $referr,
184
+ $rangestartdate,
185
+ $rangeenddate,
186
+ $start,
187
+ $end
188
+ )
189
+ );
190
  }
191
 
192
  foreach ( $result as $item ) {
193
  echo "<div class='log-item'>";
194
+ echo "<div class='log-referred'><a href='?page=" .
195
+ WP_Statistics::$page['overview'] .
196
+ "&type=last-all-visitor&ip={$item->ip}'>" .
197
+ wp_statistics_icons('dashicons-visibility', 'visibility') .
198
+ "{$item->ip}</a></div>";
199
+ echo "<div class='log-ip'>" .
200
+ date(get_option('date_format'), strtotime($item->last_counter)) .
201
+ " - <a href='http://www.geoiptool.com/en/?IP={$item->ip}' target='_blank'>{$item->ip}</a></div>";
202
  echo "<div class='clear'></div>";
203
+ echo "<a class='show-map' title='" .
204
+ __('Map', 'wp-statistics') .
205
+ "'><div class='dashicons dashicons-location-alt'></div></a>";
206
+
207
+ if ( array_search(
208
+ strtolower($item->agent),
209
+ array(
210
+ 'chrome',
211
+ 'firefox',
212
+ 'msie',
213
+ 'opera',
214
+ 'safari',
215
+ )
216
+ ) !== false
217
  ) {
218
+ $agent = "<img src='" .
219
+ plugins_url('wp-statistics/assets/images/') .
220
+ $item->agent .
221
+ ".png' class='log-tools' title='{$item->agent}'/>";
222
  } else {
223
  $agent = "<div class='dashicons dashicons-editor-help'></div>";
224
  }
225
 
226
+ echo "<div class='log-agent'><a href='?page=" .
227
+ WP_Statistics::$page['overview'] .
228
+ "&type=last-all-visitor&agent={$item->agent}'>{$agent}</a>";
229
+ echo $WP_Statistics->get_referrer_link($item->referred, 100) . '</div>';
230
  echo "</div>";
231
  }
232
  } else {
233
+ arsort($get_urls);
234
+ $get_urls = array_slice($get_urls, $start, $end);
235
 
236
  $i = $start;
237
  foreach ( $get_urls as $items => $value ) {
238
+ $i++;
239
+ $referrer_html = $WP_Statistics->html_sanitize_referrer($items);
240
  $referrer_html = parse_url($referrer_html)['host'];
241
  echo "<div class='log-item'>";
242
+ echo "<div class='log-referred'>{$i} - <a href='?page=" .
243
+ WP_Statistics::$page['referrers'] .
244
+ "&referr=" .
245
+ $referrer_html .
246
+ $date_args .
247
+ "'>" .
248
+ $referrer_html .
249
+ "</a></div>";
250
+ echo "<div class='log-ip'>" .
251
+ __('References', 'wp-statistics') .
252
+ ': ' .
253
+ number_format_i18n($value) .
254
+ '</div>';
255
  echo "<div class='clear'></div>";
256
+ echo "<div class='log-url'>" .
257
+ $WP_Statistics->get_referrer_link($items, 100) .
258
+ '</div>';
259
  echo "</div>";
260
  }
261
  }
263
 
264
  echo '</div>';
265
  ?>
266
+ </div>
267
+ </div>
268
 
269
+ <div class="pagination-log">
270
  <?php if ( $total > 0 ) {
271
  echo $Pagination->display(); ?>
272
+ <p id="result-log"><?php printf(
273
+ __('Page %1$s of %2$s', 'wp-statistics'),
274
+ $Pagination->getCurrentPage(),
275
+ $Pagination->getTotalPages()
276
+ ); ?></p>
277
  <?php } ?>
278
+ </div>
279
+ </div>
280
+ </div>
281
+ </div>
282
+ </div>
includes/log/top-visitors.php CHANGED
@@ -1,56 +1,75 @@
1
  <script type="text/javascript">
2
- jQuery(document).ready(function () {
3
- postboxes.add_postbox_toggles(pagenow);
4
- });
5
  </script>
6
  <?php
7
  $ISOCountryCode = $WP_Statistics->get_country_codes();
8
- include_once( dirname( __FILE__ ) . '/widgets/top.visitors.php' );
9
  ?>
10
  <div class="wrap">
11
- <h2><?php _e( 'Top 100 Visitors Today', 'wp-statistics' ); ?></h2>
12
  <?php
13
- wp_enqueue_script( 'jquery-ui-datepicker' );
14
- wp_register_style( 'jquery-ui-smoothness-css', $WP_Statistics->plugin_url . 'assets/css/jquery-ui-smoothness.min.css' );
15
- wp_enqueue_style( 'jquery-ui-smoothness-css' );
 
 
 
16
 
17
  $current = 0;
18
 
19
- $statsdate = $WP_Statistics->Current_Date( 'm/d/Y', '-' . $current );
20
 
21
- if ( array_key_exists( 'statsdate', $_GET ) ) {
22
  $statsdate = $_GET['statsdate'];
23
  }
24
 
25
  echo '<br><form method="get">' . "\r\n";
26
 
27
- echo ' ' . __( 'Date', 'wp-statistics' ) . ': ';
28
 
29
- echo '<input type="hidden" name="page" value="' . WP_STATISTICS_TOP_VISITORS_PAGE . '">' . "\r\n";
30
- echo '<input type="text" size="10" name="statsdate" id="statsdate" value="' . htmlentities( $statsdate, ENT_QUOTES ) . '" placeholder="' . __( 'MM/DD/YYYY', 'wp-statistics' ) . '"> <input type="submit" value="' . __( 'Go', 'wp-statistics' ) . '" class="button-primary">' . "\r\n";
 
 
 
 
 
 
 
31
 
32
  echo '</form>' . "\r\n";
33
 
34
  echo '<script>jQuery(function() { jQuery( "#statsdate" ).datepicker(); } );</script>' . "\r\n";
35
 
36
  ?>
37
- <div class="postbox-container" id="last-log" style="width: 100%;">
38
- <div class="metabox-holder">
39
- <div class="meta-box-sortables">
40
- <div class="postbox">
41
- <?php $paneltitle = __( 'Top Visitors', 'wp-statistics' ); ?>
42
- <button class="handlediv" type="button" aria-expanded="true">
43
- <span class="screen-reader-text"><?php printf( __( 'Toggle panel: %s', 'wp-statistics' ), $paneltitle ); ?></span>
44
- <span class="toggle-indicator" aria-hidden="true"></span>
45
- </button>
46
- <h2 class="hndle"><span><?php echo $paneltitle; ?></h2>
47
- <div class="inside">
48
-
49
- <?php wp_statistics_generate_top_visitors_postbox_content( $ISOCountryCode, $statsdate, 100, false ); ?>
50
-
51
- </div>
52
- </div>
53
- </div>
54
- </div>
55
- </div>
 
 
 
 
 
 
 
 
 
56
  </div>
1
  <script type="text/javascript">
2
+ jQuery(document).ready(function () {
3
+ postboxes.add_postbox_toggles(pagenow);
4
+ });
5
  </script>
6
  <?php
7
  $ISOCountryCode = $WP_Statistics->get_country_codes();
8
+ include( WP_Statistics::$reg['plugin-dir'] . 'includes/log/widgets/top.visitors.php' );
9
  ?>
10
  <div class="wrap">
11
+ <h2><?php _e('Top 100 Visitors Today', 'wp-statistics'); ?></h2>
12
  <?php
13
+ wp_enqueue_script('jquery-ui-datepicker');
14
+ wp_register_style(
15
+ 'jquery-ui-smoothness-css',
16
+ WP_Statistics::$reg['plugin-url'] . 'assets/css/jquery-ui-smoothness.min.css'
17
+ );
18
+ wp_enqueue_style('jquery-ui-smoothness-css');
19
 
20
  $current = 0;
21
 
22
+ $statsdate = $WP_Statistics->Current_Date('m/d/Y', '-' . $current);
23
 
24
+ if ( array_key_exists('statsdate', $_GET) ) {
25
  $statsdate = $_GET['statsdate'];
26
  }
27
 
28
  echo '<br><form method="get">' . "\r\n";
29
 
30
+ echo ' ' . __('Date', 'wp-statistics') . ': ';
31
 
32
+ echo '<input type="hidden" name="page" value="' . WP_Statistics::$page['top-visitors'] . '">' . "\r\n";
33
+ echo '<input type="text" size="10" name="statsdate" id="statsdate" value="' .
34
+ htmlentities($statsdate, ENT_QUOTES) .
35
+ '" placeholder="' .
36
+ __('MM/DD/YYYY', 'wp-statistics') .
37
+ '"> <input type="submit" value="' .
38
+ __('Go', 'wp-statistics') .
39
+ '" class="button-primary">' .
40
+ "\r\n";
41
 
42
  echo '</form>' . "\r\n";
43
 
44
  echo '<script>jQuery(function() { jQuery( "#statsdate" ).datepicker(); } );</script>' . "\r\n";
45
 
46
  ?>
47
+ <div class="postbox-container" id="last-log" style="width: 100%;">
48
+ <div class="metabox-holder">
49
+ <div class="meta-box-sortables">
50
+ <div class="postbox">
51
+ <?php $paneltitle = __('Top Visitors', 'wp-statistics'); ?>
52
+ <button class="handlediv" type="button" aria-expanded="true">
53
+ <span class="screen-reader-text"><?php printf(
54
+ __('Toggle panel: %s', 'wp-statistics'),
55
+ $paneltitle
56
+ ); ?></span>
57
+ <span class="toggle-indicator" aria-hidden="true"></span>
58
+ </button>
59
+ <h2 class="hndle"><span><?php echo $paneltitle; ?></h2>
60
+
61
+ <div class="inside">
62
+
63
+ <?php wp_statistics_generate_top_visitors_postbox_content(
64
+ $ISOCountryCode,
65
+ $statsdate,
66
+ 100,
67
+ false
68
+ ); ?>
69
+
70
+ </div>
71
+ </div>
72
+ </div>
73
+ </div>
74
+ </div>
75
  </div>
includes/log/widgets/about.php CHANGED
@@ -3,31 +3,43 @@ function wp_statistics_generate_about_postbox_content() {
3
 
4
  global $wpdb, $WP_Statistics;
5
  ?>
6
- <div style="text-align: center;">
7
- <a href="http://wp-statistics.com" target="_blank"><img src="<?php echo plugins_url( 'wp-statistics/assets/images/logo-250.png' ); ?>"></a>
8
- </div>
 
9
 
10
- <div id="about-links" style="text-align: center;">
11
- <p><a href="http://wp-statistics.com" target="_blank"><?php _e( 'Website', 'wp-statistics' ); ?></a></p>
12
- | <p>
13
- <a href="http://wordpress.org/support/view/plugin-reviews/wp-statistics" target="_blank"><?php _e( 'Rate and Review', 'wp-statistics' ); ?></a>
14
- </p>
 
 
 
15
  <?php
16
- if ( current_user_can( wp_statistics_validate_capability( $WP_Statistics->get_option( 'manage_capability', 'manage_options' ) ) ) ) {
 
 
17
  ?>
18
- | <p>
19
- <a href="?page=<?php echo WP_STATISTICS_SETTINGS_PAGE; ?>&tab=about"><?php _e( 'More Information', 'wp-statistics' ); ?></a>
20
- </p>
 
 
 
21
  <?php
22
  }
23
  ?>
24
- </div>
25
 
26
- <hr/>
27
 
28
- <div>
29
- <?php echo sprintf( __( 'This product includes GeoLite2 data created by %s.', 'wp-statistics' ), '<a href="http://www.maxmind.com" target=_blank>MaxMind</a>' ); ?>
30
- </div>
 
 
 
31
  <?php
32
  }
33
 
3
 
4
  global $wpdb, $WP_Statistics;
5
  ?>
6
+ <div style="text-align: center;">
7
+ <a href="http://wp-statistics.com" target="_blank"><img
8
+ src="<?php echo plugins_url('wp-statistics/assets/images/logo-250.png'); ?>"></a>
9
+ </div>
10
 
11
+ <div id="about-links" style="text-align: center;">
12
+ <p><a href="http://wp-statistics.com" target="_blank"><?php _e('Website', 'wp-statistics'); ?></a></p>
13
+ | <p>
14
+ <a href="https://wordpress.org/support/plugin/wp-statistics/reviews/?rate=5#new-post" target="_blank"><?php _e(
15
+ 'Rate and Review',
16
+ 'wp-statistics'
17
+ ); ?></a>
18
+ </p>
19
  <?php
20
+ if ( current_user_can(
21
+ wp_statistics_validate_capability($WP_Statistics->get_option('manage_capability', 'manage_options'))
22
+ ) ) {
23
  ?>
24
+ | <p>
25
+ <a href="?page=<?php echo WP_Statistics::$page['settings']; ?>&tab=about"><?php _e(
26
+ 'More Information',
27
+ 'wp-statistics'
28
+ ); ?></a>
29
+ </p>
30
  <?php
31
  }
32
  ?>
33
+ </div>
34
 
35
+ <hr/>
36
 
37
+ <div>
38
+ <?php echo sprintf(
39
+ __('This product includes GeoLite2 data created by %s.', 'wp-statistics'),
40
+ '<a href="http://www.maxmind.com" target=_blank>MaxMind</a>'
41
+ ); ?>
42
+ </div>
43
  <?php
44
  }
45
 
includes/log/widgets/browsers.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
  function wp_statistics_generate_browsers_postbox_content() {
3
  global $wpdb, $WP_Statistics;
4
- $id = 'browser-stats-' . rand( 111, 999 );
5
  $Browsers = wp_statistics_ua_list();
6
  $BrowserVisits = array();
7
  $total = 0;
@@ -11,66 +11,66 @@ function wp_statistics_generate_browsers_postbox_content() {
11
  $topten_browser_value = array();
12
 
13
  foreach ( $Browsers as $Browser ) {
14
- $BrowserVisits[ $Browser ] = wp_statistics_useragent( $Browser );
15
- $total += $BrowserVisits[ $Browser ];
16
  }
17
 
18
- arsort( $BrowserVisits );
19
 
20
  foreach ( $BrowserVisits as $key => $value ) {
21
  $topten += $value;
22
- $count ++;
23
  if ( $count > 9 ) {
24
  break;
25
  }
26
 
27
  $topten_browser_name[] = "'" . $key . "'";
28
  $topten_browser_value[] = $value;
29
- $topten_browser_color[] = wp_statistics_generate_rgba_color( $count, '0.4' );
30
  }
31
 
32
  if ( $topten_browser_name and $topten_browser_value ) {
33
- $topten_browser_name[] = "'" . __( 'Other', 'wp-statistics' ) . "'";
34
  $topten_browser_value[] = ( $total - $topten );
35
- $topten_browser_color[] = wp_statistics_generate_rgba_color( 10, '0.4' );
36
  }
37
  ?>
38
- <canvas id="<?php echo $id; ?>" height="220"></canvas>
39
- <script>
40
- var ctx = document.getElementById("<?php echo $id; ?>").getContext('2d');
41
- var ChartJs = new Chart(ctx, {
42
- type: 'pie',
43
- data: {
44
- labels: [<?php echo implode( ', ', $topten_browser_name ); ?>],
45
- datasets: [{
46
- label: '<?php _e( 'Browsers', 'wp-statistics' ); ?>',
47
- data: [<?php echo implode( ', ', $topten_browser_value ); ?>],
48
- backgroundColor: [<?php echo implode( ', ', $topten_browser_color ); ?>],
49
- }]
50
- },
51
- options: {
52
- responsive: true,
53
- legend: {
54
- position: 'bottom',
55
- },
56
- animation: {
57
- duration: 0,
58
- },
59
- tooltips: {
60
- callbacks: {
61
- label: function (tooltipItem, data) {
62
- var dataset = data.datasets[tooltipItem.datasetIndex];
63
- var total = dataset.data.reduce(function (previousValue, currentValue, currentIndex, array) {
64
- return previousValue + currentValue;
65
- });
66
- var currentValue = dataset.data[tooltipItem.index];
67
- var precentage = Math.floor(((currentValue / total) * 100) + 0.5);
68
- return precentage + "% - " + data.labels[tooltipItem.index];
69
- }
70
- }
71
- }
72
- }
73
- });
74
- </script>
75
  <?php
76
  }
1
  <?php
2
  function wp_statistics_generate_browsers_postbox_content() {
3
  global $wpdb, $WP_Statistics;
4
+ $id = 'browser-stats-' . rand(111, 999);
5
  $Browsers = wp_statistics_ua_list();
6
  $BrowserVisits = array();
7
  $total = 0;
11
  $topten_browser_value = array();
12
 
13
  foreach ( $Browsers as $Browser ) {
14
+ $BrowserVisits[ $Browser ] = wp_statistics_useragent($Browser);
15
+ $total += $BrowserVisits[ $Browser ];
16
  }
17
 
18
+ arsort($BrowserVisits);
19
 
20
  foreach ( $BrowserVisits as $key => $value ) {
21
  $topten += $value;
22
+ $count++;
23
  if ( $count > 9 ) {
24
  break;
25
  }
26
 
27
  $topten_browser_name[] = "'" . $key . "'";
28
  $topten_browser_value[] = $value;
29
+ $topten_browser_color[] = wp_statistics_generate_rgba_color($count, '0.4');
30
  }
31
 
32
  if ( $topten_browser_name and $topten_browser_value ) {
33
+ $topten_browser_name[] = "'" . __('Other', 'wp-statistics') . "'";
34
  $topten_browser_value[] = ( $total - $topten );
35
+ $topten_browser_color[] = wp_statistics_generate_rgba_color(10, '0.4');
36
  }
37
  ?>
38
+ <canvas id="<?php echo $id; ?>" height="220"></canvas>
39
+ <script>
40
+ var ctx = document.getElementById("<?php echo $id; ?>").getContext('2d');
41
+ var ChartJs = new Chart(ctx, {
42
+ type: 'pie',
43
+ data: {
44
+ labels: [<?php echo implode( ', ', $topten_browser_name ); ?>],
45
+ datasets: [{
46
+ label: '<?php _e( 'Browsers', 'wp-statistics' ); ?>',
47
+ data: [<?php echo implode( ', ', $topten_browser_value ); ?>],
48
+ backgroundColor: [<?php echo implode( ', ', $topten_browser_color ); ?>],
49
+ }]
50
+ },
51
+ options: {
52
+ responsive: true,
53
+ legend: {
54
+ position: 'bottom',
55
+ },
56
+ animation: {
57
+ duration: 0,
58
+ },
59
+ tooltips: {
60
+ callbacks: {
61
+ label: function (tooltipItem, data) {
62
+ var dataset = data.datasets[tooltipItem.datasetIndex];
63
+ var total = dataset.data.reduce(function (previousValue, currentValue, currentIndex, array) {
64
+ return previousValue + currentValue;
65
+ });
66
+ var currentValue = dataset.data[tooltipItem.index];
67
+ var precentage = Math.floor(((currentValue / total) * 100) + 0.5);
68
+ return precentage + "% - " + data.labels[tooltipItem.index];
69
+ }
70
+ }
71
+ }
72
+ }
73
+ });
74
+ </script>
75
  <?php
76
  }
includes/log/widgets/countries.php CHANGED
@@ -4,36 +4,43 @@ function wp_statistics_generate_countries_postbox_content( $ISOCountryCode, $cou
4
  global $wpdb, $WP_Statistics;
5
 
6
  ?>
7
- <table width="100%" class="widefat table-stats" id="last-referrer">
8
- <tr>
9
- <td width="10%" style='text-align: left'><?php _e( 'Rank', 'wp-statistics' ); ?></td>
10
- <td width="10%" style='text-align: left'><?php _e( 'Flag', 'wp-statistics' ); ?></td>
11
- <td width="40%" style='text-align: left'><?php _e( 'Country', 'wp-statistics' ); ?></td>
12
- <td width="40%" style='text-align: left'><?php _e( 'Visitor Count', 'wp-statistics' ); ?></td>
13
- </tr>
14
 
15
  <?php
16
  $Countries = array();
17
 
18
- $result = $wpdb->get_results( "SELECT DISTINCT `location` FROM `{$wpdb->prefix}statistics_visitor`" );
19
 
20
  foreach ( $result as $item ) {
21
- $Countries[ $item->location ] = $wpdb->get_var( $wpdb->prepare( "SELECT count(location) FROM `{$wpdb->prefix}statistics_visitor` WHERE location=%s", $item->location ) );
 
 
 
 
 
22
  }
23
 
24
- arsort( $Countries );
25
  $i = 0;
26
 
27
  foreach ( $Countries as $item => $value ) {
28
- $i ++;
29
 
30
- $item = strtoupper( $item );
31
 
32
  echo "<tr>";
33
  echo "<td style='text-align: left'>$i</td>";
34
- echo "<td style='text-align: left'><img src='" . plugins_url( 'wp-statistics/assets/images/flags/' . $item . '.png' ) . "' title='{$ISOCountryCode[$item]}'/></td>";
 
 
35
  echo "<td style='text-align: left'>{$ISOCountryCode[$item]}</td>";
36
- echo "<td style='text-align: left'>" . number_format_i18n( $value ) . "</td>";
37
  echo "</tr>";
38
 
39
  if ( $i == $count ) {
@@ -41,7 +48,7 @@ function wp_statistics_generate_countries_postbox_content( $ISOCountryCode, $cou
41
  }
42
  }
43
  ?>
44
- </table>
45
  <?php
46
  }
47
 
4
  global $wpdb, $WP_Statistics;
5
 
6
  ?>
7
+ <table width="100%" class="widefat table-stats" id="last-referrer">
8
+ <tr>
9
+ <td width="10%" style='text-align: left'><?php _e('Rank', 'wp-statistics'); ?></td>
10
+ <td width="10%" style='text-align: left'><?php _e('Flag', 'wp-statistics'); ?></td>
11
+ <td width="40%" style='text-align: left'><?php _e('Country', 'wp-statistics'); ?></td>
12
+ <td width="40%" style='text-align: left'><?php _e('Visitor Count', 'wp-statistics'); ?></td>
13
+ </tr>
14
 
15
  <?php
16
  $Countries = array();
17
 
18
+ $result = $wpdb->get_results("SELECT `location` FROM `{$wpdb->prefix}statistics_visitor` GROUP BY `location`");
19
 
20
  foreach ( $result as $item ) {
21
+ $Countries[ $item->location ] = $wpdb->get_var(
22
+ $wpdb->prepare(
23
+ "SELECT count(location) FROM `{$wpdb->prefix}statistics_visitor` WHERE location=%s",
24
+ $item->location
25
+ )
26
+ );
27
  }
28
 
29
+ arsort($Countries);
30
  $i = 0;
31
 
32
  foreach ( $Countries as $item => $value ) {
33
+ $i++;
34
 
35
+ $item = strtoupper($item);
36
 
37
  echo "<tr>";
38
  echo "<td style='text-align: left'>$i</td>";
39
+ echo "<td style='text-align: left'><img src='" .
40
+ plugins_url('wp-statistics/assets/images/flags/' . $item . '.png') .
41
+ "' title='{$ISOCountryCode[$item]}'/></td>";
42
  echo "<td style='text-align: left'>{$ISOCountryCode[$item]}</td>";
43
+ echo "<td style='text-align: left'>" . number_format_i18n($value) . "</td>";
44
  echo "</tr>";
45
 
46
  if ( $i == $count ) {
48
  }
49
  }
50
  ?>
51
+ </table>
52
  <?php
53
  }
54
 
includes/log/widgets/hits.php CHANGED
@@ -1,77 +1,77 @@
1
  <?php
2
  function wp_statistics_generate_hits_postbox_content( $size = '300', $days = 20 ) {
3
  global $wpdb, $WP_Statistics;
4
- $id = 'visits-stats-' . rand( 111, 999 );
5
  $visitors = array();
6
  $visits = array();
7
 
8
- for ( $i = $days; $i >= 0; $i -- ) {
9
- $date[] = "'" . $WP_Statistics->Current_Date( 'M j', '-' . $i ) . "'";
10
  }
11
 
12
- for ( $i = $days; $i >= 0; $i -- ) {
13
- $visitors[] = wp_statistics_visitor( '-' . $i, true );
14
  }
15
 
16
- for ( $i = $days; $i >= 0; $i -- ) {
17
- $visits[] = wp_statistics_visit( '-' . $i, true );
18
  }
19
  ?>
20
- <canvas id="<?php echo $id; ?>" height="<?php echo $size; ?>"></canvas>
21
- <script>
22
- var ctx = document.getElementById("<?php echo $id; ?>").getContext('2d');
23
- var ChartJs = new Chart(ctx, {
24
- type: 'line',
25
- data: {
26
- labels: [<?php echo implode( ', ', $date ); ?>],
27
- datasets: [
28
  <?php if ( $WP_Statistics->get_option( 'visitors' ) ) { ?>
29
- {
30
- label: '<?php _e( 'Visitors', 'wp-statistics' ); ?>',
31
- data: [<?php echo implode( ',', $visitors ); ?>],
32
- backgroundColor: 'rgba(255, 99, 132, 0.2)',
33
- borderColor: 'rgba(255, 99, 132, 1)',
34
- borderWidth: 1,
35
- fill: true,
36
- },
37
  <?php } ?>
38
  <?php if ( $WP_Statistics->get_option( 'visits' ) ) { ?>
39
- {
40
- label: '<?php _e( 'Visits', 'wp-statistics' ); ?>',
41
- data: [<?php echo implode( ',', $visits ); ?>],
42
- backgroundColor: 'rgba(54, 162, 235, 0.2)',
43
- borderColor: 'rgba(54, 162, 235, 1)',
44
- borderWidth: 1,
45
- fill: true,
46
- },
47
  <?php } ?>
48
- ]
49
- },
50
- options: {
51
- responsive: true,
52
- legend: {
53
- position: 'bottom',
54
- },
55
- animation: {
56
- duration: 0,
57
- },
58
- title: {
59
- display: true,
60
- text: '<?php echo sprintf( __( 'Hits in the last %s days', 'wp-statistics' ), $days ); ?>'
61
- },
62
- tooltips: {
63
- mode: 'index',
64
- intersect: false,
65
- },
66
- scales: {
67
- yAxes: [{
68
- ticks: {
69
- beginAtZero: true
70
- }
71
- }]
72
- }
73
- }
74
- });
75
- </script>
76
  <?php
77
  }
1
  <?php
2
  function wp_statistics_generate_hits_postbox_content( $size = '300', $days = 20 ) {
3
  global $wpdb, $WP_Statistics;
4
+ $id = 'visits-stats-' . rand(111, 999);
5
  $visitors = array();
6
  $visits = array();
7
 
8
+ for ( $i = $days; $i >= 0; $i-- ) {
9
+ $date[] = "'" . $WP_Statistics->Current_Date('M j', '-' . $i) . "'";
10
  }
11
 
12
+ for ( $i = $days; $i >= 0; $i-- ) {
13
+ $visitors[] = wp_statistics_visitor('-' . $i, true);
14
  }
15
 
16
+ for ( $i = $days; $i >= 0; $i-- ) {
17
+ $visits[] = wp_statistics_visit('-' . $i, true);
18
  }
19
  ?>
20
+ <canvas id="<?php echo $id; ?>" height="<?php echo $size; ?>"></canvas>
21
+ <script>
22
+ var ctx = document.getElementById("<?php echo $id; ?>").getContext('2d');
23
+ var ChartJs = new Chart(ctx, {
24
+ type: 'line',
25
+ data: {
26
+ labels: [<?php echo implode( ', ', $date ); ?>],
27
+ datasets: [
28
  <?php if ( $WP_Statistics->get_option( 'visitors' ) ) { ?>
29
+ {
30
+ label: '<?php _e( 'Visitors', 'wp-statistics' ); ?>',
31
+ data: [<?php echo implode( ',', $visitors ); ?>],
32
+ backgroundColor: 'rgba(255, 99, 132, 0.2)',
33
+ borderColor: 'rgba(255, 99, 132, 1)',
34
+ borderWidth: 1,
35
+ fill: true,
36
+ },
37
  <?php } ?>
38
  <?php if ( $WP_Statistics->get_option( 'visits' ) ) { ?>
39
+ {
40
+ label: '<?php _e( 'Visits', 'wp-statistics' ); ?>',
41
+ data: [<?php echo implode( ',', $visits ); ?>],
42
+ backgroundColor: 'rgba(54, 162, 235, 0.2)',
43
+ borderColor: 'rgba(54, 162, 235, 1)',
44
+ borderWidth: 1,
45
+ fill: true,
46
+ },
47
  <?php } ?>
48
+ ]
49
+ },
50
+ options: {
51
+ responsive: true,
52
+ legend: {
53
+ position: 'bottom',
54
+ },
55
+ animation: {
56
+ duration: 0,
57
+ },
58
+ title: {
59
+ display: true,
60
+ text: '<?php echo sprintf( __( 'Hits in the last %s days', 'wp-statistics' ), $days ); ?>'
61
+ },
62
+ tooltips: {
63
+ mode: 'index',
64
+ intersect: false,
65
+ },
66
+ scales: {
67
+ yAxes: [{
68
+ ticks: {
69
+ beginAtZero: true
70
+ }
71
+ }]
72
+ }
73
+ }
74
+ });
75
+ </script>
76
  <?php
77
  }
includes/log/widgets/jqv.map.php CHANGED
@@ -3,15 +3,17 @@ function wp_statistics_generate_map_postbox_content( $ISOCountryCode ) {
3
 
4
  global $wpdb, $WP_Statistics;
5
 
6
- if ( $WP_Statistics->get_option( 'geoip' ) && ! $WP_Statistics->get_option( 'disable_map' ) ) { ?>
7
- <div id="map_canvas"></div>
8
 
9
- <?php $result = $wpdb->get_row( "SELECT * FROM `{$wpdb->prefix}statistics_visitor` WHERE last_counter = '{$WP_Statistics->Current_Date('Y-m-d')}'" ); ?>
10
- <script type="text/javascript">
11
- var country_pin = Array();
12
- var country_color = Array();
 
 
13
 
14
- jQuery(document).ready(function () {
15
 
16
  <?php
17
  $result = $wpdb->get_results( "SELECT * FROM `{$wpdb->prefix}statistics_visitor` WHERE last_counter = '{$WP_Statistics->Current_Date('Y-m-d')}'" );
@@ -26,7 +28,7 @@ function wp_statistics_generate_map_postbox_content( $ISOCountryCode ) {
26
  (
27
  'location' => $new_r->location,
28
  'agent' => $new_r->agent,
29
- 'ip' => $new_r->ip
30
  );
31
  }
32
  }
@@ -53,7 +55,7 @@ function wp_statistics_generate_map_postbox_content( $ISOCountryCode ) {
53
  "firefox",
54
  "msie",
55
  "opera",
56
- "safari"
57
  ) ) !== false
58
  ) {
59
  $agent = "<img src='" . plugins_url( 'wp-statistics/assets/images/' ) . $markets['agent'] . ".png' class='log-tools' title='{$markets['agent']}'/>";
@@ -82,29 +84,29 @@ function wp_statistics_generate_map_postbox_content( $ISOCountryCode ) {
82
 
83
  $color = sprintf( "#%02X%02X%02X", round( $startColor[0] + ( $endColor[0] - $startColor[0] ) * $market_total / $final_total ), round( $startColor[1] + ( $endColor[1] - $startColor[1] ) * $market_total / $final_total ), round( $startColor[2] + ( $endColor[2] - $startColor[2] ) * $market_total / $final_total ) );
84
  ?>
85
- country_pin['<?php echo $markets['location'];?>'] = "<div class='map-html-marker'><?php echo $flag . $summary . '<hr />' . $last_five; ?></div>";
86
- country_color['<?php echo $markets['location'];?>'] = "<?php echo $color;?>";
87
  <?php
88
  }
89
  ?>
90
- var data_total = <?php echo $final_total;?>;
91
-
92
- jQuery('#map_canvas').vectorMap({
93
- map: 'world_en',
94
- colors: country_color,
95
- onLabelShow: function (element, label, code) {
96
- if (country_pin[code] !== undefined) {
97
- label.html(country_pin[code]);
98
- }
99
- else {
100
- label.html(label.html() + ' [0]<hr />');
101
- }
102
- },
103
- });
104
-
105
-
106
- });
107
- </script>
108
  <?php
109
  }
110
  }
3
 
4
  global $wpdb, $WP_Statistics;
5
 
6
+ if ( $WP_Statistics->get_option('geoip') && ! $WP_Statistics->get_option('disable_map') ) { ?>
7
+ <div id="map_canvas"></div>
8
 
9
+ <?php $result = $wpdb->get_row(
10
+ "SELECT * FROM `{$wpdb->prefix}statistics_visitor` WHERE last_counter = '{$WP_Statistics->Current_Date('Y-m-d')}'"
11
+ ); ?>
12
+ <script type="text/javascript">
13
+ var country_pin = Array();
14
+ var country_color = Array();
15
 
16
+ jQuery(document).ready(function () {
17
 
18
  <?php
19
  $result = $wpdb->get_results( "SELECT * FROM `{$wpdb->prefix}statistics_visitor` WHERE last_counter = '{$WP_Statistics->Current_Date('Y-m-d')}'" );
28
  (
29
  'location' => $new_r->location,
30
  'agent' => $new_r->agent,
31
+ 'ip' => $new_r->ip,
32
  );
33
  }
34
  }
55
  "firefox",
56
  "msie",
57
  "opera",
58
+ "safari",
59
  ) ) !== false
60
  ) {
61
  $agent = "<img src='" . plugins_url( 'wp-statistics/assets/images/' ) . $markets['agent'] . ".png' class='log-tools' title='{$markets['agent']}'/>";
84
 
85
  $color = sprintf( "#%02X%02X%02X", round( $startColor[0] + ( $endColor[0] - $startColor[0] ) * $market_total / $final_total ), round( $startColor[1] + ( $endColor[1] - $startColor[1] ) * $market_total / $final_total ), round( $startColor[2] + ( $endColor[2] - $startColor[2] ) * $market_total / $final_total ) );
86
  ?>
87
+ country_pin['<?php echo $markets['location'];?>'] = "<div class='map-html-marker'><?php echo $flag . $summary . '<hr />' . $last_five; ?></div>";
88
+ country_color['<?php echo $markets['location'];?>'] = "<?php echo $color;?>";
89
  <?php
90
  }
91
  ?>
92
+ var data_total = <?php echo $final_total;?>;
93
+
94
+ jQuery('#map_canvas').vectorMap({
95
+ map: 'world_en',
96
+ colors: country_color,
97
+ onLabelShow: function (element, label, code) {
98
+ if (country_pin[code] !== undefined) {
99
+ label.html(country_pin[code]);
100
+ }
101
+ else {
102
+ label.html(label.html() + ' [0]<hr />');
103
+ }
104
+ },
105
+ });
106
+
107
+
108
+ });
109
+ </script>
110
  <?php
111
  }
112
  }
includes/log/widgets/page.php CHANGED
@@ -1,30 +1,37 @@
1
  <?php
2
  /**
3
- * @param $pageuri
4
- * @param $pageid
5
- * @param int $days
6
- * @param null $chart_title
7
  * @param string $rangestart
8
  * @param string $rangeend
9
  */
10
- function wp_statistics_generate_page_postbox_content( $pageuri, $pageid, $days = 20, $chart_title = null, $rangestart = '', $rangeend = '' ) {
 
 
 
 
 
 
 
11
  GLOBAL $WP_Statistics;
12
 
13
- if ( ! $WP_Statistics->get_option( 'pages' ) ) {
14
  return;
15
  }
16
 
17
  if ( $chart_title == null ) {
18
- $chart_title = __( 'Page Trending Stats', 'wp-statistics' );
19
  }
20
 
21
  if ( $pageuri && ! $pageid ) {
22
- $pageid = wp_statistics_uri_to_id( $pageuri );
23
  }
24
 
25
- $post = get_post( $pageid );
26
- if ( is_object( $post ) ) {
27
- $title = esc_html( $post->post_title );
28
  } else {
29
  $title = "";
30
  }
@@ -34,59 +41,63 @@ function wp_statistics_generate_page_postbox_content( $pageuri, $pageid, $days =
34
  $urlfields .= "&page-uri={$pageuri}";
35
  }
36
 
37
- list( $daysToDisplay, $rangestart_utime, $rangeend_utime ) = wp_statistics_date_range_calculator( $days, $rangestart, $rangeend );
38
- $daysInThePast = round( ( time() - $rangeend_utime ) / 86400, 0 );
 
 
 
 
39
 
40
- for ( $i = $days; $i >= 0; $i -- ) {
41
- $date[] = "'" . $WP_Statistics->Current_Date( 'M j', '-' . $i ) . "'";
42
  }
43
 
44
- for ( $i = $daysToDisplay; $i >= 0; $i -- ) {
45
- $stats[] = wp_statistics_pages( '-' . ( $i + $daysInThePast ), $pageuri, $pageid );
46
  }
47
  ?>
48
- <canvas id="visits-stats" height="80"></canvas>
49
- <script>
50
- var ctx = document.getElementById("visits-stats").getContext('2d');
51
- var ChartJs = new Chart(ctx, {
52
- type: 'line',
53
- data: {
54
- labels: [<?php echo implode( ', ', $date ); ?>],
55
- datasets: [
56
  <?php if ( $WP_Statistics->get_option( 'visitors' ) ) { ?>
57
- {
58
- label: '<?php echo $title; ?>',
59
- data: [<?php echo implode( ',', $stats ); ?>],
60
- backgroundColor: 'rgba(255, 99, 132, 0.2)',
61
- borderColor: 'rgba(255, 99, 132, 1)',
62
- borderWidth: 1,
63
- fill: true,
64
- },
65
  <?php } ?>
66
- ]
67
- },
68
- options: {
69
- responsive: true,
70
- legend: {
71
- position: 'bottom',
72
- },
73
- title: {
74
- display: true,
75
- text: '<?php _e( 'Number of Hits', 'wp-statistics' ); ?>'
76
- },
77
- tooltips: {
78
- mode: 'index',
79
- intersect: false,
80
- },
81
- scales: {
82
- yAxes: [{
83
- ticks: {
84
- beginAtZero: true
85
- }
86
- }]
87
- }
88
- }
89
- });
90
- </script>
91
  <?php
92
  }
1
  <?php
2
  /**
3
+ * @param $pageuri
4
+ * @param $pageid
5
+ * @param int $days
6
+ * @param null $chart_title
7
  * @param string $rangestart
8
  * @param string $rangeend
9
  */
10
+ function wp_statistics_generate_page_postbox_content(
11
+ $pageuri,
12
+ $pageid,
13
+ $days = 20,
14
+ $chart_title = null,
15
+ $rangestart = '',
16
+ $rangeend = ''
17
+ ) {
18
  GLOBAL $WP_Statistics;
19
 
20
+ if ( ! $WP_Statistics->get_option('pages') ) {
21
  return;
22
  }
23
 
24
  if ( $chart_title == null ) {
25
+ $chart_title = __('Page Trending Stats', 'wp-statistics');
26
  }
27
 
28
  if ( $pageuri && ! $pageid ) {
29
+ $pageid = wp_statistics_uri_to_id($pageuri);
30
  }
31
 
32
+ $post = get_post($pageid);
33
+ if ( is_object($post) ) {
34
+ $title = esc_html($post->post_title);
35
  } else {
36
  $title = "";
37
  }
41
  $urlfields .= "&page-uri={$pageuri}";
42
  }
43
 
44
+ list( $daysToDisplay, $rangestart_utime, $rangeend_utime ) = wp_statistics_date_range_calculator(
45
+ $days,
46
+ $rangestart,
47
+ $rangeend
48
+ );
49
+ $daysInThePast = round(( time() - $rangeend_utime ) / 86400, 0);
50
 
51
+ for ( $i = $days; $i >= 0; $i-- ) {
52
+ $date[] = "'" . $WP_Statistics->Current_Date('M j', '-' . $i) . "'";
53
  }
54
 
55
+ for ( $i = $daysToDisplay; $i >= 0; $i-- ) {
56
+ $stats[] = wp_statistics_pages('-' . ( $i + $daysInThePast ), $pageuri, $pageid);
57
  }
58
  ?>
59
+ <canvas id="visits-stats" height="80"></canvas>
60
+ <script>
61
+ var ctx = document.getElementById("visits-stats").getContext('2d');
62
+ var ChartJs = new Chart(ctx, {
63
+ type: 'line',
64
+ data: {
65
+ labels: [<?php echo implode( ', ', $date ); ?>],
66
+ datasets: [
67
  <?php if ( $WP_Statistics->get_option( 'visitors' ) ) { ?>
68
+ {
69
+ label: '<?php echo $title; ?>',
70
+ data: [<?php echo implode( ',', $stats ); ?>],
71
+ backgroundColor: 'rgba(255, 99, 132, 0.2)',
72
+ borderColor: 'rgba(255, 99, 132, 1)',
73
+ borderWidth: 1,
74
+ fill: true,
75
+ },
76
  <?php } ?>
77
+ ]
78
+ },
79
+ options: {
80
+ responsive: true,
81
+ legend: {
82
+ position: 'bottom',
83
+ },
84
+ title: {
85
+ display: true,
86
+ text: '<?php _e( 'Number of Hits', 'wp-statistics' ); ?>'
87
+ },
88
+ tooltips: {
89
+ mode: 'index',
90
+ intersect: false,
91
+ },
92
+ scales: {
93
+ yAxes: [{
94
+ ticks: {
95
+ beginAtZero: true
96
+ }
97
+ }]
98
+ }
99
+ }
100
+ });
101
+ </script>
102
  <?php
103
  }
includes/log/widgets/pages.php CHANGED
@@ -7,16 +7,28 @@ function wp_statistics_generate_pages_postbox_content( $total, $uris ) {
7
  $site_url = site_url();
8
 
9
  foreach ( $uris as $uri ) {
10
- $i ++;
11
  echo '<div class="log-item">';
12
 
13
  if ( empty( $uri[3] ) ) {
14
- $uri[3] = '[' . __( 'No page title found', 'wp-statistics' ) . ']';
15
  }
16
 
17
  echo "<div class=\"log-page-title\">{$i} - {$uri[3]}</div>";
18
- echo '<div class="right-div">' . __( 'Visits', 'wp-statistics' ) . ': <a href="?page=' . WP_STATISTICS_PAGES_PAGE . '&page-uri=' . htmlentities( $uri[0], ENT_QUOTES ) . '">' . number_format_i18n( $uri[1] ) . '</a></div>';
19
- echo '<div><a href="' . htmlentities( $site_url . $uri[0], ENT_QUOTES ) . '">' . htmlentities( urldecode( $uri[0] ), ENT_QUOTES ) . '</a></div>';
 
 
 
 
 
 
 
 
 
 
 
 
20
  echo '</div>';
21
 
22
  if ( $i > 9 ) {
7
  $site_url = site_url();
8
 
9
  foreach ( $uris as $uri ) {
10
+ $i++;
11
  echo '<div class="log-item">';
12
 
13
  if ( empty( $uri[3] ) ) {
14
+ $uri[3] = '[' . __('No page title found', 'wp-statistics') . ']';
15
  }
16
 
17
  echo "<div class=\"log-page-title\">{$i} - {$uri[3]}</div>";
18
+ echo '<div class="right-div">' .
19
+ __('Visits', 'wp-statistics') .
20
+ ': <a href="?page=' .
21
+ WP_Statistics::$page['pages'] .
22
+ '&page-uri=' .
23
+ htmlentities($uri[0], ENT_QUOTES) .
24
+ '">' .
25
+ number_format_i18n($uri[1]) .
26
+ '</a></div>';
27
+ echo '<div><a href="' .
28
+ htmlentities($site_url . $uri[0], ENT_QUOTES) .
29
+ '">' .
30
+ htmlentities(urldecode($uri[0]), ENT_QUOTES) .
31
+ '</a></div>';
32
  echo '</div>';
33
 
34
  if ( $i > 9 ) {
includes/log/widgets/quickstats.php CHANGED
@@ -3,212 +3,284 @@ function wp_statistics_generate_quickstats_postbox_content( $search_engines, $se
3
 
4
  global $wpdb, $WP_Statistics;
5
 
6
- $show_visitors = $WP_Statistics->get_option( 'visitor' );
7
  ?>
8
- <table width="100%" class="widefat table-stats" id="summary-stats">
9
- <tbody>
10
- <?php if ( $WP_Statistics->get_option( 'useronline' ) ) { ?>
11
- <tr>
12
- <th><?php _e( 'Online Users', 'wp-statistics' ); ?>:</th>
13
- <th colspan="2" id="th-colspan">
14
- <span><a href="admin.php?page=<?php echo WP_STATISTICS_ONLINE_PAGE; ?>"><?php echo wp_statistics_useronline(); ?></a></span>
15
- </th>
16
- </tr>
 
 
17
  <?php }
18
 
19
- if ( $WP_Statistics->get_option( 'visitors' ) || $WP_Statistics->get_option( 'visits' ) ) {
20
  ?>
21
- <tr>
22
- <th width="60%"></th>
23
- <th class="th-center"><?php if ( $WP_Statistics->get_option( 'visitors' ) ) {
24
- _e( 'Visitors', 'wp-statistics' );
25
  } else {
26
  echo '';
27
  } ?></th>
28
- <th class="th-center"><?php if ( $WP_Statistics->get_option( 'visits' ) ) {
29
- _e( 'Visits', 'wp-statistics' );
30
  } else {
31
  echo '';
32
  } ?></th>
33
- </tr>
34
 
35
- <tr>
36
- <th><?php _e( 'Today', 'wp-statistics' ); ?>:</th>
37
- <th class="th-center"><?php if ( $WP_Statistics->get_option( 'visitors' ) ) {
38
- echo '<a href="admin.php?page=' . WP_STATISTICS_VISITORS_PAGE . '&hitdays=1"><span>' . number_format_i18n( wp_statistics_visitor( 'today', null, true ) ) . '</span></a>';
 
 
 
 
39
  } else {
40
  echo '';
41
  } ?></th>
42
- <th class="th-center"><?php if ( $WP_Statistics->get_option( 'visits' ) ) {
43
- echo '<a href="admin.php?page=' . WP_STATISTICS_HITS_PAGE . '&hitdays=1"><span>' . number_format_i18n( wp_statistics_visit( 'today' ) ) . '</span></a>';
 
 
 
 
44
  } else {
45
  echo '';
46
  } ?></th>
47
- </tr>
48
 
49
- <tr>
50
- <th><?php _e( 'Yesterday', 'wp-statistics' ); ?>:</th>
51
- <th class="th-center"><?php if ( $WP_Statistics->get_option( 'visitors' ) ) {
52
- echo '<a href="admin.php?page=' . WP_STATISTICS_VISITORS_PAGE . '&hitdays=1"><span>' . number_format_i18n( wp_statistics_visitor( 'yesterday', null, true ) ) . '</span></a>';
 
 
 
 
53
  } else {
54
  echo '';
55
  } ?></th>
56
- <th class="th-center"><?php if ( $WP_Statistics->get_option( 'visits' ) ) {
57
- echo '<a href="admin.php?page=' . WP_STATISTICS_HITS_PAGE . '&hitdays=1"><span>' . number_format_i18n( wp_statistics_visit( 'yesterday' ) ) . '</span></a>';
 
 
 
 
58
  } else {
59
  echo '';
60
  } ?></th>
61
- </tr>
62
 
63
- <tr>
64
- <th><?php _e( 'Last 7 Days (Week)', 'wp-statistics' ); ?>:</th>
65
- <th class="th-center"><?php if ( $WP_Statistics->get_option( 'visitors' ) ) {
66
- echo '<a href="admin.php?page=' . WP_STATISTICS_VISITORS_PAGE . '&hitdays=7"><span>' . number_format_i18n( wp_statistics_visitor( 'week', null, true ) ) . '</span></a>';
 
 
 
 
67
  } else {
68
  echo '';
69
  } ?></th>
70
- <th class="th-center"><?php if ( $WP_Statistics->get_option( 'visits' ) ) {
71
- echo '<a href="admin.php?page=' . WP_STATISTICS_HITS_PAGE . '&hitdays=7"><span>' . number_format_i18n( wp_statistics_visit( 'week' ) ) . '</span></a>';
 
 
 
 
72
  } else {
73
  echo '';
74
  } ?></th>
75
- </tr>
76
 
77
- <tr>
78
- <th><?php _e( 'Last 30 Days (Month)', 'wp-statistics' ); ?>:</th>
79
- <th class="th-center"><?php if ( $WP_Statistics->get_option( 'visitors' ) ) {
80
- echo '<a href="admin.php?page=' . WP_STATISTICS_VISITORS_PAGE . '&hitdays=30"><span>' . number_format_i18n( wp_statistics_visitor( 'month', null, true ) ) . '</span></a>';
 
 
 
 
81
  } else {
82
  echo '';
83
  } ?></th>
84
- <th class="th-center"><?php if ( $WP_Statistics->get_option( 'visits' ) ) {
85
- echo '<a href="admin.php?page=' . WP_STATISTICS_HITS_PAGE . '&hitdays=30"><span>' . number_format_i18n( wp_statistics_visit( 'month' ) ) . '</span></a>';
 
 
 
 
86
  } else {
87
  echo '';
88
  } ?></th>
89
- </tr>
90
 
91
- <tr>
92
- <th><?php _e( 'Last 365 Days (Year)', 'wp-statistics' ); ?>:</th>
93
- <th class="th-center"><?php if ( $WP_Statistics->get_option( 'visitors' ) ) {
94
- echo '<a href="admin.php?page=' . WP_STATISTICS_VISITORS_PAGE . '&hitdays=365"><span>' . number_format_i18n( wp_statistics_visitor( 'year', null, true ) ) . '</span></a>';
 
 
 
 
95
  } else {
96
  echo '';
97
  } ?></th>
98
- <th class="th-center"><?php if ( $WP_Statistics->get_option( 'visits' ) ) {
99
- echo '<a href="admin.php?page=' . WP_STATISTICS_HITS_PAGE . '&hitdays=365"><span>' . number_format_i18n( wp_statistics_visit( 'year' ) ) . '</span></a>';
 
 
 
 
100
  } else {
101
  echo '';
102
  } ?></th>
103
- </tr>
104
 
105
- <tr>
106
- <th><?php _e( 'Total', 'wp-statistics' ); ?>:</th>
107
- <th class="th-center"><?php if ( $WP_Statistics->get_option( 'visitors' ) ) {
108
- echo '<a href="admin.php?page=' . WP_STATISTICS_VISITORS_PAGE . '&hitdays=365"><span>' . number_format_i18n( wp_statistics_visitor( 'total', null, true ) ) . '</span></a>';
 
 
 
 
109
  } else {
110
  echo '';
111
  } ?></th>
112
- <th class="th-center"><?php if ( $WP_Statistics->get_option( 'visits' ) ) {
113
- echo '<a href="admin.php?page=' . WP_STATISTICS_HITS_PAGE . '&hitdays=365"><span>' . number_format_i18n( wp_statistics_visit( 'total' ) ) . '</span></a>';
 
 
 
 
114
  } else {
115
  echo '';
116
  } ?></th>
117
- </tr>
118
 
119
  <?php
120
  }
121
 
122
- if ( $search == true && $WP_Statistics->get_option( 'visitors' ) ) {
123
 
124
- if ( $WP_Statistics->get_option( 'visitors' ) || $WP_Statistics->get_option( 'visits' ) || $WP_Statistics->get_option( 'useronline' ) ) {
 
 
 
125
  ?>
126
- <tr>
127
- <th colspan="3"><br>
128
- <hr>
129
- </th>
130
- </tr>
131
  <?php } ?>
132
- <tr>
133
- <th colspan="3" style="text-align: center;"><?php _e( 'Search Engine Referrals', 'wp-statistics' ); ?></th>
134
- </tr>
 
 
 
135
 
136
- <tr>
137
- <th width="60%"></th>
138
- <th class="th-center"><?php _e( 'Today', 'wp-statistics' ); ?></th>
139
- <th class="th-center"><?php _e( 'Yesterday', 'wp-statistics' ); ?></th>
140
- </tr>
141
 
142
  <?php
143
- $se_today_total = 0;
144
  $se_yesterday_total = 0;
145
  foreach ( $search_engines as $se ) {
146
  ?>
147
- <tr>
148
- <th>
149
- <img src='<?php echo plugins_url( 'wp-statistics/assets/images/' . $se['image'] ); ?>'> <?php _e( $se['name'], 'wp-statistics' ); ?>
150
- :
151
- </th>
152
- <th class="th-center"><span><?php $se_temp = wp_statistics_searchengine( $se['tag'], 'today' );
153
- $se_today_total += $se_temp;
154
- echo number_format_i18n( $se_temp ); ?></span></th>
155
- <th class="th-center"><span><?php $se_temp = wp_statistics_searchengine( $se['tag'], 'yesterday' );
156
- $se_yesterday_total += $se_temp;
157
- echo number_format_i18n( $se_temp ); ?></span></th>
158
- </tr>
 
 
 
159
 
160
  <?php
161
  }
162
  ?>
163
- <tr>
164
- <th><?php _e( 'Daily Total', 'wp-statistics' ); ?>:</th>
165
- <td id="th-colspan" class="th-center"><span><?php echo number_format_i18n( $se_today_total ); ?></span>
166
- </td>
167
- <td id="th-colspan" class="th-center">
168
- <span><?php echo number_format_i18n( $se_yesterday_total ); ?></span></td>
169
- </tr>
170
-
171
- <tr>
172
- <th><?php _e( 'Total', 'wp-statistics' ); ?>:</th>
173
- <th colspan="2" id="th-colspan">
174
- <span><?php echo number_format_i18n( wp_statistics_searchengine( 'all' ) ); ?></span></th>
175
- </tr>
176
  <?php
177
  }
178
 
179
  if ( $time == true ) {
180
  ?>
181
- <tr>
182
- <th colspan="3"><br>
183
- <hr>
184
- </th>
185
- </tr>
186
-
187
- <tr>
188
- <th colspan="3" style="text-align: center;"><?php _e( 'Current Time and Date', 'wp-statistics' ); ?>
189
- <span id="time_zone"><a href="<?php echo admin_url( 'options-general.php' ); ?>"><?php _e( '(Adjustment)', 'wp-statistics' ); ?></a></span>
190
- </th>
191
- </tr>
192
-
193
- <tr>
194
- <th colspan="3"><?php echo sprintf( __( 'Date: %s', 'wp-statistics' ), '<code dir="ltr">' . $WP_Statistics->Current_Date_i18n( get_option( 'date_format' ) ) . '</code>' ); ?></th>
195
- </tr>
196
-
197
- <tr>
198
- <th colspan="3"><?php echo sprintf( __( 'Time: %s', 'wp-statistics' ), '<code dir="ltr">' . $WP_Statistics->Current_Date_i18n( get_option( 'time_format' ) ) . '</code>' ); ?></th>
199
- </tr>
3
 
4
  global $wpdb, $WP_Statistics;
5
 
6
+ $show_visitors = $WP_Statistics->get_option('visitor');
7
  ?>
8
+ <table width="100%" class="widefat table-stats" id="summary-stats">
9
+ <tbody>
10
+ <?php if ( $WP_Statistics->get_option('useronline') ) { ?>
11
+ <tr>
12
+ <th><?php _e('Online Users', 'wp-statistics'); ?>:</th>
13
+ <th colspan="2" id="th-colspan">
14
+ <span><a
15
+ href="admin.php?page=<?php echo WP_Statistics::$page['online']; ?>"><?php echo wp_statistics_useronline(
16
+ ); ?></a></span>
17
+ </th>
18
+ </tr>
19
  <?php }
20
 
21
+ if ( $WP_Statistics->get_option('visitors') || $WP_Statistics->get_option('visits') ) {
22
  ?>
23
+ <tr>
24
+ <th width="60%"></th>
25
+ <th class="th-center"><?php if ( $WP_Statistics->get_option('visitors') ) {
26
+ _e('Visitors', 'wp-statistics');
27
  } else {
28
  echo '';
29
  } ?></th>
30
+ <th class="th-center"><?php if ( $WP_Statistics->get_option('visits') ) {
31
+ _e('Visits', 'wp-statistics');
32
  } else {
33
  echo '';
34
  } ?></th>
35
+ </tr>
36
 
37
+ <tr>
38
+ <th><?php _e('Today', 'wp-statistics'); ?>:</th>
39
+ <th class="th-center"><?php if ( $WP_Statistics->get_option('visitors') ) {
40
+ echo '<a href="admin.php?page=' .
41
+ WP_Statistics::$page['visitors'] .
42
+ '&hitdays=1"><span>' .
43
+ number_format_i18n(wp_statistics_visitor('today', null, true)) .
44
+ '</span></a>';
45
  } else {
46
  echo '';
47
  } ?></th>
48
+ <th class="th-center"><?php if ( $WP_Statistics->get_option('visits') ) {
49
+ echo '<a href="admin.php?page=' .
50
+ WP_Statistics::$page['hits'] .
51
+ '&hitdays=1"><span>' .
52
+ number_format_i18n(wp_statistics_visit('today')) .
53
+ '</span></a>';
54
  } else {
55
  echo '';
56
  } ?></th>
57
+ </tr>
58
 
59
+ <tr>
60
+ <th><?php _e('Yesterday', 'wp-statistics'); ?>:</th>
61
+ <th class="th-center"><?php if ( $WP_Statistics->get_option('visitors') ) {
62
+ echo '<a href="admin.php?page=' .
63
+ WP_Statistics::$page['visitors'] .
64
+ '&hitdays=1"><span>' .
65
+ number_format_i18n(wp_statistics_visitor('yesterday', null, true)) .
66
+ '</span></a>';
67
  } else {
68
  echo '';
69
  } ?></th>
70
+ <th class="th-center"><?php if ( $WP_Statistics->get_option('visits') ) {
71
+ echo '<a href="admin.php?page=' .
72
+ WP_Statistics::$page['hits'] .
73
+ '&hitdays=1"><span>' .
74
+ number_format_i18n(wp_statistics_visit('yesterday')) .
75
+ '</span></a>';
76
  } else {
77
  echo '';
78
  } ?></th>
79
+ </tr>
80
 
81
+ <tr>
82
+ <th><?php _e('Last 7 Days (Week)', 'wp-statistics'); ?>:</th>
83
+ <th class="th-center"><?php if ( $WP_Statistics->get_option('visitors') ) {
84
+ echo '<a href="admin.php?page=' .
85
+ WP_Statistics::$page['visitors'] .
86
+ '&hitdays=7"><span>' .
87
+ number_format_i18n(wp_statistics_visitor('week', null, true)) .
88
+ '</span></a>';
89
  } else {
90
  echo '';
91
  } ?></th>
92
+ <th class="th-center"><?php if ( $WP_Statistics->get_option('visits') ) {
93
+ echo '<a href="admin.php?page=' .
94
+ WP_Statistics::$page['hits'] .
95
+ '&hitdays=7"><span>' .
96
+ number_format_i18n(wp_statistics_visit('week')) .
97
+ '</span></a>';
98
  } else {
99
  echo '';
100
  } ?></th>
101
+ </tr>
102
 
103
+ <tr>
104
+ <th><?php _e('Last 30 Days (Month)', 'wp-statistics'); ?>:</th>
105
+ <th class="th-center"><?php if ( $WP_Statistics->get_option('visitors') ) {
106
+ echo '<a href="admin.php?page=' .
107
+ WP_Statistics::$page['visitors'] .
108
+ '&hitdays=30"><span>' .
109
+ number_format_i18n(wp_statistics_visitor('month', null, true)) .
110
+ '</span></a>';
111
  } else {
112
  echo '';
113
  } ?></th>
114
+ <th class="th-center"><?php if ( $WP_Statistics->get_option('visits') ) {
115
+ echo '<a href="admin.php?page=' .
116
+ WP_Statistics::$page['hits'] .
117
+ '&hitdays=30"><span>' .
118
+ number_format_i18n(wp_statistics_visit('month')) .
119
+ '</span></a>';
120
  } else {
121
  echo '';
122
  } ?></th>
123
+ </tr>
124
 
125
+ <tr>
126
+ <th><?php _e('Last 365 Days (Year)', 'wp-statistics'); ?>:</th>
127
+ <th class="th-center"><?php if ( $WP_Statistics->get_option('visitors') ) {
128
+ echo '<a href="admin.php?page=' .
129
+ WP_Statistics::$page['visitors'] .
130
+ '&hitdays=365"><span>' .
131
+ number_format_i18n(wp_statistics_visitor('year', null, true)) .
132
+ '</span></a>';
133
  } else {
134
  echo '';
135
  } ?></th>
136
+ <th class="th-center"><?php if ( $WP_Statistics->get_option('visits') ) {
137
+ echo '<a href="admin.php?page=' .
138
+ WP_Statistics::$page['hits'] .
139
+ '&hitdays=365"><span>' .
140
+ number_format_i18n(wp_statistics_visit('year')) .
141
+ '</span></a>';
142
  } else {
143
  echo '';
144
  } ?></th>
145
+ </tr>
146
 
147
+ <tr>
148
+ <th><?php _e('Total', 'wp-statistics'); ?>:</th>
149
+ <th class="th-center"><?php if ( $WP_Statistics->get_option('visitors') ) {
150
+ echo '<a href="admin.php?page=' .
151
+ WP_Statistics::$page['visitors'] .
152
+ '&hitdays=365"><span>' .
153
+ number_format_i18n(wp_statistics_visitor('total', null, true)) .
154
+ '</span></a>';
155
  } else {
156
  echo '';
157
  } ?></th>
158
+ <th class="th-center"><?php if ( $WP_Statistics->get_option('visits') ) {
159
+ echo '<a href="admin.php?page=' .
160
+ WP_Statistics::$page['hits'] .
161
+ '&hitdays=365"><span>' .
162
+ number_format_i18n(wp_statistics_visit('total')) .
163
+ '</span></a>';
164
  } else {
165
  echo '';
166
  } ?></th>
167
+ </tr>
168
 
169
  <?php
170
  }
171
 
172
+ if ( $search == true && $WP_Statistics->get_option('visitors') ) {
173
 
174
+ if ( $WP_Statistics->get_option('visitors') ||
175
+ $WP_Statistics->get_option('visits') ||
176
+ $WP_Statistics->get_option('useronline')
177
+ ) {
178
  ?>
179
+ <tr>
180
+ <th colspan="3"><br>
181
+ <hr>
182
+ </th>
183
+ </tr>
184
  <?php } ?>
185
+ <tr>
186
+ <th colspan="3" style="text-align: center;"><?php _e(
187
+ 'Search Engine Referrals',
188
+ 'wp-statistics'
189
+ ); ?></th>
190
+ </tr>
191
 
192
+ <tr>
193
+ <th width="60%"></th>
194
+ <th class="th-center"><?php _e('Today', 'wp-statistics'); ?></th>
195
+ <th class="th-center"><?php _e('Yesterday', 'wp-statistics'); ?></th>
196
+ </tr>
197
 
198
  <?php
199
+ $se_today_total = 0;
200
  $se_yesterday_total = 0;
201
  foreach ( $search_engines as $se ) {
202
  ?>
203
+ <tr>
204
+ <th>
205
+ <img src='<?php echo plugins_url('wp-statistics/assets/images/' . $se['image']); ?>'> <?php _e(
206
+ $se['name'],
207
+ 'wp-statistics'
208
+ ); ?>
209
+ :
210
+ </th>
211
+ <th class="th-center"><span><?php $se_temp = wp_statistics_searchengine($se['tag'], 'today');
212
+ $se_today_total += $se_temp;
213
+ echo number_format_i18n($se_temp); ?></span></th>
214
+ <th class="th-center"><span><?php $se_temp = wp_statistics_searchengine($se['tag'], 'yesterday');
215
+ $se_yesterday_total += $se_temp;
216
+ echo number_format_i18n($se_temp); ?></span></th>
217
+ </tr>
218
 
219
  <?php
220
  }
221
  ?>
222
+ <tr>
223
+ <th><?php _e('Daily Total', 'wp-statistics'); ?>:</th>
224
+ <td id="th-colspan" class="th-center"><span><?php echo number_format_i18n($se_today_total); ?></span>
225
+ </td>
226
+ <td id="th-colspan" class="th-center">
227
+ <span><?php echo number_format_i18n($se_yesterday_total); ?></span></td>
228
+ </tr>
229
+
230
+ <tr>
231
+ <th><?php _e('Total', 'wp-statistics'); ?>:</th>
232
+ <th colspan="2" id="th-colspan">
233
+ <span><?php echo number_format_i18n(wp_statistics_searchengine('all')); ?></span></th>
234
+ </tr>
235
  <?php
236
  }
237
 
238
  if ( $time == true ) {
239
  ?>
240
+ <tr>
241
+ <th colspan="3"><br>
242
+ <hr>
243
+ </th>
244
+ </tr>
245
+
246
+ <tr>
247
+ <th colspan="3" style="text-align: center;"><?php _e('Current Time and Date', 'wp-statistics'); ?>
248
+ <span id="time_zone"><a href="<?php echo admin_url('options-general.php'); ?>"><?php _e(
249
+ '(Adjustment)',
250
+ 'wp-statistics'
251
+ ); ?></a></span>
252
+ </th>
253
+ </tr>
254
+
255
+ <tr>
256
+ <th colspan="3"><?php echo sprintf(
257
+ __('Date: %s', 'wp-statistics'),
258
+ '<code di