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.
Files changed (242) hide show
  1. package/README.md +7 -6
  2. package/esm2020/ngx-hana-nameserver-history-viewer.mjs +5 -0
  3. package/esm2020/public-api.mjs +2 -0
  4. package/esm2020/src/nameserver-history-viewer/components/alert/alert.component.mjs +68 -0
  5. package/esm2020/src/nameserver-history-viewer/components/alert/alert.module.mjs +22 -0
  6. package/esm2020/src/nameserver-history-viewer/components/alert/index.mjs +3 -0
  7. package/esm2020/src/nameserver-history-viewer/components/file-drop-input/file-drop-input.component.mjs +112 -0
  8. package/esm2020/src/nameserver-history-viewer/components/file-drop-input/index.mjs +2 -0
  9. package/esm2020/src/nameserver-history-viewer/components/index.mjs +9 -0
  10. package/esm2020/src/nameserver-history-viewer/components/instruction/index.mjs +2 -0
  11. package/esm2020/src/nameserver-history-viewer/components/instruction/instruction.component.mjs +42 -0
  12. package/esm2020/src/nameserver-history-viewer/components/nameserver-history.component.mjs +550 -0
  13. package/esm2020/src/nameserver-history-viewer/components/port-selector/index.mjs +2 -0
  14. package/esm2020/src/nameserver-history-viewer/components/port-selector/port-selector.component.mjs +69 -0
  15. package/esm2020/src/nameserver-history-viewer/components/port-selector/port-selector.service.mjs +41 -0
  16. package/esm2020/src/nameserver-history-viewer/components/progress-bar/index.mjs +2 -0
  17. package/esm2020/src/nameserver-history-viewer/components/progress-bar/progress-bar.component.mjs +40 -0
  18. package/esm2020/src/nameserver-history-viewer/components/time-range-selector/index.mjs +2 -0
  19. package/esm2020/src/nameserver-history-viewer/components/time-range-selector/time-range-selector.component.mjs +70 -0
  20. package/esm2020/src/nameserver-history-viewer/components/timezone-selector/index.mjs +2 -0
  21. package/esm2020/src/nameserver-history-viewer/components/timezone-selector/timezone-selector.component.mjs +90 -0
  22. package/esm2020/src/nameserver-history-viewer/components/timezone-selector/timezone-selector.service.mjs +49 -0
  23. package/esm2020/src/nameserver-history-viewer/index.mjs +3 -0
  24. package/esm2020/src/nameserver-history-viewer/nameserver-history.module.mjs +63 -0
  25. package/esm2020/src/nameserver-history-viewer/services/chart.service.mjs +323 -0
  26. package/esm2020/src/nameserver-history-viewer/services/file.service.mjs +390 -0
  27. package/esm2020/src/nameserver-history-viewer/services/index.mjs +4 -0
  28. package/esm2020/src/nameserver-history-viewer/services/ui.service.mjs +557 -0
  29. package/esm2020/src/nameserver-history-viewer/types/abort.types.mjs +6 -0
  30. package/esm2020/src/nameserver-history-viewer/types/alert.types.mjs +8 -0
  31. package/esm2020/src/nameserver-history-viewer/types/chart-content-data-item.types.mjs +2 -0
  32. package/esm2020/src/nameserver-history-viewer/types/chart-content-data.types.mjs +2 -0
  33. package/esm2020/src/nameserver-history-viewer/types/chart-content-header.types.mjs +2 -0
  34. package/esm2020/src/nameserver-history-viewer/types/chart-content-time.types.mjs +2 -0
  35. package/esm2020/src/nameserver-history-viewer/types/chart-content.types.mjs +2 -0
  36. package/esm2020/src/nameserver-history-viewer/types/color-rgba.types.mjs +2 -0
  37. package/esm2020/src/nameserver-history-viewer/types/html-element.type.mjs +9 -0
  38. package/esm2020/src/nameserver-history-viewer/types/index.mjs +28 -0
  39. package/esm2020/src/nameserver-history-viewer/types/item.types.mjs +14 -0
  40. package/esm2020/src/nameserver-history-viewer/types/legend-color.types.mjs +2 -0
  41. package/esm2020/src/nameserver-history-viewer/types/load-history-info-backup.types.mjs +2 -0
  42. package/esm2020/src/nameserver-history-viewer/types/load-history-info-columnstore.types.mjs +2 -0
  43. package/esm2020/src/nameserver-history-viewer/types/load-history-info-host.types.mjs +2 -0
  44. package/esm2020/src/nameserver-history-viewer/types/load-history-info-item.types.mjs +2 -0
  45. package/esm2020/src/nameserver-history-viewer/types/load-history-info-persistence.types.mjs +2 -0
  46. package/esm2020/src/nameserver-history-viewer/types/load-history-info-rowstore.types.mjs +2 -0
  47. package/esm2020/src/nameserver-history-viewer/types/load-history-info-server.types.mjs +2 -0
  48. package/esm2020/src/nameserver-history-viewer/types/load-history-info-session-admission-control.types.mjs +2 -0
  49. package/esm2020/src/nameserver-history-viewer/types/load-history-info-sql.types.mjs +2 -0
  50. package/esm2020/src/nameserver-history-viewer/types/load-history-info-sync-primitives.types.mjs +2 -0
  51. package/esm2020/src/nameserver-history-viewer/types/load-history-info-threads.types.mjs +2 -0
  52. package/esm2020/src/nameserver-history-viewer/types/load-history-info.types.mjs +2 -0
  53. package/esm2020/src/nameserver-history-viewer/types/port.types.mjs +2 -0
  54. package/esm2020/src/nameserver-history-viewer/types/scale-group.types.mjs +17 -0
  55. package/esm2020/src/nameserver-history-viewer/types/unit-category.types.mjs +10 -0
  56. package/esm2020/src/nameserver-history-viewer/types/unit.types.mjs +14 -0
  57. package/esm2020/src/nameserver-history-viewer/utils/chart-util.mjs +25 -0
  58. package/esm2020/src/nameserver-history-viewer/utils/chartjs-downsample/chartjs_ext.mjs +2 -0
  59. package/esm2020/src/nameserver-history-viewer/utils/chartjs-downsample/data_culling.mjs +57 -0
  60. package/esm2020/src/nameserver-history-viewer/utils/chartjs-downsample/data_mipmap.mjs +139 -0
  61. package/esm2020/src/nameserver-history-viewer/utils/chartjs-downsample/index.mjs +41 -0
  62. package/esm2020/src/nameserver-history-viewer/utils/chartjs-downsample/lttb_data_mipmap.mjs +106 -0
  63. package/esm2020/src/nameserver-history-viewer/utils/chartjs-downsample/responsive_downsample_plugin.mjs +168 -0
  64. package/esm2020/src/nameserver-history-viewer/utils/chartjs-downsample/utils.mjs +114 -0
  65. package/esm2020/src/nameserver-history-viewer/utils/chartjs-zoom/chart.zoom.mjs +527 -0
  66. package/esm2020/src/nameserver-history-viewer/utils/chartjs-zoom/index.mjs +2 -0
  67. package/esm2020/src/nameserver-history-viewer/utils/file-util.mjs +154 -0
  68. package/esm2020/src/nameserver-history-viewer/utils/index.mjs +5 -0
  69. package/esm2020/src/nameserver-history-viewer/utils/time-util.mjs +101 -0
  70. package/esm2020/src/nameserver-history-viewer/utils/ui-util.mjs +162 -0
  71. package/fesm2015/ngx-hana-nameserver-history-viewer.mjs +4081 -0
  72. package/fesm2015/ngx-hana-nameserver-history-viewer.mjs.map +1 -0
  73. package/fesm2020/ngx-hana-nameserver-history-viewer.mjs +4081 -0
  74. package/fesm2020/ngx-hana-nameserver-history-viewer.mjs.map +1 -0
  75. package/ngx-hana-nameserver-history-viewer.d.ts +1 -1
  76. package/package.json +37 -61
  77. package/src/nameserver-history-viewer/components/alert/alert.component.d.ts +4 -1
  78. package/src/nameserver-history-viewer/components/alert/alert.module.d.ts +6 -0
  79. package/src/nameserver-history-viewer/components/file-drop-input/file-drop-input.component.d.ts +3 -0
  80. package/src/nameserver-history-viewer/components/instruction/instruction.component.d.ts +3 -0
  81. package/src/nameserver-history-viewer/components/nameserver-history.component.d.ts +33 -14
  82. package/src/nameserver-history-viewer/components/port-selector/port-selector.component.d.ts +4 -1
  83. package/src/nameserver-history-viewer/components/port-selector/port-selector.service.d.ts +3 -0
  84. package/src/nameserver-history-viewer/components/progress-bar/progress-bar.component.d.ts +3 -0
  85. package/src/nameserver-history-viewer/components/time-range-selector/time-range-selector.component.d.ts +3 -0
  86. package/src/nameserver-history-viewer/components/timezone-selector/timezone-selector.component.d.ts +3 -0
  87. package/src/nameserver-history-viewer/components/timezone-selector/timezone-selector.service.d.ts +3 -0
  88. package/src/nameserver-history-viewer/index.d.ts +1 -0
  89. package/src/nameserver-history-viewer/nameserver-history.module.d.ts +17 -0
  90. package/src/nameserver-history-viewer/services/chart.service.d.ts +4 -1
  91. package/src/nameserver-history-viewer/services/file.service.d.ts +4 -0
  92. package/src/nameserver-history-viewer/services/ui.service.d.ts +5 -2
  93. package/src/nameserver-history-viewer/types/load-history-info-session-admission-control.types.d.ts +3 -0
  94. package/src/nameserver-history-viewer/utils/chartjs-downsample/lttb_data_mipmap.d.ts +1 -1
  95. package/src/nameserver-history-viewer/utils/file-util.d.ts +11 -0
  96. package/bundles/ngx-hana-nameserver-history-viewer.umd.js +0 -6298
  97. package/bundles/ngx-hana-nameserver-history-viewer.umd.js.map +0 -1
  98. package/bundles/ngx-hana-nameserver-history-viewer.umd.min.js +0 -2
  99. package/bundles/ngx-hana-nameserver-history-viewer.umd.min.js.map +0 -1
  100. package/esm2015/ngx-hana-nameserver-history-viewer.js +0 -10
  101. package/esm2015/public-api.js +0 -6
  102. package/esm2015/src/nameserver-history-viewer/components/alert/alert.component.js +0 -108
  103. package/esm2015/src/nameserver-history-viewer/components/alert/alert.module.js +0 -21
  104. package/esm2015/src/nameserver-history-viewer/components/alert/index.js +0 -7
  105. package/esm2015/src/nameserver-history-viewer/components/file-drop-input/file-drop-input.component.js +0 -141
  106. package/esm2015/src/nameserver-history-viewer/components/file-drop-input/index.js +0 -6
  107. package/esm2015/src/nameserver-history-viewer/components/index.js +0 -13
  108. package/esm2015/src/nameserver-history-viewer/components/instruction/index.js +0 -6
  109. package/esm2015/src/nameserver-history-viewer/components/instruction/instruction.component.js +0 -62
  110. package/esm2015/src/nameserver-history-viewer/components/nameserver-history.component.js +0 -742
  111. package/esm2015/src/nameserver-history-viewer/components/port-selector/index.js +0 -6
  112. package/esm2015/src/nameserver-history-viewer/components/port-selector/port-selector.component.js +0 -93
  113. package/esm2015/src/nameserver-history-viewer/components/port-selector/port-selector.service.js +0 -56
  114. package/esm2015/src/nameserver-history-viewer/components/progress-bar/index.js +0 -6
  115. package/esm2015/src/nameserver-history-viewer/components/progress-bar/progress-bar.component.js +0 -35
  116. package/esm2015/src/nameserver-history-viewer/components/time-range-selector/index.js +0 -6
  117. package/esm2015/src/nameserver-history-viewer/components/time-range-selector/time-range-selector.component.js +0 -68
  118. package/esm2015/src/nameserver-history-viewer/components/timezone-selector/index.js +0 -6
  119. package/esm2015/src/nameserver-history-viewer/components/timezone-selector/timezone-selector.component.js +0 -135
  120. package/esm2015/src/nameserver-history-viewer/components/timezone-selector/timezone-selector.service.js +0 -72
  121. package/esm2015/src/nameserver-history-viewer/index.js +0 -6
  122. package/esm2015/src/nameserver-history-viewer/nameserver-history.module.js +0 -42
  123. package/esm2015/src/nameserver-history-viewer/services/chart.service.js +0 -423
  124. package/esm2015/src/nameserver-history-viewer/services/file.service.js +0 -447
  125. package/esm2015/src/nameserver-history-viewer/services/index.js +0 -8
  126. package/esm2015/src/nameserver-history-viewer/services/ui.service.js +0 -817
  127. package/esm2015/src/nameserver-history-viewer/types/abort.types.js +0 -13
  128. package/esm2015/src/nameserver-history-viewer/types/alert.types.js +0 -13
  129. package/esm2015/src/nameserver-history-viewer/types/chart-content-data-item.types.js +0 -15
  130. package/esm2015/src/nameserver-history-viewer/types/chart-content-data.types.js +0 -9
  131. package/esm2015/src/nameserver-history-viewer/types/chart-content-header.types.js +0 -15
  132. package/esm2015/src/nameserver-history-viewer/types/chart-content-time.types.js +0 -9
  133. package/esm2015/src/nameserver-history-viewer/types/chart-content.types.js +0 -21
  134. package/esm2015/src/nameserver-history-viewer/types/color-rgba.types.js +0 -19
  135. package/esm2015/src/nameserver-history-viewer/types/html-element.type.js +0 -19
  136. package/esm2015/src/nameserver-history-viewer/types/index.js +0 -32
  137. package/esm2015/src/nameserver-history-viewer/types/item.types.js +0 -19
  138. package/esm2015/src/nameserver-history-viewer/types/legend-color.types.js +0 -9
  139. package/esm2015/src/nameserver-history-viewer/types/load-history-info-backup.types.js +0 -19
  140. package/esm2015/src/nameserver-history-viewer/types/load-history-info-columnstore.types.js +0 -19
  141. package/esm2015/src/nameserver-history-viewer/types/load-history-info-host.types.js +0 -35
  142. package/esm2015/src/nameserver-history-viewer/types/load-history-info-item.types.js +0 -31
  143. package/esm2015/src/nameserver-history-viewer/types/load-history-info-persistence.types.js +0 -27
  144. package/esm2015/src/nameserver-history-viewer/types/load-history-info-rowstore.types.js +0 -15
  145. package/esm2015/src/nameserver-history-viewer/types/load-history-info-server.types.js +0 -25
  146. package/esm2015/src/nameserver-history-viewer/types/load-history-info-session-admission-control.types.js +0 -19
  147. package/esm2015/src/nameserver-history-viewer/types/load-history-info-sql.types.js +0 -37
  148. package/esm2015/src/nameserver-history-viewer/types/load-history-info-sync-primitives.types.js +0 -15
  149. package/esm2015/src/nameserver-history-viewer/types/load-history-info-threads.types.js +0 -23
  150. package/esm2015/src/nameserver-history-viewer/types/load-history-info.types.js +0 -31
  151. package/esm2015/src/nameserver-history-viewer/types/port.types.js +0 -17
  152. package/esm2015/src/nameserver-history-viewer/types/scale-group.types.js +0 -35
  153. package/esm2015/src/nameserver-history-viewer/types/unit-category.types.js +0 -21
  154. package/esm2015/src/nameserver-history-viewer/types/unit.types.js +0 -19
  155. package/esm2015/src/nameserver-history-viewer/utils/chart-util.js +0 -38
  156. package/esm2015/src/nameserver-history-viewer/utils/chartjs-downsample/chartjs_ext.js +0 -100
  157. package/esm2015/src/nameserver-history-viewer/utils/chartjs-downsample/data_culling.js +0 -88
  158. package/esm2015/src/nameserver-history-viewer/utils/chartjs-downsample/data_mipmap.js +0 -213
  159. package/esm2015/src/nameserver-history-viewer/utils/chartjs-downsample/index.js +0 -46
  160. package/esm2015/src/nameserver-history-viewer/utils/chartjs-downsample/lttb_data_mipmap.js +0 -158
  161. package/esm2015/src/nameserver-history-viewer/utils/chartjs-downsample/responsive_downsample_plugin.js +0 -295
  162. package/esm2015/src/nameserver-history-viewer/utils/chartjs-downsample/utils.js +0 -130
  163. package/esm2015/src/nameserver-history-viewer/utils/chartjs-zoom/chart.zoom.js +0 -733
  164. package/esm2015/src/nameserver-history-viewer/utils/chartjs-zoom/index.js +0 -6
  165. package/esm2015/src/nameserver-history-viewer/utils/file-util.js +0 -149
  166. package/esm2015/src/nameserver-history-viewer/utils/index.js +0 -9
  167. package/esm2015/src/nameserver-history-viewer/utils/time-util.js +0 -135
  168. package/esm2015/src/nameserver-history-viewer/utils/ui-util.js +0 -203
  169. package/esm5/ngx-hana-nameserver-history-viewer.js +0 -10
  170. package/esm5/public-api.js +0 -6
  171. package/esm5/src/nameserver-history-viewer/components/alert/alert.component.js +0 -140
  172. package/esm5/src/nameserver-history-viewer/components/alert/alert.module.js +0 -25
  173. package/esm5/src/nameserver-history-viewer/components/alert/index.js +0 -7
  174. package/esm5/src/nameserver-history-viewer/components/file-drop-input/file-drop-input.component.js +0 -155
  175. package/esm5/src/nameserver-history-viewer/components/file-drop-input/index.js +0 -6
  176. package/esm5/src/nameserver-history-viewer/components/index.js +0 -13
  177. package/esm5/src/nameserver-history-viewer/components/instruction/index.js +0 -6
  178. package/esm5/src/nameserver-history-viewer/components/instruction/instruction.component.js +0 -67
  179. package/esm5/src/nameserver-history-viewer/components/nameserver-history.component.js +0 -990
  180. package/esm5/src/nameserver-history-viewer/components/port-selector/index.js +0 -6
  181. package/esm5/src/nameserver-history-viewer/components/port-selector/port-selector.component.js +0 -93
  182. package/esm5/src/nameserver-history-viewer/components/port-selector/port-selector.service.js +0 -81
  183. package/esm5/src/nameserver-history-viewer/components/progress-bar/index.js +0 -6
  184. package/esm5/src/nameserver-history-viewer/components/progress-bar/progress-bar.component.js +0 -26
  185. package/esm5/src/nameserver-history-viewer/components/time-range-selector/index.js +0 -6
  186. package/esm5/src/nameserver-history-viewer/components/time-range-selector/time-range-selector.component.js +0 -58
  187. package/esm5/src/nameserver-history-viewer/components/timezone-selector/index.js +0 -6
  188. package/esm5/src/nameserver-history-viewer/components/timezone-selector/timezone-selector.component.js +0 -164
  189. package/esm5/src/nameserver-history-viewer/components/timezone-selector/timezone-selector.service.js +0 -102
  190. package/esm5/src/nameserver-history-viewer/index.js +0 -6
  191. package/esm5/src/nameserver-history-viewer/nameserver-history.module.js +0 -46
  192. package/esm5/src/nameserver-history-viewer/services/chart.service.js +0 -578
  193. package/esm5/src/nameserver-history-viewer/services/file.service.js +0 -566
  194. package/esm5/src/nameserver-history-viewer/services/index.js +0 -8
  195. package/esm5/src/nameserver-history-viewer/services/ui.service.js +0 -1036
  196. package/esm5/src/nameserver-history-viewer/types/abort.types.js +0 -13
  197. package/esm5/src/nameserver-history-viewer/types/alert.types.js +0 -13
  198. package/esm5/src/nameserver-history-viewer/types/chart-content-data-item.types.js +0 -15
  199. package/esm5/src/nameserver-history-viewer/types/chart-content-data.types.js +0 -9
  200. package/esm5/src/nameserver-history-viewer/types/chart-content-header.types.js +0 -15
  201. package/esm5/src/nameserver-history-viewer/types/chart-content-time.types.js +0 -9
  202. package/esm5/src/nameserver-history-viewer/types/chart-content.types.js +0 -21
  203. package/esm5/src/nameserver-history-viewer/types/color-rgba.types.js +0 -19
  204. package/esm5/src/nameserver-history-viewer/types/html-element.type.js +0 -19
  205. package/esm5/src/nameserver-history-viewer/types/index.js +0 -32
  206. package/esm5/src/nameserver-history-viewer/types/item.types.js +0 -19
  207. package/esm5/src/nameserver-history-viewer/types/legend-color.types.js +0 -9
  208. package/esm5/src/nameserver-history-viewer/types/load-history-info-backup.types.js +0 -19
  209. package/esm5/src/nameserver-history-viewer/types/load-history-info-columnstore.types.js +0 -19
  210. package/esm5/src/nameserver-history-viewer/types/load-history-info-host.types.js +0 -35
  211. package/esm5/src/nameserver-history-viewer/types/load-history-info-item.types.js +0 -31
  212. package/esm5/src/nameserver-history-viewer/types/load-history-info-persistence.types.js +0 -27
  213. package/esm5/src/nameserver-history-viewer/types/load-history-info-rowstore.types.js +0 -15
  214. package/esm5/src/nameserver-history-viewer/types/load-history-info-server.types.js +0 -25
  215. package/esm5/src/nameserver-history-viewer/types/load-history-info-session-admission-control.types.js +0 -19
  216. package/esm5/src/nameserver-history-viewer/types/load-history-info-sql.types.js +0 -37
  217. package/esm5/src/nameserver-history-viewer/types/load-history-info-sync-primitives.types.js +0 -15
  218. package/esm5/src/nameserver-history-viewer/types/load-history-info-threads.types.js +0 -23
  219. package/esm5/src/nameserver-history-viewer/types/load-history-info.types.js +0 -31
  220. package/esm5/src/nameserver-history-viewer/types/port.types.js +0 -17
  221. package/esm5/src/nameserver-history-viewer/types/scale-group.types.js +0 -35
  222. package/esm5/src/nameserver-history-viewer/types/unit-category.types.js +0 -21
  223. package/esm5/src/nameserver-history-viewer/types/unit.types.js +0 -19
  224. package/esm5/src/nameserver-history-viewer/utils/chart-util.js +0 -39
  225. package/esm5/src/nameserver-history-viewer/utils/chartjs-downsample/chartjs_ext.js +0 -100
  226. package/esm5/src/nameserver-history-viewer/utils/chartjs-downsample/data_culling.js +0 -88
  227. package/esm5/src/nameserver-history-viewer/utils/chartjs-downsample/data_mipmap.js +0 -307
  228. package/esm5/src/nameserver-history-viewer/utils/chartjs-downsample/index.js +0 -46
  229. package/esm5/src/nameserver-history-viewer/utils/chartjs-downsample/lttb_data_mipmap.js +0 -232
  230. package/esm5/src/nameserver-history-viewer/utils/chartjs-downsample/responsive_downsample_plugin.js +0 -350
  231. package/esm5/src/nameserver-history-viewer/utils/chartjs-downsample/utils.js +0 -142
  232. package/esm5/src/nameserver-history-viewer/utils/chartjs-zoom/chart.zoom.js +0 -733
  233. package/esm5/src/nameserver-history-viewer/utils/chartjs-zoom/index.js +0 -6
  234. package/esm5/src/nameserver-history-viewer/utils/file-util.js +0 -150
  235. package/esm5/src/nameserver-history-viewer/utils/index.js +0 -9
  236. package/esm5/src/nameserver-history-viewer/utils/time-util.js +0 -135
  237. package/esm5/src/nameserver-history-viewer/utils/ui-util.js +0 -205
  238. package/fesm2015/ngx-hana-nameserver-history-viewer.js +0 -5223
  239. package/fesm2015/ngx-hana-nameserver-history-viewer.js.map +0 -1
  240. package/fesm5/ngx-hana-nameserver-history-viewer.js +0 -6295
  241. package/fesm5/ngx-hana-nameserver-history-viewer.js.map +0 -1
  242. 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==