ngx-hana-nameserver-history-viewer 1.1.2 → 1.1.9-2.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 (241) hide show
  1. package/README.md +6 -5
  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.js → ngx-hana-nameserver-history-viewer.mjs} +971 -2679
  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 +33 -57
  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/utils/chartjs-downsample/lttb_data_mipmap.d.ts +1 -1
  94. package/src/nameserver-history-viewer/utils/file-util.d.ts +11 -0
  95. package/bundles/ngx-hana-nameserver-history-viewer.umd.js +0 -6735
  96. package/bundles/ngx-hana-nameserver-history-viewer.umd.js.map +0 -1
  97. package/bundles/ngx-hana-nameserver-history-viewer.umd.min.js +0 -2
  98. package/bundles/ngx-hana-nameserver-history-viewer.umd.min.js.map +0 -1
  99. package/esm2015/ngx-hana-nameserver-history-viewer.js +0 -10
  100. package/esm2015/public-api.js +0 -6
  101. package/esm2015/src/nameserver-history-viewer/components/alert/alert.component.js +0 -114
  102. package/esm2015/src/nameserver-history-viewer/components/alert/alert.module.js +0 -21
  103. package/esm2015/src/nameserver-history-viewer/components/alert/index.js +0 -7
  104. package/esm2015/src/nameserver-history-viewer/components/file-drop-input/file-drop-input.component.js +0 -141
  105. package/esm2015/src/nameserver-history-viewer/components/file-drop-input/index.js +0 -6
  106. package/esm2015/src/nameserver-history-viewer/components/index.js +0 -13
  107. package/esm2015/src/nameserver-history-viewer/components/instruction/index.js +0 -6
  108. package/esm2015/src/nameserver-history-viewer/components/instruction/instruction.component.js +0 -62
  109. package/esm2015/src/nameserver-history-viewer/components/nameserver-history.component.js +0 -868
  110. package/esm2015/src/nameserver-history-viewer/components/port-selector/index.js +0 -6
  111. package/esm2015/src/nameserver-history-viewer/components/port-selector/port-selector.component.js +0 -93
  112. package/esm2015/src/nameserver-history-viewer/components/port-selector/port-selector.service.js +0 -60
  113. package/esm2015/src/nameserver-history-viewer/components/progress-bar/index.js +0 -6
  114. package/esm2015/src/nameserver-history-viewer/components/progress-bar/progress-bar.component.js +0 -35
  115. package/esm2015/src/nameserver-history-viewer/components/time-range-selector/index.js +0 -6
  116. package/esm2015/src/nameserver-history-viewer/components/time-range-selector/time-range-selector.component.js +0 -68
  117. package/esm2015/src/nameserver-history-viewer/components/timezone-selector/index.js +0 -6
  118. package/esm2015/src/nameserver-history-viewer/components/timezone-selector/timezone-selector.component.js +0 -151
  119. package/esm2015/src/nameserver-history-viewer/components/timezone-selector/timezone-selector.service.js +0 -80
  120. package/esm2015/src/nameserver-history-viewer/index.js +0 -6
  121. package/esm2015/src/nameserver-history-viewer/nameserver-history.module.js +0 -42
  122. package/esm2015/src/nameserver-history-viewer/services/chart.service.js +0 -504
  123. package/esm2015/src/nameserver-history-viewer/services/file.service.js +0 -487
  124. package/esm2015/src/nameserver-history-viewer/services/index.js +0 -8
  125. package/esm2015/src/nameserver-history-viewer/services/ui.service.js +0 -922
  126. package/esm2015/src/nameserver-history-viewer/types/abort.types.js +0 -13
  127. package/esm2015/src/nameserver-history-viewer/types/alert.types.js +0 -13
  128. package/esm2015/src/nameserver-history-viewer/types/chart-content-data-item.types.js +0 -15
  129. package/esm2015/src/nameserver-history-viewer/types/chart-content-data.types.js +0 -9
  130. package/esm2015/src/nameserver-history-viewer/types/chart-content-header.types.js +0 -15
  131. package/esm2015/src/nameserver-history-viewer/types/chart-content-time.types.js +0 -9
  132. package/esm2015/src/nameserver-history-viewer/types/chart-content.types.js +0 -21
  133. package/esm2015/src/nameserver-history-viewer/types/color-rgba.types.js +0 -19
  134. package/esm2015/src/nameserver-history-viewer/types/html-element.type.js +0 -19
  135. package/esm2015/src/nameserver-history-viewer/types/index.js +0 -32
  136. package/esm2015/src/nameserver-history-viewer/types/item.types.js +0 -19
  137. package/esm2015/src/nameserver-history-viewer/types/legend-color.types.js +0 -9
  138. package/esm2015/src/nameserver-history-viewer/types/load-history-info-backup.types.js +0 -19
  139. package/esm2015/src/nameserver-history-viewer/types/load-history-info-columnstore.types.js +0 -19
  140. package/esm2015/src/nameserver-history-viewer/types/load-history-info-host.types.js +0 -35
  141. package/esm2015/src/nameserver-history-viewer/types/load-history-info-item.types.js +0 -31
  142. package/esm2015/src/nameserver-history-viewer/types/load-history-info-persistence.types.js +0 -27
  143. package/esm2015/src/nameserver-history-viewer/types/load-history-info-rowstore.types.js +0 -15
  144. package/esm2015/src/nameserver-history-viewer/types/load-history-info-server.types.js +0 -25
  145. package/esm2015/src/nameserver-history-viewer/types/load-history-info-session-admission-control.types.js +0 -25
  146. package/esm2015/src/nameserver-history-viewer/types/load-history-info-sql.types.js +0 -37
  147. package/esm2015/src/nameserver-history-viewer/types/load-history-info-sync-primitives.types.js +0 -15
  148. package/esm2015/src/nameserver-history-viewer/types/load-history-info-threads.types.js +0 -23
  149. package/esm2015/src/nameserver-history-viewer/types/load-history-info.types.js +0 -31
  150. package/esm2015/src/nameserver-history-viewer/types/port.types.js +0 -17
  151. package/esm2015/src/nameserver-history-viewer/types/scale-group.types.js +0 -35
  152. package/esm2015/src/nameserver-history-viewer/types/unit-category.types.js +0 -21
  153. package/esm2015/src/nameserver-history-viewer/types/unit.types.js +0 -19
  154. package/esm2015/src/nameserver-history-viewer/utils/chart-util.js +0 -38
  155. package/esm2015/src/nameserver-history-viewer/utils/chartjs-downsample/chartjs_ext.js +0 -100
  156. package/esm2015/src/nameserver-history-viewer/utils/chartjs-downsample/data_culling.js +0 -88
  157. package/esm2015/src/nameserver-history-viewer/utils/chartjs-downsample/data_mipmap.js +0 -222
  158. package/esm2015/src/nameserver-history-viewer/utils/chartjs-downsample/index.js +0 -46
  159. package/esm2015/src/nameserver-history-viewer/utils/chartjs-downsample/lttb_data_mipmap.js +0 -166
  160. package/esm2015/src/nameserver-history-viewer/utils/chartjs-downsample/responsive_downsample_plugin.js +0 -311
  161. package/esm2015/src/nameserver-history-viewer/utils/chartjs-downsample/utils.js +0 -130
  162. package/esm2015/src/nameserver-history-viewer/utils/chartjs-zoom/chart.zoom.js +0 -827
  163. package/esm2015/src/nameserver-history-viewer/utils/chartjs-zoom/index.js +0 -6
  164. package/esm2015/src/nameserver-history-viewer/utils/file-util.js +0 -162
  165. package/esm2015/src/nameserver-history-viewer/utils/index.js +0 -9
  166. package/esm2015/src/nameserver-history-viewer/utils/time-util.js +0 -139
  167. package/esm2015/src/nameserver-history-viewer/utils/ui-util.js +0 -239
  168. package/esm5/ngx-hana-nameserver-history-viewer.js +0 -10
  169. package/esm5/public-api.js +0 -6
  170. package/esm5/src/nameserver-history-viewer/components/alert/alert.component.js +0 -146
  171. package/esm5/src/nameserver-history-viewer/components/alert/alert.module.js +0 -25
  172. package/esm5/src/nameserver-history-viewer/components/alert/index.js +0 -7
  173. package/esm5/src/nameserver-history-viewer/components/file-drop-input/file-drop-input.component.js +0 -155
  174. package/esm5/src/nameserver-history-viewer/components/file-drop-input/index.js +0 -6
  175. package/esm5/src/nameserver-history-viewer/components/index.js +0 -13
  176. package/esm5/src/nameserver-history-viewer/components/instruction/index.js +0 -6
  177. package/esm5/src/nameserver-history-viewer/components/instruction/instruction.component.js +0 -67
  178. package/esm5/src/nameserver-history-viewer/components/nameserver-history.component.js +0 -1116
  179. package/esm5/src/nameserver-history-viewer/components/port-selector/index.js +0 -6
  180. package/esm5/src/nameserver-history-viewer/components/port-selector/port-selector.component.js +0 -93
  181. package/esm5/src/nameserver-history-viewer/components/port-selector/port-selector.service.js +0 -85
  182. package/esm5/src/nameserver-history-viewer/components/progress-bar/index.js +0 -6
  183. package/esm5/src/nameserver-history-viewer/components/progress-bar/progress-bar.component.js +0 -26
  184. package/esm5/src/nameserver-history-viewer/components/time-range-selector/index.js +0 -6
  185. package/esm5/src/nameserver-history-viewer/components/time-range-selector/time-range-selector.component.js +0 -58
  186. package/esm5/src/nameserver-history-viewer/components/timezone-selector/index.js +0 -6
  187. package/esm5/src/nameserver-history-viewer/components/timezone-selector/timezone-selector.component.js +0 -180
  188. package/esm5/src/nameserver-history-viewer/components/timezone-selector/timezone-selector.service.js +0 -110
  189. package/esm5/src/nameserver-history-viewer/index.js +0 -6
  190. package/esm5/src/nameserver-history-viewer/nameserver-history.module.js +0 -46
  191. package/esm5/src/nameserver-history-viewer/services/chart.service.js +0 -659
  192. package/esm5/src/nameserver-history-viewer/services/file.service.js +0 -606
  193. package/esm5/src/nameserver-history-viewer/services/index.js +0 -8
  194. package/esm5/src/nameserver-history-viewer/services/ui.service.js +0 -1141
  195. package/esm5/src/nameserver-history-viewer/types/abort.types.js +0 -13
  196. package/esm5/src/nameserver-history-viewer/types/alert.types.js +0 -13
  197. package/esm5/src/nameserver-history-viewer/types/chart-content-data-item.types.js +0 -15
  198. package/esm5/src/nameserver-history-viewer/types/chart-content-data.types.js +0 -9
  199. package/esm5/src/nameserver-history-viewer/types/chart-content-header.types.js +0 -15
  200. package/esm5/src/nameserver-history-viewer/types/chart-content-time.types.js +0 -9
  201. package/esm5/src/nameserver-history-viewer/types/chart-content.types.js +0 -21
  202. package/esm5/src/nameserver-history-viewer/types/color-rgba.types.js +0 -19
  203. package/esm5/src/nameserver-history-viewer/types/html-element.type.js +0 -19
  204. package/esm5/src/nameserver-history-viewer/types/index.js +0 -32
  205. package/esm5/src/nameserver-history-viewer/types/item.types.js +0 -19
  206. package/esm5/src/nameserver-history-viewer/types/legend-color.types.js +0 -9
  207. package/esm5/src/nameserver-history-viewer/types/load-history-info-backup.types.js +0 -19
  208. package/esm5/src/nameserver-history-viewer/types/load-history-info-columnstore.types.js +0 -19
  209. package/esm5/src/nameserver-history-viewer/types/load-history-info-host.types.js +0 -35
  210. package/esm5/src/nameserver-history-viewer/types/load-history-info-item.types.js +0 -31
  211. package/esm5/src/nameserver-history-viewer/types/load-history-info-persistence.types.js +0 -27
  212. package/esm5/src/nameserver-history-viewer/types/load-history-info-rowstore.types.js +0 -15
  213. package/esm5/src/nameserver-history-viewer/types/load-history-info-server.types.js +0 -25
  214. package/esm5/src/nameserver-history-viewer/types/load-history-info-session-admission-control.types.js +0 -25
  215. package/esm5/src/nameserver-history-viewer/types/load-history-info-sql.types.js +0 -37
  216. package/esm5/src/nameserver-history-viewer/types/load-history-info-sync-primitives.types.js +0 -15
  217. package/esm5/src/nameserver-history-viewer/types/load-history-info-threads.types.js +0 -23
  218. package/esm5/src/nameserver-history-viewer/types/load-history-info.types.js +0 -31
  219. package/esm5/src/nameserver-history-viewer/types/port.types.js +0 -17
  220. package/esm5/src/nameserver-history-viewer/types/scale-group.types.js +0 -35
  221. package/esm5/src/nameserver-history-viewer/types/unit-category.types.js +0 -21
  222. package/esm5/src/nameserver-history-viewer/types/unit.types.js +0 -19
  223. package/esm5/src/nameserver-history-viewer/utils/chart-util.js +0 -39
  224. package/esm5/src/nameserver-history-viewer/utils/chartjs-downsample/chartjs_ext.js +0 -100
  225. package/esm5/src/nameserver-history-viewer/utils/chartjs-downsample/data_culling.js +0 -88
  226. package/esm5/src/nameserver-history-viewer/utils/chartjs-downsample/data_mipmap.js +0 -316
  227. package/esm5/src/nameserver-history-viewer/utils/chartjs-downsample/index.js +0 -46
  228. package/esm5/src/nameserver-history-viewer/utils/chartjs-downsample/lttb_data_mipmap.js +0 -240
  229. package/esm5/src/nameserver-history-viewer/utils/chartjs-downsample/responsive_downsample_plugin.js +0 -366
  230. package/esm5/src/nameserver-history-viewer/utils/chartjs-downsample/utils.js +0 -142
  231. package/esm5/src/nameserver-history-viewer/utils/chartjs-zoom/chart.zoom.js +0 -827
  232. package/esm5/src/nameserver-history-viewer/utils/chartjs-zoom/index.js +0 -6
  233. package/esm5/src/nameserver-history-viewer/utils/file-util.js +0 -163
  234. package/esm5/src/nameserver-history-viewer/utils/index.js +0 -9
  235. package/esm5/src/nameserver-history-viewer/utils/time-util.js +0 -139
  236. package/esm5/src/nameserver-history-viewer/utils/ui-util.js +0 -241
  237. package/fesm2015/ngx-hana-nameserver-history-viewer.js.map +0 -1
  238. package/fesm5/ngx-hana-nameserver-history-viewer.js +0 -6861
  239. package/fesm5/ngx-hana-nameserver-history-viewer.js.map +0 -1
  240. package/ngx-hana-nameserver-history-viewer-1.1.2.tgz +0 -0
  241. package/ngx-hana-nameserver-history-viewer.metadata.json +0 -1
