@colijnit/sharedcomponents 1.0.62 → 1.0.64

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 (479) hide show
  1. package/README.md +24 -24
  2. package/bundles/colijnit-sharedcomponents.umd.js +9888 -9855
  3. package/bundles/colijnit-sharedcomponents.umd.js.map +1 -1
  4. package/colijnit-sharedcomponents.d.ts +91 -91
  5. package/colijnit-sharedcomponents.metadata.json +1 -1
  6. package/esm2015/colijnit-sharedcomponents.js +91 -91
  7. package/esm2015/lib/assets/dictionary/text.properties.js +11 -11
  8. package/esm2015/lib/businessobject/build-images-and-documentation-result.js +2 -2
  9. package/esm2015/lib/businessobject/co-document-right.bo.js +3 -3
  10. package/esm2015/lib/businessobject/drag-drop-container-element.js +2 -2
  11. package/esm2015/lib/businessobject/drag-drop-container.js +7 -7
  12. package/esm2015/lib/components/activity-list/activity-list.component.js +130 -130
  13. package/esm2015/lib/components/activity-list/activity-list.module.js +24 -24
  14. package/esm2015/lib/components/app-file-dropzone/app-file-dropzone.component.js +47 -47
  15. package/esm2015/lib/components/app-file-dropzone/app-file-dropzone.module.js +20 -20
  16. package/esm2015/lib/components/date-planning/component/agenda/agenda-base-view.component.js +61 -61
  17. package/esm2015/lib/components/date-planning/component/agenda/agenda-day-view.component.js +36 -36
  18. package/esm2015/lib/components/date-planning/component/agenda/agenda-event.component.js +56 -56
  19. package/esm2015/lib/components/date-planning/component/agenda/agenda-events.component.js +47 -47
  20. package/esm2015/lib/components/date-planning/component/agenda/agenda-half-hour-cell.component.js +68 -68
  21. package/esm2015/lib/components/date-planning/component/agenda/agenda-header.component.js +243 -243
  22. package/esm2015/lib/components/date-planning/component/agenda/agenda-hour-cell.component.js +36 -36
  23. package/esm2015/lib/components/date-planning/component/agenda/agenda-hour-view-labels.component.js +50 -50
  24. package/esm2015/lib/components/date-planning/component/agenda/agenda-hour-view.component.js +46 -46
  25. package/esm2015/lib/components/date-planning/component/agenda/agenda-month-view.component.js +61 -61
  26. package/esm2015/lib/components/date-planning/component/agenda/agenda-select-event.component.js +39 -39
  27. package/esm2015/lib/components/date-planning/component/agenda/agenda-view.component.js +35 -35
  28. package/esm2015/lib/components/date-planning/component/agenda/agenda-week-select-view.component.js +64 -64
  29. package/esm2015/lib/components/date-planning/component/agenda/agenda-week-view.component.js +48 -48
  30. package/esm2015/lib/components/date-planning/component/agenda/view-select.component.js +42 -42
  31. package/esm2015/lib/components/date-planning/component/calendar/calendar-all-months.component.js +34 -34
  32. package/esm2015/lib/components/date-planning/component/calendar/calendar-all-years.component.js +48 -48
  33. package/esm2015/lib/components/date-planning/component/calendar/calendar-header.component.js +107 -107
  34. package/esm2015/lib/components/date-planning/component/calendar/calendar-view.component.js +178 -178
  35. package/esm2015/lib/components/date-planning/component/calendar/calendar.component.js +34 -34
  36. package/esm2015/lib/components/date-planning/date-planning.component.js +113 -113
  37. package/esm2015/lib/components/date-planning/date-planning.module.js +63 -63
  38. package/esm2015/lib/components/docsign/component/signature/signature.component.js +75 -75
  39. package/esm2015/lib/components/docsign/component/signatures/signatures.component.js +44 -44
  40. package/esm2015/lib/components/docsign/docsign.component.js +242 -242
  41. package/esm2015/lib/components/docsign/docsign.module.js +23 -23
  42. package/esm2015/lib/components/file-upload/file-upload.component.js +189 -189
  43. package/esm2015/lib/components/file-upload/file-upload.module.js +25 -25
  44. package/esm2015/lib/components/file-upload-popup/file-upload-popup.component.js +397 -397
  45. package/esm2015/lib/components/file-upload-popup/file-upload-popup.module.js +30 -30
  46. package/esm2015/lib/components/files-upload/components/base-file-upload.component.js +469 -469
  47. package/esm2015/lib/components/files-upload/components/drag-drop-container.component.js +115 -115
  48. package/esm2015/lib/components/files-upload/files-upload.component.js +131 -131
  49. package/esm2015/lib/components/files-upload/files-upload.module.js +47 -47
  50. package/esm2015/lib/components/image-display/image-display.component.js +36 -36
  51. package/esm2015/lib/components/image-display/image-display.module.js +23 -23
  52. package/esm2015/lib/components/key-pad/key-pad.component.js +200 -200
  53. package/esm2015/lib/components/key-pad/key-pad.module.js +22 -22
  54. package/esm2015/lib/components/layout-switcher/layout-switcher.component.js +74 -74
  55. package/esm2015/lib/components/layout-switcher/layout-switcher.module.js +21 -21
  56. package/esm2015/lib/components/linear-gauge/co-linear-gauge.component.js +59 -59
  57. package/esm2015/lib/components/linear-gauge/co-linear-gauge.module.js +19 -19
  58. package/esm2015/lib/components/multi-property-toggler/multiple-property-toggler.component.js +89 -89
  59. package/esm2015/lib/components/multi-property-toggler/multiple-property-toggler.module.js +21 -21
  60. package/esm2015/lib/components/send-method-dialog/components/layout-selection/layout-selection.component.js +79 -79
  61. package/esm2015/lib/components/send-method-dialog/components/layout-selection/layout-selection.module.js +21 -21
  62. package/esm2015/lib/components/send-method-dialog/components/printer-selection/printer-selection.component.js +85 -85
  63. package/esm2015/lib/components/send-method-dialog/components/printer-selection/printer-selection.module.js +21 -21
  64. package/esm2015/lib/components/send-method-dialog/components/send-method-email/send-method-email.component.js +64 -64
  65. package/esm2015/lib/components/send-method-dialog/components/send-method-email/send-method-email.module.js +26 -26
  66. package/esm2015/lib/components/send-method-dialog/components/send-method-pdf/send-method-pdf.component.js +40 -40
  67. package/esm2015/lib/components/send-method-dialog/components/send-method-pdf/send-method-pdf.module.js +23 -23
  68. package/esm2015/lib/components/send-method-dialog/components/send-method-printer/send-method-printer.component.js +61 -61
  69. package/esm2015/lib/components/send-method-dialog/components/send-method-printer/send-method-printer.module.js +28 -28
  70. package/esm2015/lib/components/send-method-dialog/components/signature-button/signature-button.component.js +38 -38
  71. package/esm2015/lib/components/send-method-dialog/components/signature-button/signature-button.module.js +21 -21
  72. package/esm2015/lib/components/send-method-dialog/model/email-address-viewmodel.js +7 -7
  73. package/esm2015/lib/components/send-method-dialog/send-method-dialog.component.js +258 -258
  74. package/esm2015/lib/components/send-method-dialog/send-method-dialog.module.js +35 -35
  75. package/esm2015/lib/components/send-method-dialog/send-method-params.interface.js +2 -2
  76. package/esm2015/lib/components/send-method-dialog/service/send-method.service.js +59 -59
  77. package/esm2015/lib/components/simple-tags/simple-tags.component.js +229 -229
  78. package/esm2015/lib/components/simple-tags/simple-tags.module.js +26 -26
  79. package/esm2015/lib/components/statusbar/statusbar-popup.component.js +97 -97
  80. package/esm2015/lib/components/statusbar/statusbar.component.js +81 -81
  81. package/esm2015/lib/components/statusbar/statusbar.module.js +27 -27
  82. package/esm2015/lib/components/stock/components/allocation-stock-history/allocation-stock-history.component.js +47 -47
  83. package/esm2015/lib/components/stock/components/order-commission-stock-history/order-commission-stock-history.component.js +47 -47
  84. package/esm2015/lib/components/stock/components/order-stock-history/order-stock-history.component.js +47 -47
  85. package/esm2015/lib/components/stock/components/order-stock-tab/order-stock-tab.component.js +47 -47
  86. package/esm2015/lib/components/stock/components/order-supply-stock-history/order-supply-stock-history.component.js +47 -47
  87. package/esm2015/lib/components/stock/components/order-tab/order-tab.component.js +67 -67
  88. package/esm2015/lib/components/stock/components/stock-history/stock-history.component.js +53 -53
  89. package/esm2015/lib/components/stock/components/stock-location/stock-location.component.js +251 -240
  90. package/esm2015/lib/components/stock/components/stock-prognose/stock-prognose.component.js +52 -52
  91. package/esm2015/lib/components/stock/components/stock-tab/stock-tab.component.js +39 -39
  92. package/esm2015/lib/components/stock/localization/translation.js +72 -63
  93. package/esm2015/lib/components/stock/stock-history-tabs/stock-history-tabs.component.js +33 -33
  94. package/esm2015/lib/components/stock/stock-information/stock-information.component.js +48 -49
  95. package/esm2015/lib/components/stock/stock-information-grid/stock-information-grid.component.js +457 -457
  96. package/esm2015/lib/components/stock/stock-tabs/stock-tabs.component.js +243 -243
  97. package/esm2015/lib/components/stock/stock-transfer/co-drop-down-list-fields.interface.js +2 -2
  98. package/esm2015/lib/components/stock/stock-transfer/stock-change-amount.component.js +72 -72
  99. package/esm2015/lib/components/stock/stock-transfer/stock-transfer.component.js +160 -149
  100. package/esm2015/lib/components/stock/stock.component.js +237 -197
  101. package/esm2015/lib/components/stock/stock.module.js +80 -80
  102. package/esm2015/lib/components/stock-statusbar/stock-statusbar.component.js +23 -23
  103. package/esm2015/lib/components/stock-statusbar/stock-statusbar.module.js +19 -19
  104. package/esm2015/lib/components/tab-bar/tab-bar.component.js +90 -90
  105. package/esm2015/lib/components/tab-bar/tab-bar.module.js +21 -21
  106. package/esm2015/lib/components/tab-bar/tab.interface.js +2 -2
  107. package/esm2015/lib/components/tile-renderer/tile-render.component.js +80 -80
  108. package/esm2015/lib/components/tile-renderer/tile-render.module.js +26 -26
  109. package/esm2015/lib/decorator/input-boolean.decorator.js +34 -34
  110. package/esm2015/lib/enum/calendar-view.enum.js +9 -9
  111. package/esm2015/lib/enum/document-email-report.enum.js +18 -18
  112. package/esm2015/lib/enum/domain-multiple-name.enum.js +13 -13
  113. package/esm2015/lib/enum/file-type.js +14 -14
  114. package/esm2015/lib/enum/files-upload-config-objects.js +3 -3
  115. package/esm2015/lib/enum/gauge-color.enum.js +10 -10
  116. package/esm2015/lib/enum/icon.enum.js +48 -44
  117. package/esm2015/lib/enum/internal-param.enum.js +38 -38
  118. package/esm2015/lib/enum/keyboard-code.enum.js +32 -32
  119. package/esm2015/lib/enum/language-code.enum.js +8 -8
  120. package/esm2015/lib/enum/month.enum.js +17 -17
  121. package/esm2015/lib/enum/read-write-access-config-names.enum.js +2 -2
  122. package/esm2015/lib/enum/table-name.enum.js +86 -86
  123. package/esm2015/lib/enum/tag-category.enum.js +22 -22
  124. package/esm2015/lib/enum/tags-component-config-names.js +2 -2
  125. package/esm2015/lib/enum/thumb-three-way-state.js +19 -19
  126. package/esm2015/lib/enum/tile-size-type.js +7 -7
  127. package/esm2015/lib/enum/time-period.enum.js +11 -11
  128. package/esm2015/lib/event/co-drag-event.js +2 -2
  129. package/esm2015/lib/event/co-drop-event.js +2 -2
  130. package/esm2015/lib/interface/key-value-pair.js +2 -2
  131. package/esm2015/lib/interface/operation-callback-simple-function.js +4 -4
  132. package/esm2015/lib/localization/localization.module.js +19 -19
  133. package/esm2015/lib/localization/localize.pipe.js +26 -26
  134. package/esm2015/lib/localization/localize.service.js +30 -30
  135. package/esm2015/lib/localization/translation.js +3 -3
  136. package/esm2015/lib/model/agenda-event-per-day.model.js +6 -6
  137. package/esm2015/lib/model/agenda-event.model.js +8 -8
  138. package/esm2015/lib/model/agenda-null-objects.js +11 -11
  139. package/esm2015/lib/model/constant/all-months.js +17 -17
  140. package/esm2015/lib/model/date-range.js +5 -5
  141. package/esm2015/lib/model/day.model.js +7 -7
  142. package/esm2015/lib/model/icon-svg.js +47 -43
  143. package/esm2015/lib/model/month.model.js +11 -11
  144. package/esm2015/lib/model/send-method.js +8 -8
  145. package/esm2015/lib/model/settings.js +4 -4
  146. package/esm2015/lib/model/tag-tree-item.bo.js +16 -16
  147. package/esm2015/lib/model/time-window.bo.js +26 -26
  148. package/esm2015/lib/model/tree-object.js +15 -15
  149. package/esm2015/lib/model/week.model.js +6 -6
  150. package/esm2015/lib/model/weekday.model.js +10 -10
  151. package/esm2015/lib/pipe/array-number.pipe.js +15 -15
  152. package/esm2015/lib/pipe/file-type-image.pipe.js +51 -51
  153. package/esm2015/lib/pipe/master-pipes.js +9 -9
  154. package/esm2015/lib/pipe/ucfirst.pipe.js +16 -16
  155. package/esm2015/lib/service/dictionary.service.js +76 -76
  156. package/esm2015/lib/service/drag-drop.service.js +365 -365
  157. package/esm2015/lib/service/icon-cache.service.js +51 -51
  158. package/esm2015/lib/service/options.service.js +48 -48
  159. package/esm2015/lib/service/shared-connector.service.js +433 -433
  160. package/esm2015/lib/service/shared.service.js +60 -60
  161. package/esm2015/lib/service/stock.service.js +110 -110
  162. package/esm2015/lib/utils/array-utils.js +202 -202
  163. package/esm2015/lib/utils/calendar.utils.js +68 -68
  164. package/esm2015/lib/utils/check-precision-and-scale-result.js +2 -2
  165. package/esm2015/lib/utils/check-within-stepped-bounds-result.js +2 -2
  166. package/esm2015/lib/utils/co-document-shared-field-logic.js +50 -50
  167. package/esm2015/lib/utils/date-utils.js +264 -264
  168. package/esm2015/lib/utils/enum-utils.js +128 -128
  169. package/esm2015/lib/utils/function/not-nill.function.js +5 -5
  170. package/esm2015/lib/utils/is-nill.function.js +5 -5
  171. package/esm2015/lib/utils/map-utils.js +41 -41
  172. package/esm2015/lib/utils/number-utils.js +390 -390
  173. package/esm2015/lib/utils/object-utils.js +278 -278
  174. package/esm2015/lib/utils/ref-code-utils.js +49 -49
  175. package/esm2015/lib/utils/string-utils.js +93 -93
  176. package/esm2015/public-api.js +31 -31
  177. package/fesm2015/colijnit-sharedcomponents.js +10411 -10335
  178. package/fesm2015/colijnit-sharedcomponents.js.map +1 -1
  179. package/lib/assets/dictionary/text.properties.d.ts +3 -3
  180. package/lib/businessobject/build-images-and-documentation-result.d.ts +5 -5
  181. package/lib/businessobject/co-document-right.bo.d.ts +6 -6
  182. package/lib/businessobject/drag-drop-container-element.d.ts +6 -6
  183. package/lib/businessobject/drag-drop-container.d.ts +6 -6
  184. package/lib/components/access/read-write-access.scss +25 -25
  185. package/lib/components/access/style/_layout.scss +23 -23
  186. package/lib/components/access/style/_material-definition.scss +12 -12
  187. package/lib/components/access/style/_theme.scss +4 -4
  188. package/lib/components/access/style/material.scss +4 -4
  189. package/lib/components/activity-list/activity-list.component.d.ts +33 -33
  190. package/lib/components/activity-list/activity-list.module.d.ts +2 -2
  191. package/lib/components/activity-list/style/_layout.scss +68 -68
  192. package/lib/components/activity-list/style/_theme.scss +4 -4
  193. package/lib/components/activity-list/style/material.scss +4 -4
  194. package/lib/components/app-file-dropzone/app-file-dropzone.component.d.ts +14 -14
  195. package/lib/components/app-file-dropzone/app-file-dropzone.module.d.ts +2 -2
  196. package/lib/components/app-file-dropzone/style/_layout.scss +61 -61
  197. package/lib/components/app-file-dropzone/style/_theme.scss +4 -4
  198. package/lib/components/app-file-dropzone/style/material.scss +4 -4
  199. package/lib/components/date-planning/component/agenda/agenda-base-view.component.d.ts +21 -21
  200. package/lib/components/date-planning/component/agenda/agenda-day-view.component.d.ts +7 -7
  201. package/lib/components/date-planning/component/agenda/agenda-event.component.d.ts +18 -18
  202. package/lib/components/date-planning/component/agenda/agenda-events.component.d.ts +13 -13
  203. package/lib/components/date-planning/component/agenda/agenda-half-hour-cell.component.d.ts +18 -18
  204. package/lib/components/date-planning/component/agenda/agenda-header.component.d.ts +48 -48
  205. package/lib/components/date-planning/component/agenda/agenda-hour-cell.component.d.ts +9 -9
  206. package/lib/components/date-planning/component/agenda/agenda-hour-view-labels.component.d.ts +8 -8
  207. package/lib/components/date-planning/component/agenda/agenda-hour-view.component.d.ts +7 -7
  208. package/lib/components/date-planning/component/agenda/agenda-month-view.component.d.ts +10 -10
  209. package/lib/components/date-planning/component/agenda/agenda-select-event.component.d.ts +12 -12
  210. package/lib/components/date-planning/component/agenda/agenda-view.component.d.ts +12 -12
  211. package/lib/components/date-planning/component/agenda/agenda-week-select-view.component.d.ts +10 -10
  212. package/lib/components/date-planning/component/agenda/agenda-week-view.component.d.ts +9 -9
  213. package/lib/components/date-planning/component/agenda/style/_layout.scss +443 -443
  214. package/lib/components/date-planning/component/agenda/style/_material-definition.scss +12 -12
  215. package/lib/components/date-planning/component/agenda/style/_theme.scss +7 -7
  216. package/lib/components/date-planning/component/agenda/style/material.scss +5 -5
  217. package/lib/components/date-planning/component/agenda/view-select.component.d.ts +11 -11
  218. package/lib/components/date-planning/component/calendar/calendar-all-months.component.d.ts +9 -9
  219. package/lib/components/date-planning/component/calendar/calendar-all-years.component.d.ts +9 -9
  220. package/lib/components/date-planning/component/calendar/calendar-header.component.d.ts +23 -23
  221. package/lib/components/date-planning/component/calendar/calendar-view.component.d.ts +31 -31
  222. package/lib/components/date-planning/component/calendar/calendar.component.d.ts +10 -10
  223. package/lib/components/date-planning/component/calendar/style/_layout.scss +167 -167
  224. package/lib/components/date-planning/component/calendar/style/_material-definition.scss +7 -7
  225. package/lib/components/date-planning/component/calendar/style/_theme.scss +7 -7
  226. package/lib/components/date-planning/component/calendar/style/material.scss +5 -5
  227. package/lib/components/date-planning/date-planning.component.d.ts +28 -28
  228. package/lib/components/date-planning/date-planning.module.d.ts +2 -2
  229. package/lib/components/date-planning/style/_layout.scss +45 -45
  230. package/lib/components/date-planning/style/_theme.scss +5 -5
  231. package/lib/components/date-planning/style/material.scss +7 -7
  232. package/lib/components/docsign/component/signature/signature.component.d.ts +16 -16
  233. package/lib/components/docsign/component/signature/style/_layout.scss +40 -40
  234. package/lib/components/docsign/component/signature/style/_material-definition.scss +11 -11
  235. package/lib/components/docsign/component/signature/style/_theme.scss +13 -13
  236. package/lib/components/docsign/component/signature/style/material.scss +4 -4
  237. package/lib/components/docsign/component/signatures/signatures.component.d.ts +12 -12
  238. package/lib/components/docsign/component/signatures/style/_layout.scss +13 -13
  239. package/lib/components/docsign/component/signatures/style/_material-definition.scss +1 -1
  240. package/lib/components/docsign/component/signatures/style/_theme.scss +4 -4
  241. package/lib/components/docsign/component/signatures/style/material.scss +5 -5
  242. package/lib/components/docsign/docsign.component.d.ts +94 -94
  243. package/lib/components/docsign/docsign.module.d.ts +2 -2
  244. package/lib/components/docsign/style/_layout.scss +40 -40
  245. package/lib/components/docsign/style/_material-definition.scss +12 -12
  246. package/lib/components/docsign/style/_theme.scss +12 -12
  247. package/lib/components/docsign/style/material.scss +15 -15
  248. package/lib/components/file-upload/file-upload.component.d.ts +42 -42
  249. package/lib/components/file-upload/file-upload.module.d.ts +2 -2
  250. package/lib/components/file-upload/style/_layout.scss +59 -59
  251. package/lib/components/file-upload/style/_material-definition.scss +2 -2
  252. package/lib/components/file-upload/style/_theme.scss +4 -4
  253. package/lib/components/file-upload/style/material.scss +4 -4
  254. package/lib/components/file-upload-popup/file-upload-popup.component.d.ts +75 -75
  255. package/lib/components/file-upload-popup/file-upload-popup.module.d.ts +2 -2
  256. package/lib/components/file-upload-popup/style/_layout.scss +48 -48
  257. package/lib/components/file-upload-popup/style/_material-definition.scss +2 -2
  258. package/lib/components/file-upload-popup/style/_theme.scss +5 -5
  259. package/lib/components/file-upload-popup/style/material.scss +4 -4
  260. package/lib/components/files-upload/components/base-file-upload.component.d.ts +98 -98
  261. package/lib/components/files-upload/components/drag-drop-container.component.d.ts +34 -34
  262. package/lib/components/files-upload/files-upload.component.d.ts +32 -32
  263. package/lib/components/files-upload/files-upload.module.d.ts +2 -2
  264. package/lib/components/files-upload/style/_layout.scss +49 -49
  265. package/lib/components/files-upload/style/_theme.scss +5 -5
  266. package/lib/components/files-upload/style/material.scss +4 -4
  267. package/lib/components/image-display/image-display.component.d.ts +14 -14
  268. package/lib/components/image-display/image-display.module.d.ts +2 -2
  269. package/lib/components/image-display/style/_layout.scss +56 -56
  270. package/lib/components/image-display/style/_material-definition.scss +4 -4
  271. package/lib/components/image-display/style/_theme.scss +6 -6
  272. package/lib/components/image-display/style/material.scss +3 -3
  273. package/lib/components/key-pad/key-pad.component.d.ts +38 -38
  274. package/lib/components/key-pad/key-pad.module.d.ts +2 -2
  275. package/lib/components/key-pad/style/_layout.scss +160 -160
  276. package/lib/components/key-pad/style/_material-definition.scss +19 -19
  277. package/lib/components/key-pad/style/_theme.scss +35 -35
  278. package/lib/components/key-pad/style/material.scss +4 -4
  279. package/lib/components/layout-switcher/layout-switcher.component.d.ts +16 -16
  280. package/lib/components/layout-switcher/layout-switcher.module.d.ts +2 -2
  281. package/lib/components/layout-switcher/style/_layout.scss +94 -94
  282. package/lib/components/layout-switcher/style/_material-definition.scss +16 -16
  283. package/lib/components/layout-switcher/style/_theme.scss +4 -4
  284. package/lib/components/layout-switcher/style/material.scss +6 -6
  285. package/lib/components/linear-gauge/co-linear-gauge.component.d.ts +11 -11
  286. package/lib/components/linear-gauge/co-linear-gauge.module.d.ts +2 -2
  287. package/lib/components/linear-gauge/style/_layout.scss +20 -20
  288. package/lib/components/linear-gauge/style/_material-definition.scss +8 -8
  289. package/lib/components/linear-gauge/style/_theme.scss +4 -4
  290. package/lib/components/linear-gauge/style/material.scss +6 -6
  291. package/lib/components/login/style/_layout.scss +57 -57
  292. package/lib/components/login/style/_material-definition.scss +23 -23
  293. package/lib/components/login/style/_theme.scss +7 -7
  294. package/lib/components/login/style/material.scss +4 -4
  295. package/lib/components/multi-property-toggler/multiple-property-toggler.component.d.ts +27 -27
  296. package/lib/components/multi-property-toggler/multiple-property-toggler.module.d.ts +2 -2
  297. package/lib/components/multi-property-toggler/style/_layout.scss +24 -24
  298. package/lib/components/multi-property-toggler/style/_theme.scss +4 -4
  299. package/lib/components/multi-property-toggler/style/material.scss +4 -4
  300. package/lib/components/screen-config-generator/style/_layout.scss +95 -95
  301. package/lib/components/screen-config-generator/style/_theme.scss +4 -4
  302. package/lib/components/screen-config-generator/style/material.scss +4 -4
  303. package/lib/components/send-method-dialog/components/layout-selection/layout-selection.component.d.ts +19 -19
  304. package/lib/components/send-method-dialog/components/layout-selection/layout-selection.module.d.ts +2 -2
  305. package/lib/components/send-method-dialog/components/layout-selection/style/_layout.scss +44 -44
  306. package/lib/components/send-method-dialog/components/layout-selection/style/_material-definition.scss +19 -19
  307. package/lib/components/send-method-dialog/components/layout-selection/style/_theme.scss +17 -17
  308. package/lib/components/send-method-dialog/components/layout-selection/style/material.scss +4 -4
  309. package/lib/components/send-method-dialog/components/printer-selection/printer-selection.component.d.ts +19 -19
  310. package/lib/components/send-method-dialog/components/printer-selection/printer-selection.module.d.ts +2 -2
  311. package/lib/components/send-method-dialog/components/printer-selection/style/_layout.scss +69 -69
  312. package/lib/components/send-method-dialog/components/printer-selection/style/_material-definition.scss +37 -37
  313. package/lib/components/send-method-dialog/components/printer-selection/style/_theme.scss +23 -23
  314. package/lib/components/send-method-dialog/components/printer-selection/style/material.scss +4 -4
  315. package/lib/components/send-method-dialog/components/send-method-email/send-method-email.component.d.ts +14 -14
  316. package/lib/components/send-method-dialog/components/send-method-email/send-method-email.module.d.ts +2 -2
  317. package/lib/components/send-method-dialog/components/send-method-email/style/_layout.scss +29 -29
  318. package/lib/components/send-method-dialog/components/send-method-email/style/_material-definition.scss +8 -8
  319. package/lib/components/send-method-dialog/components/send-method-email/style/_theme.scss +5 -5
  320. package/lib/components/send-method-dialog/components/send-method-email/style/material.scss +4 -4
  321. package/lib/components/send-method-dialog/components/send-method-pdf/send-method-pdf.component.d.ts +8 -8
  322. package/lib/components/send-method-dialog/components/send-method-pdf/send-method-pdf.module.d.ts +2 -2
  323. package/lib/components/send-method-dialog/components/send-method-pdf/style/_layout.scss +25 -25
  324. package/lib/components/send-method-dialog/components/send-method-pdf/style/_material-definition.scss +5 -5
  325. package/lib/components/send-method-dialog/components/send-method-pdf/style/_theme.scss +5 -5
  326. package/lib/components/send-method-dialog/components/send-method-pdf/style/material.scss +4 -4
  327. package/lib/components/send-method-dialog/components/send-method-printer/send-method-printer.component.d.ts +13 -13
  328. package/lib/components/send-method-dialog/components/send-method-printer/send-method-printer.module.d.ts +2 -2
  329. package/lib/components/send-method-dialog/components/send-method-printer/style/_layout.scss +30 -30
  330. package/lib/components/send-method-dialog/components/send-method-printer/style/_material-definition.scss +5 -5
  331. package/lib/components/send-method-dialog/components/send-method-printer/style/_theme.scss +5 -5
  332. package/lib/components/send-method-dialog/components/send-method-printer/style/material.scss +4 -4
  333. package/lib/components/send-method-dialog/components/signature-button/signature-button.component.d.ts +12 -12
  334. package/lib/components/send-method-dialog/components/signature-button/signature-button.module.d.ts +2 -2
  335. package/lib/components/send-method-dialog/components/signature-button/style/_layout.scss +28 -28
  336. package/lib/components/send-method-dialog/components/signature-button/style/_material-definition.scss +8 -8
  337. package/lib/components/send-method-dialog/components/signature-button/style/_theme.scss +4 -4
  338. package/lib/components/send-method-dialog/components/signature-button/style/material.scss +4 -4
  339. package/lib/components/send-method-dialog/model/email-address-viewmodel.d.ts +5 -5
  340. package/lib/components/send-method-dialog/send-method-dialog.component.d.ts +71 -71
  341. package/lib/components/send-method-dialog/send-method-dialog.module.d.ts +2 -2
  342. package/lib/components/send-method-dialog/send-method-params.interface.d.ts +13 -13
  343. package/lib/components/send-method-dialog/service/send-method.service.d.ts +23 -23
  344. package/lib/components/send-method-dialog/style/_layout.scss +165 -165
  345. package/lib/components/send-method-dialog/style/_material-definition.scss +48 -48
  346. package/lib/components/send-method-dialog/style/_theme.scss +33 -33
  347. package/lib/components/send-method-dialog/style/material.scss +10 -10
  348. package/lib/components/simple-tags/simple-tags.component.d.ts +31 -31
  349. package/lib/components/simple-tags/simple-tags.module.d.ts +2 -2
  350. package/lib/components/simple-tags/style/_layout.scss +272 -272
  351. package/lib/components/simple-tags/style/_material-definition.scss +39 -39
  352. package/lib/components/simple-tags/style/_theme.scss +4 -4
  353. package/lib/components/simple-tags/style/material.scss +4 -4
  354. package/lib/components/statusbar/statusbar-popup.component.d.ts +21 -21
  355. package/lib/components/statusbar/statusbar.component.d.ts +26 -26
  356. package/lib/components/statusbar/statusbar.module.d.ts +2 -2
  357. package/lib/components/statusbar/style/_layout.scss +70 -70
  358. package/lib/components/statusbar/style/_material-definition.scss +23 -23
  359. package/lib/components/statusbar/style/_theme.scss +13 -13
  360. package/lib/components/statusbar/style/material.scss +5 -5
  361. package/lib/components/stock/components/allocation-stock-history/allocation-stock-history.component.d.ts +9 -9
  362. package/lib/components/stock/components/order-commission-stock-history/order-commission-stock-history.component.d.ts +9 -9
  363. package/lib/components/stock/components/order-stock-history/order-stock-history.component.d.ts +9 -9
  364. package/lib/components/stock/components/order-stock-tab/order-stock-tab.component.d.ts +11 -11
  365. package/lib/components/stock/components/order-supply-stock-history/order-supply-stock-history.component.d.ts +9 -9
  366. package/lib/components/stock/components/order-tab/order-tab.component.d.ts +20 -20
  367. package/lib/components/stock/components/stock-history/stock-history.component.d.ts +13 -13
  368. package/lib/components/stock/components/stock-location/stock-location.component.d.ts +52 -50
  369. package/lib/components/stock/components/stock-prognose/stock-prognose.component.d.ts +11 -11
  370. package/lib/components/stock/components/stock-tab/stock-tab.component.d.ts +7 -7
  371. package/lib/components/stock/localization/translation.d.ts +69 -60
  372. package/lib/components/stock/stock-history-tabs/stock-history-tabs.component.d.ts +7 -7
  373. package/lib/components/stock/stock-information/stock-information.component.d.ts +9 -9
  374. package/lib/components/stock/stock-information-grid/stock-information-grid.component.d.ts +75 -75
  375. package/lib/components/stock/stock-tabs/stock-tabs.component.d.ts +56 -56
  376. package/lib/components/stock/stock-transfer/co-drop-down-list-fields.interface.d.ts +4 -4
  377. package/lib/components/stock/stock-transfer/stock-change-amount.component.d.ts +18 -18
  378. package/lib/components/stock/stock-transfer/stock-transfer.component.d.ts +38 -42
  379. package/lib/components/stock/stock.component.d.ts +64 -58
  380. package/lib/components/stock/stock.module.d.ts +2 -2
  381. package/lib/components/stock/style/_layout.scss +473 -286
  382. package/lib/components/stock/style/_material-definition.scss +28 -25
  383. package/lib/components/stock/style/_theme.scss +5 -5
  384. package/lib/components/stock/style/material.scss +4 -4
  385. package/lib/components/stock-statusbar/stock-statusbar.component.d.ts +4 -4
  386. package/lib/components/stock-statusbar/stock-statusbar.module.d.ts +2 -2
  387. package/lib/components/stock-statusbar/style/_layout.scss +24 -24
  388. package/lib/components/stock-statusbar/style/material.scss +4 -4
  389. package/lib/components/tab-bar/style/_layout.scss +83 -78
  390. package/lib/components/tab-bar/style/_material-definition.scss +6 -6
  391. package/lib/components/tab-bar/style/material.scss +4 -4
  392. package/lib/components/tab-bar/tab-bar.component.d.ts +21 -21
  393. package/lib/components/tab-bar/tab-bar.module.d.ts +2 -2
  394. package/lib/components/tab-bar/tab.interface.d.ts +5 -5
  395. package/lib/components/tags/component/style/_layout.scss +67 -67
  396. package/lib/components/tags/component/style/_material-definition.scss +1 -1
  397. package/lib/components/tags/component/style/_theme.scss +8 -8
  398. package/lib/components/tags/component/style/material.scss +3 -3
  399. package/lib/components/tags/component/tag-join-label/style/_layout.scss +97 -97
  400. package/lib/components/tags/component/tag-join-label/style/_material-definition.scss +4 -4
  401. package/lib/components/tags/component/tag-join-label/style/_theme.scss +8 -8
  402. package/lib/components/tags/component/tag-join-label/style/material.scss +3 -3
  403. package/lib/components/tile-renderer/style/_layout.scss +90 -90
  404. package/lib/components/tile-renderer/style/_theme.scss +4 -4
  405. package/lib/components/tile-renderer/style/material.scss +4 -4
  406. package/lib/components/tile-renderer/tile-render.component.d.ts +31 -31
  407. package/lib/components/tile-renderer/tile-render.module.d.ts +2 -2
  408. package/lib/decorator/input-boolean.decorator.d.ts +8 -8
  409. package/lib/enum/calendar-view.enum.d.ts +7 -7
  410. package/lib/enum/document-email-report.enum.d.ts +15 -15
  411. package/lib/enum/domain-multiple-name.enum.d.ts +10 -10
  412. package/lib/enum/file-type.d.ts +7 -7
  413. package/lib/enum/files-upload-config-objects.d.ts +22 -22
  414. package/lib/enum/gauge-color.enum.d.ts +8 -8
  415. package/lib/enum/icon.enum.d.ts +46 -42
  416. package/lib/enum/internal-param.enum.d.ts +34 -34
  417. package/lib/enum/keyboard-code.enum.d.ts +30 -30
  418. package/lib/enum/language-code.enum.d.ts +6 -6
  419. package/lib/enum/month.enum.d.ts +14 -14
  420. package/lib/enum/read-write-access-config-names.enum.d.ts +4 -4
  421. package/lib/enum/table-name.enum.d.ts +84 -84
  422. package/lib/enum/tag-category.enum.d.ts +19 -19
  423. package/lib/enum/tags-component-config-names.d.ts +4 -4
  424. package/lib/enum/thumb-three-way-state.d.ts +6 -6
  425. package/lib/enum/tile-size-type.d.ts +4 -4
  426. package/lib/enum/time-period.enum.d.ts +8 -8
  427. package/lib/event/co-drag-event.d.ts +5 -5
  428. package/lib/event/co-drop-event.d.ts +8 -8
  429. package/lib/interface/key-value-pair.d.ts +4 -4
  430. package/lib/interface/operation-callback-simple-function.d.ts +4 -4
  431. package/lib/localization/localization.module.d.ts +2 -2
  432. package/lib/localization/localize.pipe.d.ts +7 -7
  433. package/lib/localization/localize.service.d.ts +7 -7
  434. package/lib/localization/translation.d.ts +2 -2
  435. package/lib/model/agenda-event-per-day.model.d.ts +5 -5
  436. package/lib/model/agenda-event.model.d.ts +17 -17
  437. package/lib/model/agenda-null-objects.d.ts +10 -10
  438. package/lib/model/constant/all-months.d.ts +2 -2
  439. package/lib/model/date-range.d.ts +7 -7
  440. package/lib/model/day.model.d.ts +8 -8
  441. package/lib/model/icon-svg.d.ts +4 -4
  442. package/lib/model/month.model.d.ts +5 -5
  443. package/lib/model/send-method.d.ts +7 -7
  444. package/lib/model/settings.d.ts +3 -3
  445. package/lib/model/tag-tree-item.bo.d.ts +18 -18
  446. package/lib/model/time-window.bo.d.ts +13 -13
  447. package/lib/model/tree-object.d.ts +8 -8
  448. package/lib/model/week.model.d.ts +4 -4
  449. package/lib/model/weekday.model.d.ts +16 -16
  450. package/lib/pipe/array-number.pipe.d.ts +4 -4
  451. package/lib/pipe/file-type-image.pipe.d.ts +12 -12
  452. package/lib/pipe/master-pipes.d.ts +1 -1
  453. package/lib/pipe/ucfirst.pipe.d.ts +4 -4
  454. package/lib/service/dictionary.service.d.ts +21 -21
  455. package/lib/service/drag-drop.service.d.ts +86 -86
  456. package/lib/service/icon-cache.service.d.ts +18 -18
  457. package/lib/service/options.service.d.ts +13 -13
  458. package/lib/service/shared-connector.service.d.ts +55 -55
  459. package/lib/service/shared.service.d.ts +18 -18
  460. package/lib/service/stock.service.d.ts +41 -41
  461. package/lib/style/_mixin.scss +14 -14
  462. package/lib/style/_variables.scss +21 -21
  463. package/lib/style/sharedcomponents-globals.scss +10 -10
  464. package/lib/utils/array-utils.d.ts +63 -63
  465. package/lib/utils/calendar.utils.d.ts +10 -10
  466. package/lib/utils/check-precision-and-scale-result.d.ts +4 -4
  467. package/lib/utils/check-within-stepped-bounds-result.d.ts +8 -8
  468. package/lib/utils/co-document-shared-field-logic.d.ts +7 -7
  469. package/lib/utils/date-utils.d.ts +44 -44
  470. package/lib/utils/enum-utils.d.ts +31 -31
  471. package/lib/utils/function/not-nill.function.d.ts +1 -1
  472. package/lib/utils/is-nill.function.d.ts +1 -1
  473. package/lib/utils/map-utils.d.ts +16 -16
  474. package/lib/utils/number-utils.d.ts +125 -125
  475. package/lib/utils/object-utils.d.ts +40 -40
  476. package/lib/utils/ref-code-utils.d.ts +10 -10
  477. package/lib/utils/string-utils.d.ts +38 -38
  478. package/package.json +6 -6
  479. package/public-api.d.ts +27 -27
