ngx-hana-nameserver-history-viewer 1.1.1 → 1.1.9-1.beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -6
- package/esm2020/ngx-hana-nameserver-history-viewer.mjs +5 -0
- package/esm2020/public-api.mjs +2 -0
- package/esm2020/src/nameserver-history-viewer/components/alert/alert.component.mjs +68 -0
- package/esm2020/src/nameserver-history-viewer/components/alert/alert.module.mjs +22 -0
- package/esm2020/src/nameserver-history-viewer/components/alert/index.mjs +3 -0
- package/esm2020/src/nameserver-history-viewer/components/file-drop-input/file-drop-input.component.mjs +112 -0
- package/esm2020/src/nameserver-history-viewer/components/file-drop-input/index.mjs +2 -0
- package/esm2020/src/nameserver-history-viewer/components/index.mjs +9 -0
- package/esm2020/src/nameserver-history-viewer/components/instruction/index.mjs +2 -0
- package/esm2020/src/nameserver-history-viewer/components/instruction/instruction.component.mjs +42 -0
- package/esm2020/src/nameserver-history-viewer/components/nameserver-history.component.mjs +550 -0
- package/esm2020/src/nameserver-history-viewer/components/port-selector/index.mjs +2 -0
- package/esm2020/src/nameserver-history-viewer/components/port-selector/port-selector.component.mjs +69 -0
- package/esm2020/src/nameserver-history-viewer/components/port-selector/port-selector.service.mjs +41 -0
- package/esm2020/src/nameserver-history-viewer/components/progress-bar/index.mjs +2 -0
- package/esm2020/src/nameserver-history-viewer/components/progress-bar/progress-bar.component.mjs +40 -0
- package/esm2020/src/nameserver-history-viewer/components/time-range-selector/index.mjs +2 -0
- package/esm2020/src/nameserver-history-viewer/components/time-range-selector/time-range-selector.component.mjs +70 -0
- package/esm2020/src/nameserver-history-viewer/components/timezone-selector/index.mjs +2 -0
- package/esm2020/src/nameserver-history-viewer/components/timezone-selector/timezone-selector.component.mjs +90 -0
- package/esm2020/src/nameserver-history-viewer/components/timezone-selector/timezone-selector.service.mjs +49 -0
- package/esm2020/src/nameserver-history-viewer/index.mjs +3 -0
- package/esm2020/src/nameserver-history-viewer/nameserver-history.module.mjs +63 -0
- package/esm2020/src/nameserver-history-viewer/services/chart.service.mjs +323 -0
- package/esm2020/src/nameserver-history-viewer/services/file.service.mjs +390 -0
- package/esm2020/src/nameserver-history-viewer/services/index.mjs +4 -0
- package/esm2020/src/nameserver-history-viewer/services/ui.service.mjs +557 -0
- package/esm2020/src/nameserver-history-viewer/types/abort.types.mjs +6 -0
- package/esm2020/src/nameserver-history-viewer/types/alert.types.mjs +8 -0
- package/esm2020/src/nameserver-history-viewer/types/chart-content-data-item.types.mjs +2 -0
- package/esm2020/src/nameserver-history-viewer/types/chart-content-data.types.mjs +2 -0
- package/esm2020/src/nameserver-history-viewer/types/chart-content-header.types.mjs +2 -0
- package/esm2020/src/nameserver-history-viewer/types/chart-content-time.types.mjs +2 -0
- package/esm2020/src/nameserver-history-viewer/types/chart-content.types.mjs +2 -0
- package/esm2020/src/nameserver-history-viewer/types/color-rgba.types.mjs +2 -0
- package/esm2020/src/nameserver-history-viewer/types/html-element.type.mjs +9 -0
- package/esm2020/src/nameserver-history-viewer/types/index.mjs +28 -0
- package/esm2020/src/nameserver-history-viewer/types/item.types.mjs +14 -0
- package/esm2020/src/nameserver-history-viewer/types/legend-color.types.mjs +2 -0
- package/esm2020/src/nameserver-history-viewer/types/load-history-info-backup.types.mjs +2 -0
- package/esm2020/src/nameserver-history-viewer/types/load-history-info-columnstore.types.mjs +2 -0
- package/esm2020/src/nameserver-history-viewer/types/load-history-info-host.types.mjs +2 -0
- package/esm2020/src/nameserver-history-viewer/types/load-history-info-item.types.mjs +2 -0
- package/esm2020/src/nameserver-history-viewer/types/load-history-info-persistence.types.mjs +2 -0
- package/esm2020/src/nameserver-history-viewer/types/load-history-info-rowstore.types.mjs +2 -0
- package/esm2020/src/nameserver-history-viewer/types/load-history-info-server.types.mjs +2 -0
- package/esm2020/src/nameserver-history-viewer/types/load-history-info-session-admission-control.types.mjs +2 -0
- package/esm2020/src/nameserver-history-viewer/types/load-history-info-sql.types.mjs +2 -0
- package/esm2020/src/nameserver-history-viewer/types/load-history-info-sync-primitives.types.mjs +2 -0
- package/esm2020/src/nameserver-history-viewer/types/load-history-info-threads.types.mjs +2 -0
- package/esm2020/src/nameserver-history-viewer/types/load-history-info.types.mjs +2 -0
- package/esm2020/src/nameserver-history-viewer/types/port.types.mjs +2 -0
- package/esm2020/src/nameserver-history-viewer/types/scale-group.types.mjs +17 -0
- package/esm2020/src/nameserver-history-viewer/types/unit-category.types.mjs +10 -0
- package/esm2020/src/nameserver-history-viewer/types/unit.types.mjs +14 -0
- package/esm2020/src/nameserver-history-viewer/utils/chart-util.mjs +25 -0
- package/esm2020/src/nameserver-history-viewer/utils/chartjs-downsample/chartjs_ext.mjs +2 -0
- package/esm2020/src/nameserver-history-viewer/utils/chartjs-downsample/data_culling.mjs +57 -0
- package/esm2020/src/nameserver-history-viewer/utils/chartjs-downsample/data_mipmap.mjs +139 -0
- package/esm2020/src/nameserver-history-viewer/utils/chartjs-downsample/index.mjs +41 -0
- package/esm2020/src/nameserver-history-viewer/utils/chartjs-downsample/lttb_data_mipmap.mjs +106 -0
- package/esm2020/src/nameserver-history-viewer/utils/chartjs-downsample/responsive_downsample_plugin.mjs +168 -0
- package/esm2020/src/nameserver-history-viewer/utils/chartjs-downsample/utils.mjs +114 -0
- package/esm2020/src/nameserver-history-viewer/utils/chartjs-zoom/chart.zoom.mjs +527 -0
- package/esm2020/src/nameserver-history-viewer/utils/chartjs-zoom/index.mjs +2 -0
- package/esm2020/src/nameserver-history-viewer/utils/file-util.mjs +154 -0
- package/esm2020/src/nameserver-history-viewer/utils/index.mjs +5 -0
- package/esm2020/src/nameserver-history-viewer/utils/time-util.mjs +101 -0
- package/esm2020/src/nameserver-history-viewer/utils/ui-util.mjs +162 -0
- package/fesm2015/ngx-hana-nameserver-history-viewer.mjs +4081 -0
- package/fesm2015/ngx-hana-nameserver-history-viewer.mjs.map +1 -0
- package/fesm2020/ngx-hana-nameserver-history-viewer.mjs +4081 -0
- package/fesm2020/ngx-hana-nameserver-history-viewer.mjs.map +1 -0
- package/ngx-hana-nameserver-history-viewer.d.ts +1 -1
- package/package.json +37 -61
- package/src/nameserver-history-viewer/components/alert/alert.component.d.ts +4 -1
- package/src/nameserver-history-viewer/components/alert/alert.module.d.ts +6 -0
- package/src/nameserver-history-viewer/components/file-drop-input/file-drop-input.component.d.ts +3 -0
- package/src/nameserver-history-viewer/components/instruction/instruction.component.d.ts +3 -0
- package/src/nameserver-history-viewer/components/nameserver-history.component.d.ts +33 -14
- package/src/nameserver-history-viewer/components/port-selector/port-selector.component.d.ts +4 -1
- package/src/nameserver-history-viewer/components/port-selector/port-selector.service.d.ts +3 -0
- package/src/nameserver-history-viewer/components/progress-bar/progress-bar.component.d.ts +3 -0
- package/src/nameserver-history-viewer/components/time-range-selector/time-range-selector.component.d.ts +3 -0
- package/src/nameserver-history-viewer/components/timezone-selector/timezone-selector.component.d.ts +3 -0
- package/src/nameserver-history-viewer/components/timezone-selector/timezone-selector.service.d.ts +3 -0
- package/src/nameserver-history-viewer/index.d.ts +1 -0
- package/src/nameserver-history-viewer/nameserver-history.module.d.ts +17 -0
- package/src/nameserver-history-viewer/services/chart.service.d.ts +4 -1
- package/src/nameserver-history-viewer/services/file.service.d.ts +4 -0
- package/src/nameserver-history-viewer/services/ui.service.d.ts +5 -2
- package/src/nameserver-history-viewer/types/load-history-info-session-admission-control.types.d.ts +3 -0
- package/src/nameserver-history-viewer/utils/chartjs-downsample/lttb_data_mipmap.d.ts +1 -1
- package/src/nameserver-history-viewer/utils/file-util.d.ts +11 -0
- package/bundles/ngx-hana-nameserver-history-viewer.umd.js +0 -6298
- package/bundles/ngx-hana-nameserver-history-viewer.umd.js.map +0 -1
- package/bundles/ngx-hana-nameserver-history-viewer.umd.min.js +0 -2
- package/bundles/ngx-hana-nameserver-history-viewer.umd.min.js.map +0 -1
- package/esm2015/ngx-hana-nameserver-history-viewer.js +0 -10
- package/esm2015/public-api.js +0 -6
- package/esm2015/src/nameserver-history-viewer/components/alert/alert.component.js +0 -108
- package/esm2015/src/nameserver-history-viewer/components/alert/alert.module.js +0 -21
- package/esm2015/src/nameserver-history-viewer/components/alert/index.js +0 -7
- package/esm2015/src/nameserver-history-viewer/components/file-drop-input/file-drop-input.component.js +0 -141
- package/esm2015/src/nameserver-history-viewer/components/file-drop-input/index.js +0 -6
- package/esm2015/src/nameserver-history-viewer/components/index.js +0 -13
- package/esm2015/src/nameserver-history-viewer/components/instruction/index.js +0 -6
- package/esm2015/src/nameserver-history-viewer/components/instruction/instruction.component.js +0 -62
- package/esm2015/src/nameserver-history-viewer/components/nameserver-history.component.js +0 -742
- package/esm2015/src/nameserver-history-viewer/components/port-selector/index.js +0 -6
- package/esm2015/src/nameserver-history-viewer/components/port-selector/port-selector.component.js +0 -93
- package/esm2015/src/nameserver-history-viewer/components/port-selector/port-selector.service.js +0 -56
- package/esm2015/src/nameserver-history-viewer/components/progress-bar/index.js +0 -6
- package/esm2015/src/nameserver-history-viewer/components/progress-bar/progress-bar.component.js +0 -35
- package/esm2015/src/nameserver-history-viewer/components/time-range-selector/index.js +0 -6
- package/esm2015/src/nameserver-history-viewer/components/time-range-selector/time-range-selector.component.js +0 -68
- package/esm2015/src/nameserver-history-viewer/components/timezone-selector/index.js +0 -6
- package/esm2015/src/nameserver-history-viewer/components/timezone-selector/timezone-selector.component.js +0 -135
- package/esm2015/src/nameserver-history-viewer/components/timezone-selector/timezone-selector.service.js +0 -72
- package/esm2015/src/nameserver-history-viewer/index.js +0 -6
- package/esm2015/src/nameserver-history-viewer/nameserver-history.module.js +0 -42
- package/esm2015/src/nameserver-history-viewer/services/chart.service.js +0 -423
- package/esm2015/src/nameserver-history-viewer/services/file.service.js +0 -447
- package/esm2015/src/nameserver-history-viewer/services/index.js +0 -8
- package/esm2015/src/nameserver-history-viewer/services/ui.service.js +0 -817
- package/esm2015/src/nameserver-history-viewer/types/abort.types.js +0 -13
- package/esm2015/src/nameserver-history-viewer/types/alert.types.js +0 -13
- package/esm2015/src/nameserver-history-viewer/types/chart-content-data-item.types.js +0 -15
- package/esm2015/src/nameserver-history-viewer/types/chart-content-data.types.js +0 -9
- package/esm2015/src/nameserver-history-viewer/types/chart-content-header.types.js +0 -15
- package/esm2015/src/nameserver-history-viewer/types/chart-content-time.types.js +0 -9
- package/esm2015/src/nameserver-history-viewer/types/chart-content.types.js +0 -21
- package/esm2015/src/nameserver-history-viewer/types/color-rgba.types.js +0 -19
- package/esm2015/src/nameserver-history-viewer/types/html-element.type.js +0 -19
- package/esm2015/src/nameserver-history-viewer/types/index.js +0 -32
- package/esm2015/src/nameserver-history-viewer/types/item.types.js +0 -19
- package/esm2015/src/nameserver-history-viewer/types/legend-color.types.js +0 -9
- package/esm2015/src/nameserver-history-viewer/types/load-history-info-backup.types.js +0 -19
- package/esm2015/src/nameserver-history-viewer/types/load-history-info-columnstore.types.js +0 -19
- package/esm2015/src/nameserver-history-viewer/types/load-history-info-host.types.js +0 -35
- package/esm2015/src/nameserver-history-viewer/types/load-history-info-item.types.js +0 -31
- package/esm2015/src/nameserver-history-viewer/types/load-history-info-persistence.types.js +0 -27
- package/esm2015/src/nameserver-history-viewer/types/load-history-info-rowstore.types.js +0 -15
- package/esm2015/src/nameserver-history-viewer/types/load-history-info-server.types.js +0 -25
- package/esm2015/src/nameserver-history-viewer/types/load-history-info-session-admission-control.types.js +0 -19
- package/esm2015/src/nameserver-history-viewer/types/load-history-info-sql.types.js +0 -37
- package/esm2015/src/nameserver-history-viewer/types/load-history-info-sync-primitives.types.js +0 -15
- package/esm2015/src/nameserver-history-viewer/types/load-history-info-threads.types.js +0 -23
- package/esm2015/src/nameserver-history-viewer/types/load-history-info.types.js +0 -31
- package/esm2015/src/nameserver-history-viewer/types/port.types.js +0 -17
- package/esm2015/src/nameserver-history-viewer/types/scale-group.types.js +0 -35
- package/esm2015/src/nameserver-history-viewer/types/unit-category.types.js +0 -21
- package/esm2015/src/nameserver-history-viewer/types/unit.types.js +0 -19
- package/esm2015/src/nameserver-history-viewer/utils/chart-util.js +0 -38
- package/esm2015/src/nameserver-history-viewer/utils/chartjs-downsample/chartjs_ext.js +0 -100
- package/esm2015/src/nameserver-history-viewer/utils/chartjs-downsample/data_culling.js +0 -88
- package/esm2015/src/nameserver-history-viewer/utils/chartjs-downsample/data_mipmap.js +0 -213
- package/esm2015/src/nameserver-history-viewer/utils/chartjs-downsample/index.js +0 -46
- package/esm2015/src/nameserver-history-viewer/utils/chartjs-downsample/lttb_data_mipmap.js +0 -158
- package/esm2015/src/nameserver-history-viewer/utils/chartjs-downsample/responsive_downsample_plugin.js +0 -295
- package/esm2015/src/nameserver-history-viewer/utils/chartjs-downsample/utils.js +0 -130
- package/esm2015/src/nameserver-history-viewer/utils/chartjs-zoom/chart.zoom.js +0 -733
- package/esm2015/src/nameserver-history-viewer/utils/chartjs-zoom/index.js +0 -6
- package/esm2015/src/nameserver-history-viewer/utils/file-util.js +0 -149
- package/esm2015/src/nameserver-history-viewer/utils/index.js +0 -9
- package/esm2015/src/nameserver-history-viewer/utils/time-util.js +0 -135
- package/esm2015/src/nameserver-history-viewer/utils/ui-util.js +0 -203
- package/esm5/ngx-hana-nameserver-history-viewer.js +0 -10
- package/esm5/public-api.js +0 -6
- package/esm5/src/nameserver-history-viewer/components/alert/alert.component.js +0 -140
- package/esm5/src/nameserver-history-viewer/components/alert/alert.module.js +0 -25
- package/esm5/src/nameserver-history-viewer/components/alert/index.js +0 -7
- package/esm5/src/nameserver-history-viewer/components/file-drop-input/file-drop-input.component.js +0 -155
- package/esm5/src/nameserver-history-viewer/components/file-drop-input/index.js +0 -6
- package/esm5/src/nameserver-history-viewer/components/index.js +0 -13
- package/esm5/src/nameserver-history-viewer/components/instruction/index.js +0 -6
- package/esm5/src/nameserver-history-viewer/components/instruction/instruction.component.js +0 -67
- package/esm5/src/nameserver-history-viewer/components/nameserver-history.component.js +0 -990
- package/esm5/src/nameserver-history-viewer/components/port-selector/index.js +0 -6
- package/esm5/src/nameserver-history-viewer/components/port-selector/port-selector.component.js +0 -93
- package/esm5/src/nameserver-history-viewer/components/port-selector/port-selector.service.js +0 -81
- package/esm5/src/nameserver-history-viewer/components/progress-bar/index.js +0 -6
- package/esm5/src/nameserver-history-viewer/components/progress-bar/progress-bar.component.js +0 -26
- package/esm5/src/nameserver-history-viewer/components/time-range-selector/index.js +0 -6
- package/esm5/src/nameserver-history-viewer/components/time-range-selector/time-range-selector.component.js +0 -58
- package/esm5/src/nameserver-history-viewer/components/timezone-selector/index.js +0 -6
- package/esm5/src/nameserver-history-viewer/components/timezone-selector/timezone-selector.component.js +0 -164
- package/esm5/src/nameserver-history-viewer/components/timezone-selector/timezone-selector.service.js +0 -102
- package/esm5/src/nameserver-history-viewer/index.js +0 -6
- package/esm5/src/nameserver-history-viewer/nameserver-history.module.js +0 -46
- package/esm5/src/nameserver-history-viewer/services/chart.service.js +0 -578
- package/esm5/src/nameserver-history-viewer/services/file.service.js +0 -566
- package/esm5/src/nameserver-history-viewer/services/index.js +0 -8
- package/esm5/src/nameserver-history-viewer/services/ui.service.js +0 -1036
- package/esm5/src/nameserver-history-viewer/types/abort.types.js +0 -13
- package/esm5/src/nameserver-history-viewer/types/alert.types.js +0 -13
- package/esm5/src/nameserver-history-viewer/types/chart-content-data-item.types.js +0 -15
- package/esm5/src/nameserver-history-viewer/types/chart-content-data.types.js +0 -9
- package/esm5/src/nameserver-history-viewer/types/chart-content-header.types.js +0 -15
- package/esm5/src/nameserver-history-viewer/types/chart-content-time.types.js +0 -9
- package/esm5/src/nameserver-history-viewer/types/chart-content.types.js +0 -21
- package/esm5/src/nameserver-history-viewer/types/color-rgba.types.js +0 -19
- package/esm5/src/nameserver-history-viewer/types/html-element.type.js +0 -19
- package/esm5/src/nameserver-history-viewer/types/index.js +0 -32
- package/esm5/src/nameserver-history-viewer/types/item.types.js +0 -19
- package/esm5/src/nameserver-history-viewer/types/legend-color.types.js +0 -9
- package/esm5/src/nameserver-history-viewer/types/load-history-info-backup.types.js +0 -19
- package/esm5/src/nameserver-history-viewer/types/load-history-info-columnstore.types.js +0 -19
- package/esm5/src/nameserver-history-viewer/types/load-history-info-host.types.js +0 -35
- package/esm5/src/nameserver-history-viewer/types/load-history-info-item.types.js +0 -31
- package/esm5/src/nameserver-history-viewer/types/load-history-info-persistence.types.js +0 -27
- package/esm5/src/nameserver-history-viewer/types/load-history-info-rowstore.types.js +0 -15
- package/esm5/src/nameserver-history-viewer/types/load-history-info-server.types.js +0 -25
- package/esm5/src/nameserver-history-viewer/types/load-history-info-session-admission-control.types.js +0 -19
- package/esm5/src/nameserver-history-viewer/types/load-history-info-sql.types.js +0 -37
- package/esm5/src/nameserver-history-viewer/types/load-history-info-sync-primitives.types.js +0 -15
- package/esm5/src/nameserver-history-viewer/types/load-history-info-threads.types.js +0 -23
- package/esm5/src/nameserver-history-viewer/types/load-history-info.types.js +0 -31
- package/esm5/src/nameserver-history-viewer/types/port.types.js +0 -17
- package/esm5/src/nameserver-history-viewer/types/scale-group.types.js +0 -35
- package/esm5/src/nameserver-history-viewer/types/unit-category.types.js +0 -21
- package/esm5/src/nameserver-history-viewer/types/unit.types.js +0 -19
- package/esm5/src/nameserver-history-viewer/utils/chart-util.js +0 -39
- package/esm5/src/nameserver-history-viewer/utils/chartjs-downsample/chartjs_ext.js +0 -100
- package/esm5/src/nameserver-history-viewer/utils/chartjs-downsample/data_culling.js +0 -88
- package/esm5/src/nameserver-history-viewer/utils/chartjs-downsample/data_mipmap.js +0 -307
- package/esm5/src/nameserver-history-viewer/utils/chartjs-downsample/index.js +0 -46
- package/esm5/src/nameserver-history-viewer/utils/chartjs-downsample/lttb_data_mipmap.js +0 -232
- package/esm5/src/nameserver-history-viewer/utils/chartjs-downsample/responsive_downsample_plugin.js +0 -350
- package/esm5/src/nameserver-history-viewer/utils/chartjs-downsample/utils.js +0 -142
- package/esm5/src/nameserver-history-viewer/utils/chartjs-zoom/chart.zoom.js +0 -733
- package/esm5/src/nameserver-history-viewer/utils/chartjs-zoom/index.js +0 -6
- package/esm5/src/nameserver-history-viewer/utils/file-util.js +0 -150
- package/esm5/src/nameserver-history-viewer/utils/index.js +0 -9
- package/esm5/src/nameserver-history-viewer/utils/time-util.js +0 -135
- package/esm5/src/nameserver-history-viewer/utils/ui-util.js +0 -205
- package/fesm2015/ngx-hana-nameserver-history-viewer.js +0 -5223
- package/fesm2015/ngx-hana-nameserver-history-viewer.js.map +0 -1
- package/fesm5/ngx-hana-nameserver-history-viewer.js +0 -6295
- package/fesm5/ngx-hana-nameserver-history-viewer.js.map +0 -1
- package/ngx-hana-nameserver-history-viewer.metadata.json +0 -1
|
@@ -1,733 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview added by tsickle
|
|
3
|
-
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
4
|
-
*/
|
|
5
|
-
/**
|
|
6
|
-
* this plugin is adapted from: https://github.com/chartjs/chartjs-plugin-zoom
|
|
7
|
-
* for following two open issues:
|
|
8
|
-
* https://github.com/chartjs/chartjs-plugin-zoom/pull/155
|
|
9
|
-
* https://github.com/chartjs/chartjs-plugin-zoom/pull/150
|
|
10
|
-
*
|
|
11
|
-
* The MIT License (MIT) Copyright (c) 2013-2016 Nick Downie
|
|
12
|
-
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
|
13
|
-
* software and associated documentation files (the "Software"), to deal in the Software
|
|
14
|
-
* without restriction, including without limitation the rights to use, copy, modify, merge,
|
|
15
|
-
* publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
|
16
|
-
* to whom the Software is furnished to do so, subject to the following conditions:
|
|
17
|
-
*
|
|
18
|
-
* The above copyright notice and this permission notice shall be included in all copies or
|
|
19
|
-
* substantial portions of the Software.
|
|
20
|
-
*
|
|
21
|
-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
|
22
|
-
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
|
|
23
|
-
* AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
24
|
-
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
25
|
-
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
26
|
-
* THE SOFTWARE.
|
|
27
|
-
*/
|
|
28
|
-
/*jslint browser:true, devel:true, white:true, vars:true */
|
|
29
|
-
/*global require*/
|
|
30
|
-
// hammer JS for touch support
|
|
31
|
-
import * as hammerjs from 'hammerjs';
|
|
32
|
-
/** @type {?} */
|
|
33
|
-
const Hammer = window && ((/** @type {?} */ (window))).Hammer ? ((/** @type {?} */ (window))).Hammer : hammerjs.Hammer;
|
|
34
|
-
// Get the chart variable
|
|
35
|
-
import * as chartjs from 'chart.js';
|
|
36
|
-
/** @type {?} */
|
|
37
|
-
const Chart = window && ((/** @type {?} */ (window))).Chart ? ((/** @type {?} */ (window))).Chart : chartjs.Chart;
|
|
38
|
-
/** @type {?} */
|
|
39
|
-
const helpers = Chart.helpers;
|
|
40
|
-
// Take the zoom namespace of Chart
|
|
41
|
-
/** @type {?} */
|
|
42
|
-
const zoomNS = Chart.Zoom = Chart.Zoom || {};
|
|
43
|
-
// Where we store functions to handle different scale types
|
|
44
|
-
/** @type {?} */
|
|
45
|
-
const zoomFunctions = zoomNS.zoomFunctions = zoomNS.zoomFunctions || {};
|
|
46
|
-
/** @type {?} */
|
|
47
|
-
const panFunctions = zoomNS.panFunctions = zoomNS.panFunctions || {};
|
|
48
|
-
// Default options if none are provided
|
|
49
|
-
/** @type {?} */
|
|
50
|
-
const defaultOptions = zoomNS.defaults = {
|
|
51
|
-
pan: {
|
|
52
|
-
enabled: true,
|
|
53
|
-
mode: 'xy',
|
|
54
|
-
speed: 20,
|
|
55
|
-
threshold: 10
|
|
56
|
-
},
|
|
57
|
-
zoom: {
|
|
58
|
-
enabled: true,
|
|
59
|
-
mode: 'xy',
|
|
60
|
-
sensitivity: 3
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
/**
|
|
64
|
-
* @param {?} mode
|
|
65
|
-
* @param {?} dir
|
|
66
|
-
* @return {?}
|
|
67
|
-
*/
|
|
68
|
-
function directionEnabled(mode, dir) {
|
|
69
|
-
if (mode === undefined) {
|
|
70
|
-
return true;
|
|
71
|
-
}
|
|
72
|
-
else if (typeof mode === 'string') {
|
|
73
|
-
return mode.indexOf(dir) !== -1;
|
|
74
|
-
}
|
|
75
|
-
return false;
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* @param {?} zoomPanOptions
|
|
79
|
-
* @param {?} newMax
|
|
80
|
-
* @return {?}
|
|
81
|
-
*/
|
|
82
|
-
function rangeMaxLimiter(zoomPanOptions, newMax) {
|
|
83
|
-
if (zoomPanOptions.scaleAxes && zoomPanOptions.rangeMax &&
|
|
84
|
-
!helpers.isNullOrUndef(zoomPanOptions.rangeMax[zoomPanOptions.scaleAxes])) {
|
|
85
|
-
/** @type {?} */
|
|
86
|
-
const rangeMax = zoomPanOptions.rangeMax[zoomPanOptions.scaleAxes];
|
|
87
|
-
if (newMax > rangeMax) {
|
|
88
|
-
newMax = rangeMax;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
return newMax;
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* @param {?} zoomPanOptions
|
|
95
|
-
* @param {?} newMin
|
|
96
|
-
* @return {?}
|
|
97
|
-
*/
|
|
98
|
-
function rangeMinLimiter(zoomPanOptions, newMin) {
|
|
99
|
-
if (zoomPanOptions.scaleAxes && zoomPanOptions.rangeMin &&
|
|
100
|
-
!helpers.isNullOrUndef(zoomPanOptions.rangeMin[zoomPanOptions.scaleAxes])) {
|
|
101
|
-
/** @type {?} */
|
|
102
|
-
const rangeMin = zoomPanOptions.rangeMin[zoomPanOptions.scaleAxes];
|
|
103
|
-
if (newMin < rangeMin) {
|
|
104
|
-
newMin = rangeMin;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
return newMin;
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* @param {?} scale
|
|
111
|
-
* @param {?} zoom
|
|
112
|
-
* @param {?} center
|
|
113
|
-
* @param {?} zoomOptions
|
|
114
|
-
* @return {?}
|
|
115
|
-
*/
|
|
116
|
-
function zoomIndexScale(scale, zoom, center, zoomOptions) {
|
|
117
|
-
/** @type {?} */
|
|
118
|
-
const labels = scale.chart.data.labels;
|
|
119
|
-
/** @type {?} */
|
|
120
|
-
let minIndex = scale.minIndex;
|
|
121
|
-
/** @type {?} */
|
|
122
|
-
const lastLabelIndex = labels.length - 1;
|
|
123
|
-
/** @type {?} */
|
|
124
|
-
let maxIndex = scale.maxIndex;
|
|
125
|
-
/** @type {?} */
|
|
126
|
-
const sensitivity = zoomOptions.sensitivity;
|
|
127
|
-
/** @type {?} */
|
|
128
|
-
const chartCenter = scale.isHorizontal() ? scale.left + (scale.width / 2) : scale.top + (scale.height / 2);
|
|
129
|
-
/** @type {?} */
|
|
130
|
-
const centerPointer = scale.isHorizontal() ? center.x : center.y;
|
|
131
|
-
zoomNS.zoomCumulativeDelta = zoom > 1 ? zoomNS.zoomCumulativeDelta + 1 : zoomNS.zoomCumulativeDelta - 1;
|
|
132
|
-
if (Math.abs(zoomNS.zoomCumulativeDelta) > sensitivity) {
|
|
133
|
-
if (zoomNS.zoomCumulativeDelta < 0) {
|
|
134
|
-
if (centerPointer >= chartCenter) {
|
|
135
|
-
if (minIndex <= 0) {
|
|
136
|
-
maxIndex = Math.min(lastLabelIndex, maxIndex + 1);
|
|
137
|
-
}
|
|
138
|
-
else {
|
|
139
|
-
minIndex = Math.max(0, minIndex - 1);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
else if (centerPointer < chartCenter) {
|
|
143
|
-
if (maxIndex >= lastLabelIndex) {
|
|
144
|
-
minIndex = Math.max(0, minIndex - 1);
|
|
145
|
-
}
|
|
146
|
-
else {
|
|
147
|
-
maxIndex = Math.min(lastLabelIndex, maxIndex + 1);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
zoomNS.zoomCumulativeDelta = 0;
|
|
151
|
-
}
|
|
152
|
-
else if (zoomNS.zoomCumulativeDelta > 0) {
|
|
153
|
-
if (centerPointer >= chartCenter) {
|
|
154
|
-
minIndex = minIndex < maxIndex ? minIndex = Math.min(maxIndex, minIndex + 1) : minIndex;
|
|
155
|
-
}
|
|
156
|
-
else if (centerPointer < chartCenter) {
|
|
157
|
-
maxIndex = maxIndex > minIndex ? maxIndex = Math.max(minIndex, maxIndex - 1) : maxIndex;
|
|
158
|
-
}
|
|
159
|
-
zoomNS.zoomCumulativeDelta = 0;
|
|
160
|
-
}
|
|
161
|
-
scale.options.ticks.min = rangeMinLimiter(zoomOptions, labels[minIndex]);
|
|
162
|
-
scale.options.ticks.max = rangeMaxLimiter(zoomOptions, labels[maxIndex]);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* @param {?} scale
|
|
167
|
-
* @param {?} zoom
|
|
168
|
-
* @param {?} center
|
|
169
|
-
* @param {?} zoomOptions
|
|
170
|
-
* @return {?}
|
|
171
|
-
*/
|
|
172
|
-
function zoomTimeScale(scale, zoom, center, zoomOptions) {
|
|
173
|
-
/** @type {?} */
|
|
174
|
-
const options = scale.options;
|
|
175
|
-
// var range;
|
|
176
|
-
// var min_percent;
|
|
177
|
-
// if (scale.isHorizontal()) {
|
|
178
|
-
// range = scale.right - scale.left;
|
|
179
|
-
// min_percent = (center.x - scale.left) / range;
|
|
180
|
-
// } else {
|
|
181
|
-
// range = scale.bottom - scale.top;
|
|
182
|
-
// min_percent = (center.y - scale.top) / range;
|
|
183
|
-
// }
|
|
184
|
-
//
|
|
185
|
-
// var max_percent = 1 - min_percent;
|
|
186
|
-
/** @type {?} */
|
|
187
|
-
const range = scale.max - scale.min;
|
|
188
|
-
/** @type {?} */
|
|
189
|
-
const newDiff = range * (zoom - 1);
|
|
190
|
-
/** @type {?} */
|
|
191
|
-
const cursorPixel = scale.isHorizontal() ? center.x : center.y;
|
|
192
|
-
/** @type {?} */
|
|
193
|
-
const min_percent = (scale.getValueForPixel(cursorPixel) - scale.min) / range;
|
|
194
|
-
/** @type {?} */
|
|
195
|
-
const max_percent = 1 - min_percent;
|
|
196
|
-
/** @type {?} */
|
|
197
|
-
const minDelta = newDiff * min_percent;
|
|
198
|
-
/** @type {?} */
|
|
199
|
-
const maxDelta = newDiff * max_percent;
|
|
200
|
-
/** @type {?} */
|
|
201
|
-
const newMin = scale.min + minDelta;
|
|
202
|
-
/** @type {?} */
|
|
203
|
-
const newMax = scale.max - maxDelta;
|
|
204
|
-
/** @type {?} */
|
|
205
|
-
const diffMinMax = newMax - newMin;
|
|
206
|
-
/** @type {?} */
|
|
207
|
-
const minLimitExceeded = rangeMinLimiter(zoomOptions, diffMinMax) !== diffMinMax;
|
|
208
|
-
/** @type {?} */
|
|
209
|
-
const maxLimitExceeded = rangeMaxLimiter(zoomOptions, diffMinMax) !== diffMinMax;
|
|
210
|
-
if (!minLimitExceeded && !maxLimitExceeded) {
|
|
211
|
-
options.time.min = newMin;
|
|
212
|
-
options.time.max = newMax;
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
/**
|
|
216
|
-
* @param {?} scale
|
|
217
|
-
* @param {?} zoom
|
|
218
|
-
* @param {?} center
|
|
219
|
-
* @param {?} zoomOptions
|
|
220
|
-
* @return {?}
|
|
221
|
-
*/
|
|
222
|
-
function zoomNumericalScale(scale, zoom, center, zoomOptions) {
|
|
223
|
-
/** @type {?} */
|
|
224
|
-
const range = scale.max - scale.min;
|
|
225
|
-
/** @type {?} */
|
|
226
|
-
const newDiff = range * (zoom - 1);
|
|
227
|
-
/** @type {?} */
|
|
228
|
-
const cursorPixel = scale.isHorizontal() ? center.x : center.y;
|
|
229
|
-
/** @type {?} */
|
|
230
|
-
const min_percent = (scale.getValueForPixel(cursorPixel) - scale.min) / range;
|
|
231
|
-
/** @type {?} */
|
|
232
|
-
const max_percent = 1 - min_percent;
|
|
233
|
-
/** @type {?} */
|
|
234
|
-
const minDelta = newDiff * min_percent;
|
|
235
|
-
/** @type {?} */
|
|
236
|
-
const maxDelta = newDiff * max_percent;
|
|
237
|
-
scale.options.ticks.min = rangeMinLimiter(zoomOptions, scale.min + minDelta);
|
|
238
|
-
scale.options.ticks.max = rangeMaxLimiter(zoomOptions, scale.max - maxDelta);
|
|
239
|
-
}
|
|
240
|
-
/**
|
|
241
|
-
* @param {?} scale
|
|
242
|
-
* @param {?} zoom
|
|
243
|
-
* @param {?} center
|
|
244
|
-
* @param {?} zoomOptions
|
|
245
|
-
* @return {?}
|
|
246
|
-
*/
|
|
247
|
-
function zoomScale(scale, zoom, center, zoomOptions) {
|
|
248
|
-
/** @type {?} */
|
|
249
|
-
const fn = zoomFunctions[scale.options.type];
|
|
250
|
-
if (fn) {
|
|
251
|
-
fn(scale, zoom, center, zoomOptions);
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
/**
|
|
255
|
-
* @param {?} chartInstance
|
|
256
|
-
* @param {?} zoom
|
|
257
|
-
* @param {?} center
|
|
258
|
-
* @param {?=} whichAxes
|
|
259
|
-
* @return {?}
|
|
260
|
-
*/
|
|
261
|
-
function doZoom(chartInstance, zoom, center, whichAxes) {
|
|
262
|
-
/** @type {?} */
|
|
263
|
-
const ca = chartInstance.chartArea;
|
|
264
|
-
if (!center) {
|
|
265
|
-
center = {
|
|
266
|
-
x: (ca.left + ca.right) / 2,
|
|
267
|
-
y: (ca.top + ca.bottom) / 2,
|
|
268
|
-
};
|
|
269
|
-
}
|
|
270
|
-
/** @type {?} */
|
|
271
|
-
const zoomOptions = chartInstance.options.zoom;
|
|
272
|
-
if (zoomOptions && helpers.getValueOrDefault(zoomOptions.enabled, defaultOptions.zoom.enabled)) {
|
|
273
|
-
// Do the zoom here
|
|
274
|
-
/** @type {?} */
|
|
275
|
-
const zoomMode = helpers.getValueOrDefault(chartInstance.options.zoom.mode, defaultOptions.zoom.mode);
|
|
276
|
-
zoomOptions.sensitivity = helpers.getValueOrDefault(chartInstance.options.zoom.sensitivity, defaultOptions.zoom.sensitivity);
|
|
277
|
-
// Which axe should be modified when figers were used.
|
|
278
|
-
/** @type {?} */
|
|
279
|
-
let _whichAxes;
|
|
280
|
-
if (zoomMode === 'xy' && whichAxes !== undefined) {
|
|
281
|
-
// based on fingers positions
|
|
282
|
-
_whichAxes = whichAxes;
|
|
283
|
-
}
|
|
284
|
-
else {
|
|
285
|
-
// no effect
|
|
286
|
-
_whichAxes = 'xy';
|
|
287
|
-
}
|
|
288
|
-
helpers.each(chartInstance.scales, function (scale, id) {
|
|
289
|
-
if (scale.isHorizontal() && directionEnabled(zoomMode, 'x') && directionEnabled(_whichAxes, 'x')) {
|
|
290
|
-
zoomOptions.scaleAxes = 'x';
|
|
291
|
-
zoomScale(scale, zoom, center, zoomOptions);
|
|
292
|
-
}
|
|
293
|
-
else if (!scale.isHorizontal() && directionEnabled(zoomMode, 'y') && directionEnabled(_whichAxes, 'y')) {
|
|
294
|
-
// Do Y zoom
|
|
295
|
-
zoomOptions.scaleAxes = 'y';
|
|
296
|
-
zoomScale(scale, zoom, center, zoomOptions);
|
|
297
|
-
}
|
|
298
|
-
});
|
|
299
|
-
chartInstance.update(0);
|
|
300
|
-
if (typeof zoomOptions.onZoom === 'function') {
|
|
301
|
-
zoomOptions.onZoom();
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
/**
|
|
306
|
-
* @param {?} scale
|
|
307
|
-
* @param {?} delta
|
|
308
|
-
* @param {?} panOptions
|
|
309
|
-
* @return {?}
|
|
310
|
-
*/
|
|
311
|
-
function panIndexScale(scale, delta, panOptions) {
|
|
312
|
-
/** @type {?} */
|
|
313
|
-
const labels = scale.chart.data.labels;
|
|
314
|
-
/** @type {?} */
|
|
315
|
-
const lastLabelIndex = labels.length - 1;
|
|
316
|
-
/** @type {?} */
|
|
317
|
-
const offsetAmt = Math.max((scale.ticks.length - ((scale.options.gridLines.offsetGridLines) ? 0 : 1)), 1);
|
|
318
|
-
/** @type {?} */
|
|
319
|
-
const panSpeed = panOptions.speed;
|
|
320
|
-
/** @type {?} */
|
|
321
|
-
let minIndex = scale.minIndex;
|
|
322
|
-
/** @type {?} */
|
|
323
|
-
const step = Math.round(scale.width / (offsetAmt * panSpeed));
|
|
324
|
-
/** @type {?} */
|
|
325
|
-
let maxIndex;
|
|
326
|
-
zoomNS.panCumulativeDelta += delta;
|
|
327
|
-
minIndex = zoomNS.panCumulativeDelta > step ? Math.max(0, minIndex - 1) : zoomNS.panCumulativeDelta < -step ? Math.min(lastLabelIndex - offsetAmt + 1, minIndex + 1) : minIndex;
|
|
328
|
-
zoomNS.panCumulativeDelta = minIndex !== scale.minIndex ? 0 : zoomNS.panCumulativeDelta;
|
|
329
|
-
maxIndex = Math.min(lastLabelIndex, minIndex + offsetAmt - 1);
|
|
330
|
-
scale.options.ticks.min = rangeMinLimiter(panOptions, labels[minIndex]);
|
|
331
|
-
scale.options.ticks.max = rangeMaxLimiter(panOptions, labels[maxIndex]);
|
|
332
|
-
}
|
|
333
|
-
/**
|
|
334
|
-
* @param {?} scale
|
|
335
|
-
* @param {?} delta
|
|
336
|
-
* @param {?} panOptions
|
|
337
|
-
* @return {?}
|
|
338
|
-
*/
|
|
339
|
-
function panTimeScale(scale, delta, panOptions) {
|
|
340
|
-
/** @type {?} */
|
|
341
|
-
const options = scale.options;
|
|
342
|
-
/** @type {?} */
|
|
343
|
-
const limitedMax = rangeMaxLimiter(panOptions, scale.getValueForPixel(scale.getPixelForValue(scale.max) - delta));
|
|
344
|
-
/** @type {?} */
|
|
345
|
-
const limitedMin = rangeMinLimiter(panOptions, scale.getValueForPixel(scale.getPixelForValue(scale.min) - delta));
|
|
346
|
-
/** @type {?} */
|
|
347
|
-
const limitedTimeDelta = delta < 0 ? limitedMax - scale.max : limitedMin - scale.min;
|
|
348
|
-
options.time.max = scale.max + limitedTimeDelta;
|
|
349
|
-
options.time.min = scale.min + limitedTimeDelta;
|
|
350
|
-
}
|
|
351
|
-
/**
|
|
352
|
-
* @param {?} scale
|
|
353
|
-
* @param {?} delta
|
|
354
|
-
* @param {?} panOptions
|
|
355
|
-
* @return {?}
|
|
356
|
-
*/
|
|
357
|
-
function panNumericalScale(scale, delta, panOptions) {
|
|
358
|
-
/** @type {?} */
|
|
359
|
-
const tickOpts = scale.options.ticks;
|
|
360
|
-
/** @type {?} */
|
|
361
|
-
const start = scale.start;
|
|
362
|
-
/** @type {?} */
|
|
363
|
-
const end = scale.end;
|
|
364
|
-
if (tickOpts.reverse) {
|
|
365
|
-
tickOpts.max = scale.getValueForPixel(scale.getPixelForValue(start) - delta);
|
|
366
|
-
tickOpts.min = scale.getValueForPixel(scale.getPixelForValue(end) - delta);
|
|
367
|
-
}
|
|
368
|
-
else {
|
|
369
|
-
tickOpts.min = scale.getValueForPixel(scale.getPixelForValue(start) - delta);
|
|
370
|
-
tickOpts.max = scale.getValueForPixel(scale.getPixelForValue(end) - delta);
|
|
371
|
-
}
|
|
372
|
-
tickOpts.min = rangeMinLimiter(panOptions, tickOpts.min);
|
|
373
|
-
tickOpts.max = rangeMaxLimiter(panOptions, tickOpts.max);
|
|
374
|
-
}
|
|
375
|
-
/**
|
|
376
|
-
* @param {?} scale
|
|
377
|
-
* @param {?} delta
|
|
378
|
-
* @param {?} panOptions
|
|
379
|
-
* @return {?}
|
|
380
|
-
*/
|
|
381
|
-
function panScale(scale, delta, panOptions) {
|
|
382
|
-
/** @type {?} */
|
|
383
|
-
const fn = panFunctions[scale.options.type];
|
|
384
|
-
if (fn) {
|
|
385
|
-
fn(scale, delta, panOptions);
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
/**
|
|
389
|
-
* @param {?} chartInstance
|
|
390
|
-
* @param {?} deltaX
|
|
391
|
-
* @param {?} deltaY
|
|
392
|
-
* @return {?}
|
|
393
|
-
*/
|
|
394
|
-
function doPan(chartInstance, deltaX, deltaY) {
|
|
395
|
-
/** @type {?} */
|
|
396
|
-
const panOptions = chartInstance.options.pan;
|
|
397
|
-
if (panOptions && helpers.getValueOrDefault(panOptions.enabled, defaultOptions.pan.enabled)) {
|
|
398
|
-
/** @type {?} */
|
|
399
|
-
const panMode = helpers.getValueOrDefault(chartInstance.options.pan.mode, defaultOptions.pan.mode);
|
|
400
|
-
panOptions.speed = helpers.getValueOrDefault(chartInstance.options.pan.speed, defaultOptions.pan.speed);
|
|
401
|
-
helpers.each(chartInstance.scales, function (scale, id) {
|
|
402
|
-
if (scale.isHorizontal() && directionEnabled(panMode, 'x') && deltaX !== 0) {
|
|
403
|
-
panOptions.scaleAxes = 'x';
|
|
404
|
-
panScale(scale, deltaX, panOptions);
|
|
405
|
-
}
|
|
406
|
-
else if (!scale.isHorizontal() && directionEnabled(panMode, 'y') && deltaY !== 0) {
|
|
407
|
-
panOptions.scaleAxes = 'y';
|
|
408
|
-
panScale(scale, deltaY, panOptions);
|
|
409
|
-
}
|
|
410
|
-
});
|
|
411
|
-
chartInstance.update(0);
|
|
412
|
-
if (typeof panOptions.onPan === 'function') {
|
|
413
|
-
panOptions.onPan();
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
/**
|
|
418
|
-
* @param {?} chartInstance
|
|
419
|
-
* @param {?} position
|
|
420
|
-
* @return {?}
|
|
421
|
-
*/
|
|
422
|
-
function positionInChartArea(chartInstance, position) {
|
|
423
|
-
return (position.x >= chartInstance.chartArea.left && position.x <= chartInstance.chartArea.right) &&
|
|
424
|
-
(position.y >= chartInstance.chartArea.top && position.y <= chartInstance.chartArea.bottom);
|
|
425
|
-
}
|
|
426
|
-
/**
|
|
427
|
-
* @param {?} chartInstance
|
|
428
|
-
* @return {?}
|
|
429
|
-
*/
|
|
430
|
-
function getYAxis(chartInstance) {
|
|
431
|
-
/** @type {?} */
|
|
432
|
-
const scales = chartInstance.scales;
|
|
433
|
-
for (const scaleId in scales) {
|
|
434
|
-
if (scales.hasOwnProperty(scaleId)) {
|
|
435
|
-
/** @type {?} */
|
|
436
|
-
const scale = scales[scaleId];
|
|
437
|
-
if (!scale.isHorizontal()) {
|
|
438
|
-
return scale;
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
// Store these for later
|
|
444
|
-
zoomNS.zoomFunctions.category = zoomIndexScale;
|
|
445
|
-
zoomNS.zoomFunctions.time = zoomTimeScale;
|
|
446
|
-
zoomNS.zoomFunctions.linear = zoomNumericalScale;
|
|
447
|
-
zoomNS.zoomFunctions.logarithmic = zoomNumericalScale;
|
|
448
|
-
zoomNS.panFunctions.category = panIndexScale;
|
|
449
|
-
zoomNS.panFunctions.time = panTimeScale;
|
|
450
|
-
zoomNS.panFunctions.linear = panNumericalScale;
|
|
451
|
-
zoomNS.panFunctions.logarithmic = panNumericalScale;
|
|
452
|
-
// Globals for catergory pan and zoom
|
|
453
|
-
zoomNS.panCumulativeDelta = 0;
|
|
454
|
-
zoomNS.zoomCumulativeDelta = 0;
|
|
455
|
-
// Chartjs Zoom Plugin
|
|
456
|
-
/** @type {?} */
|
|
457
|
-
export const zoomPlugin = {
|
|
458
|
-
afterInit: function (chartInstance) {
|
|
459
|
-
helpers.each(chartInstance.scales, function (scale) {
|
|
460
|
-
scale.originalOptions = helpers.clone(scale.options);
|
|
461
|
-
});
|
|
462
|
-
chartInstance.resetZoom = function () {
|
|
463
|
-
helpers.each(chartInstance.scales, function (scale, id) {
|
|
464
|
-
/** @type {?} */
|
|
465
|
-
const timeOptions = scale.options.time;
|
|
466
|
-
/** @type {?} */
|
|
467
|
-
const tickOptions = scale.options.ticks;
|
|
468
|
-
if (timeOptions) {
|
|
469
|
-
timeOptions.min = scale.originalOptions.time.min;
|
|
470
|
-
timeOptions.max = scale.originalOptions.time.max;
|
|
471
|
-
}
|
|
472
|
-
if (tickOptions) {
|
|
473
|
-
tickOptions.min = scale.originalOptions.ticks.min;
|
|
474
|
-
tickOptions.max = scale.originalOptions.ticks.max;
|
|
475
|
-
}
|
|
476
|
-
});
|
|
477
|
-
helpers.each(chartInstance.data.datasets, function (dataset, id) {
|
|
478
|
-
dataset._meta = null;
|
|
479
|
-
});
|
|
480
|
-
chartInstance.update();
|
|
481
|
-
};
|
|
482
|
-
},
|
|
483
|
-
beforeInit: function (chartInstance) {
|
|
484
|
-
chartInstance.zoom = {};
|
|
485
|
-
/** @type {?} */
|
|
486
|
-
const node = chartInstance.zoom.node = chartInstance.chart.ctx.canvas;
|
|
487
|
-
/** @type {?} */
|
|
488
|
-
const options = chartInstance.options;
|
|
489
|
-
/** @type {?} */
|
|
490
|
-
const panThreshold = helpers.getValueOrDefault(options.pan ? options.pan.threshold : undefined, zoomNS.defaults.pan.threshold);
|
|
491
|
-
if (!options.zoom || !options.zoom.enabled) {
|
|
492
|
-
return;
|
|
493
|
-
}
|
|
494
|
-
if (options.zoom.drag) {
|
|
495
|
-
// Only want to zoom horizontal axis
|
|
496
|
-
options.zoom.mode = 'x';
|
|
497
|
-
chartInstance.zoom._mouseDownHandler = function (event) {
|
|
498
|
-
chartInstance.zoom._dragZoomStart = event;
|
|
499
|
-
};
|
|
500
|
-
node.addEventListener('mousedown', chartInstance.zoom._mouseDownHandler);
|
|
501
|
-
chartInstance.zoom._mouseMoveHandler = function (event) {
|
|
502
|
-
if (chartInstance.zoom._dragZoomStart) {
|
|
503
|
-
chartInstance.zoom._dragZoomEnd = event;
|
|
504
|
-
chartInstance.update(0);
|
|
505
|
-
}
|
|
506
|
-
};
|
|
507
|
-
node.addEventListener('mousemove', chartInstance.zoom._mouseMoveHandler);
|
|
508
|
-
chartInstance.zoom._mouseUpHandler = function (event) {
|
|
509
|
-
if (chartInstance.zoom._dragZoomStart) {
|
|
510
|
-
/** @type {?} */
|
|
511
|
-
const chartArea = chartInstance.chartArea;
|
|
512
|
-
/** @type {?} */
|
|
513
|
-
const yAxis = getYAxis(chartInstance);
|
|
514
|
-
/** @type {?} */
|
|
515
|
-
const beginPoint = chartInstance.zoom._dragZoomStart;
|
|
516
|
-
/** @type {?} */
|
|
517
|
-
const offsetX = beginPoint.target.getBoundingClientRect().left;
|
|
518
|
-
/** @type {?} */
|
|
519
|
-
const startX = Math.max(Math.min(beginPoint.clientX, event.clientX) - offsetX, chartArea.left);
|
|
520
|
-
/** @type {?} */
|
|
521
|
-
const endX = Math.min(Math.max(beginPoint.clientX, event.clientX) - offsetX, chartArea.right);
|
|
522
|
-
/** @type {?} */
|
|
523
|
-
const dragDistance = endX - startX;
|
|
524
|
-
/** @type {?} */
|
|
525
|
-
const chartDistance = chartArea.right - chartArea.left;
|
|
526
|
-
/** @type {?} */
|
|
527
|
-
const zoom = 1 + (chartDistance - dragDistance) / chartDistance;
|
|
528
|
-
/** @type {?} */
|
|
529
|
-
const centerX = chartArea.left + (startX - chartArea.left) / (zoom - 1);
|
|
530
|
-
// Remove drag start and end before chart update to stop drawing selected area
|
|
531
|
-
chartInstance.zoom._dragZoomStart = null;
|
|
532
|
-
chartInstance.zoom._dragZoomEnd = null;
|
|
533
|
-
if (dragDistance > 0) {
|
|
534
|
-
doZoom(chartInstance, zoom, {
|
|
535
|
-
x: centerX,
|
|
536
|
-
y: (yAxis.bottom - yAxis.top) / 2,
|
|
537
|
-
});
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
};
|
|
541
|
-
// node.addEventListener('mouseup', chartInstance.zoom._mouseUpHandler);
|
|
542
|
-
node.ownerDocument.addEventListener('mouseup', chartInstance.zoom._mouseUpHandler);
|
|
543
|
-
}
|
|
544
|
-
else {
|
|
545
|
-
chartInstance.zoom._wheelHandler = function (event) {
|
|
546
|
-
/** @type {?} */
|
|
547
|
-
const rect = event.target.getBoundingClientRect();
|
|
548
|
-
/** @type {?} */
|
|
549
|
-
const offsetX = event.clientX - rect.left;
|
|
550
|
-
/** @type {?} */
|
|
551
|
-
const offsetY = event.clientY - rect.top;
|
|
552
|
-
/** @type {?} */
|
|
553
|
-
const center = {
|
|
554
|
-
x: offsetX,
|
|
555
|
-
y: offsetY
|
|
556
|
-
};
|
|
557
|
-
if (event.deltaY < 0) {
|
|
558
|
-
doZoom(chartInstance, 1.1, center);
|
|
559
|
-
}
|
|
560
|
-
else {
|
|
561
|
-
doZoom(chartInstance, 0.909, center);
|
|
562
|
-
}
|
|
563
|
-
// Prevent the event from triggering the default behavior (eg. Content scrolling).
|
|
564
|
-
event.preventDefault();
|
|
565
|
-
};
|
|
566
|
-
node.addEventListener('wheel', chartInstance.zoom._wheelHandler);
|
|
567
|
-
}
|
|
568
|
-
if (Hammer) {
|
|
569
|
-
/** @type {?} */
|
|
570
|
-
const mc = new Hammer.Manager(node);
|
|
571
|
-
mc.add(new Hammer.Pinch());
|
|
572
|
-
mc.add(new Hammer.Pan({
|
|
573
|
-
threshold: panThreshold
|
|
574
|
-
}));
|
|
575
|
-
// Hammer reports the total scaling. We need the incremental amount
|
|
576
|
-
/** @type {?} */
|
|
577
|
-
let currentPinchScaling;
|
|
578
|
-
/** @type {?} */
|
|
579
|
-
const handlePinch = function (e) {
|
|
580
|
-
/** @type {?} */
|
|
581
|
-
const diff = 1 / (currentPinchScaling) * e.scale;
|
|
582
|
-
/** @type {?} */
|
|
583
|
-
const rect = e.target.getBoundingClientRect();
|
|
584
|
-
/** @type {?} */
|
|
585
|
-
const offsetX = e.center.x - rect.left;
|
|
586
|
-
/** @type {?} */
|
|
587
|
-
const offsetY = e.center.y - rect.top;
|
|
588
|
-
/** @type {?} */
|
|
589
|
-
const center = {
|
|
590
|
-
x: offsetX,
|
|
591
|
-
y: offsetY
|
|
592
|
-
};
|
|
593
|
-
// fingers position difference
|
|
594
|
-
/** @type {?} */
|
|
595
|
-
const x = Math.abs(e.pointers[0].clientX - e.pointers[1].clientX);
|
|
596
|
-
/** @type {?} */
|
|
597
|
-
const y = Math.abs(e.pointers[0].clientY - e.pointers[1].clientY);
|
|
598
|
-
// diagonal fingers will change both (xy) axes
|
|
599
|
-
/** @type {?} */
|
|
600
|
-
const p = x / y;
|
|
601
|
-
/** @type {?} */
|
|
602
|
-
let xy;
|
|
603
|
-
if (p > 0.3 && p < 1.7) {
|
|
604
|
-
xy = 'xy';
|
|
605
|
-
}
|
|
606
|
-
else if (x > y) {
|
|
607
|
-
// x axis
|
|
608
|
-
xy = 'x';
|
|
609
|
-
}
|
|
610
|
-
else {
|
|
611
|
-
// y axis
|
|
612
|
-
xy = 'y';
|
|
613
|
-
}
|
|
614
|
-
doZoom(chartInstance, diff, center, xy);
|
|
615
|
-
// Keep track of overall scale
|
|
616
|
-
currentPinchScaling = e.scale;
|
|
617
|
-
};
|
|
618
|
-
mc.on('pinchstart', function (e) {
|
|
619
|
-
currentPinchScaling = 1; // reset tracker
|
|
620
|
-
});
|
|
621
|
-
mc.on('pinch', handlePinch);
|
|
622
|
-
mc.on('pinchend', function (e) {
|
|
623
|
-
handlePinch(e);
|
|
624
|
-
currentPinchScaling = null; // reset
|
|
625
|
-
zoomNS.zoomCumulativeDelta = 0;
|
|
626
|
-
});
|
|
627
|
-
/** @type {?} */
|
|
628
|
-
let currentDeltaX = null;
|
|
629
|
-
/** @type {?} */
|
|
630
|
-
let currentDeltaY = null;
|
|
631
|
-
/** @type {?} */
|
|
632
|
-
let panning = false;
|
|
633
|
-
/** @type {?} */
|
|
634
|
-
const handlePan = function (e) {
|
|
635
|
-
if (currentDeltaX !== null && currentDeltaY !== null) {
|
|
636
|
-
panning = true;
|
|
637
|
-
/** @type {?} */
|
|
638
|
-
const deltaX = e.deltaX - currentDeltaX;
|
|
639
|
-
/** @type {?} */
|
|
640
|
-
const deltaY = e.deltaY - currentDeltaY;
|
|
641
|
-
currentDeltaX = e.deltaX;
|
|
642
|
-
currentDeltaY = e.deltaY;
|
|
643
|
-
doPan(chartInstance, deltaX, deltaY);
|
|
644
|
-
}
|
|
645
|
-
};
|
|
646
|
-
mc.on('panstart', function (e) {
|
|
647
|
-
currentDeltaX = 0;
|
|
648
|
-
currentDeltaY = 0;
|
|
649
|
-
handlePan(e);
|
|
650
|
-
});
|
|
651
|
-
mc.on('panmove', handlePan);
|
|
652
|
-
mc.on('panend', function (e) {
|
|
653
|
-
currentDeltaX = null;
|
|
654
|
-
currentDeltaY = null;
|
|
655
|
-
zoomNS.panCumulativeDelta = 0;
|
|
656
|
-
setTimeout(function () { panning = false; }, 500);
|
|
657
|
-
});
|
|
658
|
-
chartInstance.zoom._ghostClickHandler = function (e) {
|
|
659
|
-
if (panning) {
|
|
660
|
-
e.stopImmediatePropagation();
|
|
661
|
-
e.preventDefault();
|
|
662
|
-
}
|
|
663
|
-
};
|
|
664
|
-
node.addEventListener('click', chartInstance.zoom._ghostClickHandler);
|
|
665
|
-
chartInstance._mc = mc;
|
|
666
|
-
}
|
|
667
|
-
},
|
|
668
|
-
beforeDatasetsDraw: function (chartInstance) {
|
|
669
|
-
/** @type {?} */
|
|
670
|
-
const ctx = chartInstance.chart.ctx;
|
|
671
|
-
/** @type {?} */
|
|
672
|
-
const chartArea = chartInstance.chartArea;
|
|
673
|
-
ctx.save();
|
|
674
|
-
ctx.beginPath();
|
|
675
|
-
if (chartInstance.zoom._dragZoomEnd) {
|
|
676
|
-
/** @type {?} */
|
|
677
|
-
const yAxis = getYAxis(chartInstance);
|
|
678
|
-
/** @type {?} */
|
|
679
|
-
const beginPoint = chartInstance.zoom._dragZoomStart;
|
|
680
|
-
/** @type {?} */
|
|
681
|
-
const endPoint = chartInstance.zoom._dragZoomEnd;
|
|
682
|
-
/** @type {?} */
|
|
683
|
-
const offsetX = beginPoint.target.getBoundingClientRect().left;
|
|
684
|
-
/** @type {?} */
|
|
685
|
-
const startX = Math.min(beginPoint.clientX, endPoint.clientX) - offsetX;
|
|
686
|
-
/** @type {?} */
|
|
687
|
-
const endX = Math.max(beginPoint.clientX, endPoint.clientX) - offsetX;
|
|
688
|
-
/** @type {?} */
|
|
689
|
-
const rectWidth = endX - startX;
|
|
690
|
-
ctx.fillStyle = 'rgba(225,225,225,0.5)';
|
|
691
|
-
ctx.lineWidth = 5;
|
|
692
|
-
ctx.fillRect(startX, yAxis.top, rectWidth, yAxis.bottom - yAxis.top);
|
|
693
|
-
}
|
|
694
|
-
ctx.rect(chartArea.left, chartArea.top, chartArea.right - chartArea.left, chartArea.bottom - chartArea.top);
|
|
695
|
-
ctx.clip();
|
|
696
|
-
},
|
|
697
|
-
afterDatasetsDraw: function (chartInstance) {
|
|
698
|
-
chartInstance.chart.ctx.restore();
|
|
699
|
-
},
|
|
700
|
-
destroy: function (chartInstance) {
|
|
701
|
-
if (chartInstance.zoom) {
|
|
702
|
-
/** @type {?} */
|
|
703
|
-
const options = chartInstance.options;
|
|
704
|
-
/** @type {?} */
|
|
705
|
-
const node = chartInstance.zoom.node;
|
|
706
|
-
if (options.zoom && options.zoom.drag) {
|
|
707
|
-
node.removeEventListener('mousedown', chartInstance.zoom._mouseDownHandler);
|
|
708
|
-
node.removeEventListener('mousemove', chartInstance.zoom._mouseMoveHandler);
|
|
709
|
-
// node.removeEventListener('mouseup', chartInstance.zoom._mouseUpHandler);
|
|
710
|
-
node.ownerDocument.removeEventListener('mouseup', chartInstance.zoom._mouseUpHandler);
|
|
711
|
-
}
|
|
712
|
-
else {
|
|
713
|
-
node.removeEventListener('wheel', chartInstance.zoom._wheelHandler);
|
|
714
|
-
}
|
|
715
|
-
if (Hammer) {
|
|
716
|
-
node.removeEventListener('click', chartInstance.zoom._ghostClickHandler);
|
|
717
|
-
}
|
|
718
|
-
delete chartInstance.zoom;
|
|
719
|
-
/** @type {?} */
|
|
720
|
-
const mc = chartInstance._mc;
|
|
721
|
-
if (mc) {
|
|
722
|
-
mc.remove('pinchstart');
|
|
723
|
-
mc.remove('pinch');
|
|
724
|
-
mc.remove('pinchend');
|
|
725
|
-
mc.remove('panstart');
|
|
726
|
-
mc.remove('pan');
|
|
727
|
-
mc.remove('panend');
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
}
|
|
731
|
-
};
|
|
732
|
-
Chart.pluginService.register(zoomPlugin);
|
|
733
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhcnQuem9vbS5qcyIsInNvdXJjZVJvb3QiOiJuZzovL25neC1oYW5hLW5hbWVzZXJ2ZXItaGlzdG9yeS12aWV3ZXIvIiwic291cmNlcyI6WyJzcmMvbmFtZXNlcnZlci1oaXN0b3J5LXZpZXdlci91dGlscy9jaGFydGpzLXpvb20vY2hhcnQuem9vbS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUE0QkEsT0FBTyxLQUFLLFFBQVEsTUFBTSxVQUFVLENBQUM7O01BQy9CLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxtQkFBQSxNQUFNLEVBQU8sQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxtQkFBQSxNQUFNLEVBQU8sQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLE1BQU07O0FBRzFGLE9BQU8sS0FBSyxPQUFPLE1BQU0sVUFBVSxDQUFDOztNQUM5QixLQUFLLEdBQUcsTUFBTSxJQUFJLENBQUMsbUJBQUEsTUFBTSxFQUFPLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsbUJBQUEsTUFBTSxFQUFPLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxLQUFLOztNQUUvRSxPQUFPLEdBQUcsS0FBSyxDQUFDLE9BQU87OztNQUd2QixNQUFNLEdBQUcsS0FBSyxDQUFDLElBQUksR0FBRyxLQUFLLENBQUMsSUFBSSxJQUFJLEVBQUU7OztNQUd0QyxhQUFhLEdBQUcsTUFBTSxDQUFDLGFBQWEsR0FBRyxNQUFNLENBQUMsYUFBYSxJQUFJLEVBQUU7O01BQ2pFLFlBQVksR0FBRyxNQUFNLENBQUMsWUFBWSxHQUFHLE1BQU0sQ0FBQyxZQUFZLElBQUksRUFBRTs7O01BRzlELGNBQWMsR0FBRyxNQUFNLENBQUMsUUFBUSxHQUFHO0lBQ3ZDLEdBQUcsRUFBRTtRQUNILE9BQU8sRUFBRSxJQUFJO1FBQ2IsSUFBSSxFQUFFLElBQUk7UUFD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QWEsQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsQ0FBQzthQUMxRTtZQUVELE9BQU8sYUFBYSxDQUFDLElBQUksQ0FBQzs7a0JBRXBCLEVBQUUsR0FBRyxhQUFhLENBQUMsR0FBRztZQUM1QixJQUFJLEVBQUUsRUFBRTtnQkFDTixFQUFFLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDO2dCQUN4QixFQUFFLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO2dCQUNuQixFQUFFLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDO2dCQUN0QixFQUFFLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDO2dCQUN0QixFQUFFLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUNqQixFQUFFLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO2FBQ3JCO1NBQ0Y7SUFDSCxDQUFDO0NBQ0Y7QUFFRCxLQUFLLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxyXG4gKiB0aGlzIHBsdWdpbiBpcyBhZGFwdGVkIGZyb206IGh0dHBzOi8vZ2l0aHViLmNvbS9jaGFydGpzL2NoYXJ0anMtcGx1Z2luLXpvb21cclxuICogZm9yIGZvbGxvd2luZyB0d28gb3BlbiBpc3N1ZXM6XHJcbiAqIGh0dHBzOi8vZ2l0aHViLmNvbS9jaGFydGpzL2NoYXJ0anMtcGx1Z2luLXpvb20vcHVsbC8xNTVcclxuICogaHR0cHM6Ly9naXRodWIuY29tL2NoYXJ0anMvY2hhcnRqcy1wbHVnaW4tem9vbS9wdWxsLzE1MFxyXG4gKlxyXG4gKiBUaGUgTUlUIExpY2Vuc2UgKE1JVCkgQ29weXJpZ2h0IChjKSAyMDEzLTIwMTYgTmljayBEb3duaWVcclxuICogUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weSBvZiB0aGlzXHJcbiAqIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZVxyXG4gKiB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLFxyXG4gKiBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnNcclxuICogdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcclxuICpcclxuICogVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW4gYWxsIGNvcGllcyBvclxyXG4gKiBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXHJcbiAqXHJcbiAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1IgSU1QTElFRCwgSU5DTFVESU5HXHJcbiAqIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFXHJcbiAqIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZXHJcbiAqIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLFxyXG4gKiBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU5cclxuICogVEhFIFNPRlRXQVJFLlxyXG4gKi9cclxuXHJcbi8qanNsaW50IGJyb3dzZXI6dHJ1ZSwgZGV2ZWw6dHJ1ZSwgd2hpdGU6dHJ1ZSwgdmFyczp0cnVlICovXHJcbi8qZ2xvYmFsIHJlcXVpcmUqL1xyXG5cclxuLy8gaGFtbWVyIEpTIGZvciB0b3VjaCBzdXBwb3J0XHJcbmltcG9ydCAqIGFzIGhhbW1lcmpzIGZyb20gJ2hhbW1lcmpzJztcclxuY29uc3QgSGFtbWVyID0gd2luZG93ICYmICh3aW5kb3cgYXMgYW55KS5IYW1tZXIgPyAod2luZG93IGFzIGFueSkuSGFtbWVyIDogaGFtbWVyanMuSGFtbWVyO1xyXG5cclxuLy8gR2V0IHRoZSBjaGFydCB2YXJpYWJsZVxyXG5pbXBvcnQgKiBhcyBjaGFydGpzIGZyb20gJ2NoYXJ0LmpzJztcclxuY29uc3QgQ2hhcnQgPSB3aW5kb3cgJiYgKHdpbmRvdyBhcyBhbnkpLkNoYXJ0ID8gKHdpbmRvdyBhcyBhbnkpLkNoYXJ0IDogY2hhcnRqcy5DaGFydDtcclxuXHJcbmNvbnN0IGhlbHBlcnMgPSBDaGFydC5oZWxwZXJzO1xyXG5cclxuLy8gVGFrZSB0aGUgem9vbSBuYW1lc3BhY2Ugb2YgQ2hhcnRcclxuY29uc3Qgem9vbU5TID0gQ2hhcnQuWm9vbSA9IENoYXJ0Llpvb20gfHwge307XHJcblxyXG4vLyBXaGVyZSB3ZSBzdG9yZSBmdW5jdGlvbnMgdG8gaGFuZGxlIGRpZmZlcmVudCBzY2FsZSB0eXBlc1xyXG5jb25zdCB6b29tRnVuY3Rpb25zID0gem9vbU5TLnpvb21GdW5jdGlvbnMgPSB6b29tTlMuem9vbUZ1bmN0aW9ucyB8fCB7fTtcclxuY29uc3QgcGFuRnVuY3Rpb25zID0gem9vbU5TLnBhbkZ1bmN0aW9ucyA9IHpvb21OUy5wYW5GdW5jdGlvbnMgfHwge307XHJcblxyXG4vLyBEZWZhdWx0IG9wdGlvbnMgaWYgbm9uZSBhcmUgcHJvdmlkZWRcclxuY29uc3QgZGVmYXVsdE9wdGlvbnMgPSB6b29tTlMuZGVmYXVsdHMgPSB7XHJcbiAgcGFuOiB7XHJcbiAgICBlbmFibGVkOiB0cnVlLFxyXG4gICAgbW9kZTogJ3h5JyxcclxuICAgIHNwZWVkOiAyMCxcclxuICAgIHRocmVzaG9sZDogMTBcclxuICB9LFxyXG4gIHpvb206IHtcclxuICAgIGVuYWJsZWQ6IHRydWUsXHJcbiAgICBtb2RlOiAneHknLFxyXG4gICAgc2Vuc2l0aXZpdHk6IDNcclxuICB9XHJcbn07XHJcblxyXG5mdW5jdGlvbiBkaXJlY3Rpb25FbmFibGVkKG1vZGUsIGRpcikge1xyXG4gIGlmIChtb2RlID09PSB1bmRlZmluZWQpIHtcclxuICAgIHJldHVybiB0cnVlO1xyXG4gIH0gZWxzZSBpZiAodHlwZW9mIG1vZGUgPT09ICdzdHJpbmcnKSB7XHJcbiAgICByZXR1cm4gbW9kZS5pbmRleE9mKGRpcikgIT09IC0xO1xyXG4gIH1cclxuXHJcbiAgcmV0dXJuIGZhbHNlO1xyXG59XHJcblxyXG5mdW5jdGlvbiByYW5nZU1heExpbWl0ZXIoem9vbVBhbk9wdGlvbnMsIG5ld01heCkge1xyXG4gIGlmICh6b29tUGFuT3B0aW9ucy5zY2FsZUF4ZXMgJiYgem9vbVBhbk9wdGlvbnMucmFuZ2VNYXggJiZcclxuICAgICFoZWxwZXJzLmlzTnVsbE9yVW5kZWYoem9vbVBhbk9wdGlvbnMucmFuZ2VNYXhbem9vbVBhbk9wdGlvbnMuc2NhbGVBeGVzXSkpIHtcclxuICAgIGNvbnN0IHJhbmdlTWF4ID0gem9vbVBhbk9wdGlvbnMucmFuZ2VNYXhbem9vbVBhbk9wdGlvbnMuc2NhbGVBeGVzXTtcclxuICAgIGlmIChuZXdNYXggPiByYW5nZU1heCkge1xyXG4gICAgICBuZXdNYXggPSByYW5nZU1heDtcclxuICAgIH1cclxuICB9XHJcbiAgcmV0dXJuIG5ld01heDtcclxufVxyXG5cclxuZnVuY3Rpb24gcmFuZ2VNaW5MaW1pdGVyKHpvb21QYW5PcHRpb25zLCBuZXdNaW4pIHtcclxuICBpZiAoem9vbVBhbk9wdGlvbnMuc2NhbGVBeGVzICYmIHpvb21QYW5PcHRpb25zLnJhbmdlTWluICYmXHJcbiAgICAhaGVscGVycy5pc051bGxPclVuZGVmKHpvb21QYW5PcHRpb25zLnJhbmdlTWluW3pvb21QYW5PcHRpb25zLnNjYWxlQXhlc10pKSB7XHJcbiAgICBjb25zdCByYW5nZU1pbiA9IHpvb21QYW5PcHRpb25zLnJhbmdlTWluW3pvb21QYW5PcHRpb25zLnNjYWxlQXhlc107XHJcbiAgICBpZiAobmV3TWluIDwgcmFuZ2VNaW4pIHtcclxuICAgICAgbmV3TWluID0gcmFuZ2VNaW47XHJcbiAgICB9XHJcbiAgfVxyXG4gIHJldHVybiBuZXdNaW47XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHpvb21JbmRleFNjYWxlKHNjYWxlLCB6b29tLCBjZW50ZXIsIHpvb21PcHRpb25zKSB7XHJcbiAgY29uc3QgbGFiZWxzID0gc2NhbGUuY2hhcnQuZGF0YS5sYWJlbHM7XHJcbiAgbGV0IG1pbkluZGV4ID0gc2NhbGUubWluSW5kZXg7XHJcbiAgY29uc3QgbGFzdExhYmVsSW5kZXggPSBsYWJlbHMubGVuZ3RoIC0gMTtcclxuICBsZXQgbWF4SW5kZXggPSBzY2FsZS5tYXhJbmRleDtcclxuICBjb25zdCBzZW5zaXRpdml0eSA9IHpvb21PcHRpb25zLnNlbnNpdGl2aXR5O1xyXG4gIGNvbnN0IGNoYXJ0Q2VudGVyID0gIHNjYWxlLmlzSG9yaXpvbnRhbCgpID8gc2NhbGUubGVmdCArIChzY2FsZS53aWR0aCAvIDIpIDogc2NhbGUudG9wICsgKHNjYWxlLmhlaWdodCAvIDIpO1xyXG4gIGNvbnN0IGNlbnRlclBvaW50ZXIgPSBzY2FsZS5pc0hvcml6b250YWwoKSA/IGNlbnRlci54IDogY2VudGVyLnk7XHJcblxyXG4gIHpvb21OUy56b29tQ3VtdWxhdGl2ZURlbHRhID0gem9vbSA+IDEgPyB6b29tTlMuem9vbUN1bXVsYXRpdmVEZWx0YSArIDEgOiB6b29tTlMuem9vbUN1bXVsYXRpdmVEZWx0YSAtIDE7XHJcblxyXG4gIGlmIChNYXRoLmFicyh6b29tTlMuem9vbUN1bXVsYXRpdmVEZWx0YSkgPiBzZW5zaXRpdml0eSkge1xyXG4gICAgaWYgKHpvb21OUy56b29tQ3VtdWxhdGl2ZURlbHRhIDwgMCkge1xyXG4gICAgICBpZiAoY2VudGVyUG9pbnRlciA+PSBjaGFydENlbnRlcikge1xyXG4gICAgICAgIGlmIChtaW5JbmRleCA8PSAwKSB7XHJcbiAgICAgICAgICBtYXhJbmRleCA9IE1hdGgubWluKGxhc3RMYWJlbEluZGV4LCBtYXhJbmRleCArIDEpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICBtaW5JbmRleCA9IE1hdGgubWF4KDAsIG1pbkluZGV4IC0gMSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9IGVsc2UgaWYgKGNlbnRlclBvaW50ZXIgPCBjaGFydENlbnRlcikge1xyXG4gICAgICAgIGlmIChtYXhJbmRleCA+PSBsYXN0TGFiZWxJbmRleCkge1xyXG4gICAgICAgICAgbWluSW5kZXggPSBNYXRoLm1heCgwLCBtaW5JbmRleCAtIDEpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICBtYXhJbmRleCA9IE1hdGgubWluKGxhc3RMYWJlbEluZGV4LCBtYXhJbmRleCArIDEpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgICB6b29tTlMuem9vbUN1bXVsYXRpdmVEZWx0YSA9IDA7XHJcbiAgICB9IGVsc2UgaWYgKHpvb21OUy56b29tQ3VtdWxhdGl2ZURlbHRhID4gMCkge1xyXG4gICAgICBpZiAoY2VudGVyUG9pbnRlciA+PSBjaGFydENlbnRlcikge1xyXG4gICAgICAgIG1pbkluZGV4ID0gbWluSW5kZXggPCBtYXhJbmRleCA/IG1pbkluZGV4ID0gTWF0aC5taW4obWF4SW5kZXgsIG1pbkluZGV4ICsgMSkgOiBtaW5JbmRleDtcclxuICAgICAgfSBlbHNlIGlmIChjZW50ZXJQb2ludGVyIDwgY2hhcnRDZW50ZXIpIHtcclxuICAgICAgICBtYXhJbmRleCA9IG1heEluZGV4ID4gbWluSW5kZXggPyBtYXhJbmRleCA9IE1hdGgubWF4KG1pbkluZGV4LCBtYXhJbmRleCAtIDEpIDogbWF4SW5kZXg7XHJcbiAgICAgIH1cclxuICAgICAgem9vbU5TLnpvb21DdW11bGF0aXZlRGVsdGEgPSAwO1xyXG4gICAgfVxyXG4gICAgc2NhbGUub3B0aW9ucy50aWNrcy5taW4gPSByYW5nZU1pbkxpbWl0ZXIoem9vbU9wdGlvbnMsIGxhYmVsc1ttaW5JbmRleF0pO1xyXG4gICAgc2NhbGUub3B0aW9ucy50aWNrcy5tYXggPSByYW5nZU1heExpbWl0ZXIoem9vbU9wdGlvbnMsIGxhYmVsc1ttYXhJbmRleF0pO1xyXG4gIH1cclxufVxyXG5cclxuZnVuY3Rpb24gem9vbVRpbWVTY2FsZShzY2FsZSwgem9vbSwgY2VudGVyLCB6b29tT3B0aW9ucykge1xyXG4gIGNvbnN0IG9wdGlvbnMgPSBzY2FsZS5vcHRpb25zO1xyXG5cclxuICAvLyB2YXIgcmFuZ2U7XHJcbiAgLy8gdmFyIG1pbl9wZXJjZW50O1xyXG4gIC8vIGlmIChzY2FsZS5pc0hvcml6b250YWwoKSkge1xyXG4gIC8vICAgcmFuZ2UgPSBzY2FsZS5yaWdodCAtIHNjYWxlLmxlZnQ7XHJcbiAgLy8gICBtaW5fcGVyY2VudCA9IChjZW50ZXIueCAtIHNjYWxlLmxlZnQpIC8gcmFuZ2U7XHJcbiAgLy8gfSBlbHNlIHtcclxuICAvLyAgIHJhbmdlID0gc2NhbGUuYm90dG9tIC0gc2NhbGUudG9wO1xyXG4gIC8vICAgbWluX3BlcmNlbnQgPSAoY2VudGVyLnkgLSBzY2FsZS50b3ApIC8gcmFuZ2U7XHJcbiAgLy8gfVxyXG4gIC8vXHJcbiAgLy8gdmFyIG1heF9wZXJjZW50ID0gMSAtIG1pbl9wZXJjZW50O1xyXG4gIGNvbnN0IHJhbmdlID0gc2NhbGUubWF4IC0gc2NhbGUubWluO1xyXG4gIGNvbnN0IG5ld0RpZmYgPSByYW5nZSAqICh6b29tIC0gMSk7XHJcblxyXG4gIGNvbnN0IGN1cnNvclBpeGVsID0gc2NhbGUuaXNIb3Jpem9udGFsKCkgPyBjZW50ZXIueCA6IGNlbnRlci55O1xyXG4gIGNvbnN0IG1pbl9wZXJjZW50ID0gKHNjYWxlLmdldFZhbHVlRm9yUGl4ZWwoY3Vyc29yUGl4ZWwpIC0gc2NhbGUubWluKSAvIHJhbmdlO1xyXG4gIGNvbnN0IG1heF9wZXJjZW50ID0gMSAtIG1pbl9wZXJjZW50O1xyXG5cclxuICBjb25zdCBtaW5EZWx0YSA9IG5ld0RpZmYgKiBtaW5fcGVyY2VudDtcclxuICBjb25zdCBtYXhEZWx0YSA9IG5ld0RpZmYgKiBtYXhfcGVyY2VudDtcclxuXHJcbiAgY29uc3QgbmV3TWluID0gc2NhbGUubWluICsgbWluRGVsdGE7XHJcbiAgY29uc3QgbmV3TWF4ID0gc2NhbGUubWF4IC0gbWF4RGVsdGE7XHJcblxyXG4gIGNvbnN0IGRpZmZNaW5NYXggPSBuZXdNYXggLSBuZXdNaW47XHJcbiAgY29uc3QgbWluTGltaXRFeGNlZWRlZCA9IHJhbmdlTWluTGltaXRlcih6b29tT3B0aW9ucywgZGlmZk1pbk1heCkgIT09IGRpZmZNaW5NYXg7XHJcbiAgY29uc3QgbWF4TGltaXRFeGNlZWRlZCA9IHJhbmdlTWF4TGltaXRlcih6b29tT3B0aW9ucywgZGlmZk1pbk1heCkgIT09IGRpZmZNaW5NYXg7XHJcblxyXG4gIGlmICghbWluTGltaXRFeGNlZWRlZCAmJiAhbWF4TGltaXRFeGNlZWRlZCkge1xyXG4gICAgb3B0aW9ucy50aW1lLm1pbiA9IG5ld01pbjtcclxuICAgIG9wdGlvbnMudGltZS5tYXggPSBuZXdNYXg7XHJcbiAgfVxyXG59XHJcblxyXG5mdW5jdGlvbiB6b29tTnVtZXJpY2FsU2NhbGUoc2NhbGUsIHpvb20sIGNlbnRlciwgem9vbU9wdGlvbnMpIHtcclxuICBjb25zdCByYW5nZSA9IHNjYWxlLm1heCAtIHNjYWxlLm1pbjtcclxuICBjb25zdCBuZXdEaWZmID0gcmFuZ2UgKiAoem9vbSAtIDEpO1xyXG5cclxuICBjb25zdCBjdXJzb3JQaXhlbCA9IHNjYWxlLmlzSG9yaXpvbnRhbCgpID8gY2VudGVyLnggOiBjZW50ZXIueTtcclxuICBjb25zdCBtaW5fcGVyY2VudCA9IChzY2FsZS5nZXRWYWx1ZUZvclBpeGVsKGN1cnNvclBpeGVsKSAtIHNjYWxlLm1pbikgLyByYW5nZTtcclxuICBjb25zdCBtYXhfcGVyY2VudCA9IDEgLSBtaW5fcGVyY2VudDtcclxuXHJcbiAgY29uc3QgbWluRGVsdGEgPSBuZXdEaWZmICogbWluX3BlcmNlbnQ7XHJcbiAgY29uc3QgbWF4RGVsdGEgPSBuZXdEaWZmICogbWF4X3BlcmNlbnQ7XHJcblxyXG4gIHNjYWxlLm9wdGlvbnMudGlja3MubWluID0gcmFuZ2VNaW5MaW1pdGVyKHpvb21PcHRpb25zLCBzY2FsZS5taW4gKyBtaW5EZWx0YSk7XHJcbiAgc2NhbGUub3B0aW9ucy50aWNrcy5tYXggPSByYW5nZU1heExpbWl0ZXIoem9vbU9wdGlvbnMsIHNjYWxlLm1heCAtIG1heERlbHRhKTtcclxufVxyXG5cclxuZnVuY3Rpb24gem9vbVNjYWxlKHNjYWxlLCB6b29tLCBjZW50ZXIsIHpvb21PcHRpb25zKSB7XHJcbiAgY29uc3QgZm4gPSB6b29tRnVuY3Rpb25zW3NjYWxlLm9wdGlvbnMudHlwZV07XHJcbiAgaWYgKGZuKSB7XHJcbiAgICBmbihzY2FsZSwgem9vbSwgY2VudGVyLCB6b29tT3B0aW9ucyk7XHJcbiAgfVxyXG59XHJcblxyXG5mdW5jdGlvbiBkb1pvb20oY2hhcnRJbnN0YW5jZSwgem9vbSwgY2VudGVyLCB3aGljaEF4ZXM/KSB7XHJcbiAgY29uc3QgY2EgPSBjaGFydEluc3RhbmNlLmNoYXJ0QXJlYTtcclxuICBpZiAoIWNlbnRlcikge1xyXG4gICAgY2VudGVyID0ge1xyXG4gICAgICB4OiAoY2EubGVmdCArIGNhLnJpZ2h0KSAvIDIsXHJcbiAgICAgIHk6IChjYS50b3AgKyBjYS5ib3R0b20pIC8gMixcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICBjb25zdCB6b29tT3B0aW9ucyA9IGNoYXJ0SW5zdGFuY2Uub3B0aW9ucy56b29tO1xyXG5cclxuICBpZiAoem9vbU9wdGlvbnMgJiYgaGVscGVycy5nZXRWYWx1ZU9yRGVmYXVsdCh6b29tT3B0aW9ucy5lbmFibGVkLCBkZWZhdWx0T3B0aW9ucy56b29tLmVuYWJsZWQpKSB7XHJcbiAgICAvLyBEbyB0aGUgem9vbSBoZXJlXHJcbiAgICBjb25zdCB6b29tTW9kZSA9IGhlbHBlcnMuZ2V0VmFsdWVPckRlZmF1bHQoY2hhcnRJbnN0YW5jZS5vcHRpb25zLnpvb20ubW9kZSwgZGVmYXVsdE9wdGlvbnMuem9vbS5tb2RlKTtcclxuICAgIHpvb21PcHRpb25zLnNlbnNpdGl2aXR5ID0gaGVscGVycy5nZXRWYWx1ZU9yRGVmYXVsdChjaGFydEluc3RhbmNlLm9wdGlvbnMuem9vbS5zZW5zaXRpdml0eSwgZGVmYXVsdE9wdGlvbnMuem9vbS5zZW5zaXRpdml0eSk7XHJcblxyXG4gICAgLy8gV2hpY2ggYXhlIHNob3VsZCBiZSBtb2RpZmllZCB3aGVuIGZpZ2VycyB3ZXJlIHVzZWQuXHJcbiAgICBsZXQgX3doaWNoQXhlcztcclxuICAgIGlmICh6b29tTW9kZSA9PT0gJ3h5JyAmJiB3aGljaEF4ZXMgIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAvLyBiYXNlZCBvbiBmaW5nZXJzIHBvc2l0aW9uc1xyXG4gICAgICBfd2hpY2hBeGVzID0gd2hpY2hBeGVzO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgLy8gbm8gZWZmZWN0XHJcbiAgICAgIF93aGljaEF4ZXMgPSAneHknO1xyXG4gICAgfVxyXG5cclxuICAgIGhlbHBlcnMuZWFjaChjaGFydEluc3RhbmNlLnNjYWxlcywgZnVuY3Rpb24oc2NhbGUsIGlkKSB7XHJcbiAgICAgIGlmIChzY2FsZS5pc0hvcml6b250YWwoKSAmJiBkaXJlY3Rpb25FbmFibGVkKHpvb21Nb2RlLCAneCcpICYmIGRpcmVjdGlvbkVuYWJsZWQoX3doaWNoQXhlcywgJ3gnKSkge1xyXG4gICAgICAgIHpvb21PcHRpb25zLnNjYWxlQXhlcyA9ICd4JztcclxuICAgICAgICB6b29tU2NhbGUoc2NhbGUsIHpvb20sIGNlbnRlciwgem9vbU9wdGlvbnMpO1xyXG4gICAgICB9IGVsc2UgaWYgKCFzY2FsZS5pc0hvcml6b250YWwoKSAmJiBkaXJlY3Rpb25FbmFibGVkKHpvb21Nb2RlLCAneScpICYmIGRpcmVjdGlvbkVuYWJsZWQoX3doaWNoQXhlcywgJ3knKSkge1xyXG4gICAgICAgIC8vIERvIFkgem9vbVxyXG4gICAgICAgIHpvb21PcHRpb25zLnNjYWxlQXhlcyA9ICd5JztcclxuICAgICAgICB6b29tU2NhbGUoc2NhbGUsIHpvb20sIGNlbnRlciwgem9vbU9wdGlvbnMpO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuXHJcbiAgICBjaGFydEluc3RhbmNlLnVwZGF0ZSgwKTtcclxuICAgIGlmICh0eXBlb2Ygem9vbU9wdGlvbnMub25ab29tID09PSAnZnVuY3Rpb24nKSB7XHJcbiAgICAgIHpvb21PcHRpb25zLm9uWm9vbSgpO1xyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuZnVuY3Rpb24gcGFuSW5kZXhTY2FsZShzY2FsZSwgZGVsdGEsIHBhbk9wdGlvbnMpIHtcclxuICBjb25zdCBsYWJlbHMgPSBzY2FsZS5jaGFydC5kYXRhLmxhYmVscztcclxuICBjb25zdCBsYXN0TGFiZWxJbmRleCA9IGxhYmVscy5sZW5ndGggLSAxO1xyXG4gIGNvbnN0IG9mZnNldEFtdCA9IE1hdGgubWF4KChzY2FsZS50aWNrcy5sZW5ndGggLSAoKHNjYWxlLm9wdGlvbnMuZ3JpZExpbmVzLm9mZnNldEdyaWRMaW5lcykgPyAwIDogMSkpLCAxKTtcclxuICBjb25zdCBwYW5TcGVlZCA9IHBhbk9wdGlvbnMuc3BlZWQ7XHJcbiAgbGV0IG1pbkluZGV4ID0gc2NhbGUubWluSW5kZXg7XHJcbiAgY29uc3Qgc3RlcCA9IE1hdGgucm91bmQoc2NhbGUud2lkdGggLyAob2Zmc2V0QW10ICogcGFuU3BlZWQpKTtcclxuICBsZXQgbWF4SW5kZXg7XHJcblxyXG4gIHpvb21OUy5wYW5DdW11bGF0aXZlRGVsdGEgKz0gZGVsdGE7XHJcblxyXG4gIG1pbkluZGV4ID0gem9vbU5TLnBhbkN1bXVsYXRpdmVEZWx0YSA+IHN0ZXAgPyBNYXRoLm1heCgwLCBtaW5JbmRleCAtIDEpIDogem9vbU5TLnBhbkN1bXVsYXRpdmVEZWx0YSA8IC1zdGVwID8gTWF0aC5taW4obGFzdExhYmVsSW5kZXggLSBvZmZzZXRBbXQgKyAxLCBtaW5JbmRleCArIDEpIDogbWluSW5kZXg7XHJcbiAgem9vbU5TLnBhbkN1bXVsYXRpdmVEZWx0YSA9IG1pbkluZGV4ICE9PSBzY2FsZS5taW5JbmRleCA/IDAgOiB6b29tTlMucGFuQ3VtdWxhdGl2ZURlbHRhO1xyXG5cclxuICBtYXhJbmRleCA9IE1hdGgubWluKGxhc3RMYWJlbEluZGV4LCBtaW5JbmRleCArIG9mZnNldEFtdCAtIDEpO1xyXG5cclxuICBzY2FsZS5vcHRpb25zLnRpY2tzLm1pbiA9IHJhbmdlTWluTGltaXRlcihwYW5PcHRpb25zLCBsYWJlbHNbbWluSW5kZXhdKTtcclxuICBzY2FsZS5vcHRpb25zLnRpY2tzLm1heCA9IHJhbmdlTWF4TGltaXRlcihwYW5PcHRpb25zLCBsYWJlbHNbbWF4SW5kZXhdKTtcclxufVxyXG5cclxuZnVuY3Rpb24gcGFuVGltZVNjYWxlKHNjYWxlLCBkZWx0YSwgcGFuT3B0aW9ucykge1xyXG4gIGNvbnN0IG9wdGlvbnMgPSBzY2FsZS5vcHRpb25zO1xyXG4gIGNvbnN0IGxpbWl0ZWRNYXggPSByYW5nZU1heExpbWl0ZXIocGFuT3B0aW9ucywgc2NhbGUuZ2V0VmFsdWVGb3JQaXhlbChzY2FsZS5nZXRQaXhlbEZvclZhbHVlKHNjYWxlLm1heCkgLSBkZWx0YSkpO1xyXG4gIGNvbnN0IGxpbWl0ZWRNaW4gPSByYW5nZU1pbkxpbWl0ZXIocGFuT3B0aW9ucywgc2NhbGUuZ2V0VmFsdWVGb3JQaXhlbChzY2FsZS5nZXRQaXhlbEZvclZhbHVlKHNjYWxlLm1pbikgLSBkZWx0YSkpO1xyXG5cclxuICBjb25zdCBsaW1pdGVkVGltZURlbHRhID0gZGVsdGEgPCAwID8gbGltaXRlZE1heCAtIHNjYWxlLm1heCA6IGxpbWl0ZWRNaW4gLSBzY2FsZS5taW47XHJcblxyXG4gIG9wdGlvbnMudGltZS5tYXggPSBzY2FsZS5tYXggKyBsaW1pdGVkVGltZURlbHRhO1xyXG4gIG9wdGlvbnMudGltZS5taW4gPSBzY2FsZS5taW4gKyBsaW1pdGVkVGltZURlbHRhO1xyXG59XHJcblxyXG5mdW5jdGlvbiBwYW5OdW1lcmljYWxTY2FsZShzY2FsZSwgZGVsdGEsIHBhbk9wdGlvbnMpIHtcclxuICBjb25zdCB0aWNrT3B0cyA9IHNjYWxlLm9wdGlvbnMudGlja3M7XHJcbiAgY29uc3Qgc3RhcnQgPSBzY2FsZS5zdGFydCxcclxuICAgIGVuZCA9IHNjYWxlLmVuZDtcclxuXHJcbiAgaWYgKHRpY2tPcHRzLnJldmVyc2UpIHtcclxuICAgIHRpY2tPcHRzLm1heCA9IHNjYWxlLmdldFZhbHVlRm9yUGl4ZWwoc2NhbGUuZ2V0UGl4ZWxGb3JWYWx1ZShzdGFydCkgLSBkZWx0YSk7XHJcbiAgICB0aWNrT3B0cy5taW4gPSBzY2FsZS5nZXRWYWx1ZUZvclBpeGVsKHNjYWxlLmdldFBpeGVsRm9yVmFsdWUoZW5kKSAtIGRlbHRhKTtcclxuICB9IGVsc2Uge1xyXG4gICAgdGlja09wdHMubWluID0gc2NhbGUuZ2V0VmFsdWVGb3JQaXhlbChzY2FsZS5nZXRQaXhlbEZvclZhbHVlKHN0YXJ0KSAtIGRlbHRhKTtcclxuICAgIHRpY2tPcHRzLm1heCA9IHNjYWxlLmdldFZhbHVlRm9yUGl4ZWwoc2NhbGUuZ2V0UGl4ZWxGb3JWYWx1ZShlbmQpIC0gZGVsdGEpO1xyXG4gIH1cclxuICB0aWNrT3B0cy5taW4gPSByYW5nZU1pbkxpbWl0ZXIocGFuT3B0aW9ucywgdGlja09wdHMubWluKTtcclxuICB0aWNrT3B0cy5tYXggPSByYW5nZU1heExpbWl0ZXIocGFuT3B0aW9ucywgdGlja09wdHMubWF4KTtcclxufVxyXG5cclxuZnVuY3Rpb24gcGFuU2NhbGUoc2NhbGUsIGRlbHRhLCBwYW5PcHRpb25zKSB7XHJcbiAgY29uc3QgZm4gPSBwYW5GdW5jdGlvbnNbc2NhbGUub3B0aW9ucy50eXBlXTtcclxuICBpZiAoZm4pIHtcclxuICAgIGZuKHNjYWxlLCBkZWx0YSwgcGFuT3B0aW9ucyk7XHJcbiAgfVxyXG59XHJcblxyXG5mdW5jdGlvbiBkb1BhbihjaGFydEluc3RhbmNlLCBkZWx0YVgsIGRlbHRhWSkge1xyXG4gIGNvbnN0IHBhbk9wdGlvbnMgPSBjaGFydEluc3RhbmNlLm9wdGlvbnMucGFuO1xyXG4gIGlmIChwYW5PcHRpb25zICYmIGhlbHBlcnMuZ2V0VmFsdWVPckRlZmF1bHQocGFuT3B0aW9ucy5lbmFibGVkLCBkZWZhdWx0T3B0aW9ucy5wYW4uZW5hYmxlZCkpIHtcclxuICAgIGNvbnN0IHBhbk1vZGUgPSBoZWxwZXJzLmdldFZhbHVlT3JEZWZhdWx0KGNoYXJ0SW5zdGFuY2Uub3B0aW9ucy5wYW4ubW9kZSwgZGVmYXVsdE9wdGlvbnMucGFuLm1vZGUpO1xyXG4gICAgcGFuT3B0aW9ucy5zcGVlZCA9IGhlbHBlcnMuZ2V0VmFsdWVPckRlZmF1bHQoY2hhcnRJbnN0YW5jZS5vcHRpb25zLnBhbi5zcGVlZCwgZGVmYXVsdE9wdGlvbnMucGFuLnNwZWVkKTtcclxuXHJcbiAgICBoZWxwZXJzLmVhY2goY2hhcnRJbnN0YW5jZS5zY2FsZXMsIGZ1bmN0aW9uKHNjYWxlLCBpZCkge1xyXG4gICAgICBpZiAoc2NhbGUuaXNIb3Jpem9udGFsKCkgJiYgZGlyZWN0aW9uRW5hYmxlZChwYW5Nb2RlLCAneCcpICYmIGRlbHRhWCAhPT0gMCkge1xyXG4gICAgICAgIHBhbk9wdGlvbnMuc2NhbGVBeGVzID0gJ3gnO1xyXG4gICAgICAgIHBhblNjYWxlKHNjYWxlLCBkZWx0YVgsIHBhbk9wdGlvbnMpO1xyXG4gICAgICB9IGVsc2UgaWYgKCFzY2FsZS5pc0hvcml6b250YWwoKSAmJiBkaXJlY3Rpb25FbmFibGVkKHBhbk1vZGUsICd5JykgJiYgZGVsdGFZICE9PSAwKSB7XHJcbiAgICAgICAgcGFuT3B0aW9ucy5zY2FsZUF4ZXMgPSAneSc7XHJcbiAgICAgICAgcGFuU2NhbGUoc2NhbGUsIGRlbHRhWSwgcGFuT3B0aW9ucyk7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG5cclxuICAgIGNoYXJ0SW5zdGFuY2UudXBkYXRlKDApO1xyXG4gICAgaWYgKHR5cGVvZiBwYW5PcHRpb25zLm9uUGFuID09PSAnZnVuY3Rpb24nKSB7XHJcbiAgICAgIHBhbk9wdGlvbnMub25QYW4oKTtcclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHBvc2l0aW9uSW5DaGFydEFyZWEoY2hhcnRJbnN0YW5jZSwgcG9zaXRpb24pIHtcclxuICByZXR1cm4gICAocG9zaXRpb24ueCA+PSBjaGFydEluc3RhbmNlLmNoYXJ0QXJlYS5sZWZ0ICYmIHBvc2l0aW9uLnggPD0gY2hhcnRJbnN0YW5jZS5jaGFydEFyZWEucmlnaHQpICYmXHJcbiAgICAocG9zaXRpb24ueSA+PSBjaGFydEluc3RhbmNlLmNoYXJ0QXJlYS50b3AgJiYgcG9zaXRpb24ueSA8PSBjaGFydEluc3RhbmNlLmNoYXJ0QXJlYS5ib3R0b20pO1xyXG59XHJcblxyXG5mdW5jdGlvbiBnZXRZQXhpcyhjaGFydEluc3RhbmNlKSB7XHJcbiAgY29uc3Qgc2NhbGVzID0gY2hhcnRJbnN0YW5jZS5zY2FsZXM7XHJcblxyXG4gIGZvciAoY29uc3Qgc2NhbGVJZCBpbiBzY2FsZXMpIHtcclxuICAgIGlmIChzY2FsZXMuaGFzT3duUHJvcGVydHkoc2NhbGVJZCkpIHtcclxuICAgICAgY29uc3Qgc2NhbGUgPSBzY2FsZXNbc2NhbGVJZF07XHJcbiAgICAgIGlmICghc2NhbGUuaXNIb3Jpem9udGFsKCkpIHtcclxuICAgICAgICByZXR1cm4gc2NhbGU7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbi8vIFN0b3JlIHRoZXNlIGZvciBsYXRlclxyXG56b29tTlMuem9vbUZ1bmN0aW9ucy5jYXRlZ29yeSA9IHpvb21JbmRleFNjYWxlO1xyXG56b29tTlMuem9vbUZ1bmN0aW9ucy50aW1lID0gem9vbVRpbWVTY2FsZTtcclxuem9vbU5TLnpvb21GdW5jdGlvbnMubGluZWFyID0gem9vbU51bWVyaWNhbFNjYWxlO1xyXG56b29tTlMuem9vbUZ1bmN0aW9ucy5sb2dhcml0aG1pYyA9IHpvb21OdW1lcmljYWxTY2FsZTtcclxuem9vbU5TLnBhbkZ1bmN0aW9ucy5jYXRlZ29yeSA9IHBhbkluZGV4U2NhbGU7XHJcbnpvb21OUy5wYW5GdW5jdGlvbnMudGltZSA9IHBhblRpbWVTY2FsZTtcclxuem9vbU5TLnBhbkZ1bmN0aW9ucy5saW5lYXIgPSBwYW5OdW1lcmljYWxTY2FsZTtcclxuem9vbU5TLnBhbkZ1bmN0aW9ucy5sb2dhcml0aG1pYyA9IHBhbk51bWVyaWNhbFNjYWxlO1xyXG4vLyBHbG9iYWxzIGZvciBjYXRlcmdvcnkgcGFuIGFuZCB6b29tXHJcbnpvb21OUy5wYW5DdW11bGF0aXZlRGVsdGEgPSAwO1xyXG56b29tTlMuem9vbUN1bXVsYXRpdmVEZWx0YSA9IDA7XHJcblxyXG4vLyBDaGFydGpzIFpvb20gUGx1Z2luXHJcbmV4cG9ydCBjb25zdCB6b29tUGx1Z2luID0ge1xyXG4gIGFmdGVySW5pdDogZnVuY3Rpb24oY2hhcnRJbnN0YW5jZSkge1xyXG4gICAgaGVscGVycy5lYWNoKGNoYXJ0SW5zdGFuY2Uuc2NhbGVzLCBmdW5jdGlvbihzY2FsZSkge1xyXG4gICAgICBzY2FsZS5vcmlnaW5hbE9wdGlvbnMgPSBoZWxwZXJzLmNsb25lKHNjYWxlLm9wdGlvbnMpO1xyXG4gICAgfSk7XHJcblxyXG4gICAgY2hhcnRJbnN0YW5jZS5yZXNldFpvb20gPSBmdW5jdGlvbigpIHtcclxuICAgICAgaGVscGVycy5lYWNoKGNoYXJ0SW5zdGFuY2Uuc2NhbGVzLCBmdW5jdGlvbihzY2FsZSwgaWQpIHtcclxuICAgICAgICBjb25zdCB0aW1lT3B0aW9ucyA9IHNjYWxlLm9wdGlvbnMudGltZTtcclxuICAgICAgICBjb25zdCB0aWNrT3B0aW9ucyA9IHNjYWxlLm9wdGlvbnMudGlja3M7XHJcblxyXG4gICAgICAgIGlmICh0aW1lT3B0aW9ucykge1xyXG4gICAgICAgICAgdGltZU9wdGlvbnMubWluID0gc2NhbGUub3JpZ2luYWxPcHRpb25zLnRpbWUubWluO1xyXG4gICAgICAgICAgdGltZU9wdGlvbnMubWF4ID0gc2NhbGUub3JpZ2luYWxPcHRpb25zLnRpbWUubWF4O1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHRpY2tPcHRpb25zKSB7XHJcbiAgICAgICAgICB0aWNrT3B0aW9ucy5taW4gPSBzY2FsZS5vcmlnaW5hbE9wdGlvbnMudGlja3MubWluO1xyXG4gICAgICAgICAgdGlja09wdGlvbnMubWF4ID0gc2NhbGUub3JpZ2luYWxPcHRpb25zLnRpY2tzLm1heDtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgaGVscGVycy5lYWNoKGNoYXJ0SW5zdGFuY2UuZGF0YS5kYXRhc2V0cywgZnVuY3Rpb24oZGF0YXNldCwgaWQpIHtcclxuICAgICAgICBkYXRhc2V0Ll9tZXRhID0gbnVsbDtcclxuICAgICAgfSk7XHJcblxyXG4gICAgICBjaGFydEluc3RhbmNlLnVwZGF0ZSgpO1xyXG4gICAgfTtcclxuXHJcbiAgfSxcclxuICBiZWZvcmVJbml0OiBmdW5jdGlvbihjaGFydEluc3RhbmNlKSB7XHJcbiAgICBjaGFydEluc3RhbmNlLnpvb20gPSB7fTtcclxuXHJcbiAgICBjb25zdCBub2RlID0gY2hhcnRJbnN0YW5jZS56b29tLm5vZGUgPSBjaGFydEluc3RhbmNlLmNoYXJ0LmN0eC5jYW52YXM7XHJcblxyXG4gICAgY29uc3Qgb3B0aW9ucyA9IGNoYXJ0SW5zdGFuY2Uub3B0aW9ucztcclxuICAgIGNvbnN0IHBhblRocmVzaG9sZCA9IGhlbHBlcnMuZ2V0VmFsdWVPckRlZmF1bHQob3B0aW9ucy5wYW4gPyBvcHRpb25zLnBhbi50aHJlc2hvbGQgOiB1bmRlZmluZWQsIHpvb21OUy5kZWZhdWx0cy5wYW4udGhyZXNob2xkKTtcclxuICAgIGlmICghb3B0aW9ucy56b29tIHx8ICFvcHRpb25zLnpvb20uZW5hYmxlZCkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICBpZiAob3B0aW9ucy56b29tLmRyYWcpIHtcclxuICAgICAgLy8gT25seSB3YW50IHRvIHpvb20gaG9yaXpvbnRhbCBheGlzXHJcbiAgICAgIG9wdGlvbnMuem9vbS5tb2RlID0gJ3gnO1xyXG5cclxuICAgICAgY2hhcnRJbnN0YW5jZS56b29tLl9tb3VzZURvd25IYW5kbGVyID0gZnVuY3Rpb24oZXZlbnQpIHtcclxuICAgICAgICBjaGFydEluc3RhbmNlLnpvb20uX2RyYWdab29tU3RhcnQgPSBldmVudDtcclxuICAgICAgfTtcclxuICAgICAgbm9kZS5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCBjaGFydEluc3RhbmNlLnpvb20uX21vdXNlRG93bkhhbmRsZXIpO1xyXG5cclxuICAgICAgY2hhcnRJbnN0YW5jZS56b29tLl9tb3VzZU1vdmVIYW5kbGVyID0gZnVuY3Rpb24oZXZlbnQpIHtcclxuICAgICAgICBpZiAoY2hhcnRJbnN0YW5jZS56b29tLl9kcmFnWm9vbVN0YXJ0KSB7XHJcbiAgICAgICAgICBjaGFydEluc3RhbmNlLnpvb20uX2RyYWdab29tRW5kID0gZXZlbnQ7XHJcbiAgICAgICAgICBjaGFydEluc3RhbmNlLnVwZGF0ZSgwKTtcclxuICAgICAgICB9XHJcbiAgICAgIH07XHJcbiAgICAgIG5vZGUuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgY2hhcnRJbnN0YW5jZS56b29tLl9tb3VzZU1vdmVIYW5kbGVyKTtcclxuXHJcbiAgICAgIGNoYXJ0SW5zdGFuY2Uuem9vbS5fbW91c2VVcEhhbmRsZXIgPSBmdW5jdGlvbihldmVudCkge1xyXG4gICAgICAgIGlmIChjaGFydEluc3RhbmNlLnpvb20uX2RyYWdab29tU3RhcnQpIHtcclxuICAgICAgICAgIGNvbnN0IGNoYXJ0QXJlYSA9IGNoYXJ0SW5zdGFuY2UuY2hhcnRBcmVhO1xyXG4gICAgICAgICAgY29uc3QgeUF4aXMgPSBnZXRZQXhpcyhjaGFydEluc3RhbmNlKTtcclxuICAgICAgICAgIGNvbnN0IGJlZ2luUG9pbnQgPSBjaGFydEluc3RhbmNlLnpvb20uX2RyYWdab29tU3RhcnQ7XHJcbiAgICAgICAgICBjb25zdCBvZmZzZXRYID0gYmVnaW5Qb2ludC50YXJnZXQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkubGVmdDtcclxuICAgICAgICAgIGNvbnN0IHN0YXJ0WCA9IE1hdGgubWF4KE1hdGgubWluKGJlZ2luUG9pbnQuY2xpZW50WCwgZXZlbnQuY2xpZW50WCkgLSBvZmZzZXRYLCBjaGFydEFyZWEubGVmdCk7XHJcbiAgICAgICAgICBjb25zdCBlbmRYID0gTWF0aC5taW4oTWF0aC5tYXgoYmVnaW5Qb2ludC5jbGllbnRYLCBldmVudC5jbGllbnRYKSAtIG9mZnNldFgsIGNoYXJ0QXJlYS5yaWdodCk7XHJcbiAgICAgICAgICBjb25zdCBkcmFnRGlzdGFuY2UgPSBlbmRYIC0gc3RhcnRYO1xyXG4gICAgICAgICAgY29uc3QgY2hhcnREaXN0YW5jZSA9IGNoYXJ0QXJlYS5yaWdodCAtIGNoYXJ0QXJlYS5sZWZ0O1xyXG4gICAgICAgICAgY29uc3Qgem9vbSA9IDEgKyAoY2hhcnREaXN0YW5jZSAtIGRyYWdEaXN0YW5jZSkgLyBjaGFydERpc3RhbmNlO1xyXG4gICAgICAgICAgY29uc3QgY2VudGVyWCA9IGNoYXJ0QXJlYS5sZWZ0ICsgKHN0YXJ0WCAtIGNoYXJ0QXJlYS5sZWZ0KSAvICh6b29tIC0gMSk7XHJcblxyXG4gICAgICAgICAgLy8gUmVtb3ZlIGRyYWcgc3RhcnQgYW5kIGVuZCBiZWZvcmUgY2hhcnQgdXBkYXRlIHRvIHN0b3AgZHJhd2luZyBzZWxlY3RlZCBhcmVhXHJcbiAgICAgICAgICBjaGFydEluc3RhbmNlLnpvb20uX2RyYWdab29tU3RhcnQgPSBudWxsO1xyXG4gICAgICAgICAgY2hhcnRJbnN0YW5jZS56b29tLl9kcmFnWm9vbUVuZCA9IG51bGw7XHJcblxyXG4gICAgICAgICAgaWYgKGRyYWdEaXN0YW5jZSA+IDApIHtcclxuICAgICAgICAgICAgZG9ab29tKGNoYXJ0SW5zdGFuY2UsIHpvb20sIHtcclxuICAgICAgICAgICAgICB4OiBjZW50ZXJYLFxyXG4gICAgICAgICAgICAgIHk6ICh5QXhpcy5ib3R0b20gLSB5QXhpcy50b3ApIC8gMixcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9O1xyXG4gICAgICAvLyBub2RlLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCBjaGFydEluc3RhbmNlLnpvb20uX21vdXNlVXBIYW5kbGVyKTtcclxuICAgICAgbm9kZS5vd25lckRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCBjaGFydEluc3RhbmNlLnpvb20uX21vdXNlVXBIYW5kbGVyKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGNoYXJ0SW5zdGFuY2Uuem9vbS5fd2hlZWxIYW5kbGVyID0gZnVuY3Rpb24oZXZlbnQpIHtcclxuICAgICAgICBjb25zdCByZWN0ID0gZXZlbnQudGFyZ2V0LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xyXG4gICAgICAgIGNvbnN0IG9mZnNldFggPSBldmVudC5jbGllbnRYIC0gcmVjdC5sZWZ0O1xyXG4gICAgICAgIGNvbnN0IG9mZnNldFkgPSBldmVudC5jbGllbnRZIC0gcmVjdC50b3A7XHJcblxyXG4gICAgICAgIGNvbnN0IGNlbnRlciA9IHtcclxuICAgICAgICAgIHggOiBvZmZzZXRYLFxyXG4gICAgICAgICAgeSA6IG9mZnNldFlcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICBpZiAoZXZlbnQuZGVsdGFZIDwgMCkge1xyXG4gICAgICAgICAgZG9ab29tKGNoYXJ0SW5zdGFuY2UsIDEuMSwgY2VudGVyKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgZG9ab29tKGNoYXJ0SW5zdGFuY2UsIDAuOTA5LCBjZW50ZXIpO1xyXG4gICAgICAgIH1cclxuICAgICAgICAvLyBQcmV2ZW50IHRoZSBldmVudCBmcm9tIHRyaWdnZXJpbmcgdGhlIGRlZmF1bHQgYmVoYXZpb3IgKGVnLiBDb250ZW50IHNjcm9sbGluZykuXHJcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgfTtcclxuXHJcbiAgICAgIG5vZGUuYWRkRXZlbnRMaXN0ZW5lcignd2hlZWwnLCBjaGFydEluc3RhbmNlLnpvb20uX3doZWVsSGFuZGxlcik7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKEhhbW1lcikge1xyXG4gICAgICBjb25zdCBtYyA9IG5ldyBIYW1tZXIuTWFuYWdlcihub2RlKTtcclxuICAgICAgbWMuYWRkKG5ldyBIYW1tZXIuUGluY2goKSk7XHJcbiAgICAgIG1jLmFkZChuZXcgSGFtbWVyLlBhbih7XHJcbiAgICAgICAgdGhyZXNob2xkOiBwYW5UaHJlc2hvbGRcclxuICAgICAgfSkpO1xyXG5cclxuICAgICAgLy8gSGFtbWVyIHJlcG9ydHMgdGhlIHRvdGFsIHNjYWxpbmcuIFdlIG5lZWQgdGhlIGluY3JlbWVudGFsIGFtb3VudFxyXG4gICAgICBsZXQgY3VycmVudFBpbmNoU2NhbGluZztcclxuICAgICAgY29uc3QgaGFuZGxlUGluY2ggPSBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgIGNvbnN0IGRpZmYgPSAxIC8gKGN1cnJlbnRQaW5jaFNjYWxpbmcpICogZS5zY2FsZTtcclxuICAgICAgICBjb25zdCByZWN0ID0gZS50YXJnZXQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XHJcbiAgICAgICAgY29uc3Qgb2Zmc2V0WCA9IGUuY2VudGVyLnggLSByZWN0LmxlZnQ7XHJcbiAgICAgICAgY29uc3Qgb2Zmc2V0WSA9IGUuY2VudGVyLnkgLSByZWN0LnRvcDtcclxuICAgICAgICBjb25zdCBjZW50ZXIgPSB7XHJcbiAgICAgICAgICB4IDogb2Zmc2V0WCxcclxuICAgICAgICAgIHkgOiBvZmZzZXRZXHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgLy8gZmluZ2VycyBwb3NpdGlvbiBkaWZmZXJlbmNlXHJcbiAgICAgICAgY29uc3QgeCA9IE1hdGguYWJzKGUucG9pbnRlcnNbMF0uY2xpZW50WCAtIGUucG9pbnRlcnNbMV0uY2xpZW50WCk7XHJcbiAgICAgICAgY29uc3QgeSA9IE1hdGguYWJzKGUucG9pbnRlcnNbMF0uY2xpZW50WSAtIGUucG9pbnRlcnNbMV0uY2xpZW50WSk7XHJcblxyXG4gICAgICAgIC8vIGRpYWdvbmFsIGZpbmdlcnMgd2lsbCBjaGFuZ2UgYm90aCAoeHkpIGF4ZXNcclxuICAgICAgICBjb25zdCBwID0geCAvIHk7XHJcbiAgICAgICAgbGV0IHh5O1xyXG4gICAgICAgIGlmIChwID4gMC4zICYmIHAgPCAxLjcpIHtcclxuICAgICAgICAgIHh5ID0gJ3h5JztcclxuICAgICAgICB9IGVsc2UgaWYgKHggPiB5KSB7XHJcbiAgICAgICAgICAvLyB4IGF4aXNcclxuICAgICAgICAgIHh5ID0gJ3gnO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAvLyB5IGF4aXNcclxuICAgICAgICAgIHh5ID0gJ3knO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgZG9ab29tKGNoYXJ0SW5zdGFuY2UsIGRpZmYsIGNlbnRlciwgeHkpO1xyXG5cclxuICAgICAgICAvLyBLZWVwIHRyYWNrIG9mIG92ZXJhbGwgc2NhbGVcclxuICAgICAgICBjdXJyZW50UGluY2hTY2FsaW5nID0gZS5zY2FsZTtcclxuICAgICAgfTtcclxuXHJcbiAgICAgIG1jLm9uKCdwaW5jaHN0YXJ0JywgZnVuY3Rpb24oZSkge1xyXG4gICAgICAgIGN1cnJlbnRQaW5jaFNjYWxpbmcgPSAxOyAvLyByZXNldCB0cmFja2VyXHJcbiAgICAgIH0pO1xyXG4gICAgICBtYy5vbigncGluY2gnLCBoYW5kbGVQaW5jaCk7XHJcbiAgICAgIG1jLm9uKCdwaW5jaGVuZCcsIGZ1bmN0aW9uKGUpIHtcclxuICAgICAgICBoYW5kbGVQaW5jaChlKTtcclxuICAgICAgICBjdXJyZW50UGluY2hTY2FsaW5nID0gbnVsbDsgLy8gcmVzZXRcclxuICAgICAgICB6b29tTlMuem9vbUN1bXVsYXRpdmVEZWx0YSA9IDA7XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgbGV0IGN1cnJlbnREZWx0YVggPSBudWxsLCBjdXJyZW50RGVsdGFZID0gbnVsbCwgcGFubmluZyA9IGZhbHNlO1xyXG4gICAgICBjb25zdCBoYW5kbGVQYW4gPSBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgIGlmIChjdXJyZW50RGVsdGFYICE9PSBudWxsICYmIGN1cnJlbnREZWx0YVkgIT09IG51bGwpIHtcclxuICAgICAgICAgIHBhbm5pbmcgPSB0cnVlO1xyXG4gICAgICAgICAgY29uc3QgZGVsdGFYID0gZS5kZWx0YVggLSBjdXJyZW50RGVsdGFYO1xyXG4gICAgICAgICAgY29uc3QgZGVsdGFZID0gZS5kZWx0YVkgLSBjdXJyZW50RGVsdGFZO1xyXG4gICAgICAgICAgY3VycmVudERlbHRhWCA9IGUuZGVsdGFYO1xyXG4gICAgICAgICAgY3VycmVudERlbHRhWSA9IGUuZGVsdGFZO1xyXG4gICAgICAgICAgZG9QYW4oY2hhcnRJbnN0YW5jZSwgZGVsdGFYLCBkZWx0YVkpO1xyXG4gICAgICAgIH1cclxuICAgICAgfTtcclxuXHJcbiAgICAgIG1jLm9uKCdwYW5zdGFydCcsIGZ1bmN0aW9uKGUpIHtcclxuICAgICAgICBjdXJyZW50RGVsdGFYID0gMDtcclxuICAgICAgICBjdXJyZW50RGVsdGFZID0gMDtcclxuICAgICAgICBoYW5kbGVQYW4oZSk7XHJcbiAgICAgIH0pO1xyXG4gICAgICBtYy5vbigncGFubW92ZScsIGhhbmRsZVBhbik7XHJcbiAgICAgIG1jLm9uKCdwYW5lbmQnLCBmdW5jdGlvbihlKSB7XHJcbiAgICAgICAgY3VycmVudERlbHRhWCA9IG51bGw7XHJcbiAgICAgICAgY3VycmVudERlbHRhWSA9IG51bGw7XHJcbiAgICAgICAgem9vbU5TLnBhbkN1bXVsYXRpdmVEZWx0YSA9IDA7XHJcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHsgcGFubmluZyA9IGZhbHNlOyB9LCA1MDApO1xyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIGNoYXJ0SW5zdGFuY2Uuem9vbS5fZ2hvc3RDbGlja0hhbmRsZXIgPSBmdW5jdGlvbihlKSB7XHJcbiAgICAgICAgaWYgKHBhbm5pbmcpIHtcclxuICAgICAgICAgIGUuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XHJcbiAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9O1xyXG4gICAgICBub2RlLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgY2hhcnRJbnN0YW5jZS56b29tLl9naG9zdENsaWNrSGFuZGxlcik7XHJcblxyXG4gICAgICBjaGFydEluc3RhbmNlLl9tYyA9IG1jO1xyXG4gICAgfVxyXG4gIH0sXHJcblxyXG4gIGJlZm9yZURhdGFzZXRzRHJhdzogZnVuY3Rpb24oY2hhcnRJbnN0YW5jZSkge1xyXG4gICAgY29uc3QgY3R4ID0gY2hhcnRJbnN0YW5jZS5jaGFydC5jdHg7XHJcbiAgICBjb25zdCBjaGFydEFyZWEgPSBjaGFydEluc3RhbmNlLmNoYXJ0QXJlYTtcclxuICAgIGN0eC5zYXZlKCk7XHJcbiAgICBjdHguYmVnaW5QYXRoKCk7XHJcblxyXG4gICAgaWYgKGNoYXJ0SW5zdGFuY2Uuem9vbS5fZHJhZ1pvb21FbmQpIHtcclxuICAgICAgY29uc3QgeUF4aXMgPSBnZXRZQXhpcyhjaGFydEluc3RhbmNlKTtcclxuICAgICAgY29uc3QgYmVnaW5Qb2ludCA9IGNoYXJ0SW5zdGFuY2Uuem9vbS5fZHJhZ1pvb21TdGFydDtcclxuICAgICAgY29uc3QgZW5kUG9pbnQgPSBjaGFydEluc3RhbmNlLnpvb20uX2RyYWdab29tRW5kO1xyXG4gICAgICBjb25zdCBvZmZzZXRYID0gYmVnaW5Qb2ludC50YXJnZXQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkubGVmdDtcclxuICAgICAgY29uc3Qgc3RhcnRYID0gTWF0aC5taW4oYmVnaW5Qb2ludC5jbGllbnRYLCBlbmRQb2ludC5jbGllbnRYKSAtIG9mZnNldFg7XHJcbiAgICAgIGNvbnN0IGVuZFggPSBNYXRoLm1heChiZWdpblBvaW50LmNsaWVudFgsIGVuZFBvaW50LmNsaWVudFgpIC0gb2Zmc2V0WDtcclxuICAgICAgY29uc3QgcmVjdFdpZHRoID0gZW5kWCAtIHN0YXJ0WDtcclxuXHJcblxyXG4gICAgICBjdHguZmlsbFN0eWxlID0gJ3JnYmEoMjI1LDIyNSwyMjUsMC41KSc7XHJcbiAgICAgIGN0eC5saW5lV2lkdGggPSA1O1xyXG4gICAgICBjdHguZmlsbFJlY3Qoc3RhcnRYLCB5QXhpcy50b3AsIHJlY3RXaWR0aCwgeUF4aXMuYm90dG9tIC0geUF4aXMudG9wKTtcclxuICAgIH1cclxuXHJcbiAgICBjdHgucmVjdChjaGFydEFyZWEubGVmdCwgY2hhcnRBcmVhLnRvcCwgY2hhcnRBcmVhLnJpZ2h0IC0gY2hhcnRBcmVhLmxlZnQsIGNoYXJ0QXJlYS5ib3R0b20gLSBjaGFydEFyZWEudG9wKTtcclxuICAgIGN0eC5jbGlwKCk7XHJcbiAgfSxcclxuXHJcbiAgYWZ0ZXJEYXRhc2V0c0RyYXc6IGZ1bmN0aW9uKGNoYXJ0SW5zdGFuY2UpIHtcclxuICAgIGNoYXJ0SW5zdGFuY2UuY2hhcnQuY3R4LnJlc3RvcmUoKTtcclxuICB9LFxyXG5cclxuICBkZXN0cm95OiBmdW5jdGlvbihjaGFydEluc3RhbmNlKSB7XHJcbiAgICBpZiAoY2hhcnRJbnN0YW5jZS56b29tKSB7XHJcbiAgICAgIGNvbnN0IG9wdGlvbnMgPSBjaGFydEluc3RhbmNlLm9wdGlvbnM7XHJcbiAgICAgIGNvbnN0IG5vZGUgPSBjaGFydEluc3RhbmNlLnpvb20ubm9kZTtcclxuXHJcbiAgICAgIGlmIChvcHRpb25zLnpvb20gJiYgb3B0aW9ucy56b29tLmRyYWcpIHtcclxuICAgICAgICBub2RlLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIGNoYXJ0SW5zdGFuY2Uuem9vbS5fbW91c2VEb3duSGFuZGxlcik7XHJcbiAgICAgICAgbm9kZS5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCBjaGFydEluc3RhbmNlLnpvb20uX21vdXNlTW92ZUhhbmRsZXIpO1xyXG4gICAgICAgIC8vIG5vZGUucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIGNoYXJ0SW5zdGFuY2Uuem9vbS5fbW91c2VVcEhhbmRsZXIpO1xyXG4gICAgICAgIG5vZGUub3duZXJEb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgY2hhcnRJbnN0YW5jZS56b29tLl9tb3VzZVVwSGFuZGxlcik7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgbm9kZS5yZW1vdmVFdmVudExpc3RlbmVyKCd3aGVlbCcsIGNoYXJ0SW5zdGFuY2Uuem9vbS5fd2hlZWxIYW5kbGVyKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgaWYgKEhhbW1lcikge1xyXG4gICAgICAgIG5vZGUucmVtb3ZlRXZlbnRMaXN0ZW5lcignY2xpY2snLCBjaGFydEluc3RhbmNlLnpvb20uX2dob3N0Q2xpY2tIYW5kbGVyKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgZGVsZXRlIGNoYXJ0SW5zdGFuY2Uuem9vbTtcclxuXHJcbiAgICAgIGNvbnN0IG1jID0gY2hhcnRJbnN0YW5jZS5fbWM7XHJcbiAgICAgIGlmIChtYykge1xyXG4gICAgICAgIG1jLnJlbW92ZSgncGluY2hzdGFydCcpO1xyXG4gICAgICAgIG1jLnJlbW92ZSgncGluY2gnKTtcclxuICAgICAgICBtYy5yZW1vdmUoJ3BpbmNoZW5kJyk7XHJcbiAgICAgICAgbWMucmVtb3ZlKCdwYW5zdGFydCcpO1xyXG4gICAgICAgIG1jLnJlbW92ZSgncGFuJyk7XHJcbiAgICAgICAgbWMucmVtb3ZlKCdwYW5lbmQnKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufTtcclxuXHJcbkNoYXJ0LnBsdWdpblNlcnZpY2UucmVnaXN0ZXIoem9vbVBsdWdpbik7XHJcbiJdfQ==
|