@@ -1,606 +0,0 @@
1
- /**
2
- * @fileoverview added by tsickle
3
- * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
4
- */
5
- import { Injectable } from '@angular/core';
6
- import { calculateValue, getDefaultPort, getPort, getTimeFromTimeZone, isSamePort, isValidPort, printProcessedTime, validateData } from '../utils';
7
- import { parse } from 'papaparse';
8
- import { Abort } from '../types';
9
- /**
10
- * prevent browser from crashing, set the max rows limitation.
11
- * This could be overwritten by the input:maxRowsLimitation of the component.
12
- * @type {?}
13
- */
14
- var _DEFAULT_MAX_ROWS_IN_MEMORY = 100000;
15
- var FileService = /** @class */ (function () {
16
- function FileService() {
17
- }
18
- /**
19
- * prevent browser from crashing, set the max rows limitation.
20
- * @param limitation if this parameter is not null, the default value will be overwritten by this one.
21
- */
22
- /**
23
- * prevent browser from crashing, set the max rows limitation.
24
- * @private
25
- * @param {?=} limitation if this parameter is not null, the default value will be overwritten by this one.
26
- * @return {?}
27
- */
28
- FileService._getMaxRowsLimitation = /**
29
- * prevent browser from crashing, set the max rows limitation.
30
- * @private
31
- * @param {?=} limitation if this parameter is not null, the default value will be overwritten by this one.
32
- * @return {?}
33
- */
34
- function (limitation) {
35
- if (limitation === void 0) { limitation = null; }
36
- if (limitation == null || isNaN(limitation) || limitation.length === 0) {
37
- return _DEFAULT_MAX_ROWS_IN_MEMORY;
38
- }
39
- return Number(limitation);
40
- };
41
- /**
42
- * get all available ports from data
43
- */
44
- /**
45
- * get all available ports from data
46
- * @private
47
- * @param {?} data
48
- * @param {?} firstChunk
49
- * @param {?} ports
50
- * @return {?}
51
- */
52
- FileService._getPorts = /**
53
- * get all available ports from data
54
- * @private
55
- * @param {?} data
56
- * @param {?} firstChunk
57
- * @param {?} ports
58
- * @return {?}
59
- */
60
- function (data, firstChunk, ports) {
61
- /** @type {?} */
62
- var line = 0;
63
- if (firstChunk) {
64
- // start from line 3
65
- line = 2;
66
- }
67
- for (; line < data.length; line++) {
68
- /** @type {?} */
69
- var dataItem = data[line][1];
70
- if (dataItem != null && dataItem.length > 0) {
71
- if (isValidPort(dataItem) && ports.indexOf(dataItem) === -1) {
72
- ports.push(dataItem);
73
- }
74
- }
75
- }
76
- };
77
- /**
78
- * get the time column from the analyzed data
79
- * @param data the analyzed data
80
- * @param firstChunk whether it's first chunk or not
81
- * @param startTime selected starting time. It's millisecond, need to be converted second.
82
- * @param endTime selected ending time. It's millisecond, need to be converted second.
83
- * @param lastProcessedTime last processed time form last chunk
84
- * @param time time object which contains the time data for all ports
85
- * @param selectedPort if the selected port is empty (did not select any port), all ports info are needed
86
- * @param isMDC flag for MDC system
87
- * @param maxRowsLimitation prevent browser from crashing, set the max rows limitation.
88
- * This comes from the input: maxRowsLimitation of the component.
89
- */
90
- /**
91
- * get the time column from the analyzed data
92
- * @private
93
- * @param {?} data the analyzed data
94
- * @param {?} firstChunk whether it's first chunk or not
95
- * @param {?} startTime selected starting time. It's millisecond, need to be converted second.
96
- * @param {?} endTime selected ending time. It's millisecond, need to be converted second.
97
- * @param {?} lastProcessedTime last processed time form last chunk
98
- * @param {?} time time object which contains the time data for all ports
99
- * @param {?} selectedPort if the selected port is empty (did not select any port), all ports info are needed
100
- * @param {?} isMDC flag for MDC system
101
- * @param {?} maxRowsLimitation prevent browser from crashing, set the max rows limitation.
102
- * This comes from the input: maxRowsLimitation of the component.
103
- * @return {?}
104
- */
105
- FileService._getTimeColumn = /**
106
- * get the time column from the analyzed data
107
- * @private
108
- * @param {?} data the analyzed data
109
- * @param {?} firstChunk whether it's first chunk or not
110
- * @param {?} startTime selected starting time. It's millisecond, need to be converted second.
111
- * @param {?} endTime selected ending time. It's millisecond, need to be converted second.
112
- * @param {?} lastProcessedTime last processed time form last chunk
113
- * @param {?} time time object which contains the time data for all ports
114
- * @param {?} selectedPort if the selected port is empty (did not select any port), all ports info are needed
115
- * @param {?} isMDC flag for MDC system
116
- * @param {?} maxRowsLimitation prevent browser from crashing, set the max rows limitation.
117
- * This comes from the input: maxRowsLimitation of the component.
118
- * @return {?}
119
- */
120
- function (data, firstChunk, startTime, endTime, lastProcessedTime, time, selectedPort, isMDC, maxRowsLimitation) {
121
- // convert millisecond to second for startTime and endTime.
122
- startTime = startTime / 1000;
123
- endTime = endTime / 1000;
124
- /** @type {?} */
125
- var timeColumn = 2;
126
- /** @type {?} */
127
- var startLine = 0;
128
- /** @type {?} */
129
- var iStart = -1;
130
- /** @type {?} */
131
- var iEnd = -1;
132
- /** @type {?} */
133
- var curTime = lastProcessedTime;
134
- /** @type {?} */
135
- var lastProcessedTimeReturn;
136
- /** @type {?} */
137
- var totalNum = 0;
138
- /** @type {?} */
139
- var mdcFlag = isMDC;
140
- /** @type {?} */
141
- var defaultPort = getDefaultPort();
142
- /** @type {?} */
143
- var maxRowNum = this._getMaxRowsLimitation(maxRowsLimitation);
144
- if (firstChunk) {
145
- if (curTime >= startTime && curTime <= endTime) {
146
- iStart = 1; // start from first line
147
- // start from first line
148
- // get port for the line 1.
149
- /**
150
- * Modified at 2018/10/10,
151
- * in some case, eg: the nameserver history trace gets modified by Kook, Jin Young's python script,
152
- * the port show in the first line as well, and does not like the non-mdc system, this kind of file has
153
- * one port in it. The history for non-mdc system doesn't have port info in the port column.
154
- * @type {?}
155
- */
156
- var firstLinePort = getPort(data[1][1]);
157
- // init time array for the first line.
158
- if (!selectedPort || selectedPort.length === 0 || isSamePort(firstLinePort, selectedPort, mdcFlag)) {
159
- // does not select any port or
160
- // it's non-mdc (mdcFlag is false at the beginning) system and the selected port is the first line port
161
- time[firstLinePort] = [];
162
- time[firstLinePort][0] = curTime * 1000;
163
- }
164
- }
165
- lastProcessedTimeReturn = curTime;
166
- startLine = 2;
167
- }
168
- // get current total number
169
- Object.keys(time).forEach((/**
170
- * @param {?} key
171
- * @return {?}
172
- */
173
- function (key) {
174
- if (time[key]) {
175
- totalNum += time[key].length;
176
- }
177
- }));
178
- if (curTime == null) {
179
- console.error('getTimeColumn', 'Can not get the time from the file, internal error!');
180
- return { indexStart: null, indexEnd: null, lastProcessedTime: null, isMDC: null };
181
- }
182
- for (var i = startLine; i < data.length; i++) {
183
- // sometime the last line is empty, need to be skipped.
184
- if (data[i] == null || data[i].length === 0 || (data[i].length === 1 && data[i][0].length === 0)) {
185
- continue;
186
- }
187
- // get port number and initialize the relative port array in time
188
- /** @type {?} */
189
- var port = getPort(data[i][1]);
190
- if (!(port in time)) {
191
- // add undefined port to time, then we can find all ports in time
192
- time[port] = void 0;
193
- }
194
- if (time[port] == null && isSamePort(port, selectedPort, mdcFlag)) {
195
- time[port] = [];
196
- // if other ports exists in this file, default port will be set to undefined.
197
- if (!mdcFlag && port !== defaultPort && time[defaultPort]) {
198
- // update the total num;
199
- totalNum -= time[defaultPort].length;
200
- time[defaultPort].length = 0;
201
- time[defaultPort] = void 0;
202
- mdcFlag = true;
203
- }
204
- }
205
- curTime = calculateValue(curTime, data[i][timeColumn]);
206
- if (curTime > endTime) {
207
- if (iEnd < 0) {
208
- iEnd = i - 1;
209
- }
210
- break;
211
- }
212
- if (iStart >= 0) {
213
- if (time[port]) {
214
- // not null means it's the selected port
215
- time[port][time[port].length] = curTime * 1000;
216
- totalNum++;
217
- }
218
- }
219
- else {
220
- if (curTime >= startTime && curTime <= endTime) {
221
- if (time[port]) {
222
- // only selected port counted in
223
- if (iStart < 0) {
224
- iStart = i;
225
- }
226
- time[port][time[port].length] = curTime * 1000;
227
- totalNum++;
228
- }
229
- }
230
- }
231
- // last processed time need to be recorded anyway
232
- lastProcessedTimeReturn = curTime;
233
- if (totalNum >= maxRowNum) {
234
- iEnd = i;
235
- break;
236
- }
237
- }
238
- return { indexStart: iStart, indexEnd: iEnd, lastProcessedTime: lastProcessedTimeReturn, isMDC: mdcFlag };
239
- };
240
- /**
241
- * Get data for all columns
242
- * @param columnNum the total number of columns. For mdc system,
243
- * the length of each row is different. Host relative data does not exist in tenant line.
244
- * Needs to use column number from the first line.
245
- * @param data data parsed by papa
246
- * @param firstChunk the flag which identifies whether it's the first chunk or not.
247
- * @param time
248
- * @param indexStart
249
- * @param indexEnd
250
- * @param lastProcessedLine
251
- * @param resultData the result data after analyzed
252
- * @param selectedPort
253
- * @param isMDC
254
- */
255
- /**
256
- * Get data for all columns
257
- * @private
258
- * @param {?} columnNum the total number of columns. For mdc system,
259
- * the length of each row is different. Host relative data does not exist in tenant line.
260
- * Needs to use column number from the first line.
261
- * @param {?} data data parsed by papa
262
- * @param {?} firstChunk the flag which identifies whether it's the first chunk or not.
263
- * @param {?} time
264
- * @param {?} indexStart
265
- * @param {?} indexEnd
266
- * @param {?} lastProcessedLine
267
- * @param {?} resultData the result data after analyzed
268
- * @param {?} selectedPort
269
- * @param {?} isMDC
270
- * @return {?}
271
- */
272
- FileService._getDataColumns = /**
273
- * Get data for all columns
274
- * @private
275
- * @param {?} columnNum the total number of columns. For mdc system,
276
- * the length of each row is different. Host relative data does not exist in tenant line.
277
- * Needs to use column number from the first line.
278
- * @param {?} data data parsed by papa
279
- * @param {?} firstChunk the flag which identifies whether it's the first chunk or not.
280
- * @param {?} time
281
- * @param {?} indexStart
282
- * @param {?} indexEnd
283
- * @param {?} lastProcessedLine
284
- * @param {?} resultData the result data after analyzed
285
- * @param {?} selectedPort
286
- * @param {?} isMDC
287
- * @return {?}
288
- */
289
- function (columnNum, data, firstChunk, time, indexStart, indexEnd, lastProcessedLine, resultData, selectedPort, isMDC) {
290
- /** @type {?} */
291
- var startLine = 0;
292
- // for mdc system, the length is not correct (host relative data only exists in the "empty" port line).
293
- // Needs to use header from the first line.
294
- // const columnNum = data[0].length;
295
- if (firstChunk) {
296
- // get port for the line 1.
297
- /**
298
- * Modified at 2018/10/10,
299
- * in some case, eg: the nameserver history trace gets modified by Kook, Jin Young's python script,
300
- * the port show in the first line as well, and does not like the non-mdc system, this kind of file has
301
- * one port in it. The history for non-mdc system doesn't have port info in the port column.
302
- * @type {?}
303
- */
304
- var firstLinePort = getPort(data[1][1]);
305
- // Initialize data column with default 'DEFAULT' port if it's not MDC system. MDC system, 'DEFAULT' gets ignored
306
- if (!isMDC && time[firstLinePort]) {
307
- resultData[firstLinePort] = [];
308
- // removed below logic, because first line is the real number, do not need to do the convert.
309
- // curLine = data[1].slice(3).map(Number);
310
- for (var j = 3; j < columnNum; j++) {
311
- /** @type {?} */
312
- var index = j - 3;
313
- // initialize data array for all columns of the default '0000' port
314
- resultData[firstLinePort][index] = [];
315
- // get the first line data of the column if it's included
316
- if (indexStart === 1) {
317
- resultData[firstLinePort][index][0] = { x: time[firstLinePort][0], y: lastProcessedLine[index] };
318
- }
319
- }
320
- }
321
- startLine = 2;
322
- }
323
- for (var j = 3; j < columnNum; j++) {
324
- /** @type {?} */
325
- var index = j - 3;
326
- for (var i = startLine; i < data.length; i++) {
327
- // sometime the last line is empty, need to be skipped.
328
- if (data[i] == null || data[i].length === 0 || (data[i].length === 1 && data[i][0].length === 0)) {
329
- continue;
330
- }
331
- // get port number and initialize the relative port array in data
332
- /** @type {?} */
333
- var port = getPort(data[i][1]);
334
- if (resultData[port] == null && isSamePort(port, selectedPort, isMDC)) {
335
- resultData[port] = [];
336
- }
337
- if (resultData[port] && resultData[port][index] == null) {
338
- resultData[port][index] = [];
339
- }
340
- lastProcessedLine[index] = calculateValue(lastProcessedLine[index], data[i][j]);
341
- if (i >= indexStart && (i <= indexEnd || indexEnd < 0) && indexStart >= 0) {
342
- if (resultData[port]) {
343
- /** @type {?} */
344
- var length_1 = resultData[port][index].length;
345
- resultData[port][index][length_1] = { x: time[port][length_1], y: lastProcessedLine[index] };
346
- }
347
- }
348
- else if (indexEnd > 0 && i > indexEnd) {
349
- break;
350
- }
351
- }
352
- }
353
- };
354
- /**
355
- * Get Chart data from provided file.
356
- * @param file the nameserver history file
357
- * @param startTime
358
- * @param endTime
359
- * @param port
360
- * @param timezone
361
- * @param maxRowsLimitation prevent browser from crashing, set the max rows limitation.
362
- * @param progress call back function for updating progress
363
- */
364
- /**
365
- * Get Chart data from provided file.
366
- * @param {?} file the nameserver history file
367
- * @param {?} startTime
368
- * @param {?} endTime
369
- * @param {?} port
370
- * @param {?} timezone
371
- * @param {?} maxRowsLimitation prevent browser from crashing, set the max rows limitation.
372
- * @param {?} progress call back function for updating progress
373
- * @return {?}
374
- */
375
- FileService.prototype.getChartContentFromFile = /**
376
- * Get Chart data from provided file.
377
- * @param {?} file the nameserver history file
378
- * @param {?} startTime
379
- * @param {?} endTime
380
- * @param {?} port
381
- * @param {?} timezone
382
- * @param {?} maxRowsLimitation prevent browser from crashing, set the max rows limitation.
383
- * @param {?} progress call back function for updating progress
384
- * @return {?}
385
- */
386
- function (file, startTime, endTime, port, timezone, maxRowsLimitation, progress) {
387
- // load done, beginning parsing
388
- /** @type {?} */
389
- var beginTime = new Date();
390
- /** @type {?} */
391
- var firstChunk = true;
392
- // save last processed data just for the later calculation
393
- /** @type {?} */
394
- var lastProcessedData;
395
- // save last processed time just for the later calculation
396
- /** @type {?} */
397
- var lastProcessedTime;
398
- // save last processed cursor position for progress calculation.
399
- // let lastProcessedCursor = 0;
400
- /** @type {?} */
401
- var indexStart = -1;
402
- /** @type {?} */
403
- var indexEnd = -1;
404
- /** @type {?} */
405
- var time = {};
406
- /** @type {?} */
407
- var data = {};
408
- /** @type {?} */
409
- var header;
410
- /** @type {?} */
411
- var host;
412
- /** @type {?} */
413
- var isMDC = false;
414
- /** @type {?} */
415
- var columnNum;
416
- /** @type {?} */
417
- var abortType;
418
- /** @type {?} */
419
- var rejectAndAbort = (/**
420
- * @param {?} reject
421
- * @param {?} parser
422
- * @return {?}
423
- */
424
- function (reject, parser) {
425
- if (progress) {
426
- progress(100);
427
- }
428
- reject(file.name + " is empty or the format is not correct.");
429
- parser.abort();
430
- });
431
- return new Promise((/**
432
- * @param {?} resolve
433
- * @param {?} reject
434
- * @return {?}
435
- */
436
- function (resolve, reject) {
437
- parse(file, {
438
- chunk: (/**
439
- * @param {?} results
440
- * @param {?} parser
441
- * @return {?}
442
- */
443
- function (results, parser) {
444
- var _a;
445
- // the progress increment of this step
446
- // let analyzeStepProgress = (results.meta.cursor - lastProcessedCursor) / file.size * 100;
447
- printProcessedTime(beginTime, 'step1');
448
- if (indexEnd >= 0) {
449
- // already finished, quite.
450
- return;
451
- }
452
- else {
453
- // reset start point
454
- indexStart = -1;
455
- }
456
- // get time column
457
- if (firstChunk) {
458
- if (!validateData(results.data)) {
459
- return rejectAndAbort(reject, parser);
460
- }
461
- // initialize the header
462
- header = results.data[0].slice(3);
463
- // get column number
464
- columnNum = results.data[0].length;
465
- // get host name
466
- host = results.data[1][0];
467
- // get the first line time info from first line, it is a real number, do not need to do the convert with ">,<".
468
- lastProcessedTime = getTimeFromTimeZone(parseFloat(results.data[1][2]), timezone);
469
- // get the first line data info from first line, it is a real number, do not need to do the convert with ">,<".
470
- lastProcessedData = results.data[1].slice(3).map(Number);
471
- }
472
- printProcessedTime(beginTime, 'step2');
473
- if (!lastProcessedData) {
474
- return rejectAndAbort(reject, parser);
475
- }
476
- // get time column
477
- (_a = FileService._getTimeColumn(results.data, firstChunk, startTime, endTime, lastProcessedTime, time, port, isMDC, maxRowsLimitation), indexStart = _a.indexStart, indexEnd = _a.indexEnd, lastProcessedTime = _a.lastProcessedTime, isMDC = _a.isMDC);
478
- printProcessedTime(beginTime, 'step3');
479
- if (indexStart == null && indexEnd == null && lastProcessedTime == null && isMDC == null) {
480
- return rejectAndAbort(reject, parser);
481
- }
482
- // get all other data columns
483
- FileService._getDataColumns(columnNum, results.data, firstChunk, time, indexStart, indexEnd, lastProcessedData, data, port, isMDC);
484
- if (firstChunk) {
485
- firstChunk = false;
486
- }
487
- printProcessedTime(beginTime, 'step4');
488
- if (indexEnd >= 0) {
489
- // do not need to process the left parts, manually trigger complete
490
- /** @type {?} */
491
- var processedLines = Object.keys(time).reduce((/**
492
- * @param {?} total
493
- * @param {?} curKey
494
- * @return {?}
495
- */
496
- function (total, curKey) { return time[curKey] ? total + time[curKey].length : total; }), 0);
497
- if (processedLines >= FileService._getMaxRowsLimitation(maxRowsLimitation)) {
498
- abortType = Abort.maxLineNumReached;
499
- }
500
- else {
501
- abortType = Abort.maxTimeRangeReached;
502
- }
503
- if (progress) {
504
- progress(100);
505
- }
506
- parser.abort();
507
- return;
508
- }
509
- else {
510
- // the overall progress if this step is finished
511
- if (progress) {
512
- progress(Math.round(results.meta.cursor / file.size * 100));
513
- }
514
- // lastProcessedCursor = results.meta.cursor;
515
- }
516
- }),
517
- complete: (/**
518
- * @return {?}
519
- */
520
- function () {
521
- printProcessedTime(beginTime, 'step_complete');
522
- resolve({ header: header, host: host, time: time, data: data, aborted: abortType });
523
- })
524
- });
525
- }));
526
- };
527
- /**
528
- * Get all ports from the name server history file
529
- * @param file the name server history file
530
- * @param progress call back for updating the progress
531
- */
532
- /**
533
- * Get all ports from the name server history file
534
- * @param {?} file the name server history file
535
- * @param {?} progress call back for updating the progress
536
- * @return {?}
537
- */
538
- FileService.prototype.getPortsFromFile = /**
539
- * Get all ports from the name server history file
540
- * @param {?} file the name server history file
541
- * @param {?} progress call back for updating the progress
542
- * @return {?}
543
- */
544
- function (file, progress) {
545
- /** @type {?} */
546
- var beginTime = new Date();
547
- /** @type {?} */
548
- var firstChunk = true;
549
- /** @type {?} */
550
- var ports = [];
551
- /** @type {?} */
552
- var defaultPort = getDefaultPort();
553
- return new Promise((/**
554
- * @param {?} resolve
555
- * @param {?} reject
556
- * @return {?}
557
- */
558
- function (resolve, reject) {
559
- parse(file, {
560
- chunk: (/**
561
- * @param {?} results
562
- * @param {?} parser
563
- * @return {?}
564
- */
565
- function (results, parser) {
566
- // get time column
567
- if (firstChunk) {
568
- if (!validateData(results.data)) {
569
- if (progress) {
570
- progress(100);
571
- }
572
- reject(file.name + " is empty or the format is not correct.");
573
- parser.abort();
574
- return;
575
- }
576
- }
577
- printProcessedTime(beginTime, 'port.step1');
578
- FileService._getPorts(results.data, firstChunk, ports);
579
- if (firstChunk) {
580
- firstChunk = false;
581
- }
582
- if (progress) {
583
- progress(Math.round(results.meta.cursor / file.size * 100));
584
- }
585
- }),
586
- complete: (/**
587
- * @return {?}
588
- */
589
- function () {
590
- // parsing done
591
- printProcessedTime(beginTime, 'step_complete');
592
- if (ports.length === 0) {
593
- ports[0] = defaultPort;
594
- }
595
- resolve(ports);
596
- })
597
- });
598
- }));
599
- };
600
- FileService.decorators = [
601
- { type: Injectable }
602
- ];
603
- return FileService;
604
- }());
605
- export { FileService };
606
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsZS5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6Im5nOi8vbmd4LWhhbmEtbmFtZXNlcnZlci1oaXN0b3J5LXZpZXdlci8iLCJzb3VyY2VzIjpbInNyYy9uYW1lc2VydmVyLWhpc3Rvcnktdmlld2VyL3NlcnZpY2VzL2ZpbGUuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsT0FBTyxFQUFDLFVBQVUsRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUN6QyxPQUFPLEVBQ0wsY0FBYyxFQUNkLGNBQWMsRUFDZCxPQUFPLEVBQ1AsbUJBQW1CLEVBQ25CLFVBQVUsRUFDVixXQUFXLEVBQ1gsa0JBQWtCLEVBQ2xCLFlBQVksRUFDYixNQUFNLFVBQVUsQ0FBQztBQUNsQixPQUFPLEVBQUMsS0FBSyxFQUFDLE1BQU0sV0FBVyxDQUFDO0FBQ2hDLE9BQU8sRUFBQyxLQUFLLEVBQW1ELE1BQU0sVUFBVSxDQUFDOzs7Ozs7SUFNM0UsMkJBQTJCLEdBQUcsTUFBTTtBQUUxQztJQUFBO0lBMGFBLENBQUM7SUF4YUM7OztPQUdHOzs7Ozs7O0lBQ1ksaUNBQXFCOzs7Ozs7SUFBcEMsVUFBcUMsVUFBc0I7UUFBdEIsMkJBQUEsRUFBQSxpQkFBc0I7UUFDekQsSUFBSSxVQUFVLElBQUksSUFBSSxJQUFJLEtBQUssQ0FBQyxVQUFVLENBQUMsSUFBSSxVQUFVLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtZQUN0RSxPQUFPLDJCQUEyQixDQUFDO1NBQ3BDO1FBQ0QsT0FBTyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDNUIsQ0FBQztJQUVEOztPQUVHOzs7Ozs7Ozs7SUFDWSxxQkFBUzs7Ozs7Ozs7SUFBeEIsVUFBeUIsSUFBZ0IsRUFBRSxVQUFtQixFQUFFLEtBQWU7O1lBQ3pFLElBQUksR0FBRyxDQUFDO1FBQ1osSUFBSSxVQUFVLEVBQUU7WUFDZCxvQkFBb0I7WUFDcEIsSUFBSSxHQUFHLENBQUMsQ0FBQztTQUNWO1FBRUQsT0FBTyxJQUFJLEdBQUcs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LENBQUMsQ0FBQztvQkFDL0MsSUFBSSxLQUFLLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTt3QkFDdEIsS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLFdBQVcsQ0FBQztxQkFDeEI7b0JBQ0QsT0FBTyxDQUFFLEtBQUssQ0FBQyxDQUFDO2dCQUNsQixDQUFDLENBQUE7YUFDRixDQUFDLENBQUM7UUFDTCxDQUFDLEVBQUMsQ0FBQztJQUNMLENBQUM7O2dCQXphRixVQUFVOztJQTBhWCxrQkFBQztDQUFBLEFBMWFELElBMGFDO1NBemFZLFdBQVciLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0luamVjdGFibGV9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQge1xyXG4gIGNhbGN1bGF0ZVZhbHVlLFxyXG4gIGdldERlZmF1bHRQb3J0LFxyXG4gIGdldFBvcnQsXHJcbiAgZ2V0VGltZUZyb21UaW1lWm9uZSxcclxuICBpc1NhbWVQb3J0LFxyXG4gIGlzVmFsaWRQb3J0LFxyXG4gIHByaW50UHJvY2Vzc2VkVGltZSxcclxuICB2YWxpZGF0ZURhdGFcclxufSBmcm9tICcuLi91dGlscyc7XHJcbmltcG9ydCB7cGFyc2V9IGZyb20gJ3BhcGFwYXJzZSc7XHJcbmltcG9ydCB7QWJvcnQsIENoYXJ0Q29udGVudCwgQ2hhcnRDb250ZW50RGF0YSwgQ2hhcnRDb250ZW50VGltZX0gZnJvbSAnLi4vdHlwZXMnO1xyXG5cclxuLyoqXHJcbiAqIHByZXZlbnQgYnJvd3NlciBmcm9tIGNyYXNoaW5nLCBzZXQgdGhlIG1heCByb3dzIGxpbWl0YXRpb24uXHJcbiAqIFRoaXMgY291bGQgYmUgb3ZlcndyaXR0ZW4gYnkgdGhlIGlucHV0Om1heFJvd3NMaW1pdGF0aW9uIG9mIHRoZSBjb21wb25lbnQuXHJcbiAqL1xyXG5jb25zdCBfREVGQVVMVF9NQVhfUk9XU19JTl9NRU1PUlkgPSAxMDAwMDA7XHJcblxyXG5ASW5qZWN0YWJsZSgpXHJcbmV4cG9ydCBjbGFzcyBGaWxlU2VydmljZSB7XHJcbiAgLyoqXHJcbiAgICogcHJldmVudCBicm93c2VyIGZyb20gY3Jhc2hpbmcsIHNldCB0aGUgbWF4IHJvd3MgbGltaXRhdGlvbi5cclxuICAgKiBAcGFyYW0gbGltaXRhdGlvbiBpZiB0aGlzIHBhcmFtZXRlciBpcyBub3QgbnVsbCwgdGhlIGRlZmF1bHQgdmFsdWUgd2lsbCBiZSBvdmVyd3JpdHRlbiBieSB0aGlzIG9uZS5cclxuICAgKi9cclxuICBwcml2YXRlIHN0YXRpYyBfZ2V0TWF4Um93c0xpbWl0YXRpb24obGltaXRhdGlvbjogYW55ID0gbnVsbCkge1xyXG4gICAgaWYgKGxpbWl0YXRpb24gPT0gbnVsbCB8fCBpc05hTihsaW1pdGF0aW9uKSB8fCBsaW1pdGF0aW9uLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICByZXR1cm4gX0RFRkFVTFRfTUFYX1JPV1NfSU5fTUVNT1JZO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIE51bWJlcihsaW1pdGF0aW9uKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIGdldCBhbGwgYXZhaWxhYmxlIHBvcnRzIGZyb20gZGF0YVxyXG4gICAqL1xyXG4gIHByaXZhdGUgc3RhdGljIF9nZXRQb3J0cyhkYXRhOiBzdHJpbmdbXVtdLCBmaXJzdENodW5rOiBib29sZWFuLCBwb3J0czogc3RyaW5nW10pIHtcclxuICAgIGxldCBsaW5lID0gMDtcclxuICAgIGlmIChmaXJzdENodW5rKSB7XHJcbiAgICAgIC8vIHN0YXJ0IGZyb20gbGluZSAzXHJcbiAgICAgIGxpbmUgPSAyO1xyXG4gICAgfVxyXG5cclxuICAgIGZvciAoOyBsaW5lIDwgZGF0YS5sZW5ndGg7IGxpbmUrKykge1xyXG4gICAgICBjb25zdCBkYXRhSXRlbSA9IGRhdGFbbGluZV1bMV07XHJcbiAgICAgIGlmIChkYXRhSXRlbSAhPSBudWxsICYmIGRhdGFJdGVtLmxlbmd0aCA+IDApIHtcclxuICAgICAgICBpZiAoaXNWYWxpZFBvcnQoZGF0YUl0ZW0pICYmIHBvcnRzLmluZGV4T2YoZGF0YUl0ZW0pID09PSAtMSkge1xyXG4gICAgICAgICAgcG9ydHMucHVzaChkYXRhSXRlbSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBnZXQgdGhlIHRpbWUgY29sdW1uIGZyb20gdGhlIGFuYWx5emVkIGRhdGFcclxuICAgKiBAcGFyYW0gZGF0YSB0aGUgYW5hbHl6ZWQgZGF0YVxyXG4gICAqIEBwYXJhbSBmaXJzdENodW5rIHdoZXRoZXIgaXQncyBmaXJzdCBjaHVuayBvciBub3RcclxuICAgKiBAcGFyYW0gc3RhcnRUaW1lIHNlbGVjdGVkIHN0YXJ0aW5nIHRpbWUuIEl0J3MgbWlsbGlzZWNvbmQsIG5lZWQgdG8gYmUgY29udmVydGVkIHNlY29uZC5cclxuICAgKiBAcGFyYW0gZW5kVGltZSBzZWxlY3RlZCBlbmRpbmcgdGltZS4gSXQncyBtaWxsaXNlY29uZCwgbmVlZCB0byBiZSBjb252ZXJ0ZWQgc2Vjb25kLlxyXG4gICAqIEBwYXJhbSBsYXN0UHJvY2Vzc2VkVGltZSBsYXN0IHByb2Nlc3NlZCB0aW1lIGZvcm0gbGFzdCBjaHVua1xyXG4gICAqIEBwYXJhbSB0aW1lIHRpbWUgb2JqZWN0IHdoaWNoIGNvbnRhaW5zIHRoZSB0aW1lIGRhdGEgZm9yIGFsbCBwb3J0c1xyXG4gICAqIEBwYXJhbSBzZWxlY3RlZFBvcnQgaWYgdGhlIHNlbGVjdGVkIHBvcnQgaXMgZW1wdHkgKGRpZCBub3Qgc2VsZWN0IGFueSBwb3J0KSwgYWxsIHBvcnRzIGluZm8gYXJlIG5lZWRlZFxyXG4gICAqIEBwYXJhbSBpc01EQyBmbGFnIGZvciBNREMgc3lzdGVtXHJcbiAgICogQHBhcmFtIG1heFJvd3NMaW1pdGF0aW9uIHByZXZlbnQgYnJvd3NlciBmcm9tIGNyYXNoaW5nLCBzZXQgdGhlIG1heCByb3dzIGxpbWl0YXRpb24uXHJcbiAgICogVGhpcyBjb21lcyBmcm9tIHRoZSBpbnB1dDogbWF4Um93c0xpbWl0YXRpb24gb2YgdGhlIGNvbXBvbmVudC5cclxuICAgKi9cclxuICBwcml2YXRlIHN0YXRpYyBfZ2V0VGltZUNvbHVtbihkYXRhOiBzdHJpbmdbXVtdLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpcnN0Q2h1bms6IGJvb2xlYW4sXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnRUaW1lOiBudW1iZXIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5kVGltZTogbnVtYmVyLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RQcm9jZXNzZWRUaW1lOiBudW1iZXIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGltZTogQ2hhcnRDb250ZW50VGltZSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZFBvcnQ6IHN0cmluZyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc01EQzogYm9vbGVhbixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhSb3dzTGltaXRhdGlvbjogYW55KSB7XHJcbiAgICAvLyBjb252ZXJ0IG1pbGxpc2Vjb25kIHRvIHNlY29uZCBmb3Igc3RhcnRUaW1lIGFuZCBlbmRUaW1lLlxyXG4gICAgc3RhcnRUaW1lID0gc3RhcnRUaW1lIC8gMTAwMDtcclxuICAgIGVuZFRpbWUgPSBlbmRUaW1lIC8gMTAwMDtcclxuICAgIGNvbnN0IHRpbWVDb2x1bW4gPSAyO1xyXG4gICAgbGV0IHN0YXJ0TGluZSA9IDA7XHJcbiAgICBsZXQgaVN0YXJ0ID0gLTE7XHJcbiAgICBsZXQgaUVuZCA9IC0xO1xyXG5cclxuICAgIGxldCBjdXJUaW1lID0gbGFzdFByb2Nlc3NlZFRpbWU7XHJcbiAgICBsZXQgbGFzdFByb2Nlc3NlZFRpbWVSZXR1cm47XHJcbiAgICBsZXQgdG90YWxOdW0gPSAwO1xyXG4gICAgbGV0IG1kY0ZsYWcgPSBpc01EQztcclxuICAgIGNvbnN0IGRlZmF1bHRQb3J0ID0gZ2V0RGVmYXVsdFBvcnQoKTtcclxuICAgIGNvbnN0IG1heFJvd051bSA9IHRoaXMuX2dldE1heFJvd3NMaW1pdGF0aW9uKG1heFJvd3NMaW1pdGF0aW9uKTtcclxuXHJcbiAgICBpZiAoZmlyc3RDaHVuaykge1xyXG4gICAgICBpZiAoY3VyVGltZSA+PSBzdGFydFRpbWUgJiYgY3VyVGltZSA8PSBlbmRUaW1lKSB7XHJcbiAgICAgICAgaVN0YXJ0ID0gMTsgLy8gc3RhcnQgZnJvbSBmaXJzdCBsaW5lXHJcblxyXG4gICAgICAgIC8qKiBNb2RpZmllZCBhdCAyMDE4LzEwLzEwLFxyXG4gICAgICAgICAqIGluIHNvbWUgY2FzZSwgZWc6IHRoZSBuYW1lc2VydmVyIGhpc3RvcnkgdHJhY2UgZ2V0cyBtb2RpZmllZCBieSBLb29rLCBKaW4gWW91bmcncyBweXRob24gc2NyaXB0LFxyXG4gICAgICAgICAqIHRoZSBwb3J0IHNob3cgaW4gdGhlIGZpcnN0IGxpbmUgYXMgd2VsbCwgYW5kIGRvZXMgbm90IGxpa2UgdGhlIG5vbi1tZGMgc3lzdGVtLCB0aGlzIGtpbmQgb2YgZmlsZSBoYXNcclxuICAgICAgICAgKiBvbmUgcG9ydCBpbiBpdC4gVGhlIGhpc3RvcnkgZm9yIG5vbi1tZGMgc3lzdGVtIGRvZXNuJ3QgaGF2ZSBwb3J0IGluZm8gaW4gdGhlIHBvcnQgY29sdW1uLiovXHJcblxyXG4gICAgICAgICAgLy8gZ2V0IHBvcnQgZm9yIHRoZSBsaW5lIDEuXHJcbiAgICAgICAgY29uc3QgZmlyc3RMaW5lUG9ydCA9IGdldFBvcnQoZGF0YVsxXVsxXSk7XHJcbiAgICAgICAgLy8gaW5pdCB0aW1lIGFycmF5IGZvciB0aGUgZmlyc3QgbGluZS5cclxuICAgICAgICBpZiAoIXNlbGVjdGVkUG9ydCB8fCBzZWxlY3RlZFBvcnQubGVuZ3RoID09PSAwIHx8IGlzU2FtZVBvcnQoZmlyc3RMaW5lUG9ydCwgc2VsZWN0ZWRQb3J0LCBtZGNGbGFnKSkge1xyXG4gICAgICAgICAgLy8gZG9lcyBub3Qgc2VsZWN0IGFueSBwb3J0IG9yXHJcbiAgICAgICAgICAvLyBpdCdzIG5vbi1tZGMgKG1kY0ZsYWcgaXMgZmFsc2UgYXQgdGhlIGJlZ2lubmluZykgc3lzdGVtIGFuZCB0aGUgc2VsZWN0ZWQgcG9ydCBpcyB0aGUgZmlyc3QgbGluZSBwb3J0XHJcbiAgICAgICAgICB0aW1lW2ZpcnN0TGluZVBvcnRdID0gW107XHJcbiAgICAgICAgICB0aW1lW2ZpcnN0TGluZVBvcnRdWzBdID0gY3VyVGltZSAqIDEwMDA7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICAgIGxhc3RQcm9jZXNzZWRUaW1lUmV0dXJuID0gY3VyVGltZTtcclxuICAgICAgc3RhcnRMaW5lID0gMjtcclxuICAgIH1cclxuXHJcbiAgICAvLyBnZXQgY3VycmVudCB0b3RhbCBudW1iZXJcclxuICAgIE9iamVjdC5rZXlzKHRpbWUpLmZvckVhY2goa2V5ID0+IHtcclxuICAgICAgaWYgKHRpbWVba2V5XSkge1xyXG4gICAgICAgIHRvdGFsTnVtICs9IHRpbWVba2V5XS5sZW5ndGg7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG5cclxuICAgIGlmIChjdXJUaW1lID09IG51bGwpIHtcclxuICAgICAgY29uc29sZS5lcnJvcignZ2V0VGltZUNvbHVtbicsICdDYW4gbm90IGdldCB0aGUgdGltZSBmcm9tIHRoZSBmaWxlLCBpbnRlcm5hbCBlcnJvciEnKTtcclxuICAgICAgcmV0dXJuIHtpbmRleFN0YXJ0OiBudWxsLCBpbmRleEVuZDogbnVsbCwgbGFzdFByb2Nlc3NlZFRpbWU6IG51bGwsIGlzTURDOiBudWxsfTtcclxuICAgIH1cclxuXHJcbiAgICBmb3IgKGxldCBpID0gc3RhcnRMaW5lOyBpIDwgZGF0YS5sZW5ndGg7IGkrKykge1xyXG4gICAgICAvLyBzb21ldGltZSB0aGUgbGFzdCBsaW5lIGlzIGVtcHR5LCBuZWVkIHRvIGJlIHNraXBwZWQuXHJcbiAgICAgIGlmIChkYXRhW2ldID09IG51bGwgfHwgZGF0YVtpXS5sZW5ndGggPT09IDAgfHwgKGRhdGFbaV0ubGVuZ3RoID09PSAxICYmIGRhdGFbaV1bMF0ubGVuZ3RoID09PSAwKSkge1xyXG4gICAgICAgIGNvbnRpbnVlO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBnZXQgcG9ydCBudW1iZXIgYW5kIGluaXRpYWxpemUgdGhlIHJlbGF0aXZlIHBvcnQgYXJyYXkgaW4gdGltZVxyXG4gICAgICBjb25zdCBwb3J0ID0gZ2V0UG9ydChkYXRhW2ldWzFdKTsgLy8gZGF0YVtpXVsxXSA9PSBudWxsIHx8IGRhdGFbaV1bMV0ubGVuZ3RoID09IDAgPyBfX0RFRkFVTFRfUE9SVCA6IGRhdGFbaV1bMV07XHJcbiAgICAgIGlmICghKHBvcnQgaW4gdGltZSkpIHtcclxuICAgICAgICAvLyBhZGQgdW5kZWZpbmVkIHBvcnQgdG8gdGltZSwgdGhlbiB3ZSBjYW4gZmluZCBhbGwgcG9ydHMgaW4gdGltZVxyXG4gICAgICAgIHRpbWVbcG9ydF0gPSB2b2lkIDA7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKHRpbWVbcG9ydF0gPT0gbnVsbCAmJiBpc1NhbWVQb3J0KHBvcnQsIHNlbGVjdGVkUG9ydCwgbWRjRmxhZykpIHtcclxuICAgICAgICB0aW1lW3BvcnRdID0gW107XHJcbiAgICAgICAgLy8gaWYgb3RoZXIgcG9ydHMgZXhpc3RzIGluIHRoaXMgZmlsZSwgZGVmYXVsdCBwb3J0IHdpbGwgYmUgc2V0IHRvIHVuZGVmaW5lZC5cclxuICAgICAgICBpZiAoIW1kY0ZsYWcgJiYgcG9ydCAhPT0gZGVmYXVsdFBvcnQgJiYgdGltZVtkZWZhdWx0UG9ydF0pIHtcclxuICAgICAgICAgIC8vIHVwZGF0ZSB0aGUgdG90YWwgbnVtO1xyXG4gICAgICAgICAgdG90YWxOdW0gLT0gdGltZVtkZWZhdWx0UG9ydF0ubGVuZ3RoO1xyXG4gICAgICAgICAgdGltZVtkZWZhdWx0UG9ydF0ubGVuZ3RoID0gMDtcclxuICAgICAgICAgIHRpbWVbZGVmYXVsdFBvcnRdID0gdm9pZCAwO1xyXG4gICAgICAgICAgbWRjRmxhZyA9IHRydWU7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICAgIGN1clRpbWUgPSBjYWxjdWxhdGVWYWx1ZShjdXJUaW1lLCBkYXRhW2ldW3RpbWVDb2x1bW5dKTtcclxuICAgICAgaWYgKGN1clRpbWUgPiBlbmRUaW1lKSB7XHJcbiAgICAgICAgaWYgKGlFbmQgPCAwKSB7XHJcbiAgICAgICAgICBpRW5kID0gaSAtIDE7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGJyZWFrO1xyXG4gICAgICB9XHJcbiAgICAgIGlmIChpU3RhcnQgPj0gMCkge1xyXG4gICAgICAgIGlmICh0aW1lW3BvcnRdKSB7XHJcbiAgICAgICAgICAvLyBub3QgbnVsbCBtZWFucyBpdCdzIHRoZSBzZWxlY3RlZCBwb3J0XHJcbiAgICAgICAgICB0aW1lW3BvcnRdW3RpbWVbcG9ydF0ubGVuZ3RoXSA9IGN1clRpbWUgKiAxMDAwO1xyXG4gICAgICAgICAgdG90YWxOdW0gKys7XHJcbiAgICAgICAgfVxyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIGlmIChjdXJUaW1lID49IHN0YXJ0VGltZSAmJiBjdXJUaW1lIDw9IGVuZFRpbWUpIHtcclxuICAgICAgICAgIGlmICh0aW1lW3BvcnRdKSB7XHJcbiAgICAgICAgICAgIC8vIG9ubHkgc2VsZWN0ZWQgcG9ydCBjb3VudGVkIGluXHJcbiAgICAgICAgICAgIGlmIChpU3RhcnQgPCAwKSB7XHJcbiAgICAgICAgICAgICAgaVN0YXJ0ID0gaTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB0aW1lW3BvcnRdW3RpbWVbcG9ydF0ubGVuZ3RoXSA9IGN1clRpbWUgKiAxMDAwO1xyXG4gICAgICAgICAgICB0b3RhbE51bSArKztcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgLy8gbGFzdCBwcm9jZXNzZWQgdGltZSBuZWVkIHRvIGJlIHJlY29yZGVkIGFueXdheVxyXG4gICAgICBsYXN0UHJvY2Vzc2VkVGltZVJldHVybiA9IGN1clRpbWU7XHJcblxyXG4gICAgICBpZiAodG90YWxOdW0gPj0gbWF4Um93TnVtKSB7XHJcbiAgICAgICAgaUVuZCA9IGk7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiB7aW5kZXhTdGFydDogaVN0YXJ0LCBpbmRleEVuZDogaUVuZCwgbGFzdFByb2Nlc3NlZFRpbWU6IGxhc3RQcm9jZXNzZWRUaW1lUmV0dXJuLCBpc01EQzogbWRjRmxhZ307XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXQgZGF0YSBmb3IgYWxsIGNvbHVtbnNcclxuICAgKiBAcGFyYW0gY29sdW1uTnVtIHRoZSB0b3RhbCBudW1iZXIgb2YgY29sdW1ucy4gRm9yIG1kYyBzeXN0ZW0sXHJcbiAgICogICAgICAgICAgICAgICAgICB0aGUgbGVuZ3RoIG9mIGVhY2ggcm93IGlzIGRpZmZlcmVudC4gSG9zdCByZWxhdGl2ZSBkYXRhIGRvZXMgbm90IGV4aXN0IGluIHRlbmFudCBsaW5lLlxyXG4gICAqICAgICAgICAgICAgICAgICAgTmVlZHMgdG8gdXNlIGNvbHVtbiBudW1iZXIgZnJvbSB0aGUgZmlyc3QgbGluZS5cclxuICAgKiBAcGFyYW0gZGF0YSAgICAgIGRhdGEgcGFyc2VkIGJ5IHBhcGFcclxuICAgKiBAcGFyYW0gZmlyc3RDaHVuayB0aGUgZmxhZyB3aGljaCBpZGVudGlmaWVzIHdoZXRoZXIgaXQncyB0aGUgZmlyc3QgY2h1bmsgb3Igbm90LlxyXG4gICAqIEBwYXJhbSB0aW1lXHJcbiAgICogQHBhcmFtIGluZGV4U3RhcnRcclxuICAgKiBAcGFyYW0gaW5kZXhFbmRcclxuICAgKiBAcGFyYW0gbGFzdFByb2Nlc3NlZExpbmVcclxuICAgKiBAcGFyYW0gcmVzdWx0RGF0YSAgIHRoZSByZXN1bHQgZGF0YSBhZnRlciBhbmFseXplZFxyXG4gICAqIEBwYXJhbSBzZWxlY3RlZFBvcnRcclxuICAgKiBAcGFyYW0gaXNNRENcclxuICAgKi9cclxuICBwcml2YXRlIHN0YXRpYyBfZ2V0RGF0YUNvbHVtbnMoY29sdW1uTnVtOiBudW1iZXIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGE6IHN0cmluZ1tdW10sXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpcnN0Q2h1bms6IGJvb2xlYW4sXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpbWU6IENoYXJ0Q29udGVudFRpbWUsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4U3RhcnQ6IG51bWJlcixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXhFbmQ6IG51bWJlcixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdFByb2Nlc3NlZExpbmU6IG51bWJlcltdLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHREYXRhOiBDaGFydENvbnRlbnREYXRhLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZFBvcnQ6IHN0cmluZyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNNREM6IGJvb2xlYW4pIHtcclxuICAgIGxldCBzdGFydExpbmUgPSAwO1xyXG4gICAgLy8gZm9yIG1kYyBzeXN0ZW0sIHRoZSBsZW5ndGggaXMgbm90IGNvcnJlY3QgKGhvc3QgcmVsYXRpdmUgZGF0YSBvbmx5IGV4aXN0cyBpbiB0aGUgXCJlbXB0eVwiIHBvcnQgbGluZSkuXHJcbiAgICAvLyBOZWVkcyB0byB1c2UgaGVhZGVyIGZyb20gdGhlIGZpcnN0IGxpbmUuXHJcbiAgICAvLyBjb25zdCBjb2x1bW5OdW0gPSBkYXRhWzBdLmxlbmd0aDtcclxuXHJcbiAgICBpZiAoZmlyc3RDaHVuaykge1xyXG4gICAgICAvKipcclxuICAgICAgICogTW9kaWZpZWQgYXQgMjAxOC8xMC8xMCxcclxuICAgICAgICogaW4gc29tZSBjYXNlLCBlZzogdGhlIG5hbWVzZXJ2ZXIgaGlzdG9yeSB0cmFjZSBnZXRzIG1vZGlmaWVkIGJ5IEtvb2ssIEppbiBZb3VuZydzIHB5dGhvbiBzY3JpcHQsXHJcbiAgICAgICAqIHRoZSBwb3J0IHNob3cgaW4gdGhlIGZpcnN0IGxpbmUgYXMgd2VsbCwgYW5kIGRvZXMgbm90IGxpa2UgdGhlIG5vbi1tZGMgc3lzdGVtLCB0aGlzIGtpbmQgb2YgZmlsZSBoYXNcclxuICAgICAgICogb25lIHBvcnQgaW4gaXQuIFRoZSBoaXN0b3J5IGZvciBub24tbWRjIHN5c3RlbSBkb2Vzbid0IGhhdmUgcG9ydCBpbmZvIGluIHRoZSBwb3J0IGNvbHVtbi5cclxuICAgICAgICovXHJcblxyXG4gICAgICAvLyBnZXQgcG9ydCBmb3IgdGhlIGxpbmUgMS5cclxuICAgICAgY29uc3QgZmlyc3RMaW5lUG9ydCA9IGdldFBvcnQoZGF0YVsxXVsxXSk7XHJcbiAgICAgIC8vIEluaXRpYWxpemUgZGF0YSBjb2x1bW4gd2l0aCBkZWZhdWx0ICdERUZBVUxUJyBwb3J0IGlmIGl0J3Mgbm90IE1EQyBzeXN0ZW0uIE1EQyBzeXN0ZW0sICdERUZBVUxUJyBnZXRzIGlnbm9yZWRcclxuICAgICAgaWYgKCFpc01EQyAmJiB0aW1lW2ZpcnN0TGluZVBvcnRdKSB7XHJcbiAgICAgICAgcmVzdWx0RGF0YVtmaXJzdExpbmVQb3J0XSA9IFtdO1xyXG4gICAgICAgIC8vIHJlbW92ZWQgYmVsb3cgbG9naWMsIGJlY2F1c2UgZmlyc3QgbGluZSBpcyB0aGUgcmVhbCBudW1iZXIsIGRvIG5vdCBuZWVkIHRvIGRvIHRoZSBjb252ZXJ0LlxyXG4gICAgICAgIC8vIGN1ckxpbmUgPSBkYXRhWzFdLnNsaWNlKDMpLm1hcChOdW1iZXIpO1xyXG4gICAgICAgIGZvciAobGV0IGogPSAzOyBqIDwgY29sdW1uTnVtOyBqKyspIHtcclxuICAgICAgICAgIGNvbnN0IGluZGV4ID0gaiAtIDM7XHJcblxyXG4gICAgICAgICAgLy8gaW5pdGlhbGl6ZSBkYXRhIGFycmF5IGZvciBhbGwgY29sdW1ucyBvZiB0aGUgZGVmYXVsdCAnMDAwMCcgcG9ydFxyXG4gICAgICAgICAgcmVzdWx0RGF0YVtmaXJzdExpbmVQb3J0XVtpbmRleF0gPSBbXTtcclxuICAgICAgICAgIC8vIGdldCB0aGUgZmlyc3QgbGluZSBkYXRhIG9mIHRoZSBjb2x1bW4gaWYgaXQncyBpbmNsdWRlZFxyXG4gICAgICAgICAgaWYgKGluZGV4U3RhcnQgPT09IDEpIHtcclxuICAgICAgICAgICAgcmVzdWx0RGF0YVtmaXJzdExpbmVQb3J0XVtpbmRleF1bMF0gPSB7eDogdGltZVtmaXJzdExpbmVQb3J0XVswXSwgeTogbGFzdFByb2Nlc3NlZExpbmVbaW5kZXhdfTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgc3RhcnRMaW5lID0gMjtcclxuICAgIH1cclxuXHJcbiAgICBmb3IgKGxldCBqID0gMzsgaiA8IGNvbHVtbk51bTsgaisrKSB7XHJcbiAgICAgIGNvbnN0IGluZGV4ID0gaiAtIDM7XHJcbiAgICAgIGZvciAobGV0IGkgPSBzdGFydExpbmU7IGkgPCBkYXRhLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgLy8gc29tZXRpbWUgdGhlIGxhc3QgbGluZSBpcyBlbXB0eSwgbmVlZCB0byBiZSBza2lwcGVkLlxyXG4gICAgICAgIGlmIChkYXRhW2ldID09IG51bGwgfHwgZGF0YVtpXS5sZW5ndGggPT09IDAgfHwgKGRhdGFbaV0ubGVuZ3RoID09PSAxICYmIGRhdGFbaV1bMF0ubGVuZ3RoID09PSAwKSkge1xyXG4gICAgICAgICAgY29udGludWU7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBnZXQgcG9ydCBudW1iZXIgYW5kIGluaXRpYWxpemUgdGhlIHJlbGF0aXZlIHBvcnQgYXJyYXkgaW4gZGF0YVxyXG4gICAgICAgIGNvbnN0IHBvcnQgPSBnZXRQb3J0KGRhdGFbaV1bMV0pO1xyXG4gICAgICAgIGlmIChyZXN1bHREYXRhW3BvcnRdID09IG51bGwgJiYgaXNTYW1lUG9ydChwb3J0LCBzZWxlY3RlZFBvcnQsIGlzTURDKSkge1xyXG4gICAgICAgICAgcmVzdWx0RGF0YVtwb3J0XSA9IFtdO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAocmVzdWx0RGF0YVtwb3J0XSAmJiByZXN1bHREYXRhW3BvcnRdW2luZGV4XSA9PSBudWxsKSB7XHJcbiAgICAgICAgICByZXN1bHREYXRhW3BvcnRdW2luZGV4XSA9IFtdO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgbGFzdFByb2Nlc3NlZExpbmVbaW5kZXhdID0gY2FsY3VsYXRlVmFsdWUobGFzdFByb2Nlc3NlZExpbmVbaW5kZXhdLCBkYXRhW2ldW2pdKTtcclxuICAgICAgICBpZiAoaSA+PSBpbmRleFN0YXJ0ICYmIChpIDw9IGluZGV4RW5kIHx8IGluZGV4RW5kIDwgMCkgJiYgaW5kZXhTdGFydCA+PSAwKSB7XHJcbiAgICAgICAgICBpZiAocmVzdWx0RGF0YVtwb3J0XSkge1xyXG4gICAgICAgICAgICBjb25zdCBsZW5ndGggPSByZXN1bHREYXRhW3BvcnRdW2luZGV4XS5sZW5ndGg7XHJcbiAgICAgICAgICAgIHJlc3VsdERhdGFbcG9ydF1baW5kZXhdW2xlbmd0aF0gPSB7eDogdGltZVtwb3J0XVtsZW5ndGhdLCB5OiBsYXN0UHJvY2Vzc2VkTGluZVtpbmRleF19O1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH0gZWxzZSBpZiAoaW5kZXhFbmQgPiAwICYmIGkgPiBpbmRleEVuZCkge1xyXG4gICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXQgQ2hhcnQgZGF0YSBmcm9tIHByb3ZpZGVkIGZpbGUuXHJcbiAgICogQHBhcmFtIGZpbGUgdGhlIG5hbWVzZXJ2ZXIgaGlzdG9yeSBmaWxlXHJcbiAgICogQHBhcmFtIHN0YXJ0VGltZVxyXG4gICAqIEBwYXJhbSBlbmRUaW1lXHJcbiAgICogQHBhcmFtIHBvcnRcclxuICAgKiBAcGFyYW0gdGltZXpvbmVcclxuICAgKiBAcGFyYW0gbWF4Um93c0xpbWl0YXRpb24gcHJldmVudCBicm93c2VyIGZyb20gY3Jhc2hpbmcsIHNldCB0aGUgbWF4IHJvd3MgbGltaXRhdGlvbi5cclxuICAgKiBAcGFyYW0gcHJvZ3Jlc3MgY2FsbCBiYWNrIGZ1bmN0aW9uIGZvciB1cGRhdGluZyBwcm9ncmVzc1xyXG4gICAqL1xyXG4gIHB1YmxpYyBnZXRDaGFydENvbnRlbnRGcm9tRmlsZShmaWxlOiBGaWxlLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGFydFRpbWU6IG51bWJlcixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5kVGltZTogbnVtYmVyLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3J0OiBzdHJpbmcsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpbWV6b25lOiBzdHJpbmcsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heFJvd3NMaW1pdGF0aW9uOiBhbnksXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb2dyZXNzOiBhbnkpOiBQcm9taXNlPENoYXJ0Q29udGVudD4ge1xyXG4gICAgLy8gbG9hZCBkb25lLCBiZWdpbm5pbmcgcGFyc2luZ1xyXG4gICAgY29uc3QgYmVnaW5UaW1lID0gbmV3IERhdGUoKTtcclxuICAgIGxldCBmaXJzdENodW5rID0gdHJ1ZTtcclxuICAgIC8vIHNhdmUgbGFzdCBwcm9jZXNzZWQgZGF0YSBqdXN0IGZvciB0aGUgbGF0ZXIgY2FsY3VsYXRpb25cclxuICAgIGxldCBsYXN0UHJvY2Vzc2VkRGF0YTtcclxuICAgIC8vIHNhdmUgbGFzdCBwcm9jZXNzZWQgdGltZSBqdXN0IGZvciB0aGUgbGF0ZXIgY2FsY3VsYXRpb25cclxuICAgIGxldCBsYXN0UHJvY2Vzc2VkVGltZTtcclxuICAgIC8vIHNhdmUgbGFzdCBwcm9jZXNzZWQgY3Vyc29yIHBvc2l0aW9uIGZvciBwcm9ncmVzcyBjYWxjdWxhdGlvbi5cclxuICAgIC8vIGxldCBsYXN0UHJvY2Vzc2VkQ3Vyc29yID0gMDtcclxuICAgIGxldCBpbmRleFN0YXJ0ID0gLTEsIGluZGV4RW5kID0gLTE7XHJcbiAgICBjb25zdCB0aW1lOiBDaGFydENvbnRlbnRUaW1lID0ge307XHJcbiAgICBjb25zdCBkYXRhOiBDaGFydENvbnRlbnREYXRhID0ge307XHJcbiAgICBsZXQgaGVhZGVyO1xyXG4gICAgbGV0IGhvc3Q7XHJcbiAgICBsZXQgaXNNREMgPSBmYWxzZTtcclxuICAgIGxldCBjb2x1bW5OdW07XHJcbiAgICBsZXQgYWJvcnRUeXBlOiBBYm9ydDtcclxuXHJcbiAgICBjb25zdCByZWplY3RBbmRBYm9ydCA9IChyZWplY3QsIHBhcnNlcikgPT4ge1xyXG4gICAgICBpZiAocHJvZ3Jlc3MpIHtcclxuICAgICAgICBwcm9ncmVzcygxMDApO1xyXG4gICAgICB9XHJcbiAgICAgIHJlamVjdChgJHtmaWxlLm5hbWV9IGlzIGVtcHR5IG9yIHRoZSBmb3JtYXQgaXMgbm90IGNvcnJlY3QuYCk7XHJcbiAgICAgIHBhcnNlci5hYm9ydCgpO1xyXG4gICAgfTtcclxuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XHJcbiAgICAgIHBhcnNlKGZpbGUsIHtcclxuICAgICAgICBjaHVuazogKHJlc3VsdHMsIHBhcnNlcikgPT4ge1xyXG4gICAgICAgICAgLy8gdGhlIHByb2dyZXNzIGluY3JlbWVudCBvZiB0aGlzIHN0ZXBcclxuICAgICAgICAgIC8vIGxldCBhbmFseXplU3RlcFByb2dyZXNzID0gKHJlc3VsdHMubWV0YS5jdXJzb3IgLSBsYXN0UHJvY2Vzc2VkQ3Vyc29yKSAvIGZpbGUuc2l6ZSAqIDEwMDtcclxuICAgICAgICAgIHByaW50UHJvY2Vzc2VkVGltZShiZWdpblRpbWUsICdzdGVwMScpO1xyXG4gICAgICAgICAgaWYgKGluZGV4RW5kID49IDApIHtcclxuICAgICAgICAgICAgLy8gYWxyZWFkeSBmaW5pc2hlZCwgcXVpdGUuXHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIC8vIHJlc2V0IHN0YXJ0IHBvaW50XHJcbiAgICAgICAgICAgIGluZGV4U3RhcnQgPSAtMTtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAvLyBnZXQgdGltZSBjb2x1bW5cclxuICAgICAgICAgIGlmIChmaXJzdENodW5rKSB7XHJcbiAgICAgICAgICAgIGlmICghdmFsaWRhdGVEYXRhKHJlc3VsdHMuZGF0YSkpIHtcclxuICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0QW5kQWJvcnQocmVqZWN0LCBwYXJzZXIpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvLyBpbml0aWFsaXplIHRoZSBoZWFkZXJcclxuICAgICAgICAgICAgaGVhZGVyID0gcmVzdWx0cy5kYXRhWzBdLnNsaWNlKDMpO1xyXG4gICAgICAgICAgICAvLyBnZXQgY29sdW1uIG51bWJlclxyXG4gICAgICAgICAgICBjb2x1bW5OdW0gPSByZXN1bHRzLmRhdGFbMF0ubGVuZ3RoO1xyXG4gICAgICAgICAgICAvLyBnZXQgaG9zdCBuYW1lXHJcbiAgICAgICAgICAgIGhvc3QgPSByZXN1bHRzLmRhdGFbMV1bMF07XHJcbiAgICAgICAgICAgIC8vIGdldCB0aGUgZmlyc3QgbGluZSB0aW1lIGluZm8gZnJvbSBmaXJzdCBsaW5lLCBpdCBpcyBhIHJlYWwgbnVtYmVyLCBkbyBub3QgbmVlZCB0byBkbyB0aGUgY29udmVydCB3aXRoIFwiPiw8XCIuXHJcbiAgICAgICAgICAgIGxhc3RQcm9jZXNzZWRUaW1lID0gZ2V0VGltZUZyb21UaW1lWm9uZShwYXJzZUZsb2F0KHJlc3VsdHMuZGF0YVsxXVsyXSksIHRpbWV6b25lKTtcclxuICAgICAgICAgICAgLy8gZ2V0IHRoZSBmaXJzdCBsaW5lIGRhdGEgaW5mbyBmcm9tIGZpcnN0IGxpbmUsIGl0IGlzIGEgcmVhbCBudW1iZXIsIGRvIG5vdCBuZWVkIHRvIGRvIHRoZSBjb252ZXJ0IHdpdGggXCI+LDxcIi5cclxuICAgICAgICAgICAgbGFzdFByb2Nlc3NlZERhdGEgPSByZXN1bHRzLmRhdGFbMV0uc2xpY2UoMykubWFwKE51bWJlcik7XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgcHJpbnRQcm9jZXNzZWRUaW1lKGJlZ2luVGltZSwgJ3N0ZXAyJyk7XHJcblxyXG4gICAgICAgICAgaWYgKCFsYXN0UHJvY2Vzc2VkRGF0YSkge1xyXG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0QW5kQWJvcnQocmVqZWN0LCBwYXJzZXIpO1xyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIC8vIGdldCB0aW1lIGNvbHVtblxyXG4gICAgICAgICAgKHtpbmRleFN0YXJ0LCBpbmRleEVuZCwgbGFzdFByb2Nlc3NlZFRpbWUsIGlzTURDfSA9IEZpbGVTZXJ2aWNlLl9nZXRUaW1lQ29sdW1uKFxyXG4gICAgICAgICAgICByZXN1bHRzLmRhdGEsIGZpcnN0Q2h1bmssIHN0YXJ0VGltZSwgZW5kVGltZSwgbGFzdFByb2Nlc3NlZFRpbWUsIHRpbWUsIHBvcnQsIGlzTURDLCBtYXhSb3dzTGltaXRhdGlvbikpO1xyXG4gICAgICAgICAgcHJpbnRQcm9jZXNzZWRUaW1lKGJlZ2luVGltZSwgJ3N0ZXAzJyk7XHJcblxyXG4gICAgICAgICAgaWYgKGluZGV4U3RhcnQgPT0gbnVsbCAmJiBpbmRleEVuZCA9PSBudWxsICYmIGxhc3RQcm9jZXNzZWRUaW1lID09IG51bGwgJiYgaXNNREMgPT0gbnVsbCkge1xyXG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0QW5kQWJvcnQocmVqZWN0LCBwYXJzZXIpO1xyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIC8vIGdldCBhbGwgb3RoZXIgZGF0YSBjb2x1bW5zXHJcbiAgICAgICAgICBGaWxlU2VydmljZS5fZ2V0RGF0YUNvbHVtbnMoXHJcbiAgICAgICAgICAgIGNvbHVtbk51bSwgcmVzdWx0cy5kYXRhLCBmaXJzdENodW5rLCB0aW1lLCBpbmRleFN0YXJ0LCBpbmRleEVuZCwgbGFzdFByb2Nlc3NlZERhdGEsIGRhdGEsIHBvcnQsIGlzTURDKTtcclxuXHJcbiAgICAgICAgICBpZiAoZmlyc3RDaHVuaykge1xyXG4gICAgICAgICAgICBmaXJzdENodW5rID0gZmFsc2U7XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgcHJpbnRQcm9jZXNzZWRUaW1lKGJlZ2luVGltZSwgJ3N0ZXA0Jyk7XHJcblxyXG4gICAgICAgICAgaWYgKGluZGV4RW5kID49IDApIHtcclxuICAgICAgICAgICAgLy8gZG8gbm90IG5lZWQgdG8gcHJvY2VzcyB0aGUgbGVmdCBwYXJ0cywgbWFudWFsbHkgdHJpZ2dlciBjb21wbGV0ZVxyXG4gICAgICAgICAgICBjb25zdCBwcm9jZXNzZWRMaW5lcyA9IE9iamVjdC5rZXlzKHRpbWUpLnJlZHVjZSgodG90YWwsIGN1cktleSkgPT4gdGltZVtjdXJLZXldID8gdG90YWwgKyB0aW1lW2N1cktleV0ubGVuZ3RoIDogdG90YWwsIDApO1xyXG4gICAgICAgICAgICBpZiAocHJvY2Vzc2VkTGluZXMgPj0gRmlsZVNlcnZpY2UuX2dldE1heFJvd3NMaW1pdGF0aW9uKG1heFJvd3NMaW1pdGF0aW9uKSkge1xyXG4gICAgICAgICAgICAgIGFib3J0VHlwZSA9IEFib3J0Lm1heExpbmVOdW1SZWFjaGVkO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgIGFib3J0VHlwZSA9IEFib3J0Lm1heFRpbWVSYW5nZVJlYWNoZWQ7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmIChwcm9ncmVzcykge1xyXG4gICAgICAgICAgICAgIHByb2dyZXNzKDEwMCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcGFyc2VyLmFib3J0KCk7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIC8vIHRoZSBvdmVyYWxsIHByb2dyZXNzIGlmIHRoaXMgc3RlcCBpcyBmaW5pc2hlZFxyXG4gICAgICAgICAgICBpZiAocHJvZ3Jlc3MpIHtcclxuICAgICAgICAgICAgICBwcm9ncmVzcyhNYXRoLnJvdW5kKHJlc3VsdHMubWV0YS5jdXJzb3IgLyBmaWxlLnNpemUgKiAxMDApKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAvLyBsYXN0UHJvY2Vzc2VkQ3Vyc29yID0gcmVzdWx0cy5tZXRhLmN1cnNvcjtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9LFxyXG4gICAgICAgIGNvbXBsZXRlOiAoKSA9PiB7XHJcbiAgICAgICAgICBwcmludFByb2Nlc3NlZFRpbWUoYmVnaW5UaW1lLCAnc3RlcF9jb21wbGV0ZScpO1xyXG4gICAgICAgICAgcmVzb2x2ZSAoe2hlYWRlcjogaGVhZGVyLCBob3N0OiBob3N0LCB0aW1lOiB0aW1lLCBkYXRhOiBkYXRhLCBhYm9ydGVkOiBhYm9ydFR5cGV9KTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXQgYWxsIHBvcnRzIGZyb20gdGhlIG5hbWUgc2VydmVyIGhpc3RvcnkgZmlsZVxyXG4gICAqIEBwYXJhbSBmaWxlIHRoZSBuYW1lIHNlcnZlciBoaXN0b3J5IGZpbGVcclxuICAgKiBAcGFyYW0gcHJvZ3Jlc3MgY2FsbCBiYWNrIGZvciB1cGRhdGluZyB0aGUgcHJvZ3Jlc3NcclxuICAgKi9cclxuICBwdWJsaWMgZ2V0UG9ydHNGcm9tRmlsZShmaWxlOiBGaWxlLCBwcm9ncmVzczogYW55KTogUHJvbWlzZTxzdHJpbmdbXT4ge1xyXG4gICAgY29uc3QgYmVnaW5UaW1lID0gbmV3IERhdGUoKTtcclxuICAgIGxldCBmaXJzdENodW5rID0gdHJ1ZTtcclxuICAgIGNvbnN0IHBvcnRzID0gW107XHJcbiAgICBjb25zdCBkZWZhdWx0UG9ydCA9IGdldERlZmF1bHRQb3J0KCk7XHJcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xyXG4gICAgICBwYXJzZShmaWxlLCB7XHJcbiAgICAgICAgY2h1bms6IChyZXN1bHRzLCBwYXJzZXIpID0+IHtcclxuICAgICAgICAgIC8vIGdldCB0aW1lIGNvbHVtblxyXG4gICAgICAgICAgaWYgKGZpcnN0Q2h1bmspIHtcclxuICAgICAgICAgICAgaWYgKCF2YWxpZGF0ZURhdGEocmVzdWx0cy5kYXRhKSkge1xyXG4gICAgICAgICAgICAgIGlmIChwcm9ncmVzcykge1xyXG4gICAgICAgICAgICAgICAgcHJvZ3Jlc3MoMTAwKTtcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgcmVqZWN0KGAke2ZpbGUubmFtZX0gaXMgZW1wdHkgb3IgdGhlIGZvcm1hdCBpcyBub3QgY29ycmVjdC5gKTtcclxuICAgICAgICAgICAgICBwYXJzZXIuYWJvcnQoKTtcclxuICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICAgIHByaW50UHJvY2Vzc2VkVGltZShiZWdpblRpbWUsICdwb3J0LnN0ZXAxJyk7XHJcbiAgICAgICAgICBGaWxlU2VydmljZS5fZ2V0UG9ydHMocmVzdWx0cy5kYXRhLCBmaXJzdENodW5rLCBwb3J0cyk7XHJcbiAgICAgICAgICBpZiAoZmlyc3RDaHVuaykge1xyXG4gICAgICAgICAgICBmaXJzdENodW5rID0gZmFsc2U7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICBpZiAocHJvZ3Jlc3MpIHtcclxuICAgICAgICAgICAgcHJvZ3Jlc3MoTWF0aC5yb3VuZChyZXN1bHRzLm1ldGEuY3Vyc29yIC8gZmlsZS5zaXplICogMTAwKSk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSxcclxuICAgICAgICBjb21wbGV0ZTogKCkgPT4ge1xyXG4gICAgICAgICAgLy8gcGFyc2luZyBkb25lXHJcbiAgICAgICAgICBwcmludFByb2Nlc3NlZFRpbWUoYmVnaW5UaW1lLCAnc3RlcF9jb21wbGV0ZScpO1xyXG4gICAgICAgICAgaWYgKHBvcnRzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICBwb3J0c1swXSA9IGRlZmF1bHRQb3J0O1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgcmVzb2x2ZSAocG9ydHMpO1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcbiAgICB9KTtcclxuICB9XHJcbn1cclxuIl19