@@ -1,390 +1,390 @@
1
- import { ObjectUtils } from "./object-utils";
2
- import { ArrayUtils } from "./array-utils";
3
- import { isNill } from "./is-nill.function";
4
- import { notNill } from "./function/not-nill.function";
5
- // Static utility function holder related to numeric variable evaluations and operations.
6
- export class NumberUtils {
7
- // For user-typed number input; supports comma's as decimal delimiter.
8
- static ParseIntNumberInput(arg) {
9
- return NumberUtils.ParseInt(NumberUtils._NumberInputToNumberStr(arg));
10
- }
11
- // Parses given argument to an integer, using a native parseInt() function with a radix of 10. Returns NaN if parsing was not possible.
12
- static ParseInt(arg) {
13
- if (isNill(arg) || Array.isArray(arg)) {
14
- return undefined;
15
- }
16
- return parseInt(arg, 10);
17
- }
18
- // For user-typed number input; supports comma's as decimal delimiter.
19
- static ParseFloatNumberInput(arg, decimalPrecision = 2) {
20
- return NumberUtils.ParseFloat(NumberUtils._NumberInputToNumberStr(arg), decimalPrecision);
21
- }
22
- static ParseFloatNumberInputKeepPrecision(arg) {
23
- const correctedInputStr = NumberUtils._NumberInputToNumberStr(arg);
24
- const decimalPrecision = this.GetDecimalPlaces(correctedInputStr);
25
- return NumberUtils.ParseFloat(correctedInputStr, decimalPrecision);
26
- }
27
- /**
28
- * Returns given arg as a float number with given decimal precision, if possible. Returns NaN if parse conversion failed.
29
- *
30
- * @param {any} arg The argument to parse to a float
31
- * @param {number} decimalPrecision The number of decimals, or the precision, the parsed return float should have
32
- * @returns {number} NaN if not possible, else the parsed float value
33
- */
34
- static ParseFloat(arg, decimalPrecision = 2) {
35
- if (!ObjectUtils.AllExist(arg, decimalPrecision) || Array.isArray(arg)) {
36
- return NaN;
37
- }
38
- if (!NumberUtils.IsInteger(decimalPrecision) || decimalPrecision < 0) {
39
- decimalPrecision = 2;
40
- // toFixed() can only handle up until 20
41
- }
42
- else if (decimalPrecision > 20) {
43
- decimalPrecision = 20;
44
- }
45
- return parseFloat(parseFloat(arg).toFixed(decimalPrecision));
46
- }
47
- /**
48
- * Returns given arg as a float number with given decimal precision, if possible. Returns NaN if parse conversion failed.
49
- *
50
- * @param arg The argument to parse to a float
51
- * @returns {number} The argument as a float with its original decimal precision intact
52
- */
53
- static ParseFloatKeepPrecision(arg) {
54
- const decimalPrecision = this.GetDecimalPlaces(arg);
55
- return this.ParseFloat(arg, decimalPrecision);
56
- }
57
- /**
58
- * Returns the given argument as a number. Returns given defaultValue if conversion of argument was impossible.
59
- * @param arg
60
- * @param {number} [defaultValue = 0]
61
- * @returns {number}
62
- */
63
- static ParseNumberOrDefault(arg, defaultValue = 0) {
64
- if (Array.isArray(arg)) {
65
- return defaultValue;
66
- }
67
- if (!NumberUtils.IsNumber(arg)) {
68
- arg = parseFloat(arg);
69
- arg = isNaN(arg) ? defaultValue : arg;
70
- }
71
- return arg;
72
- }
73
- // Returns true iff given argument is an integer number. Returns false on non-numbers or numbers with significant decimals.
74
- static IsInteger(arg) {
75
- if (isNaN(arg) || Array.isArray(arg)) {
76
- return false;
77
- }
78
- const argAsFloat = parseFloat(arg);
79
- return ((argAsFloat | 0) === argAsFloat); // returns whether 'arg converted to an integer equals arg'
80
- }
81
- // Returns the number of decimal places of the given number. Returns 0 if no decimals whatsoever could be found on given arg.
82
- static GetDecimalPlaces(arg, maxAnswer = 1000) {
83
- const match = ("" + arg).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
84
- if (!match) {
85
- return 0;
86
- }
87
- let answer = Math.max(0,
88
- // number of digits right of decimal point.
89
- (match[1] ? match[1].length : 0)
90
- // adjust for scientific notation
91
- - (match[2] ? +match[2] : 0));
92
- if (answer > maxAnswer) {
93
- answer = maxAnswer;
94
- }
95
- return answer;
96
- }
97
- // Parses given numberInput to a number, or returns given defaultValue if parse not possible. Allows ',' char as decimal delimiter.
98
- static ParseNumberInputOrDefault(numberInput, defaultValue = 0) {
99
- return NumberUtils.ParseNumberOrDefault(NumberUtils._NumberInputToNumberStr(numberInput), defaultValue);
100
- }
101
- // Returns whether the type of given argument is 'number'.
102
- static IsNumber(arg) {
103
- return typeof arg === "number" && !isNaN(arg);
104
- }
105
- /**
106
- * Returns whether given arg is indeed not a number (it's NaN or it has another type than 'number')
107
- * Our exact copy of AS Flex'es isNaN(arg) function. Always use this method for copying Flex isNaN(..) occurences into TypeScript.
108
- * @param arg
109
- * @returns {boolean}
110
- * @constructor
111
- */
112
- static IsNaN(arg) {
113
- return isNaN(arg) || !NumberUtils.IsNumber(arg);
114
- }
115
- // Our copy of CoMath.NaN. Returns number, or substitute if NumberUtils.IsNaN(number) holds true.
116
- static NaN(number, substitute = 0) {
117
- return NumberUtils.IsNaN(number) ? substitute : number;
118
- }
119
- // Returns whether the value is parasable as a number.
120
- static IsParsableNumber(arg) {
121
- if (Array.isArray(arg)) {
122
- return false;
123
- }
124
- return !isNaN(parseFloat(arg));
125
- }
126
- static IsParsableNumberInput(numberInput) {
127
- return NumberUtils.IsParsableNumber(NumberUtils._NumberInputToNumberStr(numberInput));
128
- }
129
- /**
130
- * Returns whether given arg is parseable as a number, and whether the lengts of its number parse result is equal to its original length.
131
- * I.e. this function returns FALSE with given number-parsable strings, but that have non-numeric appendices, eg '2233ff'. That arg
132
- * IS number-parseable, but not a strict 'string number', the latter being what this method actually checks for.
133
- */
134
- static IsStringNumber(arg) {
135
- if (!NumberUtils.IsParsableNumber(arg)) {
136
- return false;
137
- }
138
- else {
139
- return arg.toString().length === parseFloat(arg).toString().length;
140
- }
141
- }
142
- static IsListOfNumbers(arg, separator = ",") {
143
- const nrs = arg.split(separator);
144
- if (nrs.length === 0) {
145
- return false;
146
- }
147
- return nrs.filter(s => NumberUtils.IsStringNumber(s)).length === nrs.length;
148
- }
149
- // Returns given argument as a string representation of a number parse, e.g. "1" for a number parse result of arg to 1.
150
- static ParseStringNumber(arg) {
151
- if (!this.IsStringNumber(arg)) {
152
- return NaN;
153
- }
154
- return NumberUtils.ParseFloatKeepPrecision(arg);
155
- }
156
- static ParseStringNumberDefault(arg, defaultValue = 0) {
157
- return NumberUtils.NaN(NumberUtils.ParseStringNumber(arg), defaultValue);
158
- }
159
- /**
160
- * Returns a random integer in range [lowerBound .. upperBound], an inclusive range. Returns NaN if not possible.
161
- * Given bounds are truncated first, before serving as the true lower- and upper bounds for the random int.
162
- */
163
- static RandomInt(lowerBoundInt, upperBoundInt) {
164
- if (!NumberUtils.IsNumber(lowerBoundInt) || !NumberUtils.IsNumber(upperBoundInt) || lowerBoundInt > upperBoundInt) {
165
- return NaN;
166
- }
167
- lowerBoundInt = Math.trunc(lowerBoundInt);
168
- upperBoundInt = Math.trunc(upperBoundInt);
169
- if (lowerBoundInt === upperBoundInt) {
170
- return lowerBoundInt;
171
- }
172
- const delta = upperBoundInt - lowerBoundInt;
173
- return (Math.round(Math.random() * delta) + lowerBoundInt);
174
- }
175
- // Adds thousands comma's to given value, E.g. '1000' to '1,000'. Returns empty string if value was undefined.
176
- static AddThousandsCommasTo(value) {
177
- if (isNill(value)) {
178
- return "";
179
- }
180
- return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
181
- }
182
- /**
183
- * Function used to check wether a given number is composed of another number, power-of-two wise.
184
- * Example usage: NumberUtils.NumIsComposedOf(articleListObject.publication, ArticlePublication.Selector).
185
- * This would return whether or not that articleListObject was publicated for selector or not, where articleListObject.publication
186
- * was possibly a 'COMPOSITE that was made out of (including)' ArticlePublication.Selector.
187
- */
188
- static NumIsComposedOfOtherPowTwoNum(bigNrToCheck, powTwoNumItShouldBeComposedOf) {
189
- if (!bigNrToCheck) {
190
- return false;
191
- }
192
- else if (!powTwoNumItShouldBeComposedOf) {
193
- return true;
194
- }
195
- else {
196
- return ((bigNrToCheck & powTwoNumItShouldBeComposedOf) === powTwoNumItShouldBeComposedOf);
197
- }
198
- }
199
- /**
200
- * Returns given nr, or the given default number (default 0) if the nr number was undefined or otherwise not a number.
201
- * Same as CoMath.NaN from AS code (used as its substitute in transaction logic)
202
- * @param nr
203
- * @param defaultNr
204
- * @returns {number}
205
- */
206
- static NrOrDefault(nr, defaultNr = 0) {
207
- if (notNill(nr) && NumberUtils.IsNumber(nr)) {
208
- return nr;
209
- }
210
- else {
211
- return defaultNr;
212
- }
213
- }
214
- /**
215
- * Returns whether given nrToCheck is within the given precision and scale limits. Precision and scale, here, are Oracle DB terms.
216
- * This function can thus be used to check whether the given number is safe to send to the 'database' beforehand, if we know the
217
- * precision and scale of the number in the db declaration.
218
- *
219
- * I.e. A number declared in the Oracle DB as number(5, 2) has a precision of 5 and a scale of 2.
220
- *
221
- * @param {number} nrToCheck
222
- * @param {number} precision The number of significant digits, including possibly negative scale. E.g. 3 in '123' and 5 in '51.123'
223
- * @param {number} [scale = 0] The number of significant digits AFTER the decimal point. E.g. 1 in 5432.1 and 3 in 54000.003
224
- * @returns {CheckPrecisionAndScaleResult} Whether given nrToCheck is ok for given precision and scale, and if not, the
225
- * nearest number that IS ok for those constraints.
226
- */
227
- static CheckPrecisionAndScale(nrToCheck, precision, scale = 0) {
228
- // let's say any undefined number is checked OK, and all numbers are checked OK for an undefined precision
229
- if (!ObjectUtils.AllExist(nrToCheck, precision, scale)) {
230
- return { isOk: true, nearestOkNr: NaN };
231
- }
232
- // no number can have 0 or less than 0 significant digits, in our universe
233
- if (precision < 1 || precision - scale < 1) {
234
- return { isOk: false, nearestOkNr: NaN };
235
- }
236
- // begin check
237
- const isNegative = (nrToCheck < 0);
238
- const nrParts = nrToCheck.toString().split(".");
239
- // remove minus sign if negative
240
- if (isNegative) {
241
- nrParts[0] = nrParts[0].slice(1);
242
- }
243
- const numCountBeforeDot = nrParts[0].length;
244
- const allowedNumCountBeforeDot = precision - scale;
245
- if (numCountBeforeDot <= allowedNumCountBeforeDot) {
246
- return { isOk: true, nearestOkNr: nrToCheck };
247
- }
248
- else {
249
- // cut a part from the "before decimal number" so that the number is not too big anymore
250
- const numCountToRemove = numCountBeforeDot - allowedNumCountBeforeDot;
251
- // remove the right-most numbers before the decimal dot
252
- nrParts[0] = nrParts[0].slice(0, -1 * numCountToRemove);
253
- // add minus sign again if it was negative
254
- if (isNegative) {
255
- nrParts[0] = "-" + nrParts[0];
256
- }
257
- // build and return composite number again
258
- let nearestOkNr;
259
- if (nrParts[1]) {
260
- nearestOkNr = Number(nrParts[0] + "." + nrParts[1]);
261
- }
262
- else {
263
- nearestOkNr = Number(nrParts[0]);
264
- }
265
- return { isOk: false, nearestOkNr: nearestOkNr };
266
- }
267
- }
268
- /**
269
- * Returns whether given x is OK within the given min, max and step boundaries, where it should hold that nrToCheck = min + N * step,
270
- * with N integer or 0.
271
- * @param {number} nrToCheck Number to check whether it's within the given bounds
272
- * @param min Inclusive
273
- * @param max Inclusive
274
- * @param stepSize
275
- * @returns {CheckWithinSteppedBounds} Returns remainder of undefined when nrToCheck was OUTSIDE [min, max], else full result object.
276
- */
277
- static CheckWithinSteppedBounds(nrToCheck, min, max, stepSize = 1) {
278
- if (nrToCheck < min || nrToCheck > max) {
279
- return { isOk: false, remainder: undefined };
280
- }
281
- // we're in [min, max], but still check if nrToCheck = min + N * step holds (for N integer or 0)
282
- let remainder = (nrToCheck - min) % stepSize;
283
- // correct float for largest precision amongst input numbers
284
- remainder = NumberUtils.ParseFloat(remainder, NumberUtils._GetLargestDecimalPrecisionOf(nrToCheck, min, stepSize));
285
- return { isOk: (remainder === 0), remainder: remainder };
286
- }
287
- /**
288
- * Finds the number closest to the originalNumber, that adheres to the given bounds. That is, for which it holds that
289
- * nr = min + N * step with N integer or 0.
290
- * @param {number} originalNr Find closest answer to this number
291
- * @param min Inclusive
292
- * @param max Inclusive
293
- * @param stepSize
294
- * @returns {boolean} The closest OK number for bounds.
295
- */
296
- static GetNearestNumberWithinSteppedBounds(originalNr, min, max, stepSize = 1) {
297
- if (originalNr < min) {
298
- return min;
299
- }
300
- else if (originalNr > max) {
301
- return NumberUtils.GetTrueSteppedBoundsMax(min, max, stepSize);
302
- }
303
- const boundsCheck = NumberUtils.CheckWithinSteppedBounds(originalNr, min, max, stepSize);
304
- if (boundsCheck.isOk) {
305
- return originalNr;
306
- }
307
- let answer;
308
- const remainder = boundsCheck.remainder;
309
- if (remainder) {
310
- // round up or down?
311
- if ((remainder / stepSize) < 0.5) {
312
- // round down, but not below min
313
- answer = (originalNr - remainder >= min ? originalNr - remainder : min);
314
- }
315
- else {
316
- // round up, but not above max
317
- answer = (originalNr + stepSize - remainder <= max ? originalNr + stepSize - remainder :
318
- NumberUtils.GetTrueSteppedBoundsMax(min, max, stepSize));
319
- }
320
- }
321
- else {
322
- // is this real life, why wasn't our stepped bounds check OK?
323
- answer = originalNr;
324
- }
325
- // 'correct' float errors
326
- answer = NumberUtils.ParseFloat(answer, NumberUtils._GetLargestDecimalPrecisionOf(originalNr, min, max, stepSize));
327
- return answer;
328
- }
329
- /**
330
- * Returns the true maximum allowed value for the given "stepped bounds": min, stepSize and max, for which it holds that each allowed
331
- * value Y = min + stepSize * N, for any INTEGER or 0 N where it also holds, of course, that Y <= max.
332
- * @param min
333
- * @param max
334
- * @param stepSize
335
- */
336
- static GetTrueSteppedBoundsMax(min, max, stepSize = 1) {
337
- // solve max integer X in formula min + X * step <= max, and return min + X * stepSize for that X
338
- const maxSteps = Math.floor((max - min) / stepSize);
339
- // 'correct' float errors
340
- return NumberUtils.ParseFloat(min + maxSteps * stepSize, NumberUtils._GetLargestDecimalPrecisionOf(min, min, max));
341
- }
342
- // Returns the nearest number, relative to the given originalNr, that is within the given [min, max] inclusive bounds.
343
- static GetNearestNumberWithinBounds(originalNr, min, max) {
344
- let answer = originalNr;
345
- if (originalNr < min) {
346
- answer = min;
347
- }
348
- else if (originalNr > max) {
349
- answer = max;
350
- }
351
- return answer;
352
- }
353
- // Returns the string representation of given number. If it's not a number, returns the empty string.
354
- static ToString(nr) {
355
- if (!NumberUtils.IsNaN(nr)) {
356
- return "" + nr;
357
- }
358
- else {
359
- return "";
360
- }
361
- }
362
- static DecimalsToStepIncrement(numberOfDecimals) {
363
- return Math.pow(10, -1 * numberOfDecimals);
364
- }
365
- static Round(value, decimals) {
366
- const factor = Math.pow(10, decimals);
367
- return Math.round(value * factor) / factor;
368
- }
369
- // @returns The inclusive max value
370
- static PrecisionScaleToMaxValue(precision, scale) {
371
- const oneStep = this.DecimalsToStepIncrement(scale);
372
- const maxExclusive = Math.pow(10, precision - scale);
373
- return maxExclusive - oneStep;
374
- }
375
- // @returns the difference between given 2 numbers
376
- static DifferenceBetweenNumbers(numberA, numberB) {
377
- return Math.abs(numberA - numberB);
378
- }
379
- static _GetLargestDecimalPrecisionOf(...args) {
380
- const result = ArrayUtils.GetMaxCalculatedValue(args, (arg) => {
381
- return NumberUtils.GetDecimalPlaces(arg);
382
- });
383
- return result;
384
- }
385
- // Returns given number input as a number that's useable by Javascript. Allows for incoming ',' decimal delimiter.
386
- static _NumberInputToNumberStr(numberInput) {
387
- return (numberInput + "").replace(",", ".");
388
- }
389
- }
390
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibnVtYmVyLXV0aWxzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvc2hhcmVkY29tcG9uZW50cy9zcmMvbGliL3V0aWxzL251bWJlci11dGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUMsV0FBVyxFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFFM0MsT0FBTyxFQUFDLFVBQVUsRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUV6QyxPQUFPLEVBQUMsTUFBTSxFQUFDLE1BQU0sb0JBQW9CLENBQUM7QUFDMUMsT0FBTyxFQUFDLE9BQU8sRUFBQyxNQUFNLDhCQUE4QixDQUFDO0FBRXJELHlGQUF5RjtBQUN6RixNQUFNLE9BQU8sV0FBVztJQUNwQixzRUFBc0U7SUFDL0QsTUFBTSxDQUFDLG1CQUFtQixDQUFDLEdBQVE7UUFDdEMsT0FBTyxXQUFXLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyx1QkFBdUIsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQzFFLENBQUM7SUFFRCx1SUFBdUk7SUFDaEksTUFBTSxDQUFDLFFBQVEsQ0FBQyxHQUFRO1FBQzNCLElBQUksTUFBTSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUU7WUFDbkMsT0FBTyxTQUFTLENBQUM7U0FDcEI7UUFFRCxPQUFPLFFBQVEsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDN0IsQ0FBQztJQUVELHNFQUFzRTtJQUMvRCxNQUFNLENBQUMscUJBQXFCLENBQUMsR0FBUSxFQUFFLG1CQUEyQixDQUFDO1FBQ3RFLE9BQU8sV0FBVyxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsdUJBQXVCLENBQUMsR0FBRyxDQUFDLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztJQUM5RixDQUFDO0lBRU0sTUFBTSxDQUFDLGtDQUFrQyxDQUFDLEdBQVE7UUFDckQsTUFBTSxpQkFBaUIs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QUMsQ0FBQztRQUM1RCxNQUFNLFlBQVksR0FBVyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxTQUFTLEdBQUcsS0FBSyxDQUFDLENBQUM7UUFDN0QsT0FBTyxZQUFZLEdBQUcsT0FBTyxDQUFDO0lBQ2xDLENBQUM7SUFFRCxrREFBa0Q7SUFDM0MsTUFBTSxDQUFDLHdCQUF3QixDQUFDLE9BQWUsRUFBRSxPQUFlO1FBQ25FLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDLENBQUM7SUFDdkMsQ0FBQztJQUVPLE1BQU0sQ0FBQyw2QkFBNkIsQ0FBQyxHQUFHLElBQWM7UUFDMUQsTUFBTSxNQUFNLEdBQUcsVUFBVSxDQUFDLHFCQUFxQixDQUFDLElBQUksRUFBRSxDQUFDLEdBQVcsRUFBRSxFQUFFO1lBQ2xFLE9BQU8sV0FBVyxDQUFDLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzdDLENBQUMsQ0FBQyxDQUFDO1FBQ0gsT0FBTyxNQUFNLENBQUM7SUFDbEIsQ0FBQztJQUVELGtIQUFrSDtJQUMxRyxNQUFNLENBQUMsdUJBQXVCLENBQUMsV0FBbUI7UUFDdEQsT0FBTyxDQUFDLFdBQVcsR0FBRyxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ2hELENBQUM7Q0FDSiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7T2JqZWN0VXRpbHN9IGZyb20gXCIuL29iamVjdC11dGlsc1wiO1xyXG5pbXBvcnQge0NoZWNrV2l0aGluU3RlcHBlZEJvdW5kc1Jlc3VsdH0gZnJvbSBcIi4vY2hlY2std2l0aGluLXN0ZXBwZWQtYm91bmRzLXJlc3VsdFwiO1xyXG5pbXBvcnQge0FycmF5VXRpbHN9IGZyb20gXCIuL2FycmF5LXV0aWxzXCI7XHJcbmltcG9ydCB7Q2hlY2tQcmVjaXNpb25BbmRTY2FsZVJlc3VsdH0gZnJvbSBcIi4vY2hlY2stcHJlY2lzaW9uLWFuZC1zY2FsZS1yZXN1bHRcIjtcclxuaW1wb3J0IHtpc05pbGx9IGZyb20gXCIuL2lzLW5pbGwuZnVuY3Rpb25cIjtcclxuaW1wb3J0IHtub3ROaWxsfSBmcm9tIFwiLi9mdW5jdGlvbi9ub3QtbmlsbC5mdW5jdGlvblwiO1xyXG5cclxuLy8gU3RhdGljIHV0aWxpdHkgZnVuY3Rpb24gaG9sZGVyIHJlbGF0ZWQgdG8gbnVtZXJpYyB2YXJpYWJsZSBldmFsdWF0aW9ucyBhbmQgb3BlcmF0aW9ucy5cclxuZXhwb3J0IGNsYXNzIE51bWJlclV0aWxzIHtcclxuICAgIC8vIEZvciB1c2VyLXR5cGVkIG51bWJlciBpbnB1dDsgc3VwcG9ydHMgY29tbWEncyBhcyBkZWNpbWFsIGRlbGltaXRlci5cclxuICAgIHB1YmxpYyBzdGF0aWMgUGFyc2VJbnROdW1iZXJJbnB1dChhcmc6IGFueSk6IG51bWJlciB7XHJcbiAgICAgICAgcmV0dXJuIE51bWJlclV0aWxzLlBhcnNlSW50KE51bWJlclV0aWxzLl9OdW1iZXJJbnB1dFRvTnVtYmVyU3RyKGFyZykpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFBhcnNlcyBnaXZlbiBhcmd1bWVudCB0byBhbiBpbnRlZ2VyLCB1c2luZyBhIG5hdGl2ZSBwYXJzZUludCgpIGZ1bmN0aW9uIHdpdGggYSByYWRpeCBvZiAxMC4gUmV0dXJucyBOYU4gaWYgcGFyc2luZyB3YXMgbm90IHBvc3NpYmxlLlxyXG4gICAgcHVibGljIHN0YXRpYyBQYXJzZUludChhcmc6IGFueSk6IG51bWJlciB7XHJcbiAgICAgICAgaWYgKGlzTmlsbChhcmcpIHx8IEFycmF5LmlzQXJyYXkoYXJnKSkge1xyXG4gICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIHBhcnNlSW50KGFyZywgMTApO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIEZvciB1c2VyLXR5cGVkIG51bWJlciBpbnB1dDsgc3VwcG9ydHMgY29tbWEncyBhcyBkZWNpbWFsIGRlbGltaXRlci5cclxuICAgIHB1YmxpYyBzdGF0aWMgUGFyc2VGbG9hdE51bWJlcklucHV0KGFyZzogYW55LCBkZWNpbWFsUHJlY2lzaW9uOiBudW1iZXIgPSAyKTogbnVtYmVyIHtcclxuICAgICAgICByZXR1cm4gTnVtYmVyVXRpbHMuUGFyc2VGbG9hdChOdW1iZXJVdGlscy5fTnVtYmVySW5wdXRUb051bWJlclN0cihhcmcpLCBkZWNpbWFsUHJlY2lzaW9uKTtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgc3RhdGljIFBhcnNlRmxvYXROdW1iZXJJbnB1dEtlZXBQcmVjaXNpb24oYXJnOiBhbnkpOiBudW1iZXIge1xyXG4gICAgICAgIGNvbnN0IGNvcnJlY3RlZElucHV0U3RyOiBzdHJpbmcgPSBOdW1iZXJVdGlscy5fTnVtYmVySW5wdXRUb051bWJlclN0cihhcmcpO1xyXG4gICAgICAgIGNvbnN0IGRlY2ltYWxQcmVjaXNpb246IG51bWJlciA9IHRoaXMuR2V0RGVjaW1hbFBsYWNlcyhjb3JyZWN0ZWRJbnB1dFN0cik7XHJcbiAgICAgICAgcmV0dXJuIE51bWJlclV0aWxzLlBhcnNlRmxvYXQoY29ycmVjdGVkSW5wdXRTdHIsIGRlY2ltYWxQcmVjaXNpb24pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmV0dXJucyBnaXZlbiBhcmcgYXMgYSBmbG9hdCBudW1iZXIgd2l0aCBnaXZlbiBkZWNpbWFsIHByZWNpc2lvbiwgaWYgcG9zc2libGUuIFJldHVybnMgTmFOIGlmIHBhcnNlIGNvbnZlcnNpb24gZmFpbGVkLlxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7YW55fSBhcmcgVGhlIGFyZ3VtZW50IHRvIHBhcnNlIHRvIGEgZmxvYXRcclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBkZWNpbWFsUHJlY2lzaW9uIFRoZSBudW1iZXIgb2YgZGVjaW1hbHMsIG9yIHRoZSBwcmVjaXNpb24sIHRoZSBwYXJzZWQgcmV0dXJuIGZsb2F0IHNob3VsZCBoYXZlXHJcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBOYU4gaWYgbm90IHBvc3NpYmxlLCBlbHNlIHRoZSBwYXJzZWQgZmxvYXQgdmFsdWVcclxuICAgICAqL1xyXG4gICAgcHVibGljIHN0YXRpYyBQYXJzZUZsb2F0KGFyZzogYW55LCBkZWNpbWFsUHJlY2lzaW9uOiBudW1iZXIgPSAyKTogbnVtYmVyIHtcclxuICAgICAgICBpZiAoIU9iamVjdFV0aWxzLkFsbEV4aXN0KGFyZywgZGVjaW1hbFByZWNpc2lvbikgfHwgQXJyYXkuaXNBcnJheShhcmcpKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBOYU47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoIU51bWJlclV0aWxzLklzSW50ZWdlcihkZWNpbWFsUHJlY2lzaW9uKSB8fCBkZWNpbWFsUHJlY2lzaW9uIDwgMCkge1xyXG4gICAgICAgICAgICBkZWNpbWFsUHJlY2lzaW9uID0gMjtcclxuICAgICAgICAgICAgLy8gdG9GaXhlZCgpIGNhbiBvbmx5IGhhbmRsZSB1cCB1bnRpbCAyMFxyXG4gICAgICAgIH0gZWxzZSBpZiAoZGVjaW1hbFByZWNpc2lvbiA+IDIwKSB7XHJcbiAgICAgICAgICAgIGRlY2ltYWxQcmVjaXNpb24gPSAyMDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBwYXJzZUZsb2F0KHBhcnNlRmxvYXQoYXJnKS50b0ZpeGVkKGRlY2ltYWxQcmVjaXNpb24pKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFJldHVybnMgZ2l2ZW4gYXJnIGFzIGEgZmxvYXQgbnVtYmVyIHdpdGggZ2l2ZW4gZGVjaW1hbCBwcmVjaXNpb24sIGlmIHBvc3NpYmxlLiBSZXR1cm5zIE5hTiBpZiBwYXJzZSBjb252ZXJzaW9uIGZhaWxlZC5cclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0gYXJnIFRoZSBhcmd1bWVudCB0byBwYXJzZSB0byBhIGZsb2F0XHJcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBUaGUgYXJndW1lbnQgYXMgYSBmbG9hdCB3aXRoIGl0cyBvcmlnaW5hbCBkZWNpbWFsIHByZWNpc2lvbiBpbnRhY3RcclxuICAgICAqL1xyXG4gICAgcHVibGljIHN0YXRpYyBQYXJzZUZsb2F0S2VlcFByZWNpc2lvbihhcmc6IGFueSk6IG51bWJlciB7XHJcbiAgICAgICAgY29uc3QgZGVjaW1hbFByZWNpc2lvbjogbnVtYmVyID0gdGhpcy5HZXREZWNpbWFsUGxhY2VzKGFyZyk7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuUGFyc2VGbG9hdChhcmcsIGRlY2ltYWxQcmVjaXNpb24pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmV0dXJucyB0aGUgZ2l2ZW4gYXJndW1lbnQgYXMgYSBudW1iZXIuIFJldHVybnMgZ2l2ZW4gZGVmYXVsdFZhbHVlIGlmIGNvbnZlcnNpb24gb2YgYXJndW1lbnQgd2FzIGltcG9zc2libGUuXHJcbiAgICAgKiBAcGFyYW0gYXJnXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2RlZmF1bHRWYWx1ZSA9IDBdXHJcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc3RhdGljIFBhcnNlTnVtYmVyT3JEZWZhdWx0KGFyZzogYW55LCBkZWZhdWx0VmFsdWU6IG51bWJlciA9IDApOiBudW1iZXIge1xyXG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KGFyZykpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGRlZmF1bHRWYWx1ZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICghTnVtYmVyVXRpbHMuSXNOdW1iZXIoYXJnKSkge1xyXG4gICAgICAgICAgICBhcmcgPSBwYXJzZUZsb2F0KGFyZyk7XHJcbiAgICAgICAgICAgIGFyZyA9IGlzTmFOKGFyZykgPyBkZWZhdWx0VmFsdWUgOiBhcmc7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBhcmc7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gUmV0dXJucyB0cnVlIGlmZiBnaXZlbiBhcmd1bWVudCBpcyBhbiBpbnRlZ2VyIG51bWJlci4gUmV0dXJucyBmYWxzZSBvbiBub24tbnVtYmVycyBvciBudW1iZXJzIHdpdGggc2lnbmlmaWNhbnQgZGVjaW1hbHMuXHJcbiAgICBwdWJsaWMgc3RhdGljIElzSW50ZWdlcihhcmc6IGFueSk6IGJvb2xlYW4ge1xyXG4gICAgICAgIGlmIChpc05hTihhcmcpIHx8IEFycmF5LmlzQXJyYXkoYXJnKSkge1xyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGNvbnN0IGFyZ0FzRmxvYXQ6IG51bWJlciA9IHBhcnNlRmxvYXQoYXJnKTtcclxuICAgICAgICByZXR1cm4gKChhcmdBc0Zsb2F0IHwgMCkgPT09IGFyZ0FzRmxvYXQpOyAvLyByZXR1cm5zIHdoZXRoZXIgJ2FyZyBjb252ZXJ0ZWQgdG8gYW4gaW50ZWdlciBlcXVhbHMgYXJnJ1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFJldHVybnMgdGhlIG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyBvZiB0aGUgZ2l2ZW4gbnVtYmVyLiBSZXR1cm5zIDAgaWYgbm8gZGVjaW1hbHMgd2hhdHNvZXZlciBjb3VsZCBiZSBmb3VuZCBvbiBnaXZlbiBhcmcuXHJcbiAgICBwdWJsaWMgc3RhdGljIEdldERlY2ltYWxQbGFjZXMoYXJnOiBhbnksIG1heEFuc3dlcjogbnVtYmVyID0gMTAwMCk6IG51bWJlciB7XHJcbiAgICAgICAgY29uc3QgbWF0Y2g6IFJlZ0V4cE1hdGNoQXJyYXkgPSAoXCJcIiArIGFyZykubWF0Y2goLyg/OlxcLihcXGQrKSk/KD86W2VFXShbKy1dP1xcZCspKT8kLyk7XHJcbiAgICAgICAgaWYgKCFtYXRjaCkge1xyXG4gICAgICAgICAgICByZXR1cm4gMDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGxldCBhbnN3ZXI6IG51bWJlciA9IE1hdGgubWF4KDAsXHJcbiAgICAgICAgICAgIC8vIG51bWJlciBvZiBkaWdpdHMgcmlnaHQgb2YgZGVjaW1hbCBwb2ludC5cclxuICAgICAgICAgICAgKG1hdGNoWzFdID8gbWF0Y2hbMV0ubGVuZ3RoIDogMClcclxuICAgICAgICAgICAgLy8gYWRqdXN0IGZvciBzY2llbnRpZmljIG5vdGF0aW9uXHJcbiAgICAgICAgICAgIC0gKG1hdGNoWzJdID8gK21hdGNoWzJdIDogMCkpO1xyXG5cclxuICAgICAgICBpZiAoYW5zd2VyID4gbWF4QW5zd2VyKSB7XHJcbiAgICAgICAgICAgIGFuc3dlciA9IG1heEFuc3dlcjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBhbnN3ZXI7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gUGFyc2VzIGdpdmVuIG51bWJlcklucHV0IHRvIGEgbnVtYmVyLCBvciByZXR1cm5zIGdpdmVuIGRlZmF1bHRWYWx1ZSBpZiBwYXJzZSBub3QgcG9zc2libGUuIEFsbG93cyAnLCcgY2hhciBhcyBkZWNpbWFsIGRlbGltaXRlci5cclxuICAgIHB1YmxpYyBzdGF0aWMgUGFyc2VOdW1iZXJJbnB1dE9yRGVmYXVsdChudW1iZXJJbnB1dDogYW55LCBkZWZhdWx0VmFsdWU6IG51bWJlciA9IDApOiBudW1iZXIge1xyXG4gICAgICAgIHJldHVybiBOdW1iZXJVdGlscy5QYXJzZU51bWJlck9yRGVmYXVsdChOdW1iZXJVdGlscy5fTnVtYmVySW5wdXRUb051bWJlclN0cihudW1iZXJJbnB1dCksIGRlZmF1bHRWYWx1ZSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gUmV0dXJucyB3aGV0aGVyIHRoZSB0eXBlIG9mIGdpdmVuIGFyZ3VtZW50IGlzICdudW1iZXInLlxyXG4gICAgcHVibGljIHN0YXRpYyBJc051bWJlcihhcmc6IGFueSk6IGJvb2xlYW4ge1xyXG4gICAgICAgIHJldHVybiB0eXBlb2YgYXJnID09PSBcIm51bWJlclwiICYmICFpc05hTihhcmcpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmV0dXJucyB3aGV0aGVyIGdpdmVuIGFyZyBpcyBpbmRlZWQgbm90IGEgbnVtYmVyIChpdCdzIE5hTiBvciBpdCBoYXMgYW5vdGhlciB0eXBlIHRoYW4gJ251bWJlcicpXHJcbiAgICAgKiBPdXIgZXhhY3QgY29weSBvZiBBUyBGbGV4J2VzIGlzTmFOKGFyZykgZnVuY3Rpb24uIEFsd2F5cyB1c2UgdGhpcyBtZXRob2QgZm9yIGNvcHlpbmcgRmxleCBpc05hTiguLikgb2NjdXJlbmNlcyBpbnRvIFR5cGVTY3JpcHQuXHJcbiAgICAgKiBAcGFyYW0gYXJnXHJcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cclxuICAgICAqIEBjb25zdHJ1Y3RvclxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc3RhdGljIElzTmFOKGFyZzogYW55KTogYm9vbGVhbiB7XHJcbiAgICAgICAgcmV0dXJuIGlzTmFOKGFyZykgfHwgIU51bWJlclV0aWxzLklzTnVtYmVyKGFyZyk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gT3VyIGNvcHkgb2YgQ29NYXRoLk5hTi4gUmV0dXJucyBudW1iZXIsIG9yIHN1YnN0aXR1dGUgaWYgTnVtYmVyVXRpbHMuSXNOYU4obnVtYmVyKSBob2xkcyB0cnVlLlxyXG4gICAgcHVibGljIHN0YXRpYyBOYU4obnVtYmVyOiBhbnksIHN1YnN0aXR1dGU6IG51bWJlciA9IDApOiBudW1iZXIge1xyXG4gICAgICAgIHJldHVybiBOdW1iZXJVdGlscy5Jc05hTihudW1iZXIpID8gc3Vic3RpdHV0ZSA6IG51bWJlcjtcclxuICAgIH1cclxuXHJcbiAgICAvLyBSZXR1cm5zIHdoZXRoZXIgdGhlIHZhbHVlIGlzIHBhcmFzYWJsZSBhcyBhIG51bWJlci5cclxuICAgIHB1YmxpYyBzdGF0aWMgSXNQYXJzYWJsZU51bWJlcihhcmc6IGFueSk6IGJvb2xlYW4ge1xyXG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KGFyZykpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuICFpc05hTihwYXJzZUZsb2F0KGFyZykpO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBzdGF0aWMgSXNQYXJzYWJsZU51bWJlcklucHV0KG51bWJlcklucHV0OiBhbnkpOiBib29sZWFuIHtcclxuICAgICAgICByZXR1cm4gTnVtYmVyVXRpbHMuSXNQYXJzYWJsZU51bWJlcihOdW1iZXJVdGlscy5fTnVtYmVySW5wdXRUb051bWJlclN0cihudW1iZXJJbnB1dCkpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmV0dXJucyB3aGV0aGVyIGdpdmVuIGFyZyBpcyBwYXJzZWFibGUgYXMgYSBudW1iZXIsIGFuZCB3aGV0aGVyIHRoZSBsZW5ndHMgb2YgaXRzIG51bWJlciBwYXJzZSByZXN1bHQgaXMgZXF1YWwgdG8gaXRzIG9yaWdpbmFsIGxlbmd0aC5cclxuICAgICAqIEkuZS4gdGhpcyBmdW5jdGlvbiByZXR1cm5zIEZBTFNFIHdpdGggZ2l2ZW4gbnVtYmVyLXBhcnNhYmxlIHN0cmluZ3MsIGJ1dCB0aGF0IGhhdmUgbm9uLW51bWVyaWMgYXBwZW5kaWNlcywgZWcgJzIyMzNmZicuIFRoYXQgYXJnXHJcbiAgICAgKiBJUyBudW1iZXItcGFyc2VhYmxlLCBidXQgbm90IGEgc3RyaWN0ICdzdHJpbmcgbnVtYmVyJywgdGhlIGxhdHRlciBiZWluZyB3aGF0IHRoaXMgbWV0aG9kIGFjdHVhbGx5IGNoZWNrcyBmb3IuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBzdGF0aWMgSXNTdHJpbmdOdW1iZXIoYXJnOiBzdHJpbmcpOiBib29sZWFuIHtcclxuICAgICAgICBpZiAoIU51bWJlclV0aWxzLklzUGFyc2FibGVOdW1iZXIoYXJnKSkge1xyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgcmV0dXJuIGFyZy50b1N0cmluZygpLmxlbmd0aCA9PT0gcGFyc2VGbG9hdChhcmcpLnRvU3RyaW5nKCkubGVuZ3RoO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgc3RhdGljIElzTGlzdE9mTnVtYmVycyhhcmc6IHN0cmluZywgc2VwYXJhdG9yOiBzdHJpbmcgPSBcIixcIik6IGJvb2xlYW4ge1xyXG4gICAgICAgIGNvbnN0IG5yczogc3RyaW5nW10gPSBhcmcuc3BsaXQoc2VwYXJhdG9yKTtcclxuICAgICAgICBpZiAobnJzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBucnMuZmlsdGVyKHMgPT4gTnVtYmVyVXRpbHMuSXNTdHJpbmdOdW1iZXIocykpLmxlbmd0aCA9PT0gbnJzLmxlbmd0aDtcclxuICAgIH1cclxuXHJcbiAgICAvLyBSZXR1cm5zIGdpdmVuIGFyZ3VtZW50IGFzIGEgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIGEgbnVtYmVyIHBhcnNlLCBlLmcuIFwiMVwiIGZvciBhIG51bWJlciBwYXJzZSByZXN1bHQgb2YgYXJnIHRvIDEuXHJcbiAgICBwdWJsaWMgc3RhdGljIFBhcnNlU3RyaW5nTnVtYmVyKGFyZzogc3RyaW5nKTogbnVtYmVyIHtcclxuICAgICAgICBpZiAoIXRoaXMuSXNTdHJpbmdOdW1iZXIoYXJnKSkge1xyXG4gICAgICAgICAgICByZXR1cm4gTmFOO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIE51bWJlclV0aWxzLlBhcnNlRmxvYXRLZWVwUHJlY2lzaW9uKGFyZyk7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIHN0YXRpYyBQYXJzZVN0cmluZ051bWJlckRlZmF1bHQoYXJnOiBzdHJpbmcgfCBhbnksIGRlZmF1bHRWYWx1ZTogbnVtYmVyID0gMCk6IG51bWJlciB7XHJcbiAgICAgICAgcmV0dXJuIE51bWJlclV0aWxzLk5hTihOdW1iZXJVdGlscy5QYXJzZVN0cmluZ051bWJlcihhcmcpLCBkZWZhdWx0VmFsdWUpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmV0dXJucyBhIHJhbmRvbSBpbnRlZ2VyIGluIHJhbmdlIFtsb3dlckJvdW5kIC4uIHVwcGVyQm91bmRdLCBhbiBpbmNsdXNpdmUgcmFuZ2UuIFJldHVybnMgTmFOIGlmIG5vdCBwb3NzaWJsZS5cclxuICAgICAqIEdpdmVuIGJvdW5kcyBhcmUgdHJ1bmNhdGVkIGZpcnN0LCBiZWZvcmUgc2VydmluZyBhcyB0aGUgdHJ1ZSBsb3dlci0gYW5kIHVwcGVyIGJvdW5kcyBmb3IgdGhlIHJhbmRvbSBpbnQuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBzdGF0aWMgUmFuZG9tSW50KGxvd2VyQm91bmRJbnQ6IG51bWJlciwgdXBwZXJCb3VuZEludDogbnVtYmVyKTogbnVtYmVyIHtcclxuICAgICAgICBpZiAoIU51bWJlclV0aWxzLklzTnVtYmVyKGxvd2VyQm91bmRJbnQpIHx8ICFOdW1iZXJVdGlscy5Jc051bWJlcih1cHBlckJvdW5kSW50KSB8fCBsb3dlckJvdW5kSW50ID4gdXBwZXJCb3VuZEludCkge1xyXG4gICAgICAgICAgICByZXR1cm4gTmFOO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgbG93ZXJCb3VuZEludCA9IE1hdGgudHJ1bmMobG93ZXJCb3VuZEludCk7XHJcbiAgICAgICAgdXBwZXJCb3VuZEludCA9IE1hdGgudHJ1bmModXBwZXJCb3VuZEludCk7XHJcblxyXG4gICAgICAgIGlmIChsb3dlckJvdW5kSW50ID09PSB1cHBlckJvdW5kSW50KSB7XHJcbiAgICAgICAgICAgIHJldHVybiBsb3dlckJvdW5kSW50O1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgZGVsdGE6IG51bWJlciA9IHVwcGVyQm91bmRJbnQgLSBsb3dlckJvdW5kSW50O1xyXG4gICAgICAgIHJldHVybiAoTWF0aC5yb3VuZChNYXRoLnJhbmRvbSgpICogZGVsdGEpICsgbG93ZXJCb3VuZEludCk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQWRkcyB0aG91c2FuZHMgY29tbWEncyB0byBnaXZlbiB2YWx1ZSwgRS5nLiAnMTAwMCcgdG8gJzEsMDAwJy4gUmV0dXJucyBlbXB0eSBzdHJpbmcgaWYgdmFsdWUgd2FzIHVuZGVmaW5lZC5cclxuICAgIHB1YmxpYyBzdGF0aWMgQWRkVGhvdXNhbmRzQ29tbWFzVG8odmFsdWU6IGFueSk6IHN0cmluZyB7XHJcbiAgICAgICAgaWYgKGlzTmlsbCh2YWx1ZSkpIHtcclxuICAgICAgICAgICAgcmV0dXJuIFwiXCI7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gdmFsdWUudG9TdHJpbmcoKS5yZXBsYWNlKC9cXEIoPz0oXFxkezN9KSsoPyFcXGQpKS9nLCBcIixcIik7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBGdW5jdGlvbiB1c2VkIHRvIGNoZWNrIHdldGhlciBhIGdpdmVuIG51bWJlciBpcyBjb21wb3NlZCBvZiBhbm90aGVyIG51bWJlciwgcG93ZXItb2YtdHdvIHdpc2UuXHJcbiAgICAgKiBFeGFtcGxlIHVzYWdlOiBOdW1iZXJVdGlscy5OdW1Jc0NvbXBvc2VkT2YoYXJ0aWNsZUxpc3RPYmplY3QucHVibGljYXRpb24sIEFydGljbGVQdWJsaWNhdGlvbi5TZWxlY3RvcikuXHJcbiAgICAgKiBUaGlzIHdvdWxkIHJldHVybiB3aGV0aGVyIG9yIG5vdCB0aGF0IGFydGljbGVMaXN0T2JqZWN0IHdhcyBwdWJsaWNhdGVkIGZvciBzZWxlY3RvciBvciBub3QsIHdoZXJlIGFydGljbGVMaXN0T2JqZWN0LnB1YmxpY2F0aW9uXHJcbiAgICAgKiB3YXMgcG9zc2libHkgYSAnQ09NUE9TSVRFIHRoYXQgd2FzIG1hZGUgb3V0IG9mIChpbmNsdWRpbmcpJyBBcnRpY2xlUHVibGljYXRpb24uU2VsZWN0b3IuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBzdGF0aWMgTnVtSXNDb21wb3NlZE9mT3RoZXJQb3dUd29OdW0oYmlnTnJUb0NoZWNrOiBudW1iZXIsIHBvd1R3b051bUl0U2hvdWxkQmVDb21wb3NlZE9mOiBudW1iZXIpOiBib29sZWFuIHtcclxuICAgICAgICBpZiAoIWJpZ05yVG9DaGVjaykge1xyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgfSBlbHNlIGlmICghcG93VHdvTnVtSXRTaG91bGRCZUNvbXBvc2VkT2YpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgcmV0dXJuICgoYmlnTnJUb0NoZWNrICYgcG93VHdvTnVtSXRTaG91bGRCZUNvbXBvc2VkT2YpID09PSBwb3dUd29OdW1JdFNob3VsZEJlQ29tcG9zZWRPZik7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmV0dXJucyBnaXZlbiBuciwgb3IgdGhlIGdpdmVuIGRlZmF1bHQgbnVtYmVyIChkZWZhdWx0IDApIGlmIHRoZSBuciBudW1iZXIgd2FzIHVuZGVmaW5lZCBvciBvdGhlcndpc2Ugbm90IGEgbnVtYmVyLlxyXG4gICAgICogU2FtZSBhcyBDb01hdGguTmFOIGZyb20gQVMgY29kZSAodXNlZCBhcyBpdHMgc3Vic3RpdHV0ZSBpbiB0cmFuc2FjdGlvbiBsb2dpYylcclxuICAgICAqIEBwYXJhbSBuclxyXG4gICAgICogQHBhcmFtIGRlZmF1bHROclxyXG4gICAgICogQHJldHVybnMge251bWJlcn1cclxuICAgICAqL1xyXG4gICAgcHVibGljIHN0YXRpYyBOck9yRGVmYXVsdChucjogbnVtYmVyLCBkZWZhdWx0TnI6IG51bWJlciA9IDApOiBudW1iZXIge1xyXG4gICAgICAgIGlmIChub3ROaWxsKG5yKSAmJiBOdW1iZXJVdGlscy5Jc051bWJlcihucikpIHtcclxuICAgICAgICAgICAgcmV0dXJuIG5yO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHJldHVybiBkZWZhdWx0TnI7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmV0dXJucyB3aGV0aGVyIGdpdmVuIG5yVG9DaGVjayBpcyB3aXRoaW4gdGhlIGdpdmVuIHByZWNpc2lvbiBhbmQgc2NhbGUgbGltaXRzLiBQcmVjaXNpb24gYW5kIHNjYWxlLCBoZXJlLCBhcmUgT3JhY2xlIERCIHRlcm1zLlxyXG4gICAgICogVGhpcyBmdW5jdGlvbiBjYW4gdGh1cyBiZSB1c2VkIHRvIGNoZWNrIHdoZXRoZXIgdGhlIGdpdmVuIG51bWJlciBpcyBzYWZlIHRvIHNlbmQgdG8gdGhlICdkYXRhYmFzZScgYmVmb3JlaGFuZCwgaWYgd2Uga25vdyB0aGVcclxuICAgICAqIHByZWNpc2lvbiBhbmQgc2NhbGUgb2YgdGhlIG51bWJlciBpbiB0aGUgZGIgZGVjbGFyYXRpb24uXHJcbiAgICAgKlxyXG4gICAgICogSS5lLiBBIG51bWJlciBkZWNsYXJlZCBpbiB0aGUgT3JhY2xlIERCIGFzIG51bWJlcig1LCAyKSBoYXMgYSBwcmVjaXNpb24gb2YgNSBhbmQgYSBzY2FsZSBvZiAyLlxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBuclRvQ2hlY2tcclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBwcmVjaXNpb24gVGhlIG51bWJlciBvZiBzaWduaWZpY2FudCBkaWdpdHMsIGluY2x1ZGluZyBwb3NzaWJseSBuZWdhdGl2ZSBzY2FsZS4gRS5nLiAzIGluICcxMjMnIGFuZCA1IGluICc1MS4xMjMnXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3NjYWxlID0gMF0gVGhlIG51bWJlciBvZiBzaWduaWZpY2FudCBkaWdpdHMgQUZURVIgdGhlIGRlY2ltYWwgcG9pbnQuIEUuZy4gMSBpbiA1NDMyLjEgYW5kIDMgaW4gNTQwMDAuMDAzXHJcbiAgICAgKiBAcmV0dXJucyB7Q2hlY2tQcmVjaXNpb25BbmRTY2FsZVJlc3VsdH0gV2hldGhlciBnaXZlbiBuclRvQ2hlY2sgaXMgb2sgZm9yIGdpdmVuIHByZWNpc2lvbiBhbmQgc2NhbGUsIGFuZCBpZiBub3QsIHRoZVxyXG4gICAgICogbmVhcmVzdCBudW1iZXIgdGhhdCBJUyBvayBmb3IgdGhvc2UgY29uc3RyYWludHMuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBzdGF0aWMgQ2hlY2tQcmVjaXNpb25BbmRTY2FsZShuclRvQ2hlY2s6IG51bWJlciwgcHJlY2lzaW9uOiBudW1iZXIsIHNjYWxlOiBudW1iZXIgPSAwKTogQ2hlY2tQcmVjaXNpb25BbmRTY2FsZVJlc3VsdCB7XHJcbiAgICAgICAgLy8gbGV0J3Mgc2F5IGFueSB1bmRlZmluZWQgbnVtYmVyIGlzIGNoZWNrZWQgT0ssIGFuZCBhbGwgbnVtYmVycyBhcmUgY2hlY2tlZCBPSyBmb3IgYW4gdW5kZWZpbmVkIHByZWNpc2lvblxyXG4gICAgICAgIGlmICghT2JqZWN0VXRpbHMuQWxsRXhpc3QobnJUb0NoZWNrLCBwcmVjaXNpb24sIHNjYWxlKSkge1xyXG4gICAgICAgICAgICByZXR1cm4ge2lzT2s6IHRydWUsIG5lYXJlc3RPa05yOiBOYU59O1xyXG4gICAgICAgIH1cclxuICAgICAgICAvLyBubyBudW1iZXIgY2FuIGhhdmUgMCBvciBsZXNzIHRoYW4gMCBzaWduaWZpY2FudCBkaWdpdHMsIGluIG91ciB1bml2ZXJzZVxyXG4gICAgICAgIGlmIChwcmVjaXNpb24gPCAxIHx8IHByZWNpc2lvbiAtIHNjYWxlIDwgMSkge1xyXG4gICAgICAgICAgICByZXR1cm4ge2lzT2s6IGZhbHNlLCBuZWFyZXN0T2tOcjogTmFOfTtcclxuICAgICAgICB9XHJcbiAgICAgICAgLy8gYmVnaW4gY2hlY2tcclxuICAgICAgICBjb25zdCBpc05lZ2F0aXZlOiBib29sZWFuID0gKG5yVG9DaGVjayA8IDApO1xyXG4gICAgICAgIGNvbnN0IG5yUGFydHM6IHN0cmluZ1tdID0gbnJUb0NoZWNrLnRvU3RyaW5nKCkuc3BsaXQoXCIuXCIpO1xyXG4gICAgICAgIC8vIHJlbW92ZSBtaW51cyBzaWduIGlmIG5lZ2F0aXZlXHJcbiAgICAgICAgaWYgKGlzTmVnYXRpdmUpIHtcclxuICAgICAgICAgICAgbnJQYXJ0c1swXSA9IG5yUGFydHNbMF0uc2xpY2UoMSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGNvbnN0IG51bUNvdW50QmVmb3JlRG90OiBudW1iZXIgPSBuclBhcnRzWzBdLmxlbmd0aDtcclxuICAgICAgICBjb25zdCBhbGxvd2VkTnVtQ291bnRCZWZvcmVEb3Q6IG51bWJlciA9IHByZWNpc2lvbiAtIHNjYWxlO1xyXG4gICAgICAgIGlmIChudW1Db3VudEJlZm9yZURvdCA8PSBhbGxvd2VkTnVtQ291bnRCZWZvcmVEb3QpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHtpc09rOiB0cnVlLCBuZWFyZXN0T2tOcjogbnJUb0NoZWNrfTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAvLyBjdXQgYSBwYXJ0IGZyb20gdGhlIFwiYmVmb3JlIGRlY2ltYWwgbnVtYmVyXCIgc28gdGhhdCB0aGUgbnVtYmVyIGlzIG5vdCB0b28gYmlnIGFueW1vcmVcclxuICAgICAgICAgICAgY29uc3QgbnVtQ291bnRUb1JlbW92ZTogbnVtYmVyID0gbnVtQ291bnRCZWZvcmVEb3QgLSBhbGxvd2VkTnVtQ291bnRCZWZvcmVEb3Q7XHJcbiAgICAgICAgICAgIC8vIHJlbW92ZSB0aGUgcmlnaHQtbW9zdCBudW1iZXJzIGJlZm9yZSB0aGUgZGVjaW1hbCBkb3RcclxuICAgICAgICAgICAgbnJQYXJ0c1swXSA9IG5yUGFydHNbMF0uc2xpY2UoMCwgLTEgKiBudW1Db3VudFRvUmVtb3ZlKTtcclxuICAgICAgICAgICAgLy8gYWRkIG1pbnVzIHNpZ24gYWdhaW4gaWYgaXQgd2FzIG5lZ2F0aXZlXHJcbiAgICAgICAgICAgIGlmIChpc05lZ2F0aXZlKSB7XHJcbiAgICAgICAgICAgICAgICBuclBhcnRzWzBdID0gXCItXCIgKyBuclBhcnRzWzBdO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIC8vIGJ1aWxkIGFuZCByZXR1cm4gY29tcG9zaXRlIG51bWJlciBhZ2FpblxyXG4gICAgICAgICAgICBsZXQgbmVhcmVzdE9rTnI6IG51bWJlcjtcclxuICAgICAgICAgICAgaWYgKG5yUGFydHNbMV0pIHtcclxuICAgICAgICAgICAgICAgIG5lYXJlc3RPa05yID0gTnVtYmVyKG5yUGFydHNbMF0gKyBcIi5cIiArIG5yUGFydHNbMV0pO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgbmVhcmVzdE9rTnIgPSBOdW1iZXIobnJQYXJ0c1swXSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcmV0dXJuIHtpc09rOiBmYWxzZSwgbmVhcmVzdE9rTnI6IG5lYXJlc3RPa05yfTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZXR1cm5zIHdoZXRoZXIgZ2l2ZW4geCBpcyBPSyB3aXRoaW4gdGhlIGdpdmVuIG1pbiwgbWF4IGFuZCBzdGVwIGJvdW5kYXJpZXMsIHdoZXJlIGl0IHNob3VsZCBob2xkIHRoYXQgbnJUb0NoZWNrID0gbWluICsgTiAqIHN0ZXAsXHJcbiAgICAgKiB3aXRoIE4gaW50ZWdlciBvciAwLlxyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG5yVG9DaGVjayBOdW1iZXIgdG8gY2hlY2sgd2hldGhlciBpdCdzIHdpdGhpbiB0aGUgZ2l2ZW4gYm91bmRzXHJcbiAgICAgKiBAcGFyYW0gbWluIEluY2x1c2l2ZVxyXG4gICAgICogQHBhcmFtIG1heCBJbmNsdXNpdmVcclxuICAgICAqIEBwYXJhbSBzdGVwU2l6ZVxyXG4gICAgICogQHJldHVybnMge0NoZWNrV2l0aGluU3RlcHBlZEJvdW5kc30gUmV0dXJucyByZW1haW5kZXIgb2YgdW5kZWZpbmVkIHdoZW4gbnJUb0NoZWNrIHdhcyBPVVRTSURFIFttaW4sIG1heF0sIGVsc2UgZnVsbCByZXN1bHQgb2JqZWN0LlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc3RhdGljIENoZWNrV2l0aGluU3RlcHBlZEJvdW5kcyhcclxuICAgICAgICBuclRvQ2hlY2s6IG51bWJlcixcclxuICAgICAgICBtaW46IG51bWJlcixcclxuICAgICAgICBtYXg6IG51bWJlcixcclxuICAgICAgICBzdGVwU2l6ZTogbnVtYmVyID0gMVxyXG4gICAgKTogQ2hlY2tXaXRoaW5TdGVwcGVkQm91bmRzUmVzdWx0IHtcclxuICAgICAgICBpZiAobnJUb0NoZWNrIDwgbWluIHx8IG5yVG9DaGVjayA+IG1heCkge1xyXG4gICAgICAgICAgICByZXR1cm4ge2lzT2s6IGZhbHNlLCByZW1haW5kZXI6IHVuZGVmaW5lZH07XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyB3ZSdyZSBpbiBbbWluLCBtYXhdLCBidXQgc3RpbGwgY2hlY2sgaWYgbnJUb0NoZWNrID0gbWluICsgTiAqIHN0ZXAgaG9sZHMgKGZvciBOIGludGVnZXIgb3IgMClcclxuICAgICAgICBsZXQgcmVtYWluZGVyOiBudW1iZXIgPSAobnJUb0NoZWNrIC0gbWluKSAlIHN0ZXBTaXplO1xyXG4gICAgICAgIC8vIGNvcnJlY3QgZmxvYXQgZm9yIGxhcmdlc3QgcHJlY2lzaW9uIGFtb25nc3QgaW5wdXQgbnVtYmVyc1xyXG4gICAgICAgIHJlbWFpbmRlciA9IE51bWJlclV0aWxzLlBhcnNlRmxvYXQocmVtYWluZGVyLCBOdW1iZXJVdGlscy5fR2V0TGFyZ2VzdERlY2ltYWxQcmVjaXNpb25PZihuclRvQ2hlY2ssIG1pbiwgc3RlcFNpemUpKTtcclxuICAgICAgICByZXR1cm4ge2lzT2s6IChyZW1haW5kZXIgPT09IDApLCByZW1haW5kZXI6IHJlbWFpbmRlcn07XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBGaW5kcyB0aGUgbnVtYmVyIGNsb3Nlc3QgdG8gdGhlIG9yaWdpbmFsTnVtYmVyLCB0aGF0IGFkaGVyZXMgdG8gdGhlIGdpdmVuIGJvdW5kcy4gVGhhdCBpcywgZm9yIHdoaWNoIGl0IGhvbGRzIHRoYXRcclxuICAgICAqIG5yID0gbWluICsgTiAqIHN0ZXAgd2l0aCBOIGludGVnZXIgb3IgMC5cclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBvcmlnaW5hbE5yIEZpbmQgY2xvc2VzdCBhbnN3ZXIgdG8gdGhpcyBudW1iZXJcclxuICAgICAqIEBwYXJhbSBtaW4gSW5jbHVzaXZlXHJcbiAgICAgKiBAcGFyYW0gbWF4IEluY2x1c2l2ZVxyXG4gICAgICogQHBhcmFtIHN0ZXBTaXplXHJcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gVGhlIGNsb3Nlc3QgT0sgbnVtYmVyIGZvciBib3VuZHMuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBzdGF0aWMgR2V0TmVhcmVzdE51bWJlcldpdGhpblN0ZXBwZWRCb3VuZHMob3JpZ2luYWxOcjogbnVtYmVyLCBtaW46IG51bWJlciwgbWF4OiBudW1iZXIsIHN0ZXBTaXplOiBudW1iZXIgPSAxKTogbnVtYmVyIHtcclxuICAgICAgICBpZiAob3JpZ2luYWxOciA8IG1pbikge1xyXG4gICAgICAgICAgICByZXR1cm4gbWluO1xyXG4gICAgICAgIH0gZWxzZSBpZiAob3JpZ2luYWxOciA+IG1heCkge1xyXG4gICAgICAgICAgICByZXR1cm4gTnVtYmVyVXRpbHMuR2V0VHJ1ZVN0ZXBwZWRCb3VuZHNNYXgobWluLCBtYXgsIHN0ZXBTaXplKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IGJvdW5kc0NoZWNrOiBDaGVja1dpdGhpblN0ZXBwZWRCb3VuZHNSZXN1bHQgPSBOdW1iZXJVdGlscy5DaGVja1dpdGhpblN0ZXBwZWRCb3VuZHMob3JpZ2luYWxOciwgbWluLCBtYXgsIHN0ZXBTaXplKTtcclxuICAgICAgICBpZiAoYm91bmRzQ2hlY2suaXNPaykge1xyXG4gICAgICAgICAgICByZXR1cm4gb3JpZ2luYWxOcjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGxldCBhbnN3ZXI6IG51bWJlcjtcclxuXHJcbiAgICAgICAgY29uc3QgcmVtYWluZGVyOiBudW1iZXIgPSBib3VuZHNDaGVjay5yZW1haW5kZXI7XHJcbiAgICAgICAgaWYgKHJlbWFpbmRlcikge1xyXG4gICAgICAgICAgICAvLyByb3VuZCB1cCBvciBkb3duP1xyXG4gICAgICAgICAgICBpZiAoKHJlbWFpbmRlciAvIHN0ZXBTaXplKSA8IDAuNSkge1xyXG4gICAgICAgICAgICAgICAgLy8gIHJvdW5kIGRvd24sIGJ1dCBub3QgYmVsb3cgbWluXHJcbiAgICAgICAgICAgICAgICBhbnN3ZXIgPSAob3JpZ2luYWxOciAtIHJlbWFpbmRlciA+PSBtaW4gPyBvcmlnaW5hbE5yIC0gcmVtYWluZGVyIDogbWluKTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIC8vIHJvdW5kIHVwLCBidXQgbm90IGFib3ZlIG1heFxyXG4gICAgICAgICAgICAgICAgYW5zd2VyID0gKG9yaWdpbmFsTnIgKyBzdGVwU2l6ZSAtIHJlbWFpbmRlciA8PSBtYXggPyBvcmlnaW5hbE5yICsgc3RlcFNpemUgLSByZW1haW5kZXIgOlxyXG4gICAgICAgICAgICAgICAgICAgIE51bWJlclV0aWxzLkdldFRydWVTdGVwcGVkQm91bmRzTWF4KG1pbiwgbWF4LCBzdGVwU2l6ZSkpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgLy8gaXMgdGhpcyByZWFsIGxpZmUsIHdoeSB3YXNuJ3Qgb3VyIHN0ZXBwZWQgYm91bmRzIGNoZWNrIE9LP1xyXG4gICAgICAgICAgICBhbnN3ZXIgPSBvcmlnaW5hbE5yO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gJ2NvcnJlY3QnIGZsb2F0IGVycm9yc1xyXG4gICAgICAgIGFuc3dlciA9IE51bWJlclV0aWxzLlBhcnNlRmxvYXQoYW5zd2VyLCBOdW1iZXJVdGlscy5fR2V0TGFyZ2VzdERlY2ltYWxQcmVjaXNpb25PZihvcmlnaW5hbE5yLCBtaW4sIG1heCwgc3RlcFNpemUpKTtcclxuICAgICAgICByZXR1cm4gYW5zd2VyO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmV0dXJucyB0aGUgdHJ1ZSBtYXhpbXVtIGFsbG93ZWQgdmFsdWUgZm9yIHRoZSBnaXZlbiBcInN0ZXBwZWQgYm91bmRzXCI6IG1pbiwgc3RlcFNpemUgYW5kIG1heCwgZm9yIHdoaWNoIGl0IGhvbGRzIHRoYXQgZWFjaCBhbGxvd2VkXHJcbiAgICAgKiB2YWx1ZSBZID0gbWluICsgc3RlcFNpemUgKiBOLCBmb3IgYW55IElOVEVHRVIgb3IgMCBOIHdoZXJlIGl0IGFsc28gaG9sZHMsIG9mIGNvdXJzZSwgdGhhdCBZIDw9IG1heC5cclxuICAgICAqIEBwYXJhbSBtaW5cclxuICAgICAqIEBwYXJhbSBtYXhcclxuICAgICAqIEBwYXJhbSBzdGVwU2l6ZVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc3RhdGljIEdldFRydWVTdGVwcGVkQm91bmRzTWF4KG1pbjogbnVtYmVyLCBtYXg6IG51bWJlciwgc3RlcFNpemU6IG51bWJlciA9IDEpOiBudW1iZXIge1xyXG4gICAgICAgIC8vIHNvbHZlIG1heCBpbnRlZ2VyIFggaW4gZm9ybXVsYSBtaW4gKyBYICogc3RlcCA8PSBtYXgsIGFuZCByZXR1cm4gbWluICsgWCAqIHN0ZXBTaXplIGZvciB0aGF0IFhcclxuICAgICAgICBjb25zdCBtYXhTdGVwczogbnVtYmVyID0gTWF0aC5mbG9vcigobWF4IC0gbWluKSAvIHN0ZXBTaXplKTtcclxuICAgICAgICAvLyAnY29ycmVjdCcgZmxvYXQgZXJyb3JzXHJcbiAgICAgICAgcmV0dXJuIE51bWJlclV0aWxzLlBhcnNlRmxvYXQobWluICsgbWF4U3RlcHMgKiBzdGVwU2l6ZSwgTnVtYmVyVXRpbHMuX0dldExhcmdlc3REZWNpbWFsUHJlY2lzaW9uT2YobWluLCBtaW4sIG1heCkpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFJldHVybnMgdGhlIG5lYXJlc3QgbnVtYmVyLCByZWxhdGl2ZSB0byB0aGUgZ2l2ZW4gb3JpZ2luYWxOciwgdGhhdCBpcyB3aXRoaW4gdGhlIGdpdmVuIFttaW4sIG1heF0gaW5jbHVzaXZlIGJvdW5kcy5cclxuICAgIHB1YmxpYyBzdGF0aWMgR2V0TmVhcmVzdE51bWJlcldpdGhpbkJvdW5kcyhvcmlnaW5hbE5yOiBudW1iZXIsIG1pbjogbnVtYmVyLCBtYXg6IG51bWJlcik6IG51bWJlciB7XHJcbiAgICAgICAgbGV0IGFuc3dlcjogbnVtYmVyID0gb3JpZ2luYWxOcjtcclxuXHJcbiAgICAgICAgaWYgKG9yaWdpbmFsTnIgPCBtaW4pIHtcclxuICAgICAgICAgICAgYW5zd2VyID0gbWluO1xyXG4gICAgICAgIH0gZWxzZSBpZiAob3JpZ2luYWxOciA+IG1heCkge1xyXG4gICAgICAgICAgICBhbnN3ZXIgPSBtYXg7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gYW5zd2VyO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFJldHVybnMgdGhlIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiBnaXZlbiBudW1iZXIuIElmIGl0J3Mgbm90IGEgbnVtYmVyLCByZXR1cm5zIHRoZSBlbXB0eSBzdHJpbmcuXHJcbiAgICBwdWJsaWMgc3RhdGljIFRvU3RyaW5nKG5yOiBudW1iZXIpOiBzdHJpbmcge1xyXG4gICAgICAgIGlmICghTnVtYmVyVXRpbHMuSXNOYU4obnIpKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBcIlwiICsgbnI7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgcmV0dXJuIFwiXCI7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBzdGF0aWMgRGVjaW1hbHNUb1N0ZXBJbmNyZW1lbnQobnVtYmVyT2ZEZWNpbWFsczogbnVtYmVyKTogbnVtYmVyIHtcclxuICAgICAgICByZXR1cm4gTWF0aC5wb3coMTAsIC0xICogbnVtYmVyT2ZEZWNpbWFscyk7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIHN0YXRpYyBSb3VuZCh2YWx1ZTogbnVtYmVyLCBkZWNpbWFsczogbnVtYmVyKTogbnVtYmVyIHtcclxuICAgICAgICBjb25zdCBmYWN0b3I6IG51bWJlciA9IE1hdGgucG93KDEwLCBkZWNpbWFscyk7XHJcbiAgICAgICAgcmV0dXJuIE1hdGgucm91bmQodmFsdWUgKiBmYWN0b3IpIC8gZmFjdG9yO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIEByZXR1cm5zIFRoZSBpbmNsdXNpdmUgbWF4IHZhbHVlXHJcbiAgICBwdWJsaWMgc3RhdGljIFByZWNpc2lvblNjYWxlVG9NYXhWYWx1ZShwcmVjaXNpb246IG51bWJlciwgc2NhbGU6IG51bWJlcik6IG51bWJlciB7XHJcbiAgICAgICAgY29uc3Qgb25lU3RlcDogbnVtYmVyID0gdGhpcy5EZWNpbWFsc1RvU3RlcEluY3JlbWVudChzY2FsZSk7XHJcbiAgICAgICAgY29uc3QgbWF4RXhjbHVzaXZlOiBudW1iZXIgPSBNYXRoLnBvdygxMCwgcHJlY2lzaW9uIC0gc2NhbGUpO1xyXG4gICAgICAgIHJldHVybiBtYXhFeGNsdXNpdmUgLSBvbmVTdGVwO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIEByZXR1cm5zIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gZ2l2ZW4gMiBudW1iZXJzXHJcbiAgICBwdWJsaWMgc3RhdGljIERpZmZlcmVuY2VCZXR3ZWVuTnVtYmVycyhudW1iZXJBOiBudW1iZXIsIG51bWJlckI6IG51bWJlcik6IG51bWJlciB7XHJcbiAgICAgICAgcmV0dXJuIE1hdGguYWJzKG51bWJlckEgLSBudW1iZXJCKTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIHN0YXRpYyBfR2V0TGFyZ2VzdERlY2ltYWxQcmVjaXNpb25PZiguLi5hcmdzOiBudW1iZXJbXSk6IG51bWJlciB7XHJcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gQXJyYXlVdGlscy5HZXRNYXhDYWxjdWxhdGVkVmFsdWUoYXJncywgKGFyZzogbnVtYmVyKSA9PiB7XHJcbiAgICAgICAgICAgIHJldHVybiBOdW1iZXJVdGlscy5HZXREZWNpbWFsUGxhY2VzKGFyZyk7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcclxuICAgIH1cclxuXHJcbiAgICAvLyBSZXR1cm5zIGdpdmVuIG51bWJlciBpbnB1dCBhcyBhIG51bWJlciB0aGF0J3MgdXNlYWJsZSBieSBKYXZhc2NyaXB0LiBBbGxvd3MgZm9yIGluY29taW5nICcsJyBkZWNpbWFsIGRlbGltaXRlci5cclxuICAgIHByaXZhdGUgc3RhdGljIF9OdW1iZXJJbnB1dFRvTnVtYmVyU3RyKG51bWJlcklucHV0OiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gICAgICAgIHJldHVybiAobnVtYmVySW5wdXQgKyBcIlwiKS5yZXBsYWNlKFwiLFwiLCBcIi5cIik7XHJcbiAgICB9XHJcbn1cclxuIl19
1
+ import { ObjectUtils } from "./object-utils";
2
+ import { ArrayUtils } from "./array-utils";
3
+ import { isNill } from "./is-nill.function";
4
+ import { notNill } from "./function/not-nill.function";
5
+ // Static utility function holder related to numeric variable evaluations and operations.
6
+ export class NumberUtils {
7
+ // For user-typed number input; supports comma's as decimal delimiter.
8
+ static ParseIntNumberInput(arg) {
9
+ return NumberUtils.ParseInt(NumberUtils._NumberInputToNumberStr(arg));
10
+ }
11
+ // Parses given argument to an integer, using a native parseInt() function with a radix of 10. Returns NaN if parsing was not possible.
12
+ static ParseInt(arg) {
13
+ if (isNill(arg) || Array.isArray(arg)) {
14
+ return undefined;
15
+ }
16
+ return parseInt(arg, 10);
17
+ }
18
+ // For user-typed number input; supports comma's as decimal delimiter.
19
+ static ParseFloatNumberInput(arg, decimalPrecision = 2) {
20
+ return NumberUtils.ParseFloat(NumberUtils._NumberInputToNumberStr(arg), decimalPrecision);
21
+ }
22
+ static ParseFloatNumberInputKeepPrecision(arg) {
23
+ const correctedInputStr = NumberUtils._NumberInputToNumberStr(arg);
24
+ const decimalPrecision = this.GetDecimalPlaces(correctedInputStr);
25
+ return NumberUtils.ParseFloat(correctedInputStr, decimalPrecision);
26
+ }
27
+ /**
28
+ * Returns given arg as a float number with given decimal precision, if possible. Returns NaN if parse conversion failed.
29
+ *
30
+ * @param {any} arg The argument to parse to a float
31
+ * @param {number} decimalPrecision The number of decimals, or the precision, the parsed return float should have
32
+ * @returns {number} NaN if not possible, else the parsed float value
33
+ */
34
+ static ParseFloat(arg, decimalPrecision = 2) {
35
+ if (!ObjectUtils.AllExist(arg, decimalPrecision) || Array.isArray(arg)) {
36
+ return NaN;
37
+ }
38
+ if (!NumberUtils.IsInteger(decimalPrecision) || decimalPrecision < 0) {
39
+ decimalPrecision = 2;
40
+ // toFixed() can only handle up until 20
41
+ }
42
+ else if (decimalPrecision > 20) {
43
+ decimalPrecision = 20;
44
+ }
45
+ return parseFloat(parseFloat(arg).toFixed(decimalPrecision));
46
+ }
47
+ /**
48
+ * Returns given arg as a float number with given decimal precision, if possible. Returns NaN if parse conversion failed.
49
+ *
50
+ * @param arg The argument to parse to a float
51
+ * @returns {number} The argument as a float with its original decimal precision intact
52
+ */
53
+ static ParseFloatKeepPrecision(arg) {
54
+ const decimalPrecision = this.GetDecimalPlaces(arg);
55
+ return this.ParseFloat(arg, decimalPrecision);
56
+ }
57
+ /**
58
+ * Returns the given argument as a number. Returns given defaultValue if conversion of argument was impossible.
59
+ * @param arg
60
+ * @param {number} [defaultValue = 0]
61
+ * @returns {number}
62
+ */
63
+ static ParseNumberOrDefault(arg, defaultValue = 0) {
64
+ if (Array.isArray(arg)) {
65
+ return defaultValue;
66
+ }
67
+ if (!NumberUtils.IsNumber(arg)) {
68
+ arg = parseFloat(arg);
69
+ arg = isNaN(arg) ? defaultValue : arg;
70
+ }
71
+ return arg;
72
+ }
73
+ // Returns true iff given argument is an integer number. Returns false on non-numbers or numbers with significant decimals.
74
+ static IsInteger(arg) {
75
+ if (isNaN(arg) || Array.isArray(arg)) {
76
+ return false;
77
+ }
78
+ const argAsFloat = parseFloat(arg);
79
+ return ((argAsFloat | 0) === argAsFloat); // returns whether 'arg converted to an integer equals arg'
80
+ }
81
+ // Returns the number of decimal places of the given number. Returns 0 if no decimals whatsoever could be found on given arg.
82
+ static GetDecimalPlaces(arg, maxAnswer = 1000) {
83
+ const match = ("" + arg).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
84
+ if (!match) {
85
+ return 0;
86
+ }
87
+ let answer = Math.max(0,
88
+ // number of digits right of decimal point.
89
+ (match[1] ? match[1].length : 0)
90
+ // adjust for scientific notation
91
+ - (match[2] ? +match[2] : 0));
92
+ if (answer > maxAnswer) {
93
+ answer = maxAnswer;
94
+ }
95
+ return answer;
96
+ }
97
+ // Parses given numberInput to a number, or returns given defaultValue if parse not possible. Allows ',' char as decimal delimiter.
98
+ static ParseNumberInputOrDefault(numberInput, defaultValue = 0) {
99
+ return NumberUtils.ParseNumberOrDefault(NumberUtils._NumberInputToNumberStr(numberInput), defaultValue);
100
+ }
101
+ // Returns whether the type of given argument is 'number'.
102
+ static IsNumber(arg) {
103
+ return typeof arg === "number" && !isNaN(arg);
104
+ }
105
+ /**
106
+ * Returns whether given arg is indeed not a number (it's NaN or it has another type than 'number')
107
+ * Our exact copy of AS Flex'es isNaN(arg) function. Always use this method for copying Flex isNaN(..) occurences into TypeScript.
108
+ * @param arg
109
+ * @returns {boolean}
110
+ * @constructor
111
+ */
112
+ static IsNaN(arg) {
113
+ return isNaN(arg) || !NumberUtils.IsNumber(arg);
114
+ }
115
+ // Our copy of CoMath.NaN. Returns number, or substitute if NumberUtils.IsNaN(number) holds true.
116
+ static NaN(number, substitute = 0) {
117
+ return NumberUtils.IsNaN(number) ? substitute : number;
118
+ }
119
+ // Returns whether the value is parasable as a number.
120
+ static IsParsableNumber(arg) {
121
+ if (Array.isArray(arg)) {
122
+ return false;
123
+ }
124
+ return !isNaN(parseFloat(arg));
125
+ }
126
+ static IsParsableNumberInput(numberInput) {
127
+ return NumberUtils.IsParsableNumber(NumberUtils._NumberInputToNumberStr(numberInput));
128
+ }
129
+ /**
130
+ * Returns whether given arg is parseable as a number, and whether the lengts of its number parse result is equal to its original length.
131
+ * I.e. this function returns FALSE with given number-parsable strings, but that have non-numeric appendices, eg '2233ff'. That arg
132
+ * IS number-parseable, but not a strict 'string number', the latter being what this method actually checks for.
133
+ */
134
+ static IsStringNumber(arg) {
135
+ if (!NumberUtils.IsParsableNumber(arg)) {
136
+ return false;
137
+ }
138
+ else {
139
+ return arg.toString().length === parseFloat(arg).toString().length;
140
+ }
141
+ }
142
+ static IsListOfNumbers(arg, separator = ",") {
143
+ const nrs = arg.split(separator);
144
+ if (nrs.length === 0) {
145
+ return false;
146
+ }
147
+ return nrs.filter(s => NumberUtils.IsStringNumber(s)).length === nrs.length;
148
+ }
149
+ // Returns given argument as a string representation of a number parse, e.g. "1" for a number parse result of arg to 1.
150
+ static ParseStringNumber(arg) {
151
+ if (!this.IsStringNumber(arg)) {
152
+ return NaN;
153
+ }
154
+ return NumberUtils.ParseFloatKeepPrecision(arg);
155
+ }
156
+ static ParseStringNumberDefault(arg, defaultValue = 0) {
157
+ return NumberUtils.NaN(NumberUtils.ParseStringNumber(arg), defaultValue);
158
+ }
159
+ /**
160
+ * Returns a random integer in range [lowerBound .. upperBound], an inclusive range. Returns NaN if not possible.
161
+ * Given bounds are truncated first, before serving as the true lower- and upper bounds for the random int.
162
+ */
163
+ static RandomInt(lowerBoundInt, upperBoundInt) {
164
+ if (!NumberUtils.IsNumber(lowerBoundInt) || !NumberUtils.IsNumber(upperBoundInt) || lowerBoundInt > upperBoundInt) {
165
+ return NaN;
166
+ }
167
+ lowerBoundInt = Math.trunc(lowerBoundInt);
168
+ upperBoundInt = Math.trunc(upperBoundInt);
169
+ if (lowerBoundInt === upperBoundInt) {
170
+ return lowerBoundInt;
171
+ }
172
+ const delta = upperBoundInt - lowerBoundInt;
173
+ return (Math.round(Math.random() * delta) + lowerBoundInt);
174
+ }
175
+ // Adds thousands comma's to given value, E.g. '1000' to '1,000'. Returns empty string if value was undefined.
176
+ static AddThousandsCommasTo(value) {
177
+ if (isNill(value)) {
178
+ return "";
179
+ }
180
+ return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
181
+ }
182
+ /**
183
+ * Function used to check wether a given number is composed of another number, power-of-two wise.
184
+ * Example usage: NumberUtils.NumIsComposedOf(articleListObject.publication, ArticlePublication.Selector).
185
+ * This would return whether or not that articleListObject was publicated for selector or not, where articleListObject.publication
186
+ * was possibly a 'COMPOSITE that was made out of (including)' ArticlePublication.Selector.
187
+ */
188
+ static NumIsComposedOfOtherPowTwoNum(bigNrToCheck, powTwoNumItShouldBeComposedOf) {
189
+ if (!bigNrToCheck) {
190
+ return false;
191
+ }
192
+ else if (!powTwoNumItShouldBeComposedOf) {
193
+ return true;
194
+ }
195
+ else {
196
+ return ((bigNrToCheck & powTwoNumItShouldBeComposedOf) === powTwoNumItShouldBeComposedOf);
197
+ }
198
+ }
199
+ /**
200
+ * Returns given nr, or the given default number (default 0) if the nr number was undefined or otherwise not a number.
201
+ * Same as CoMath.NaN from AS code (used as its substitute in transaction logic)
202
+ * @param nr
203
+ * @param defaultNr
204
+ * @returns {number}
205
+ */
206
+ static NrOrDefault(nr, defaultNr = 0) {
207
+ if (notNill(nr) && NumberUtils.IsNumber(nr)) {
208
+ return nr;
209
+ }
210
+ else {
211
+ return defaultNr;
212
+ }
213
+ }
214
+ /**
215
+ * Returns whether given nrToCheck is within the given precision and scale limits. Precision and scale, here, are Oracle DB terms.
216
+ * This function can thus be used to check whether the given number is safe to send to the 'database' beforehand, if we know the
217
+ * precision and scale of the number in the db declaration.
218
+ *
219
+ * I.e. A number declared in the Oracle DB as number(5, 2) has a precision of 5 and a scale of 2.
220
+ *
221
+ * @param {number} nrToCheck
222
+ * @param {number} precision The number of significant digits, including possibly negative scale. E.g. 3 in '123' and 5 in '51.123'
223
+ * @param {number} [scale = 0] The number of significant digits AFTER the decimal point. E.g. 1 in 5432.1 and 3 in 54000.003
224
+ * @returns {CheckPrecisionAndScaleResult} Whether given nrToCheck is ok for given precision and scale, and if not, the
225
+ * nearest number that IS ok for those constraints.
226
+ */
227
+ static CheckPrecisionAndScale(nrToCheck, precision, scale = 0) {
228
+ // let's say any undefined number is checked OK, and all numbers are checked OK for an undefined precision
229
+ if (!ObjectUtils.AllExist(nrToCheck, precision, scale)) {
230
+ return { isOk: true, nearestOkNr: NaN };
231
+ }
232
+ // no number can have 0 or less than 0 significant digits, in our universe
233
+ if (precision < 1 || precision - scale < 1) {
234
+ return { isOk: false, nearestOkNr: NaN };
235
+ }
236
+ // begin check
237
+ const isNegative = (nrToCheck < 0);
238
+ const nrParts = nrToCheck.toString().split(".");
239
+ // remove minus sign if negative
240
+ if (isNegative) {
241
+ nrParts[0] = nrParts[0].slice(1);
242
+ }
243
+ const numCountBeforeDot = nrParts[0].length;
244
+ const allowedNumCountBeforeDot = precision - scale;
245
+ if (numCountBeforeDot <= allowedNumCountBeforeDot) {
246
+ return { isOk: true, nearestOkNr: nrToCheck };
247
+ }
248
+ else {
249
+ // cut a part from the "before decimal number" so that the number is not too big anymore
250
+ const numCountToRemove = numCountBeforeDot - allowedNumCountBeforeDot;
251
+ // remove the right-most numbers before the decimal dot
252
+ nrParts[0] = nrParts[0].slice(0, -1 * numCountToRemove);
253
+ // add minus sign again if it was negative
254
+ if (isNegative) {
255
+ nrParts[0] = "-" + nrParts[0];
256
+ }
257
+ // build and return composite number again
258
+ let nearestOkNr;
259
+ if (nrParts[1]) {
260
+ nearestOkNr = Number(nrParts[0] + "." + nrParts[1]);
261
+ }
262
+ else {
263
+ nearestOkNr = Number(nrParts[0]);
264
+ }
265
+ return { isOk: false, nearestOkNr: nearestOkNr };
266
+ }
267
+ }
268
+ /**
269
+ * Returns whether given x is OK within the given min, max and step boundaries, where it should hold that nrToCheck = min + N * step,
270
+ * with N integer or 0.
271
+ * @param {number} nrToCheck Number to check whether it's within the given bounds
272
+ * @param min Inclusive
273
+ * @param max Inclusive
274
+ * @param stepSize
275
+ * @returns {CheckWithinSteppedBounds} Returns remainder of undefined when nrToCheck was OUTSIDE [min, max], else full result object.
276
+ */
277
+ static CheckWithinSteppedBounds(nrToCheck, min, max, stepSize = 1) {
278
+ if (nrToCheck < min || nrToCheck > max) {
279
+ return { isOk: false, remainder: undefined };
280
+ }
281
+ // we're in [min, max], but still check if nrToCheck = min + N * step holds (for N integer or 0)
282
+ let remainder = (nrToCheck - min) % stepSize;
283
+ // correct float for largest precision amongst input numbers
284
+ remainder = NumberUtils.ParseFloat(remainder, NumberUtils._GetLargestDecimalPrecisionOf(nrToCheck, min, stepSize));
285
+ return { isOk: (remainder === 0), remainder: remainder };
286
+ }
287
+ /**
288
+ * Finds the number closest to the originalNumber, that adheres to the given bounds. That is, for which it holds that
289
+ * nr = min + N * step with N integer or 0.
290
+ * @param {number} originalNr Find closest answer to this number
291
+ * @param min Inclusive
292
+ * @param max Inclusive
293
+ * @param stepSize
294
+ * @returns {boolean} The closest OK number for bounds.
295
+ */
296
+ static GetNearestNumberWithinSteppedBounds(originalNr, min, max, stepSize = 1) {
297
+ if (originalNr < min) {
298
+ return min;
299
+ }
300
+ else if (originalNr > max) {
301
+ return NumberUtils.GetTrueSteppedBoundsMax(min, max, stepSize);
302
+ }
303
+ const boundsCheck = NumberUtils.CheckWithinSteppedBounds(originalNr, min, max, stepSize);
304
+ if (boundsCheck.isOk) {
305
+ return originalNr;
306
+ }
307
+ let answer;
308
+ const remainder = boundsCheck.remainder;
309
+ if (remainder) {
310
+ // round up or down?
311
+ if ((remainder / stepSize) < 0.5) {
312
+ // round down, but not below min
313
+ answer = (originalNr - remainder >= min ? originalNr - remainder : min);
314
+ }
315
+ else {
316
+ // round up, but not above max
317
+ answer = (originalNr + stepSize - remainder <= max ? originalNr + stepSize - remainder :
318
+ NumberUtils.GetTrueSteppedBoundsMax(min, max, stepSize));
319
+ }
320
+ }
321
+ else {
322
+ // is this real life, why wasn't our stepped bounds check OK?
323
+ answer = originalNr;
324
+ }
325
+ // 'correct' float errors
326
+ answer = NumberUtils.ParseFloat(answer, NumberUtils._GetLargestDecimalPrecisionOf(originalNr, min, max, stepSize));
327
+ return answer;
328
+ }
329
+ /**
330
+ * Returns the true maximum allowed value for the given "stepped bounds": min, stepSize and max, for which it holds that each allowed
331
+ * value Y = min + stepSize * N, for any INTEGER or 0 N where it also holds, of course, that Y <= max.
332
+ * @param min
333
+ * @param max
334
+ * @param stepSize
335
+ */
336
+ static GetTrueSteppedBoundsMax(min, max, stepSize = 1) {
337
+ // solve max integer X in formula min + X * step <= max, and return min + X * stepSize for that X
338
+ const maxSteps = Math.floor((max - min) / stepSize);
339
+ // 'correct' float errors
340
+ return NumberUtils.ParseFloat(min + maxSteps * stepSize, NumberUtils._GetLargestDecimalPrecisionOf(min, min, max));
341
+ }
342
+ // Returns the nearest number, relative to the given originalNr, that is within the given [min, max] inclusive bounds.
343
+ static GetNearestNumberWithinBounds(originalNr, min, max) {
344
+ let answer = originalNr;
345
+ if (originalNr < min) {
346
+ answer = min;
347
+ }
348
+ else if (originalNr > max) {
349
+ answer = max;
350
+ }
351
+ return answer;
352
+ }
353
+ // Returns the string representation of given number. If it's not a number, returns the empty string.
354
+ static ToString(nr) {
355
+ if (!NumberUtils.IsNaN(nr)) {
356
+ return "" + nr;
357
+ }
358
+ else {
359
+ return "";
360
+ }
361
+ }
362
+ static DecimalsToStepIncrement(numberOfDecimals) {
363
+ return Math.pow(10, -1 * numberOfDecimals);
364
+ }
365
+ static Round(value, decimals) {
366
+ const factor = Math.pow(10, decimals);
367
+ return Math.round(value * factor) / factor;
368
+ }
369
+ // @returns The inclusive max value
370
+ static PrecisionScaleToMaxValue(precision, scale) {
371
+ const oneStep = this.DecimalsToStepIncrement(scale);
372
+ const maxExclusive = Math.pow(10, precision - scale);
373
+ return maxExclusive - oneStep;
374
+ }
375
+ // @returns the difference between given 2 numbers
376
+ static DifferenceBetweenNumbers(numberA, numberB) {
377
+ return Math.abs(numberA - numberB);
378
+ }
379
+ static _GetLargestDecimalPrecisionOf(...args) {
380
+ const result = ArrayUtils.GetMaxCalculatedValue(args, (arg) => {
381
+ return NumberUtils.GetDecimalPlaces(arg);
382
+ });
383
+ return result;
384
+ }
385
+ // Returns given number input as a number that's useable by Javascript. Allows for incoming ',' decimal delimiter.
386
+ static _NumberInputToNumberStr(numberInput) {
387
+ return (numberInput + "").replace(",", ".");
388
+ }
389
+ }
390
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibnVtYmVyLXV0aWxzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvc2hhcmVkY29tcG9uZW50cy9zcmMvbGliL3V0aWxzL251bWJlci11dGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUMsV0FBVyxFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFFM0MsT0FBTyxFQUFDLFVBQVUsRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUV6QyxPQUFPLEVBQUMsTUFBTSxFQUFDLE1BQU0sb0JBQW9CLENBQUM7QUFDMUMsT0FBTyxFQUFDLE9BQU8sRUFBQyxNQUFNLDhCQUE4QixDQUFDO0FBRXJELHlGQUF5RjtBQUN6RixNQUFNLE9BQU8sV0FBVztJQUNwQixzRUFBc0U7SUFDL0QsTUFBTSxDQUFDLG1CQUFtQixDQUFDLEdBQVE7UUFDdEMsT0FBTyxXQUFXLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyx1QkFBdUIsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQzFFLENBQUM7SUFFRCx1SUFBdUk7SUFDaEksTUFBTSxDQUFDLFFBQVEsQ0FBQyxHQUFRO1FBQzNCLElBQUksTUFBTSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUU7WUFDbkMsT0FBTyxTQUFTLENBQUM7U0FDcEI7UUFFRCxPQUFPLFFBQVEsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDN0IsQ0FBQztJQUVELHNFQUFzRTtJQUMvRCxNQUFNLENBQUMscUJBQXFCLENBQUMsR0FBUSxFQUFFLG1CQUEyQixDQUFDO1FBQ3RFLE9BQU8sV0FBVyxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsdUJBQXVCLENBQUMsR0FBRyxDQUFDLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztJQUM5RixDQUFDO0lBRU0sTUFBTSxDQUFDLGtDQUFrQyxDQUFDLEdBQVE7UUFDckQsTUFBTSxpQkFBaUIs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QUMsQ0FBQztRQUM1RCxNQUFNLFlBQVksR0FBVyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxTQUFTLEdBQUcsS0FBSyxDQUFDLENBQUM7UUFDN0QsT0FBTyxZQUFZLEdBQUcsT0FBTyxDQUFDO0lBQ2xDLENBQUM7SUFFRCxrREFBa0Q7SUFDM0MsTUFBTSxDQUFDLHdCQUF3QixDQUFDLE9BQWUsRUFBRSxPQUFlO1FBQ25FLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDLENBQUM7SUFDdkMsQ0FBQztJQUVPLE1BQU0sQ0FBQyw2QkFBNkIsQ0FBQyxHQUFHLElBQWM7UUFDMUQsTUFBTSxNQUFNLEdBQUcsVUFBVSxDQUFDLHFCQUFxQixDQUFDLElBQUksRUFBRSxDQUFDLEdBQVcsRUFBRSxFQUFFO1lBQ2xFLE9BQU8sV0FBVyxDQUFDLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzdDLENBQUMsQ0FBQyxDQUFDO1FBQ0gsT0FBTyxNQUFNLENBQUM7SUFDbEIsQ0FBQztJQUVELGtIQUFrSDtJQUMxRyxNQUFNLENBQUMsdUJBQXVCLENBQUMsV0FBbUI7UUFDdEQsT0FBTyxDQUFDLFdBQVcsR0FBRyxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ2hELENBQUM7Q0FDSiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7T2JqZWN0VXRpbHN9IGZyb20gXCIuL29iamVjdC11dGlsc1wiO1xuaW1wb3J0IHtDaGVja1dpdGhpblN0ZXBwZWRCb3VuZHNSZXN1bHR9IGZyb20gXCIuL2NoZWNrLXdpdGhpbi1zdGVwcGVkLWJvdW5kcy1yZXN1bHRcIjtcbmltcG9ydCB7QXJyYXlVdGlsc30gZnJvbSBcIi4vYXJyYXktdXRpbHNcIjtcbmltcG9ydCB7Q2hlY2tQcmVjaXNpb25BbmRTY2FsZVJlc3VsdH0gZnJvbSBcIi4vY2hlY2stcHJlY2lzaW9uLWFuZC1zY2FsZS1yZXN1bHRcIjtcbmltcG9ydCB7aXNOaWxsfSBmcm9tIFwiLi9pcy1uaWxsLmZ1bmN0aW9uXCI7XG5pbXBvcnQge25vdE5pbGx9IGZyb20gXCIuL2Z1bmN0aW9uL25vdC1uaWxsLmZ1bmN0aW9uXCI7XG5cbi8vIFN0YXRpYyB1dGlsaXR5IGZ1bmN0aW9uIGhvbGRlciByZWxhdGVkIHRvIG51bWVyaWMgdmFyaWFibGUgZXZhbHVhdGlvbnMgYW5kIG9wZXJhdGlvbnMuXG5leHBvcnQgY2xhc3MgTnVtYmVyVXRpbHMge1xuICAgIC8vIEZvciB1c2VyLXR5cGVkIG51bWJlciBpbnB1dDsgc3VwcG9ydHMgY29tbWEncyBhcyBkZWNpbWFsIGRlbGltaXRlci5cbiAgICBwdWJsaWMgc3RhdGljIFBhcnNlSW50TnVtYmVySW5wdXQoYXJnOiBhbnkpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gTnVtYmVyVXRpbHMuUGFyc2VJbnQoTnVtYmVyVXRpbHMuX051bWJlcklucHV0VG9OdW1iZXJTdHIoYXJnKSk7XG4gICAgfVxuXG4gICAgLy8gUGFyc2VzIGdpdmVuIGFyZ3VtZW50IHRvIGFuIGludGVnZXIsIHVzaW5nIGEgbmF0aXZlIHBhcnNlSW50KCkgZnVuY3Rpb24gd2l0aCBhIHJhZGl4IG9mIDEwLiBSZXR1cm5zIE5hTiBpZiBwYXJzaW5nIHdhcyBub3QgcG9zc2libGUuXG4gICAgcHVibGljIHN0YXRpYyBQYXJzZUludChhcmc6IGFueSk6IG51bWJlciB7XG4gICAgICAgIGlmIChpc05pbGwoYXJnKSB8fCBBcnJheS5pc0FycmF5KGFyZykpIHtcbiAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcGFyc2VJbnQoYXJnLCAxMCk7XG4gICAgfVxuXG4gICAgLy8gRm9yIHVzZXItdHlwZWQgbnVtYmVyIGlucHV0OyBzdXBwb3J0cyBjb21tYSdzIGFzIGRlY2ltYWwgZGVsaW1pdGVyLlxuICAgIHB1YmxpYyBzdGF0aWMgUGFyc2VGbG9hdE51bWJlcklucHV0KGFyZzogYW55LCBkZWNpbWFsUHJlY2lzaW9uOiBudW1iZXIgPSAyKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIE51bWJlclV0aWxzLlBhcnNlRmxvYXQoTnVtYmVyVXRpbHMuX051bWJlcklucHV0VG9OdW1iZXJTdHIoYXJnKSwgZGVjaW1hbFByZWNpc2lvbik7XG4gICAgfVxuXG4gICAgcHVibGljIHN0YXRpYyBQYXJzZUZsb2F0TnVtYmVySW5wdXRLZWVwUHJlY2lzaW9uKGFyZzogYW55KTogbnVtYmVyIHtcbiAgICAgICAgY29uc3QgY29ycmVjdGVkSW5wdXRTdHI6IHN0cmluZyA9IE51bWJlclV0aWxzLl9OdW1iZXJJbnB1dFRvTnVtYmVyU3RyKGFyZyk7XG4gICAgICAgIGNvbnN0IGRlY2ltYWxQcmVjaXNpb246IG51bWJlciA9IHRoaXMuR2V0RGVjaW1hbFBsYWNlcyhjb3JyZWN0ZWRJbnB1dFN0cik7XG4gICAgICAgIHJldHVybiBOdW1iZXJVdGlscy5QYXJzZUZsb2F0KGNvcnJlY3RlZElucHV0U3RyLCBkZWNpbWFsUHJlY2lzaW9uKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGdpdmVuIGFyZyBhcyBhIGZsb2F0IG51bWJlciB3aXRoIGdpdmVuIGRlY2ltYWwgcHJlY2lzaW9uLCBpZiBwb3NzaWJsZS4gUmV0dXJucyBOYU4gaWYgcGFyc2UgY29udmVyc2lvbiBmYWlsZWQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge2FueX0gYXJnIFRoZSBhcmd1bWVudCB0byBwYXJzZSB0byBhIGZsb2F0XG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGRlY2ltYWxQcmVjaXNpb24gVGhlIG51bWJlciBvZiBkZWNpbWFscywgb3IgdGhlIHByZWNpc2lvbiwgdGhlIHBhcnNlZCByZXR1cm4gZmxvYXQgc2hvdWxkIGhhdmVcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBOYU4gaWYgbm90IHBvc3NpYmxlLCBlbHNlIHRoZSBwYXJzZWQgZmxvYXQgdmFsdWVcbiAgICAgKi9cbiAgICBwdWJsaWMgc3RhdGljIFBhcnNlRmxvYXQoYXJnOiBhbnksIGRlY2ltYWxQcmVjaXNpb246IG51bWJlciA9IDIpOiBudW1iZXIge1xuICAgICAgICBpZiAoIU9iamVjdFV0aWxzLkFsbEV4aXN0KGFyZywgZGVjaW1hbFByZWNpc2lvbikgfHwgQXJyYXkuaXNBcnJheShhcmcpKSB7XG4gICAgICAgICAgICByZXR1cm4gTmFOO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFOdW1iZXJVdGlscy5Jc0ludGVnZXIoZGVjaW1hbFByZWNpc2lvbikgfHwgZGVjaW1hbFByZWNpc2lvbiA8IDApIHtcbiAgICAgICAgICAgIGRlY2ltYWxQcmVjaXNpb24gPSAyO1xuICAgICAgICAgICAgLy8gdG9GaXhlZCgpIGNhbiBvbmx5IGhhbmRsZSB1cCB1bnRpbCAyMFxuICAgICAgICB9IGVsc2UgaWYgKGRlY2ltYWxQcmVjaXNpb24gPiAyMCkge1xuICAgICAgICAgICAgZGVjaW1hbFByZWNpc2lvbiA9IDIwO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHBhcnNlRmxvYXQocGFyc2VGbG9hdChhcmcpLnRvRml4ZWQoZGVjaW1hbFByZWNpc2lvbikpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgZ2l2ZW4gYXJnIGFzIGEgZmxvYXQgbnVtYmVyIHdpdGggZ2l2ZW4gZGVjaW1hbCBwcmVjaXNpb24sIGlmIHBvc3NpYmxlLiBSZXR1cm5zIE5hTiBpZiBwYXJzZSBjb252ZXJzaW9uIGZhaWxlZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBhcmcgVGhlIGFyZ3VtZW50IHRvIHBhcnNlIHRvIGEgZmxvYXRcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBUaGUgYXJndW1lbnQgYXMgYSBmbG9hdCB3aXRoIGl0cyBvcmlnaW5hbCBkZWNpbWFsIHByZWNpc2lvbiBpbnRhY3RcbiAgICAgKi9cbiAgICBwdWJsaWMgc3RhdGljIFBhcnNlRmxvYXRLZWVwUHJlY2lzaW9uKGFyZzogYW55KTogbnVtYmVyIHtcbiAgICAgICAgY29uc3QgZGVjaW1hbFByZWNpc2lvbjogbnVtYmVyID0gdGhpcy5HZXREZWNpbWFsUGxhY2VzKGFyZyk7XG4gICAgICAgIHJldHVybiB0aGlzLlBhcnNlRmxvYXQoYXJnLCBkZWNpbWFsUHJlY2lzaW9uKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBnaXZlbiBhcmd1bWVudCBhcyBhIG51bWJlci4gUmV0dXJucyBnaXZlbiBkZWZhdWx0VmFsdWUgaWYgY29udmVyc2lvbiBvZiBhcmd1bWVudCB3YXMgaW1wb3NzaWJsZS5cbiAgICAgKiBAcGFyYW0gYXJnXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtkZWZhdWx0VmFsdWUgPSAwXVxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9XG4gICAgICovXG4gICAgcHVibGljIHN0YXRpYyBQYXJzZU51bWJlck9yRGVmYXVsdChhcmc6IGFueSwgZGVmYXVsdFZhbHVlOiBudW1iZXIgPSAwKTogbnVtYmVyIHtcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoYXJnKSkge1xuICAgICAgICAgICAgcmV0dXJuIGRlZmF1bHRWYWx1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghTnVtYmVyVXRpbHMuSXNOdW1iZXIoYXJnKSkge1xuICAgICAgICAgICAgYXJnID0gcGFyc2VGbG9hdChhcmcpO1xuICAgICAgICAgICAgYXJnID0gaXNOYU4oYXJnKSA/IGRlZmF1bHRWYWx1ZSA6IGFyZztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYXJnO1xuICAgIH1cblxuICAgIC8vIFJldHVybnMgdHJ1ZSBpZmYgZ2l2ZW4gYXJndW1lbnQgaXMgYW4gaW50ZWdlciBudW1iZXIuIFJldHVybnMgZmFsc2Ugb24gbm9uLW51bWJlcnMgb3IgbnVtYmVycyB3aXRoIHNpZ25pZmljYW50IGRlY2ltYWxzLlxuICAgIHB1YmxpYyBzdGF0aWMgSXNJbnRlZ2VyKGFyZzogYW55KTogYm9vbGVhbiB7XG4gICAgICAgIGlmIChpc05hTihhcmcpIHx8IEFycmF5LmlzQXJyYXkoYXJnKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGFyZ0FzRmxvYXQ6IG51bWJlciA9IHBhcnNlRmxvYXQoYXJnKTtcbiAgICAgICAgcmV0dXJuICgoYXJnQXNGbG9hdCB8IDApID09PSBhcmdBc0Zsb2F0KTsgLy8gcmV0dXJucyB3aGV0aGVyICdhcmcgY29udmVydGVkIHRvIGFuIGludGVnZXIgZXF1YWxzIGFyZydcbiAgICB9XG5cbiAgICAvLyBSZXR1cm5zIHRoZSBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMgb2YgdGhlIGdpdmVuIG51bWJlci4gUmV0dXJucyAwIGlmIG5vIGRlY2ltYWxzIHdoYXRzb2V2ZXIgY291bGQgYmUgZm91bmQgb24gZ2l2ZW4gYXJnLlxuICAgIHB1YmxpYyBzdGF0aWMgR2V0RGVjaW1hbFBsYWNlcyhhcmc6IGFueSwgbWF4QW5zd2VyOiBudW1iZXIgPSAxMDAwKTogbnVtYmVyIHtcbiAgICAgICAgY29uc3QgbWF0Y2g6IFJlZ0V4cE1hdGNoQXJyYXkgPSAoXCJcIiArIGFyZykubWF0Y2goLyg/OlxcLihcXGQrKSk/KD86W2VFXShbKy1dP1xcZCspKT8kLyk7XG4gICAgICAgIGlmICghbWF0Y2gpIHtcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGFuc3dlcjogbnVtYmVyID0gTWF0aC5tYXgoMCxcbiAgICAgICAgICAgIC8vIG51bWJlciBvZiBkaWdpdHMgcmlnaHQgb2YgZGVjaW1hbCBwb2ludC5cbiAgICAgICAgICAgIChtYXRjaFsxXSA/IG1hdGNoWzFdLmxlbmd0aCA6IDApXG4gICAgICAgICAgICAvLyBhZGp1c3QgZm9yIHNjaWVudGlmaWMgbm90YXRpb25cbiAgICAgICAgICAgIC0gKG1hdGNoWzJdID8gK21hdGNoWzJdIDogMCkpO1xuXG4gICAgICAgIGlmIChhbnN3ZXIgPiBtYXhBbnN3ZXIpIHtcbiAgICAgICAgICAgIGFuc3dlciA9IG1heEFuc3dlcjtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBhbnN3ZXI7XG4gICAgfVxuXG4gICAgLy8gUGFyc2VzIGdpdmVuIG51bWJlcklucHV0IHRvIGEgbnVtYmVyLCBvciByZXR1cm5zIGdpdmVuIGRlZmF1bHRWYWx1ZSBpZiBwYXJzZSBub3QgcG9zc2libGUuIEFsbG93cyAnLCcgY2hhciBhcyBkZWNpbWFsIGRlbGltaXRlci5cbiAgICBwdWJsaWMgc3RhdGljIFBhcnNlTnVtYmVySW5wdXRPckRlZmF1bHQobnVtYmVySW5wdXQ6IGFueSwgZGVmYXVsdFZhbHVlOiBudW1iZXIgPSAwKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIE51bWJlclV0aWxzLlBhcnNlTnVtYmVyT3JEZWZhdWx0KE51bWJlclV0aWxzLl9OdW1iZXJJbnB1dFRvTnVtYmVyU3RyKG51bWJlcklucHV0KSwgZGVmYXVsdFZhbHVlKTtcbiAgICB9XG5cbiAgICAvLyBSZXR1cm5zIHdoZXRoZXIgdGhlIHR5cGUgb2YgZ2l2ZW4gYXJndW1lbnQgaXMgJ251bWJlcicuXG4gICAgcHVibGljIHN0YXRpYyBJc051bWJlcihhcmc6IGFueSk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gXCJudW1iZXJcIiAmJiAhaXNOYU4oYXJnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHdoZXRoZXIgZ2l2ZW4gYXJnIGlzIGluZGVlZCBub3QgYSBudW1iZXIgKGl0J3MgTmFOIG9yIGl0IGhhcyBhbm90aGVyIHR5cGUgdGhhbiAnbnVtYmVyJylcbiAgICAgKiBPdXIgZXhhY3QgY29weSBvZiBBUyBGbGV4J2VzIGlzTmFOKGFyZykgZnVuY3Rpb24uIEFsd2F5cyB1c2UgdGhpcyBtZXRob2QgZm9yIGNvcHlpbmcgRmxleCBpc05hTiguLikgb2NjdXJlbmNlcyBpbnRvIFR5cGVTY3JpcHQuXG4gICAgICogQHBhcmFtIGFyZ1xuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqIEBjb25zdHJ1Y3RvclxuICAgICAqL1xuICAgIHB1YmxpYyBzdGF0aWMgSXNOYU4oYXJnOiBhbnkpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIGlzTmFOKGFyZykgfHwgIU51bWJlclV0aWxzLklzTnVtYmVyKGFyZyk7XG4gICAgfVxuXG4gICAgLy8gT3VyIGNvcHkgb2YgQ29NYXRoLk5hTi4gUmV0dXJucyBudW1iZXIsIG9yIHN1YnN0aXR1dGUgaWYgTnVtYmVyVXRpbHMuSXNOYU4obnVtYmVyKSBob2xkcyB0cnVlLlxuICAgIHB1YmxpYyBzdGF0aWMgTmFOKG51bWJlcjogYW55LCBzdWJzdGl0dXRlOiBudW1iZXIgPSAwKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIE51bWJlclV0aWxzLklzTmFOKG51bWJlcikgPyBzdWJzdGl0dXRlIDogbnVtYmVyO1xuICAgIH1cblxuICAgIC8vIFJldHVybnMgd2hldGhlciB0aGUgdmFsdWUgaXMgcGFyYXNhYmxlIGFzIGEgbnVtYmVyLlxuICAgIHB1YmxpYyBzdGF0aWMgSXNQYXJzYWJsZU51bWJlcihhcmc6IGFueSk6IGJvb2xlYW4ge1xuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShhcmcpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gIWlzTmFOKHBhcnNlRmxvYXQoYXJnKSk7XG4gICAgfVxuXG4gICAgcHVibGljIHN0YXRpYyBJc1BhcnNhYmxlTnVtYmVySW5wdXQobnVtYmVySW5wdXQ6IGFueSk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gTnVtYmVyVXRpbHMuSXNQYXJzYWJsZU51bWJlcihOdW1iZXJVdGlscy5fTnVtYmVySW5wdXRUb051bWJlclN0cihudW1iZXJJbnB1dCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgd2hldGhlciBnaXZlbiBhcmcgaXMgcGFyc2VhYmxlIGFzIGEgbnVtYmVyLCBhbmQgd2hldGhlciB0aGUgbGVuZ3RzIG9mIGl0cyBudW1iZXIgcGFyc2UgcmVzdWx0IGlzIGVxdWFsIHRvIGl0cyBvcmlnaW5hbCBsZW5ndGguXG4gICAgICogSS5lLiB0aGlzIGZ1bmN0aW9uIHJldHVybnMgRkFMU0Ugd2l0aCBnaXZlbiBudW1iZXItcGFyc2FibGUgc3RyaW5ncywgYnV0IHRoYXQgaGF2ZSBub24tbnVtZXJpYyBhcHBlbmRpY2VzLCBlZyAnMjIzM2ZmJy4gVGhhdCBhcmdcbiAgICAgKiBJUyBudW1iZXItcGFyc2VhYmxlLCBidXQgbm90IGEgc3RyaWN0ICdzdHJpbmcgbnVtYmVyJywgdGhlIGxhdHRlciBiZWluZyB3aGF0IHRoaXMgbWV0aG9kIGFjdHVhbGx5IGNoZWNrcyBmb3IuXG4gICAgICovXG4gICAgcHVibGljIHN0YXRpYyBJc1N0cmluZ051bWJlcihhcmc6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgICAgICBpZiAoIU51bWJlclV0aWxzLklzUGFyc2FibGVOdW1iZXIoYXJnKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGFyZy50b1N0cmluZygpLmxlbmd0aCA9PT0gcGFyc2VGbG9hdChhcmcpLnRvU3RyaW5nKCkubGVuZ3RoO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIHN0YXRpYyBJc0xpc3RPZk51bWJlcnMoYXJnOiBzdHJpbmcsIHNlcGFyYXRvcjogc3RyaW5nID0gXCIsXCIpOiBib29sZWFuIHtcbiAgICAgICAgY29uc3QgbnJzOiBzdHJpbmdbXSA9IGFyZy5zcGxpdChzZXBhcmF0b3IpO1xuICAgICAgICBpZiAobnJzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBucnMuZmlsdGVyKHMgPT4gTnVtYmVyVXRpbHMuSXNTdHJpbmdOdW1iZXIocykpLmxlbmd0aCA9PT0gbnJzLmxlbmd0aDtcbiAgICB9XG5cbiAgICAvLyBSZXR1cm5zIGdpdmVuIGFyZ3VtZW50IGFzIGEgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIGEgbnVtYmVyIHBhcnNlLCBlLmcuIFwiMVwiIGZvciBhIG51bWJlciBwYXJzZSByZXN1bHQgb2YgYXJnIHRvIDEuXG4gICAgcHVibGljIHN0YXRpYyBQYXJzZVN0cmluZ051bWJlcihhcmc6IHN0cmluZyk6IG51bWJlciB7XG4gICAgICAgIGlmICghdGhpcy5Jc1N0cmluZ051bWJlcihhcmcpKSB7XG4gICAgICAgICAgICByZXR1cm4gTmFOO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIE51bWJlclV0aWxzLlBhcnNlRmxvYXRLZWVwUHJlY2lzaW9uKGFyZyk7XG4gICAgfVxuXG4gICAgcHVibGljIHN0YXRpYyBQYXJzZVN0cmluZ051bWJlckRlZmF1bHQoYXJnOiBzdHJpbmcgfCBhbnksIGRlZmF1bHRWYWx1ZTogbnVtYmVyID0gMCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiBOdW1iZXJVdGlscy5OYU4oTnVtYmVyVXRpbHMuUGFyc2VTdHJpbmdOdW1iZXIoYXJnKSwgZGVmYXVsdFZhbHVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGEgcmFuZG9tIGludGVnZXIgaW4gcmFuZ2UgW2xvd2VyQm91bmQgLi4gdXBwZXJCb3VuZF0sIGFuIGluY2x1c2l2ZSByYW5nZS4gUmV0dXJucyBOYU4gaWYgbm90IHBvc3NpYmxlLlxuICAgICAqIEdpdmVuIGJvdW5kcyBhcmUgdHJ1bmNhdGVkIGZpcnN0LCBiZWZvcmUgc2VydmluZyBhcyB0aGUgdHJ1ZSBsb3dlci0gYW5kIHVwcGVyIGJvdW5kcyBmb3IgdGhlIHJhbmRvbSBpbnQuXG4gICAgICovXG4gICAgcHVibGljIHN0YXRpYyBSYW5kb21JbnQobG93ZXJCb3VuZEludDogbnVtYmVyLCB1cHBlckJvdW5kSW50OiBudW1iZXIpOiBudW1iZXIge1xuICAgICAgICBpZiAoIU51bWJlclV0aWxzLklzTnVtYmVyKGxvd2VyQm91bmRJbnQpIHx8ICFOdW1iZXJVdGlscy5Jc051bWJlcih1cHBlckJvdW5kSW50KSB8fCBsb3dlckJvdW5kSW50ID4gdXBwZXJCb3VuZEludCkge1xuICAgICAgICAgICAgcmV0dXJuIE5hTjtcbiAgICAgICAgfVxuXG4gICAgICAgIGxvd2VyQm91bmRJbnQgPSBNYXRoLnRydW5jKGxvd2VyQm91bmRJbnQpO1xuICAgICAgICB1cHBlckJvdW5kSW50ID0gTWF0aC50cnVuYyh1cHBlckJvdW5kSW50KTtcblxuICAgICAgICBpZiAobG93ZXJCb3VuZEludCA9PT0gdXBwZXJCb3VuZEludCkge1xuICAgICAgICAgICAgcmV0dXJuIGxvd2VyQm91bmRJbnQ7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBkZWx0YTogbnVtYmVyID0gdXBwZXJCb3VuZEludCAtIGxvd2VyQm91bmRJbnQ7XG4gICAgICAgIHJldHVybiAoTWF0aC5yb3VuZChNYXRoLnJhbmRvbSgpICogZGVsdGEpICsgbG93ZXJCb3VuZEludCk7XG4gICAgfVxuXG4gICAgLy8gQWRkcyB0aG91c2FuZHMgY29tbWEncyB0byBnaXZlbiB2YWx1ZSwgRS5nLiAnMTAwMCcgdG8gJzEsMDAwJy4gUmV0dXJucyBlbXB0eSBzdHJpbmcgaWYgdmFsdWUgd2FzIHVuZGVmaW5lZC5cbiAgICBwdWJsaWMgc3RhdGljIEFkZFRob3VzYW5kc0NvbW1hc1RvKHZhbHVlOiBhbnkpOiBzdHJpbmcge1xuICAgICAgICBpZiAoaXNOaWxsKHZhbHVlKSkge1xuICAgICAgICAgICAgcmV0dXJuIFwiXCI7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdmFsdWUudG9TdHJpbmcoKS5yZXBsYWNlKC9cXEIoPz0oXFxkezN9KSsoPyFcXGQpKS9nLCBcIixcIik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRnVuY3Rpb24gdXNlZCB0byBjaGVjayB3ZXRoZXIgYSBnaXZlbiBudW1iZXIgaXMgY29tcG9zZWQgb2YgYW5vdGhlciBudW1iZXIsIHBvd2VyLW9mLXR3byB3aXNlLlxuICAgICAqIEV4YW1wbGUgdXNhZ2U6IE51bWJlclV0aWxzLk51bUlzQ29tcG9zZWRPZihhcnRpY2xlTGlzdE9iamVjdC5wdWJsaWNhdGlvbiwgQXJ0aWNsZVB1YmxpY2F0aW9uLlNlbGVjdG9yKS5cbiAgICAgKiBUaGlzIHdvdWxkIHJldHVybiB3aGV0aGVyIG9yIG5vdCB0aGF0IGFydGljbGVMaXN0T2JqZWN0IHdhcyBwdWJsaWNhdGVkIGZvciBzZWxlY3RvciBvciBub3QsIHdoZXJlIGFydGljbGVMaXN0T2JqZWN0LnB1YmxpY2F0aW9uXG4gICAgICogd2FzIHBvc3NpYmx5IGEgJ0NPTVBPU0lURSB0aGF0IHdhcyBtYWRlIG91dCBvZiAoaW5jbHVkaW5nKScgQXJ0aWNsZVB1YmxpY2F0aW9uLlNlbGVjdG9yLlxuICAgICAqL1xuICAgIHB1YmxpYyBzdGF0aWMgTnVtSXNDb21wb3NlZE9mT3RoZXJQb3dUd29OdW0oYmlnTnJUb0NoZWNrOiBudW1iZXIsIHBvd1R3b051bUl0U2hvdWxkQmVDb21wb3NlZE9mOiBudW1iZXIpOiBib29sZWFuIHtcbiAgICAgICAgaWYgKCFiaWdOclRvQ2hlY2spIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfSBlbHNlIGlmICghcG93VHdvTnVtSXRTaG91bGRCZUNvbXBvc2VkT2YpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuICgoYmlnTnJUb0NoZWNrICYgcG93VHdvTnVtSXRTaG91bGRCZUNvbXBvc2VkT2YpID09PSBwb3dUd29OdW1JdFNob3VsZEJlQ29tcG9zZWRPZik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGdpdmVuIG5yLCBvciB0aGUgZ2l2ZW4gZGVmYXVsdCBudW1iZXIgKGRlZmF1bHQgMCkgaWYgdGhlIG5yIG51bWJlciB3YXMgdW5kZWZpbmVkIG9yIG90aGVyd2lzZSBub3QgYSBudW1iZXIuXG4gICAgICogU2FtZSBhcyBDb01hdGguTmFOIGZyb20gQVMgY29kZSAodXNlZCBhcyBpdHMgc3Vic3RpdHV0ZSBpbiB0cmFuc2FjdGlvbiBsb2dpYylcbiAgICAgKiBAcGFyYW0gbnJcbiAgICAgKiBAcGFyYW0gZGVmYXVsdE5yXG4gICAgICogQHJldHVybnMge251bWJlcn1cbiAgICAgKi9cbiAgICBwdWJsaWMgc3RhdGljIE5yT3JEZWZhdWx0KG5yOiBudW1iZXIsIGRlZmF1bHROcjogbnVtYmVyID0gMCk6IG51bWJlciB7XG4gICAgICAgIGlmIChub3ROaWxsKG5yKSAmJiBOdW1iZXJVdGlscy5Jc051bWJlcihucikpIHtcbiAgICAgICAgICAgIHJldHVybiBucjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBkZWZhdWx0TnI7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHdoZXRoZXIgZ2l2ZW4gbnJUb0NoZWNrIGlzIHdpdGhpbiB0aGUgZ2l2ZW4gcHJlY2lzaW9uIGFuZCBzY2FsZSBsaW1pdHMuIFByZWNpc2lvbiBhbmQgc2NhbGUsIGhlcmUsIGFyZSBPcmFjbGUgREIgdGVybXMuXG4gICAgICogVGhpcyBmdW5jdGlvbiBjYW4gdGh1cyBiZSB1c2VkIHRvIGNoZWNrIHdoZXRoZXIgdGhlIGdpdmVuIG51bWJlciBpcyBzYWZlIHRvIHNlbmQgdG8gdGhlICdkYXRhYmFzZScgYmVmb3JlaGFuZCwgaWYgd2Uga25vdyB0aGVcbiAgICAgKiBwcmVjaXNpb24gYW5kIHNjYWxlIG9mIHRoZSBudW1iZXIgaW4gdGhlIGRiIGRlY2xhcmF0aW9uLlxuICAgICAqXG4gICAgICogSS5lLiBBIG51bWJlciBkZWNsYXJlZCBpbiB0aGUgT3JhY2xlIERCIGFzIG51bWJlcig1LCAyKSBoYXMgYSBwcmVjaXNpb24gb2YgNSBhbmQgYSBzY2FsZSBvZiAyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG5yVG9DaGVja1xuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBwcmVjaXNpb24gVGhlIG51bWJlciBvZiBzaWduaWZpY2FudCBkaWdpdHMsIGluY2x1ZGluZyBwb3NzaWJseSBuZWdhdGl2ZSBzY2FsZS4gRS5nLiAzIGluICcxMjMnIGFuZCA1IGluICc1MS4xMjMnXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtzY2FsZSA9IDBdIFRoZSBudW1iZXIgb2Ygc2lnbmlmaWNhbnQgZGlnaXRzIEFGVEVSIHRoZSBkZWNpbWFsIHBvaW50LiBFLmcuIDEgaW4gNTQzMi4xIGFuZCAzIGluIDU0MDAwLjAwM1xuICAgICAqIEByZXR1cm5zIHtDaGVja1ByZWNpc2lvbkFuZFNjYWxlUmVzdWx0fSBXaGV0aGVyIGdpdmVuIG5yVG9DaGVjayBpcyBvayBmb3IgZ2l2ZW4gcHJlY2lzaW9uIGFuZCBzY2FsZSwgYW5kIGlmIG5vdCwgdGhlXG4gICAgICogbmVhcmVzdCBudW1iZXIgdGhhdCBJUyBvayBmb3IgdGhvc2UgY29uc3RyYWludHMuXG4gICAgICovXG4gICAgcHVibGljIHN0YXRpYyBDaGVja1ByZWNpc2lvbkFuZFNjYWxlKG5yVG9DaGVjazogbnVtYmVyLCBwcmVjaXNpb246IG51bWJlciwgc2NhbGU6IG51bWJlciA9IDApOiBDaGVja1ByZWNpc2lvbkFuZFNjYWxlUmVzdWx0IHtcbiAgICAgICAgLy8gbGV0J3Mgc2F5IGFueSB1bmRlZmluZWQgbnVtYmVyIGlzIGNoZWNrZWQgT0ssIGFuZCBhbGwgbnVtYmVycyBhcmUgY2hlY2tlZCBPSyBmb3IgYW4gdW5kZWZpbmVkIHByZWNpc2lvblxuICAgICAgICBpZiAoIU9iamVjdFV0aWxzLkFsbEV4aXN0KG5yVG9DaGVjaywgcHJlY2lzaW9uLCBzY2FsZSkpIHtcbiAgICAgICAgICAgIHJldHVybiB7aXNPazogdHJ1ZSwgbmVhcmVzdE9rTnI6IE5hTn07XG4gICAgICAgIH1cbiAgICAgICAgLy8gbm8gbnVtYmVyIGNhbiBoYXZlIDAgb3IgbGVzcyB0aGFuIDAgc2lnbmlmaWNhbnQgZGlnaXRzLCBpbiBvdXIgdW5pdmVyc2VcbiAgICAgICAgaWYgKHByZWNpc2lvbiA8IDEgfHwgcHJlY2lzaW9uIC0gc2NhbGUgPCAxKSB7XG4gICAgICAgICAgICByZXR1cm4ge2lzT2s6IGZhbHNlLCBuZWFyZXN0T2tOcjogTmFOfTtcbiAgICAgICAgfVxuICAgICAgICAvLyBiZWdpbiBjaGVja1xuICAgICAgICBjb25zdCBpc05lZ2F0aXZlOiBib29sZWFuID0gKG5yVG9DaGVjayA8IDApO1xuICAgICAgICBjb25zdCBuclBhcnRzOiBzdHJpbmdbXSA9IG5yVG9DaGVjay50b1N0cmluZygpLnNwbGl0KFwiLlwiKTtcbiAgICAgICAgLy8gcmVtb3ZlIG1pbnVzIHNpZ24gaWYgbmVnYXRpdmVcbiAgICAgICAgaWYgKGlzTmVnYXRpdmUpIHtcbiAgICAgICAgICAgIG5yUGFydHNbMF0gPSBuclBhcnRzWzBdLnNsaWNlKDEpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IG51bUNvdW50QmVmb3JlRG90OiBudW1iZXIgPSBuclBhcnRzWzBdLmxlbmd0aDtcbiAgICAgICAgY29uc3QgYWxsb3dlZE51bUNvdW50QmVmb3JlRG90OiBudW1iZXIgPSBwcmVjaXNpb24gLSBzY2FsZTtcbiAgICAgICAgaWYgKG51bUNvdW50QmVmb3JlRG90IDw9IGFsbG93ZWROdW1Db3VudEJlZm9yZURvdCkge1xuICAgICAgICAgICAgcmV0dXJuIHtpc09rOiB0cnVlLCBuZWFyZXN0T2tOcjogbnJUb0NoZWNrfTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIGN1dCBhIHBhcnQgZnJvbSB0aGUgXCJiZWZvcmUgZGVjaW1hbCBudW1iZXJcIiBzbyB0aGF0IHRoZSBudW1iZXIgaXMgbm90IHRvbyBiaWcgYW55bW9yZVxuICAgICAgICAgICAgY29uc3QgbnVtQ291bnRUb1JlbW92ZTogbnVtYmVyID0gbnVtQ291bnRCZWZvcmVEb3QgLSBhbGxvd2VkTnVtQ291bnRCZWZvcmVEb3Q7XG4gICAgICAgICAgICAvLyByZW1vdmUgdGhlIHJpZ2h0LW1vc3QgbnVtYmVycyBiZWZvcmUgdGhlIGRlY2ltYWwgZG90XG4gICAgICAgICAgICBuclBhcnRzWzBdID0gbnJQYXJ0c1swXS5zbGljZSgwLCAtMSAqIG51bUNvdW50VG9SZW1vdmUpO1xuICAgICAgICAgICAgLy8gYWRkIG1pbnVzIHNpZ24gYWdhaW4gaWYgaXQgd2FzIG5lZ2F0aXZlXG4gICAgICAgICAgICBpZiAoaXNOZWdhdGl2ZSkge1xuICAgICAgICAgICAgICAgIG5yUGFydHNbMF0gPSBcIi1cIiArIG5yUGFydHNbMF07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBidWlsZCBhbmQgcmV0dXJuIGNvbXBvc2l0ZSBudW1iZXIgYWdhaW5cbiAgICAgICAgICAgIGxldCBuZWFyZXN0T2tOcjogbnVtYmVyO1xuICAgICAgICAgICAgaWYgKG5yUGFydHNbMV0pIHtcbiAgICAgICAgICAgICAgICBuZWFyZXN0T2tOciA9IE51bWJlcihuclBhcnRzWzBdICsgXCIuXCIgKyBuclBhcnRzWzFdKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbmVhcmVzdE9rTnIgPSBOdW1iZXIobnJQYXJ0c1swXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4ge2lzT2s6IGZhbHNlLCBuZWFyZXN0T2tOcjogbmVhcmVzdE9rTnJ9O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB3aGV0aGVyIGdpdmVuIHggaXMgT0sgd2l0aGluIHRoZSBnaXZlbiBtaW4sIG1heCBhbmQgc3RlcCBib3VuZGFyaWVzLCB3aGVyZSBpdCBzaG91bGQgaG9sZCB0aGF0IG5yVG9DaGVjayA9IG1pbiArIE4gKiBzdGVwLFxuICAgICAqIHdpdGggTiBpbnRlZ2VyIG9yIDAuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG5yVG9DaGVjayBOdW1iZXIgdG8gY2hlY2sgd2hldGhlciBpdCdzIHdpdGhpbiB0aGUgZ2l2ZW4gYm91bmRzXG4gICAgICogQHBhcmFtIG1pbiBJbmNsdXNpdmVcbiAgICAgKiBAcGFyYW0gbWF4IEluY2x1c2l2ZVxuICAgICAqIEBwYXJhbSBzdGVwU2l6ZVxuICAgICAqIEByZXR1cm5zIHtDaGVja1dpdGhpblN0ZXBwZWRCb3VuZHN9IFJldHVybnMgcmVtYWluZGVyIG9mIHVuZGVmaW5lZCB3aGVuIG5yVG9DaGVjayB3YXMgT1VUU0lERSBbbWluLCBtYXhdLCBlbHNlIGZ1bGwgcmVzdWx0IG9iamVjdC5cbiAgICAgKi9cbiAgICBwdWJsaWMgc3RhdGljIENoZWNrV2l0aGluU3RlcHBlZEJvdW5kcyhcbiAgICAgICAgbnJUb0NoZWNrOiBudW1iZXIsXG4gICAgICAgIG1pbjogbnVtYmVyLFxuICAgICAgICBtYXg6IG51bWJlcixcbiAgICAgICAgc3RlcFNpemU6IG51bWJlciA9IDFcbiAgICApOiBDaGVja1dpdGhpblN0ZXBwZWRCb3VuZHNSZXN1bHQge1xuICAgICAgICBpZiAobnJUb0NoZWNrIDwgbWluIHx8IG5yVG9DaGVjayA+IG1heCkge1xuICAgICAgICAgICAgcmV0dXJuIHtpc09rOiBmYWxzZSwgcmVtYWluZGVyOiB1bmRlZmluZWR9O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gd2UncmUgaW4gW21pbiwgbWF4XSwgYnV0IHN0aWxsIGNoZWNrIGlmIG5yVG9DaGVjayA9IG1pbiArIE4gKiBzdGVwIGhvbGRzIChmb3IgTiBpbnRlZ2VyIG9yIDApXG4gICAgICAgIGxldCByZW1haW5kZXI6IG51bWJlciA9IChuclRvQ2hlY2sgLSBtaW4pICUgc3RlcFNpemU7XG4gICAgICAgIC8vIGNvcnJlY3QgZmxvYXQgZm9yIGxhcmdlc3QgcHJlY2lzaW9uIGFtb25nc3QgaW5wdXQgbnVtYmVyc1xuICAgICAgICByZW1haW5kZXIgPSBOdW1iZXJVdGlscy5QYXJzZUZsb2F0KHJlbWFpbmRlciwgTnVtYmVyVXRpbHMuX0dldExhcmdlc3REZWNpbWFsUHJlY2lzaW9uT2YobnJUb0NoZWNrLCBtaW4sIHN0ZXBTaXplKSk7XG4gICAgICAgIHJldHVybiB7aXNPazogKHJlbWFpbmRlciA9PT0gMCksIHJlbWFpbmRlcjogcmVtYWluZGVyfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGaW5kcyB0aGUgbnVtYmVyIGNsb3Nlc3QgdG8gdGhlIG9yaWdpbmFsTnVtYmVyLCB0aGF0IGFkaGVyZXMgdG8gdGhlIGdpdmVuIGJvdW5kcy4gVGhhdCBpcywgZm9yIHdoaWNoIGl0IGhvbGRzIHRoYXRcbiAgICAgKiBuciA9IG1pbiArIE4gKiBzdGVwIHdpdGggTiBpbnRlZ2VyIG9yIDAuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG9yaWdpbmFsTnIgRmluZCBjbG9zZXN0IGFuc3dlciB0byB0aGlzIG51bWJlclxuICAgICAqIEBwYXJhbSBtaW4gSW5jbHVzaXZlXG4gICAgICogQHBhcmFtIG1heCBJbmNsdXNpdmVcbiAgICAgKiBAcGFyYW0gc3RlcFNpemVcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gVGhlIGNsb3Nlc3QgT0sgbnVtYmVyIGZvciBib3VuZHMuXG4gICAgICovXG4gICAgcHVibGljIHN0YXRpYyBHZXROZWFyZXN0TnVtYmVyV2l0aGluU3RlcHBlZEJvdW5kcyhvcmlnaW5hbE5yOiBudW1iZXIsIG1pbjogbnVtYmVyLCBtYXg6IG51bWJlciwgc3RlcFNpemU6IG51bWJlciA9IDEpOiBudW1iZXIge1xuICAgICAgICBpZiAob3JpZ2luYWxOciA8IG1pbikge1xuICAgICAgICAgICAgcmV0dXJuIG1pbjtcbiAgICAgICAgfSBlbHNlIGlmIChvcmlnaW5hbE5yID4gbWF4KSB7XG4gICAgICAgICAgICByZXR1cm4gTnVtYmVyVXRpbHMuR2V0VHJ1ZVN0ZXBwZWRCb3VuZHNNYXgobWluLCBtYXgsIHN0ZXBTaXplKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGJvdW5kc0NoZWNrOiBDaGVja1dpdGhpblN0ZXBwZWRCb3VuZHNSZXN1bHQgPSBOdW1iZXJVdGlscy5DaGVja1dpdGhpblN0ZXBwZWRCb3VuZHMob3JpZ2luYWxOciwgbWluLCBtYXgsIHN0ZXBTaXplKTtcbiAgICAgICAgaWYgKGJvdW5kc0NoZWNrLmlzT2spIHtcbiAgICAgICAgICAgIHJldHVybiBvcmlnaW5hbE5yO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGFuc3dlcjogbnVtYmVyO1xuXG4gICAgICAgIGNvbnN0IHJlbWFpbmRlcjogbnVtYmVyID0gYm91bmRzQ2hlY2sucmVtYWluZGVyO1xuICAgICAgICBpZiAocmVtYWluZGVyKSB7XG4gICAgICAgICAgICAvLyByb3VuZCB1cCBvciBkb3duP1xuICAgICAgICAgICAgaWYgKChyZW1haW5kZXIgLyBzdGVwU2l6ZSkgPCAwLjUpIHtcbiAgICAgICAgICAgICAgICAvLyAgcm91bmQgZG93biwgYnV0IG5vdCBiZWxvdyBtaW5cbiAgICAgICAgICAgICAgICBhbnN3ZXIgPSAob3JpZ2luYWxOciAtIHJlbWFpbmRlciA+PSBtaW4gPyBvcmlnaW5hbE5yIC0gcmVtYWluZGVyIDogbWluKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gcm91bmQgdXAsIGJ1dCBub3QgYWJvdmUgbWF4XG4gICAgICAgICAgICAgICAgYW5zd2VyID0gKG9yaWdpbmFsTnIgKyBzdGVwU2l6ZSAtIHJlbWFpbmRlciA8PSBtYXggPyBvcmlnaW5hbE5yICsgc3RlcFNpemUgLSByZW1haW5kZXIgOlxuICAgICAgICAgICAgICAgICAgICBOdW1iZXJVdGlscy5HZXRUcnVlU3RlcHBlZEJvdW5kc01heChtaW4sIG1heCwgc3RlcFNpemUpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIGlzIHRoaXMgcmVhbCBsaWZlLCB3aHkgd2Fzbid0IG91ciBzdGVwcGVkIGJvdW5kcyBjaGVjayBPSz9cbiAgICAgICAgICAgIGFuc3dlciA9IG9yaWdpbmFsTnI7XG4gICAgICAgIH1cblxuICAgICAgICAvLyAnY29ycmVjdCcgZmxvYXQgZXJyb3JzXG4gICAgICAgIGFuc3dlciA9IE51bWJlclV0aWxzLlBhcnNlRmxvYXQoYW5zd2VyLCBOdW1iZXJVdGlscy5fR2V0TGFyZ2VzdERlY2ltYWxQcmVjaXNpb25PZihvcmlnaW5hbE5yLCBtaW4sIG1heCwgc3RlcFNpemUpKTtcbiAgICAgICAgcmV0dXJuIGFuc3dlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSB0cnVlIG1heGltdW0gYWxsb3dlZCB2YWx1ZSBmb3IgdGhlIGdpdmVuIFwic3RlcHBlZCBib3VuZHNcIjogbWluLCBzdGVwU2l6ZSBhbmQgbWF4LCBmb3Igd2hpY2ggaXQgaG9sZHMgdGhhdCBlYWNoIGFsbG93ZWRcbiAgICAgKiB2YWx1ZSBZID0gbWluICsgc3RlcFNpemUgKiBOLCBmb3IgYW55IElOVEVHRVIgb3IgMCBOIHdoZXJlIGl0IGFsc28gaG9sZHMsIG9mIGNvdXJzZSwgdGhhdCBZIDw9IG1heC5cbiAgICAgKiBAcGFyYW0gbWluXG4gICAgICogQHBhcmFtIG1heFxuICAgICAqIEBwYXJhbSBzdGVwU2l6ZVxuICAgICAqL1xuICAgIHB1YmxpYyBzdGF0aWMgR2V0VHJ1ZVN0ZXBwZWRCb3VuZHNNYXgobWluOiBudW1iZXIsIG1heDogbnVtYmVyLCBzdGVwU2l6ZTogbnVtYmVyID0gMSk6IG51bWJlciB7XG4gICAgICAgIC8vIHNvbHZlIG1heCBpbnRlZ2VyIFggaW4gZm9ybXVsYSBtaW4gKyBYICogc3RlcCA8PSBtYXgsIGFuZCByZXR1cm4gbWluICsgWCAqIHN0ZXBTaXplIGZvciB0aGF0IFhcbiAgICAgICAgY29uc3QgbWF4U3RlcHM6IG51bWJlciA9IE1hdGguZmxvb3IoKG1heCAtIG1pbikgLyBzdGVwU2l6ZSk7XG4gICAgICAgIC8vICdjb3JyZWN0JyBmbG9hdCBlcnJvcnNcbiAgICAgICAgcmV0dXJuIE51bWJlclV0aWxzLlBhcnNlRmxvYXQobWluICsgbWF4U3RlcHMgKiBzdGVwU2l6ZSwgTnVtYmVyVXRpbHMuX0dldExhcmdlc3REZWNpbWFsUHJlY2lzaW9uT2YobWluLCBtaW4sIG1heCkpO1xuICAgIH1cblxuICAgIC8vIFJldHVybnMgdGhlIG5lYXJlc3QgbnVtYmVyLCByZWxhdGl2ZSB0byB0aGUgZ2l2ZW4gb3JpZ2luYWxOciwgdGhhdCBpcyB3aXRoaW4gdGhlIGdpdmVuIFttaW4sIG1heF0gaW5jbHVzaXZlIGJvdW5kcy5cbiAgICBwdWJsaWMgc3RhdGljIEdldE5lYXJlc3ROdW1iZXJXaXRoaW5Cb3VuZHMob3JpZ2luYWxOcjogbnVtYmVyLCBtaW46IG51bWJlciwgbWF4OiBudW1iZXIpOiBudW1iZXIge1xuICAgICAgICBsZXQgYW5zd2VyOiBudW1iZXIgPSBvcmlnaW5hbE5yO1xuXG4gICAgICAgIGlmIChvcmlnaW5hbE5yIDwgbWluKSB7XG4gICAgICAgICAgICBhbnN3ZXIgPSBtaW47XG4gICAgICAgIH0gZWxzZSBpZiAob3JpZ2luYWxOciA+IG1heCkge1xuICAgICAgICAgICAgYW5zd2VyID0gbWF4O1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGFuc3dlcjtcbiAgICB9XG5cbiAgICAvLyBSZXR1cm5zIHRoZSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgZ2l2ZW4gbnVtYmVyLiBJZiBpdCdzIG5vdCBhIG51bWJlciwgcmV0dXJucyB0aGUgZW1wdHkgc3RyaW5nLlxuICAgIHB1YmxpYyBzdGF0aWMgVG9TdHJpbmcobnI6IG51bWJlcik6IHN0cmluZyB7XG4gICAgICAgIGlmICghTnVtYmVyVXRpbHMuSXNOYU4obnIpKSB7XG4gICAgICAgICAgICByZXR1cm4gXCJcIiArIG5yO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIFwiXCI7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgc3RhdGljIERlY2ltYWxzVG9TdGVwSW5jcmVtZW50KG51bWJlck9mRGVjaW1hbHM6IG51bWJlcik6IG51bWJlciB7XG4gICAgICAgIHJldHVybiBNYXRoLnBvdygxMCwgLTEgKiBudW1iZXJPZkRlY2ltYWxzKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgc3RhdGljIFJvdW5kKHZhbHVlOiBudW1iZXIsIGRlY2ltYWxzOiBudW1iZXIpOiBudW1iZXIge1xuICAgICAgICBjb25zdCBmYWN0b3I6IG51bWJlciA9IE1hdGgucG93KDEwLCBkZWNpbWFscyk7XG4gICAgICAgIHJldHVybiBNYXRoLnJvdW5kKHZhbHVlICogZmFjdG9yKSAvIGZhY3RvcjtcbiAgICB9XG5cbiAgICAvLyBAcmV0dXJucyBUaGUgaW5jbHVzaXZlIG1heCB2YWx1ZVxuICAgIHB1YmxpYyBzdGF0aWMgUHJlY2lzaW9uU2NhbGVUb01heFZhbHVlKHByZWNpc2lvbjogbnVtYmVyLCBzY2FsZTogbnVtYmVyKTogbnVtYmVyIHtcbiAgICAgICAgY29uc3Qgb25lU3RlcDogbnVtYmVyID0gdGhpcy5EZWNpbWFsc1RvU3RlcEluY3JlbWVudChzY2FsZSk7XG4gICAgICAgIGNvbnN0IG1heEV4Y2x1c2l2ZTogbnVtYmVyID0gTWF0aC5wb3coMTAsIHByZWNpc2lvbiAtIHNjYWxlKTtcbiAgICAgICAgcmV0dXJuIG1heEV4Y2x1c2l2ZSAtIG9uZVN0ZXA7XG4gICAgfVxuXG4gICAgLy8gQHJldHVybnMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBnaXZlbiAyIG51bWJlcnNcbiAgICBwdWJsaWMgc3RhdGljIERpZmZlcmVuY2VCZXR3ZWVuTnVtYmVycyhudW1iZXJBOiBudW1iZXIsIG51bWJlckI6IG51bWJlcik6IG51bWJlciB7XG4gICAgICAgIHJldHVybiBNYXRoLmFicyhudW1iZXJBIC0gbnVtYmVyQik7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgX0dldExhcmdlc3REZWNpbWFsUHJlY2lzaW9uT2YoLi4uYXJnczogbnVtYmVyW10pOiBudW1iZXIge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBBcnJheVV0aWxzLkdldE1heENhbGN1bGF0ZWRWYWx1ZShhcmdzLCAoYXJnOiBudW1iZXIpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBOdW1iZXJVdGlscy5HZXREZWNpbWFsUGxhY2VzKGFyZyk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8vIFJldHVybnMgZ2l2ZW4gbnVtYmVyIGlucHV0IGFzIGEgbnVtYmVyIHRoYXQncyB1c2VhYmxlIGJ5IEphdmFzY3JpcHQuIEFsbG93cyBmb3IgaW5jb21pbmcgJywnIGRlY2ltYWwgZGVsaW1pdGVyLlxuICAgIHByaXZhdGUgc3RhdGljIF9OdW1iZXJJbnB1dFRvTnVtYmVyU3RyKG51bWJlcklucHV0OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gKG51bWJlcklucHV0ICsgXCJcIikucmVwbGFjZShcIixcIiwgXCIuXCIpO1xuICAgIH1cbn1cbiJdfQ==