ngwr 3.0.0 → 4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -7
- package/alert/alert-type.d.ts +7 -0
- package/alert/alert.component.d.ts +21 -0
- package/alert/alert.module.d.ts +7 -0
- package/alert/index.d.ts +5 -0
- package/alert/public-api.d.ts +9 -0
- package/alert/styles/_index.scss +58 -0
- package/alert/styles/theming.scss +26 -0
- package/alert/styles/vars.scss +11 -0
- package/avatar/avatar.component.d.ts +27 -0
- package/avatar/avatar.module.d.ts +7 -0
- package/avatar/index.d.ts +5 -0
- package/avatar/public-api.d.ts +8 -0
- package/avatar/styles/_index.scss +39 -0
- package/button/button-group.component.d.ts +12 -0
- package/button/button.component.d.ts +26 -58
- package/button/button.module.d.ts +2 -1
- package/button/index.d.ts +5 -2
- package/button/public-api.d.ts +9 -0
- package/button/styles/_index.scss +187 -0
- package/button/styles/vars.scss +13 -0
- package/{core/abstract/base.d.ts → cdk/base.directive.d.ts} +7 -1
- package/cdk/index.d.ts +5 -0
- package/cdk/public-api.d.ts +7 -0
- package/cdk/rxjs/index.d.ts +5 -0
- package/cdk/rxjs/is-array.d.ts +8 -0
- package/cdk/rxjs/is-defined.d.ts +8 -0
- package/cdk/rxjs/is-not-empty-array.d.ts +8 -0
- package/cdk/rxjs/is-observable.d.ts +9 -0
- package/cdk/rxjs/public-api.d.ts +10 -0
- package/cdk/types/index.d.ts +5 -0
- package/cdk/types/maybe.d.ts +7 -0
- package/cdk/types/public-api.d.ts +9 -0
- package/cdk/types/safe-any.d.ts +7 -0
- package/{core/color/color.d.ts → cdk/types/theme-color.d.ts} +6 -0
- package/cdk/utils/generate-random-id.d.ts +12 -0
- package/cdk/utils/index.d.ts +5 -0
- package/cdk/utils/public-api.d.ts +7 -0
- package/checkbox/checkbox.component.d.ts +24 -45
- package/checkbox/checkbox.module.d.ts +1 -1
- package/checkbox/index.d.ts +5 -2
- package/checkbox/public-api.d.ts +8 -0
- package/checkbox/styles/_index.scss +86 -0
- package/checkbox/styles/vars.scss +16 -0
- package/dialog/dialog-animations.d.ts +7 -1
- package/dialog/{dialog-base.d.ts → dialog-base.directive.d.ts} +13 -7
- package/dialog/dialog-close.directive.d.ts +9 -0
- package/dialog/dialog-content.directive.d.ts +6 -0
- package/dialog/dialog-data.token.d.ts +8 -0
- package/dialog/dialog-footer.directive.d.ts +8 -0
- package/dialog/dialog-options.d.ts +19 -0
- package/dialog/dialog-ref.d.ts +19 -13
- package/dialog/dialog-title.directive.d.ts +6 -0
- package/dialog/dialog.component.d.ts +28 -0
- package/dialog/dialog.module.d.ts +11 -0
- package/dialog/dialog.service.d.ts +28 -0
- package/dialog/index.d.ts +5 -9
- package/dialog/public-api.d.ts +18 -0
- package/dialog/{dialog.scss → styles/_index.scss} +2 -0
- package/dialog/styles/vars.scss +7 -0
- package/divider/divider.component.d.ts +8 -35
- package/divider/divider.module.d.ts +1 -1
- package/divider/index.d.ts +5 -2
- package/divider/public-api.d.ts +8 -0
- package/divider/{divider.scss → styles/_index.scss} +1 -1
- package/esm2022/alert/alert-type.mjs +8 -0
- package/esm2022/alert/alert.component.mjs +54 -0
- package/esm2022/alert/alert.module.mjs +22 -0
- package/esm2022/alert/ngwr-alert.mjs +5 -0
- package/esm2022/alert/public-api.mjs +10 -0
- package/esm2022/avatar/avatar.component.mjs +77 -0
- package/esm2022/avatar/avatar.module.mjs +22 -0
- package/esm2022/avatar/ngwr-avatar.mjs +5 -0
- package/esm2022/avatar/public-api.mjs +9 -0
- package/esm2022/button/button-group.component.mjs +36 -0
- package/esm2022/button/button.component.mjs +55 -163
- package/esm2022/button/button.module.mjs +15 -8
- package/esm2022/button/ngwr-button.mjs +2 -2
- package/esm2022/button/public-api.mjs +10 -0
- package/esm2022/cdk/base.directive.mjs +27 -0
- package/esm2022/cdk/ngwr-cdk.mjs +5 -0
- package/esm2022/cdk/public-api.mjs +8 -0
- package/esm2022/cdk/rxjs/is-array.mjs +10 -0
- package/esm2022/cdk/rxjs/is-defined.mjs +10 -0
- package/esm2022/cdk/rxjs/is-not-empty-array.mjs +10 -0
- package/esm2022/cdk/rxjs/is-observable.mjs +10 -0
- package/esm2022/cdk/rxjs/ngwr-cdk-rxjs.mjs +5 -0
- package/esm2022/cdk/rxjs/public-api.mjs +11 -0
- package/esm2022/cdk/types/maybe.mjs +8 -0
- package/esm2022/cdk/types/ngwr-cdk-types.mjs +5 -0
- package/esm2022/cdk/types/public-api.mjs +10 -0
- package/esm2022/cdk/types/safe-any.mjs +8 -0
- package/esm2022/cdk/types/theme-color.mjs +17 -0
- package/esm2022/cdk/utils/generate-random-id.mjs +17 -0
- package/esm2022/cdk/utils/ngwr-cdk-utils.mjs +5 -0
- package/esm2022/cdk/utils/public-api.mjs +8 -0
- package/esm2022/checkbox/checkbox.component.mjs +54 -120
- package/esm2022/checkbox/checkbox.module.mjs +14 -8
- package/esm2022/checkbox/ngwr-checkbox.mjs +2 -2
- package/esm2022/checkbox/public-api.mjs +9 -0
- package/esm2022/dialog/dialog-animations.mjs +8 -2
- package/esm2022/dialog/dialog-base.directive.mjs +95 -0
- package/esm2022/dialog/dialog-close.directive.mjs +33 -0
- package/esm2022/dialog/dialog-content.directive.mjs +25 -0
- package/esm2022/dialog/dialog-data.token.mjs +9 -0
- package/esm2022/dialog/dialog-footer.directive.mjs +36 -0
- package/esm2022/dialog/dialog-options.mjs +9 -0
- package/esm2022/dialog/dialog-ref.mjs +22 -16
- package/esm2022/dialog/dialog-title.directive.mjs +25 -0
- package/esm2022/dialog/dialog.component.mjs +57 -0
- package/esm2022/dialog/dialog.module.mjs +38 -0
- package/esm2022/dialog/dialog.service.mjs +107 -0
- package/esm2022/dialog/ngwr-dialog.mjs +2 -2
- package/esm2022/dialog/public-api.mjs +19 -0
- package/esm2022/divider/divider.component.mjs +16 -57
- package/esm2022/divider/divider.module.mjs +8 -8
- package/esm2022/divider/ngwr-divider.mjs +2 -2
- package/esm2022/divider/public-api.mjs +9 -0
- package/esm2022/form/form-error.component.mjs +33 -0
- package/esm2022/form/form-item.component.mjs +43 -0
- package/esm2022/form/form.module.mjs +23 -0
- package/esm2022/form/ngwr-form.mjs +2 -2
- package/esm2022/form/public-api.mjs +10 -0
- package/esm2022/icon/icon.component.mjs +82 -0
- package/esm2022/icon/icon.module.mjs +22 -0
- package/esm2022/icon/icon.service.mjs +40 -0
- package/esm2022/icon/icons.mjs +289 -279
- package/esm2022/icon/ngwr-icon.mjs +2 -2
- package/esm2022/icon/provide-wr-icons.mjs +17 -0
- package/esm2022/icon/public-api.mjs +12 -0
- package/esm2022/input/input-types.mjs +1 -1
- package/esm2022/input/input.component.mjs +123 -0
- package/esm2022/input/input.module.mjs +22 -0
- package/esm2022/input/ngwr-input.mjs +2 -2
- package/esm2022/input/public-api.mjs +10 -0
- package/esm2022/ngwr.mjs +2 -2
- package/esm2022/pipes/new-array.pipe.mjs +23 -0
- package/esm2022/pipes/ngwr-pipes.mjs +5 -0
- package/esm2022/pipes/pipes.module.mjs +22 -0
- package/esm2022/pipes/public-api.mjs +9 -0
- package/esm2022/progress/ngwr-progress.mjs +5 -0
- package/esm2022/progress/progress.component.mjs +42 -0
- package/esm2022/progress/progress.module.mjs +22 -0
- package/esm2022/progress/public-api.mjs +9 -0
- package/esm2022/public-api.mjs +3 -0
- package/esm2022/qr/generator.mjs +84 -0
- package/esm2022/qr/ngwr-qr.mjs +5 -0
- package/esm2022/qr/public-api.mjs +9 -0
- package/esm2022/qr/qr.component.mjs +90 -0
- package/esm2022/qr/qr.module.mjs +22 -0
- package/esm2022/qr/qrcodegen.mjs +872 -0
- package/esm2022/skeleton/index.mjs +3 -3
- package/esm2022/skeleton/skeleton.component.mjs +43 -0
- package/esm2022/skeleton/skeleton.module.mjs +16 -0
- package/esm2022/spinner/index.mjs +3 -3
- package/esm2022/spinner/spinner.component.mjs +33 -0
- package/esm2022/spinner/spinner.module.mjs +22 -0
- package/esm2022/tag/ngwr-tag.mjs +2 -2
- package/esm2022/tag/public-api.mjs +9 -0
- package/esm2022/tag/tag.component.mjs +74 -0
- package/esm2022/tag/tag.module.mjs +16 -0
- package/fesm2022/ngwr-alert.mjs +94 -0
- package/fesm2022/ngwr-alert.mjs.map +1 -0
- package/fesm2022/ngwr-avatar.mjs +110 -0
- package/fesm2022/ngwr-avatar.mjs.map +1 -0
- package/fesm2022/ngwr-button.mjs +108 -169
- package/fesm2022/ngwr-button.mjs.map +1 -1
- package/fesm2022/ngwr-cdk-rxjs.mjs +53 -0
- package/fesm2022/ngwr-cdk-rxjs.mjs.map +1 -0
- package/fesm2022/ngwr-cdk-types.mjs +44 -0
- package/fesm2022/ngwr-cdk-types.mjs.map +1 -0
- package/fesm2022/ngwr-cdk-utils.mjs +30 -0
- package/fesm2022/ngwr-cdk-utils.mjs.map +1 -0
- package/fesm2022/ngwr-cdk.mjs +41 -0
- package/fesm2022/ngwr-cdk.mjs.map +1 -0
- package/fesm2022/ngwr-checkbox.mjs +73 -126
- package/fesm2022/ngwr-checkbox.mjs.map +1 -1
- package/fesm2022/ngwr-dialog.mjs +225 -165
- package/fesm2022/ngwr-dialog.mjs.map +1 -1
- package/fesm2022/ngwr-divider.mjs +29 -63
- package/fesm2022/ngwr-divider.mjs.map +1 -1
- package/fesm2022/ngwr-form.mjs +72 -54
- package/fesm2022/ngwr-form.mjs.map +1 -1
- package/fesm2022/ngwr-icon.mjs +445 -368
- package/fesm2022/ngwr-icon.mjs.map +1 -1
- package/fesm2022/ngwr-input.mjs +101 -208
- package/fesm2022/ngwr-input.mjs.map +1 -1
- package/fesm2022/ngwr-pipes.mjs +56 -0
- package/fesm2022/ngwr-pipes.mjs.map +1 -0
- package/fesm2022/ngwr-progress.mjs +75 -0
- package/fesm2022/ngwr-progress.mjs.map +1 -0
- package/fesm2022/{ngwr-qrcode.mjs → ngwr-qr.mjs} +72 -113
- package/fesm2022/ngwr-qr.mjs.map +1 -0
- package/fesm2022/ngwr-skeleton.mjs +19 -22
- package/fesm2022/ngwr-skeleton.mjs.map +1 -1
- package/fesm2022/ngwr-spinner.mjs +35 -19
- package/fesm2022/ngwr-spinner.mjs.map +1 -1
- package/fesm2022/ngwr-tag.mjs +46 -49
- package/fesm2022/ngwr-tag.mjs.map +1 -1
- package/fesm2022/ngwr.mjs +1 -1
- package/fesm2022/ngwr.mjs.map +1 -1
- package/form/form-error.component.d.ts +11 -0
- package/form/form-item.component.d.ts +14 -0
- package/form/form.module.d.ts +8 -0
- package/form/index.d.ts +5 -3
- package/form/public-api.d.ts +9 -0
- package/icon/icon.component.d.ts +19 -0
- package/icon/icon.module.d.ts +7 -0
- package/icon/icon.service.d.ts +23 -0
- package/icon/icons.d.ts +115 -101
- package/icon/index.d.ts +5 -4
- package/icon/provide-wr-icons.d.ts +9 -0
- package/icon/public-api.d.ts +11 -0
- package/icon/{icon.scss → styles/_index.scss} +4 -2
- package/icon/styles/vars.scss +3 -0
- package/index.d.ts +5 -2
- package/input/index.d.ts +5 -2
- package/input/input-types.d.ts +0 -2
- package/input/input.component.d.ts +43 -0
- package/input/input.module.d.ts +7 -0
- package/input/public-api.d.ts +9 -0
- package/input/styles/_index.scss +107 -0
- package/input/styles/vars.scss +16 -0
- package/package.json +110 -57
- package/pipes/index.d.ts +5 -0
- package/pipes/new-array.pipe.d.ts +13 -0
- package/pipes/pipes.module.d.ts +7 -0
- package/pipes/public-api.d.ts +8 -0
- package/progress/index.d.ts +5 -0
- package/progress/progress.component.d.ts +10 -0
- package/progress/progress.module.d.ts +7 -0
- package/progress/public-api.d.ts +8 -0
- package/progress/styles/_index.scss +24 -0
- package/progress/styles/theming.scss +8 -0
- package/progress/styles/vars.scss +6 -0
- package/public-api.d.ts +2 -0
- package/qr/index.d.ts +5 -0
- package/qr/public-api.d.ts +8 -0
- package/qr/qr.component.d.ts +31 -0
- package/qr/qr.module.d.ts +7 -0
- package/skeleton/index.d.ts +2 -2
- package/skeleton/skeleton.component.d.ts +10 -0
- package/skeleton/{skeleton-module.d.ts → skeleton.module.d.ts} +2 -3
- package/skeleton/{skeleton.scss → styles/_index.scss} +1 -1
- package/spinner/index.d.ts +2 -2
- package/spinner/spinner.component.d.ts +11 -0
- package/spinner/{spinner-module.d.ts → spinner.module.d.ts} +2 -2
- package/spinner/{spinner.scss → styles/_index.scss} +2 -1
- package/styles/animations.scss +4 -4
- package/styles/cdk.scss +4 -0
- package/styles/colors.scss +72 -0
- package/styles/grid.scss +1 -2
- package/styles/reset.scss +2 -2
- package/styles/variables.scss +78 -0
- package/styles.scss +23 -0
- package/tag/index.d.ts +5 -2
- package/tag/public-api.d.ts +8 -0
- package/tag/styles/_index.scss +32 -0
- package/tag/styles/theming.scss +21 -0
- package/tag/styles/vars.scss +12 -0
- package/tag/tag.component.d.ts +21 -0
- package/tag/tag.module.d.ts +7 -0
- package/_grid.scss +0 -2
- package/_index.scss +0 -31
- package/backdrop/backdrop.scss +0 -3
- package/button/button.scss +0 -160
- package/checkbox/checkbox.scss +0 -103
- package/core/abstract/index.d.ts +0 -1
- package/core/color/index.d.ts +0 -2
- package/core/color/is-theme-color.d.ts +0 -2
- package/core/decorators/index.d.ts +0 -1
- package/core/decorators/input-boolean.d.ts +0 -1
- package/core/overlay/connected-overlay-directive.d.ts +0 -16
- package/core/overlay/get-placement-name.d.ts +0 -2
- package/core/overlay/index.d.ts +0 -5
- package/core/overlay/overlay-module.d.ts +0 -7
- package/core/overlay/overlay.scss +0 -9
- package/core/overlay/position-map.d.ts +0 -17
- package/core/overlay/position-type.d.ts +0 -2
- package/core/types/index.d.ts +0 -3
- package/core/types/on-change-type.d.ts +0 -2
- package/core/types/on-touched-type.d.ts +0 -2
- package/core/types/safe-any.d.ts +0 -1
- package/dialog/dialog-config.d.ts +0 -11
- package/dialog/dialog-container.d.ts +0 -22
- package/dialog/dialog-content-directives.d.ts +0 -31
- package/dialog/dialog-module.d.ts +0 -12
- package/dialog/dialog-service.d.ts +0 -27
- package/dialog/dialog-tokens.d.ts +0 -2
- package/esm2022/button/index.mjs +0 -3
- package/esm2022/checkbox/index.mjs +0 -3
- package/esm2022/core/abstract/base.mjs +0 -18
- package/esm2022/core/abstract/index.mjs +0 -2
- package/esm2022/core/abstract/ngwr-core-abstract.mjs +0 -5
- package/esm2022/core/color/color.mjs +0 -11
- package/esm2022/core/color/index.mjs +0 -3
- package/esm2022/core/color/is-theme-color.mjs +0 -9
- package/esm2022/core/color/ngwr-core-color.mjs +0 -5
- package/esm2022/core/decorators/index.mjs +0 -2
- package/esm2022/core/decorators/input-boolean.mjs +0 -15
- package/esm2022/core/decorators/ngwr-core-decorators.mjs +0 -5
- package/esm2022/core/overlay/connected-overlay-directive.mjs +0 -98
- package/esm2022/core/overlay/get-placement-name.mjs +0 -13
- package/esm2022/core/overlay/index.mjs +0 -5
- package/esm2022/core/overlay/ngwr-core-overlay.mjs +0 -5
- package/esm2022/core/overlay/overlay-module.mjs +0 -16
- package/esm2022/core/overlay/position-map.mjs +0 -18
- package/esm2022/core/overlay/position-type.mjs +0 -2
- package/esm2022/core/types/index.mjs +0 -4
- package/esm2022/core/types/ngwr-core-types.mjs +0 -5
- package/esm2022/core/types/on-change-type.mjs +0 -2
- package/esm2022/core/types/on-touched-type.mjs +0 -2
- package/esm2022/core/types/safe-any.mjs +0 -2
- package/esm2022/dialog/dialog-base.mjs +0 -92
- package/esm2022/dialog/dialog-config.mjs +0 -3
- package/esm2022/dialog/dialog-container.mjs +0 -58
- package/esm2022/dialog/dialog-content-directives.mjs +0 -98
- package/esm2022/dialog/dialog-module.mjs +0 -24
- package/esm2022/dialog/dialog-service.mjs +0 -109
- package/esm2022/dialog/dialog-tokens.mjs +0 -3
- package/esm2022/dialog/index.mjs +0 -10
- package/esm2022/divider/index.mjs +0 -3
- package/esm2022/form/form-error.mjs +0 -23
- package/esm2022/form/form-item.mjs +0 -46
- package/esm2022/form/form-module.mjs +0 -19
- package/esm2022/form/index.mjs +0 -4
- package/esm2022/icon/icon-module.mjs +0 -21
- package/esm2022/icon/icon-service.mjs +0 -21
- package/esm2022/icon/icon.mjs +0 -60
- package/esm2022/icon/index.mjs +0 -5
- package/esm2022/index.mjs +0 -3
- package/esm2022/input/index.mjs +0 -3
- package/esm2022/input/input-module.mjs +0 -20
- package/esm2022/input/input.mjs +0 -240
- package/esm2022/qrcode/generator.mjs +0 -84
- package/esm2022/qrcode/index.mjs +0 -3
- package/esm2022/qrcode/ngwr-qrcode.mjs +0 -5
- package/esm2022/qrcode/qrcode-module.mjs +0 -19
- package/esm2022/qrcode/qrcode.mjs +0 -142
- package/esm2022/qrcode/qrcodegen.mjs +0 -872
- package/esm2022/skeleton/skeleton-module.mjs +0 -18
- package/esm2022/skeleton/skeleton.mjs +0 -44
- package/esm2022/spinner/spinner-module.mjs +0 -16
- package/esm2022/spinner/spinner.mjs +0 -23
- package/esm2022/tag/index.mjs +0 -3
- package/esm2022/tag/tag-module.mjs +0 -20
- package/esm2022/tag/tag.mjs +0 -80
- package/esm2022/tooltip/index.mjs +0 -5
- package/esm2022/tooltip/ngwr-tooltip.mjs +0 -5
- package/esm2022/tooltip/tooltip-component.mjs +0 -93
- package/esm2022/tooltip/tooltip-default-positions.mjs +0 -8
- package/esm2022/tooltip/tooltip-directive.mjs +0 -85
- package/esm2022/tooltip/tooltip-module.mjs +0 -21
- package/esm2022/tooltip/tooltip-trigger.mjs +0 -2
- package/fesm2022/ngwr-core-abstract.mjs +0 -25
- package/fesm2022/ngwr-core-abstract.mjs.map +0 -1
- package/fesm2022/ngwr-core-color.mjs +0 -25
- package/fesm2022/ngwr-core-color.mjs.map +0 -1
- package/fesm2022/ngwr-core-decorators.mjs +0 -22
- package/fesm2022/ngwr-core-decorators.mjs.map +0 -1
- package/fesm2022/ngwr-core-overlay.mjs +0 -146
- package/fesm2022/ngwr-core-overlay.mjs.map +0 -1
- package/fesm2022/ngwr-core-types.mjs +0 -4
- package/fesm2022/ngwr-core-types.mjs.map +0 -1
- package/fesm2022/ngwr-qrcode.mjs.map +0 -1
- package/fesm2022/ngwr-tooltip.mjs +0 -204
- package/fesm2022/ngwr-tooltip.mjs.map +0 -1
- package/form/form-error.d.ts +0 -6
- package/form/form-item.d.ts +0 -15
- package/form/form-module.d.ts +0 -9
- package/icon/icon-module.d.ts +0 -9
- package/icon/icon-service.d.ts +0 -8
- package/icon/icon.d.ts +0 -20
- package/input/input-module.d.ts +0 -10
- package/input/input.d.ts +0 -65
- package/input/input.scss +0 -163
- package/qrcode/index.d.ts +0 -2
- package/qrcode/qrcode-module.d.ts +0 -9
- package/qrcode/qrcode.d.ts +0 -46
- package/skeleton/skeleton.d.ts +0 -11
- package/spinner/spinner.d.ts +0 -6
- package/styles/root.scss +0 -172
- package/tag/tag-module.d.ts +0 -10
- package/tag/tag.d.ts +0 -18
- package/tag/tag.scss +0 -106
- package/tooltip/index.d.ts +0 -5
- package/tooltip/tooltip-component.d.ts +0 -31
- package/tooltip/tooltip-default-positions.d.ts +0 -1
- package/tooltip/tooltip-directive.d.ts +0 -22
- package/tooltip/tooltip-module.d.ts +0 -11
- package/tooltip/tooltip-trigger.d.ts +0 -1
- package/tooltip/tooltip.scss +0 -67
- /package/form/{form.scss → styles/_index.scss} +0 -0
- /package/{qrcode → qr}/generator.d.ts +0 -0
- /package/{qrcode → qr}/qrcodegen.d.ts +0 -0
- /package/{qrcode/qrcode.scss → qr/styles/_index.scss} +0 -0
|
@@ -0,0 +1,872 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* QR Code generator library (TypeScript)
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) Project Nayuki. (MIT License)
|
|
5
|
+
* https://www.nayuki.io/page/qr-code-generator-library
|
|
6
|
+
*
|
|
7
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
8
|
+
* this software and associated documentation files (the "Software"), to deal in
|
|
9
|
+
* the Software without restriction, including without limitation the rights to
|
|
10
|
+
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
11
|
+
* the Software, and to permit persons to whom the Software is furnished to do so,
|
|
12
|
+
* subject to the following conditions:
|
|
13
|
+
* - The above copyright notice and this permission notice shall be included in
|
|
14
|
+
* all copies or substantial portions of the Software.
|
|
15
|
+
* - The Software is provided "as is", without warranty of any kind, express or
|
|
16
|
+
* implied, including but not limited to the warranties of merchantability,
|
|
17
|
+
* fitness for a particular purpose and noninfringement. In no event shall the
|
|
18
|
+
* authors or copyright holders be liable for any claim, damages or other
|
|
19
|
+
* liability, whether in an action of contract, tort or otherwise, arising from,
|
|
20
|
+
* out of or in connection with the Software or the use or other dealings in the
|
|
21
|
+
* Software.
|
|
22
|
+
*/
|
|
23
|
+
'use strict';
|
|
24
|
+
var qrcodegen;
|
|
25
|
+
(function (qrcodegen) {
|
|
26
|
+
/*---- QR Code symbol class ----*/
|
|
27
|
+
/*
|
|
28
|
+
* A QR Code symbol, which is a type of two-dimension barcode.
|
|
29
|
+
* Invented by Denso Wave and described in the ISO/IEC 18004 standard.
|
|
30
|
+
* Instances of this class represent an immutable square grid of dark and light cells.
|
|
31
|
+
* The class provides static factory functions to create a QR Code from text or binary data.
|
|
32
|
+
* The class covers the QR Code Model 2 specification, supporting all versions (sizes)
|
|
33
|
+
* from 1 to 40, all 4 error correction levels, and 4 character encoding modes.
|
|
34
|
+
*
|
|
35
|
+
* Ways to create a QR Code object:
|
|
36
|
+
* - High level: Take the payload data and call QrCode.encodeText() or QrCode.encodeBinary().
|
|
37
|
+
* - Mid level: Custom-make the list of segments and call QrCode.encodeSegments().
|
|
38
|
+
* - Low level: Custom-make the array of data codeword bytes (including
|
|
39
|
+
* segment headers and final padding, excluding error correction codewords),
|
|
40
|
+
* supply the appropriate version number, and call the QrCode() constructor.
|
|
41
|
+
* (Note that all ways require supplying the desired error correction level.)
|
|
42
|
+
*/
|
|
43
|
+
class QrCode {
|
|
44
|
+
/*-- Static factory functions (high level) --*/
|
|
45
|
+
// Returns a QR Code representing the given Unicode text string at the given error correction level.
|
|
46
|
+
// As a conservative upper bound, this function is guaranteed to succeed for strings that have 738 or fewer
|
|
47
|
+
// Unicode code points (not UTF-16 code units) if the low error correction level is used. The smallest possible
|
|
48
|
+
// QR Code version is automatically chosen for the output. The ECC level of the result may be higher than the
|
|
49
|
+
// ecl argument if it can be done without increasing the version.
|
|
50
|
+
static encodeText(text, ecl) {
|
|
51
|
+
const segs = qrcodegen.QrSegment.makeSegments(text);
|
|
52
|
+
return QrCode.encodeSegments(segs, ecl);
|
|
53
|
+
}
|
|
54
|
+
// Returns a QR Code representing the given binary data at the given error correction level.
|
|
55
|
+
// This function always encodes using the binary segment mode, not any text mode. The maximum number of
|
|
56
|
+
// bytes allowed is 2953. The smallest possible QR Code version is automatically chosen for the output.
|
|
57
|
+
// The ECC level of the result may be higher than the ecl argument if it can be done without increasing the version.
|
|
58
|
+
static encodeBinary(data, ecl) {
|
|
59
|
+
const seg = qrcodegen.QrSegment.makeBytes(data);
|
|
60
|
+
return QrCode.encodeSegments([seg], ecl);
|
|
61
|
+
}
|
|
62
|
+
/*-- Static factory functions (mid level) --*/
|
|
63
|
+
// Returns a QR Code representing the given segments with the given encoding parameters.
|
|
64
|
+
// The smallest possible QR Code version within the given range is automatically
|
|
65
|
+
// chosen for the output. Iff boostEcl is true, then the ECC level of the result
|
|
66
|
+
// may be higher than the ecl argument if it can be done without increasing the
|
|
67
|
+
// version. The mask number is either between 0 to 7 (inclusive) to force that
|
|
68
|
+
// mask, or -1 to automatically choose an appropriate mask (which may be slow).
|
|
69
|
+
// This function allows the user to create a custom sequence of segments that switches
|
|
70
|
+
// between modes (such as alphanumeric and byte) to encode text in less space.
|
|
71
|
+
// This is a mid-level API; the high-level API is encodeText() and encodeBinary().
|
|
72
|
+
static encodeSegments(segs, ecl, minVersion = 1, maxVersion = 40, mask = -1, boostEcl = true) {
|
|
73
|
+
if (!(QrCode.MIN_VERSION <= minVersion && minVersion <= maxVersion && maxVersion <= QrCode.MAX_VERSION) ||
|
|
74
|
+
mask < -1 ||
|
|
75
|
+
mask > 7)
|
|
76
|
+
throw new RangeError('Invalid value');
|
|
77
|
+
// Find the minimal version number to use
|
|
78
|
+
let version;
|
|
79
|
+
let dataUsedBits;
|
|
80
|
+
for (version = minVersion;; version++) {
|
|
81
|
+
const dataCapacityBits = QrCode.getNumDataCodewords(version, ecl) * 8; // Number of data bits available
|
|
82
|
+
const usedBits = QrSegment.getTotalBits(segs, version);
|
|
83
|
+
if (usedBits <= dataCapacityBits) {
|
|
84
|
+
dataUsedBits = usedBits;
|
|
85
|
+
break; // This version number is found to be suitable
|
|
86
|
+
}
|
|
87
|
+
if (version >= maxVersion)
|
|
88
|
+
// All versions in the range could not fit the given data
|
|
89
|
+
throw new RangeError('Data too long');
|
|
90
|
+
}
|
|
91
|
+
// Increase the error correction level while the data still fits in the current version number
|
|
92
|
+
for (const newEcl of [QrCode.Ecc.MEDIUM, QrCode.Ecc.QUARTILE, QrCode.Ecc.HIGH]) {
|
|
93
|
+
// From low to high
|
|
94
|
+
if (boostEcl && dataUsedBits <= QrCode.getNumDataCodewords(version, newEcl) * 8)
|
|
95
|
+
ecl = newEcl;
|
|
96
|
+
}
|
|
97
|
+
// Concatenate all segments to create the data bit string
|
|
98
|
+
let bb = [];
|
|
99
|
+
for (const seg of segs) {
|
|
100
|
+
appendBits(seg.mode.modeBits, 4, bb);
|
|
101
|
+
appendBits(seg.numChars, seg.mode.numCharCountBits(version), bb);
|
|
102
|
+
for (const b of seg.getData())
|
|
103
|
+
bb.push(b);
|
|
104
|
+
}
|
|
105
|
+
assert(bb.length == dataUsedBits);
|
|
106
|
+
// Add terminator and pad up to a byte if applicable
|
|
107
|
+
const dataCapacityBits = QrCode.getNumDataCodewords(version, ecl) * 8;
|
|
108
|
+
assert(bb.length <= dataCapacityBits);
|
|
109
|
+
appendBits(0, Math.min(4, dataCapacityBits - bb.length), bb);
|
|
110
|
+
appendBits(0, (8 - (bb.length % 8)) % 8, bb);
|
|
111
|
+
assert(bb.length % 8 == 0);
|
|
112
|
+
// Pad with alternating bytes until data capacity is reached
|
|
113
|
+
for (let padByte = 0xec; bb.length < dataCapacityBits; padByte ^= 0xec ^ 0x11)
|
|
114
|
+
appendBits(padByte, 8, bb);
|
|
115
|
+
// Pack bits into bytes in big endian
|
|
116
|
+
let dataCodewords = [];
|
|
117
|
+
while (dataCodewords.length * 8 < bb.length)
|
|
118
|
+
dataCodewords.push(0);
|
|
119
|
+
bb.forEach((b, i) => (dataCodewords[i >>> 3] |= b << (7 - (i & 7))));
|
|
120
|
+
// Create the QR Code object
|
|
121
|
+
return new QrCode(version, ecl, dataCodewords, mask);
|
|
122
|
+
}
|
|
123
|
+
/*-- Constructor (low level) and fields --*/
|
|
124
|
+
// Creates a new QR Code with the given version number,
|
|
125
|
+
// error correction level, data codeword bytes, and mask number.
|
|
126
|
+
// This is a low-level API that most users should not use directly.
|
|
127
|
+
// A mid-level API is the encodeSegments() function.
|
|
128
|
+
constructor(
|
|
129
|
+
// The version number of this QR Code, which is between 1 and 40 (inclusive).
|
|
130
|
+
// This determines the size of this barcode.
|
|
131
|
+
version,
|
|
132
|
+
// The error correction level used in this QR Code.
|
|
133
|
+
errorCorrectionLevel, dataCodewords, msk) {
|
|
134
|
+
this.version = version;
|
|
135
|
+
this.errorCorrectionLevel = errorCorrectionLevel;
|
|
136
|
+
// The modules of this QR Code (false = light, true = dark).
|
|
137
|
+
// Immutable after constructor finishes. Accessed through getModule().
|
|
138
|
+
this.modules = [];
|
|
139
|
+
// Indicates function modules that are not subjected to masking. Discarded when constructor finishes.
|
|
140
|
+
this.isFunction = [];
|
|
141
|
+
// Check scalar arguments
|
|
142
|
+
if (version < QrCode.MIN_VERSION || version > QrCode.MAX_VERSION)
|
|
143
|
+
throw new RangeError('Version value out of range');
|
|
144
|
+
if (msk < -1 || msk > 7)
|
|
145
|
+
throw new RangeError('Mask value out of range');
|
|
146
|
+
this.size = version * 4 + 17;
|
|
147
|
+
// Initialize both grids to be size*size arrays of Boolean false
|
|
148
|
+
let row = [];
|
|
149
|
+
for (let i = 0; i < this.size; i++)
|
|
150
|
+
row.push(false);
|
|
151
|
+
for (let i = 0; i < this.size; i++) {
|
|
152
|
+
this.modules.push(row.slice()); // Initially all light
|
|
153
|
+
this.isFunction.push(row.slice());
|
|
154
|
+
}
|
|
155
|
+
// Compute ECC, draw modules
|
|
156
|
+
this.drawFunctionPatterns();
|
|
157
|
+
const allCodewords = this.addEccAndInterleave(dataCodewords);
|
|
158
|
+
this.drawCodewords(allCodewords);
|
|
159
|
+
// Do masking
|
|
160
|
+
if (msk == -1) {
|
|
161
|
+
// Automatically choose best mask
|
|
162
|
+
let minPenalty = 1000000000;
|
|
163
|
+
for (let i = 0; i < 8; i++) {
|
|
164
|
+
this.applyMask(i);
|
|
165
|
+
this.drawFormatBits(i);
|
|
166
|
+
const penalty = this.getPenaltyScore();
|
|
167
|
+
if (penalty < minPenalty) {
|
|
168
|
+
msk = i;
|
|
169
|
+
minPenalty = penalty;
|
|
170
|
+
}
|
|
171
|
+
this.applyMask(i); // Undoes the mask due to XOR
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
assert(msk >= 0 && msk <= 7);
|
|
175
|
+
this.mask = msk;
|
|
176
|
+
this.applyMask(msk); // Apply the final choice of mask
|
|
177
|
+
this.drawFormatBits(msk); // Overwrite old format bits
|
|
178
|
+
this.isFunction = [];
|
|
179
|
+
}
|
|
180
|
+
/*-- Accessor methods --*/
|
|
181
|
+
// Returns the color of the module (pixel) at the given coordinates, which is false
|
|
182
|
+
// for light or true for dark. The top left corner has the coordinates (x=0, y=0).
|
|
183
|
+
// If the given coordinates are out of bounds, then false (light) is returned.
|
|
184
|
+
getModule(x, y) {
|
|
185
|
+
return x >= 0 && x < this.size && y >= 0 && y < this.size && this.modules[y][x];
|
|
186
|
+
}
|
|
187
|
+
/*-- Private helper methods for constructor: Drawing function modules --*/
|
|
188
|
+
// Reads this object's version field, and draws and marks all function modules.
|
|
189
|
+
drawFunctionPatterns() {
|
|
190
|
+
// Draw horizontal and vertical timing patterns
|
|
191
|
+
for (let i = 0; i < this.size; i++) {
|
|
192
|
+
this.setFunctionModule(6, i, i % 2 == 0);
|
|
193
|
+
this.setFunctionModule(i, 6, i % 2 == 0);
|
|
194
|
+
}
|
|
195
|
+
// Draw 3 finder patterns (all corners except bottom right; overwrites some timing modules)
|
|
196
|
+
this.drawFinderPattern(3, 3);
|
|
197
|
+
this.drawFinderPattern(this.size - 4, 3);
|
|
198
|
+
this.drawFinderPattern(3, this.size - 4);
|
|
199
|
+
// Draw numerous alignment patterns
|
|
200
|
+
const alignPatPos = this.getAlignmentPatternPositions();
|
|
201
|
+
const numAlign = alignPatPos.length;
|
|
202
|
+
for (let i = 0; i < numAlign; i++) {
|
|
203
|
+
for (let j = 0; j < numAlign; j++) {
|
|
204
|
+
// Don't draw on the three finder corners
|
|
205
|
+
if (!((i == 0 && j == 0) || (i == 0 && j == numAlign - 1) || (i == numAlign - 1 && j == 0)))
|
|
206
|
+
this.drawAlignmentPattern(alignPatPos[i], alignPatPos[j]);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
// Draw configuration data
|
|
210
|
+
this.drawFormatBits(0); // Dummy mask value; overwritten later in the constructor
|
|
211
|
+
this.drawVersion();
|
|
212
|
+
}
|
|
213
|
+
// Draws two copies of the format bits (with its own error correction code)
|
|
214
|
+
// based on the given mask and this object's error correction level field.
|
|
215
|
+
drawFormatBits(mask) {
|
|
216
|
+
// Calculate error correction code and pack bits
|
|
217
|
+
const data = (this.errorCorrectionLevel.formatBits << 3) | mask; // errCorrLvl is uint2, mask is uint3
|
|
218
|
+
let rem = data;
|
|
219
|
+
for (let i = 0; i < 10; i++)
|
|
220
|
+
rem = (rem << 1) ^ ((rem >>> 9) * 0x537);
|
|
221
|
+
const bits = ((data << 10) | rem) ^ 0x5412; // uint15
|
|
222
|
+
assert(bits >>> 15 == 0);
|
|
223
|
+
// Draw first copy
|
|
224
|
+
for (let i = 0; i <= 5; i++)
|
|
225
|
+
this.setFunctionModule(8, i, getBit(bits, i));
|
|
226
|
+
this.setFunctionModule(8, 7, getBit(bits, 6));
|
|
227
|
+
this.setFunctionModule(8, 8, getBit(bits, 7));
|
|
228
|
+
this.setFunctionModule(7, 8, getBit(bits, 8));
|
|
229
|
+
for (let i = 9; i < 15; i++)
|
|
230
|
+
this.setFunctionModule(14 - i, 8, getBit(bits, i));
|
|
231
|
+
// Draw second copy
|
|
232
|
+
for (let i = 0; i < 8; i++)
|
|
233
|
+
this.setFunctionModule(this.size - 1 - i, 8, getBit(bits, i));
|
|
234
|
+
for (let i = 8; i < 15; i++)
|
|
235
|
+
this.setFunctionModule(8, this.size - 15 + i, getBit(bits, i));
|
|
236
|
+
this.setFunctionModule(8, this.size - 8, true); // Always dark
|
|
237
|
+
}
|
|
238
|
+
// Draws two copies of the version bits (with its own error correction code),
|
|
239
|
+
// based on this object's version field, iff 7 <= version <= 40.
|
|
240
|
+
drawVersion() {
|
|
241
|
+
if (this.version < 7)
|
|
242
|
+
return;
|
|
243
|
+
// Calculate error correction code and pack bits
|
|
244
|
+
let rem = this.version; // version is uint6, in the range [7, 40]
|
|
245
|
+
for (let i = 0; i < 12; i++)
|
|
246
|
+
rem = (rem << 1) ^ ((rem >>> 11) * 0x1f25);
|
|
247
|
+
const bits = (this.version << 12) | rem; // uint18
|
|
248
|
+
assert(bits >>> 18 == 0);
|
|
249
|
+
// Draw two copies
|
|
250
|
+
for (let i = 0; i < 18; i++) {
|
|
251
|
+
const color = getBit(bits, i);
|
|
252
|
+
const a = this.size - 11 + (i % 3);
|
|
253
|
+
const b = Math.floor(i / 3);
|
|
254
|
+
this.setFunctionModule(a, b, color);
|
|
255
|
+
this.setFunctionModule(b, a, color);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
// Draws a 9*9 finder pattern including the border separator,
|
|
259
|
+
// with the center module at (x, y). Modules can be out of bounds.
|
|
260
|
+
drawFinderPattern(x, y) {
|
|
261
|
+
for (let dy = -4; dy <= 4; dy++) {
|
|
262
|
+
for (let dx = -4; dx <= 4; dx++) {
|
|
263
|
+
const dist = Math.max(Math.abs(dx), Math.abs(dy)); // Chebyshev/infinity norm
|
|
264
|
+
const xx = x + dx;
|
|
265
|
+
const yy = y + dy;
|
|
266
|
+
if (xx >= 0 && xx < this.size && yy >= 0 && yy < this.size)
|
|
267
|
+
this.setFunctionModule(xx, yy, dist != 2 && dist != 4);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
// Draws a 5*5 alignment pattern, with the center module
|
|
272
|
+
// at (x, y). All modules must be in bounds.
|
|
273
|
+
drawAlignmentPattern(x, y) {
|
|
274
|
+
for (let dy = -2; dy <= 2; dy++) {
|
|
275
|
+
for (let dx = -2; dx <= 2; dx++)
|
|
276
|
+
this.setFunctionModule(x + dx, y + dy, Math.max(Math.abs(dx), Math.abs(dy)) != 1);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
// Sets the color of a module and marks it as a function module.
|
|
280
|
+
// Only used by the constructor. Coordinates must be in bounds.
|
|
281
|
+
setFunctionModule(x, y, isDark) {
|
|
282
|
+
this.modules[y][x] = isDark;
|
|
283
|
+
this.isFunction[y][x] = true;
|
|
284
|
+
}
|
|
285
|
+
/*-- Private helper methods for constructor: Codewords and masking --*/
|
|
286
|
+
// Returns a new byte string representing the given data with the appropriate error correction
|
|
287
|
+
// codewords appended to it, based on this object's version and error correction level.
|
|
288
|
+
addEccAndInterleave(data) {
|
|
289
|
+
const ver = this.version;
|
|
290
|
+
const ecl = this.errorCorrectionLevel;
|
|
291
|
+
if (data.length != QrCode.getNumDataCodewords(ver, ecl))
|
|
292
|
+
throw new RangeError('Invalid argument');
|
|
293
|
+
// Calculate parameter numbers
|
|
294
|
+
const numBlocks = QrCode.NUM_ERROR_CORRECTION_BLOCKS[ecl.ordinal][ver];
|
|
295
|
+
const blockEccLen = QrCode.ECC_CODEWORDS_PER_BLOCK[ecl.ordinal][ver];
|
|
296
|
+
const rawCodewords = Math.floor(QrCode.getNumRawDataModules(ver) / 8);
|
|
297
|
+
const numShortBlocks = numBlocks - (rawCodewords % numBlocks);
|
|
298
|
+
const shortBlockLen = Math.floor(rawCodewords / numBlocks);
|
|
299
|
+
// Split data into blocks and append ECC to each block
|
|
300
|
+
let blocks = [];
|
|
301
|
+
const rsDiv = QrCode.reedSolomonComputeDivisor(blockEccLen);
|
|
302
|
+
for (let i = 0, k = 0; i < numBlocks; i++) {
|
|
303
|
+
let dat = data.slice(k, k + shortBlockLen - blockEccLen + (i < numShortBlocks ? 0 : 1));
|
|
304
|
+
k += dat.length;
|
|
305
|
+
const ecc = QrCode.reedSolomonComputeRemainder(dat, rsDiv);
|
|
306
|
+
if (i < numShortBlocks)
|
|
307
|
+
dat.push(0);
|
|
308
|
+
blocks.push(dat.concat(ecc));
|
|
309
|
+
}
|
|
310
|
+
// Interleave (not concatenate) the bytes from every block into a single sequence
|
|
311
|
+
let result = [];
|
|
312
|
+
for (let i = 0; i < blocks[0].length; i++) {
|
|
313
|
+
blocks.forEach((block, j) => {
|
|
314
|
+
// Skip the padding byte in short blocks
|
|
315
|
+
if (i != shortBlockLen - blockEccLen || j >= numShortBlocks)
|
|
316
|
+
result.push(block[i]);
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
assert(result.length == rawCodewords);
|
|
320
|
+
return result;
|
|
321
|
+
}
|
|
322
|
+
// Draws the given sequence of 8-bit codewords (data and error correction) onto the entire
|
|
323
|
+
// data area of this QR Code. Function modules need to be marked off before this is called.
|
|
324
|
+
drawCodewords(data) {
|
|
325
|
+
if (data.length != Math.floor(QrCode.getNumRawDataModules(this.version) / 8))
|
|
326
|
+
throw new RangeError('Invalid argument');
|
|
327
|
+
let i = 0; // Bit index into the data
|
|
328
|
+
// Do the funny zigzag scan
|
|
329
|
+
for (let right = this.size - 1; right >= 1; right -= 2) {
|
|
330
|
+
// Index of right column in each column pair
|
|
331
|
+
if (right == 6)
|
|
332
|
+
right = 5;
|
|
333
|
+
for (let vert = 0; vert < this.size; vert++) {
|
|
334
|
+
// Vertical counter
|
|
335
|
+
for (let j = 0; j < 2; j++) {
|
|
336
|
+
const x = right - j; // Actual x coordinate
|
|
337
|
+
const upward = ((right + 1) & 2) == 0;
|
|
338
|
+
const y = upward ? this.size - 1 - vert : vert; // Actual y coordinate
|
|
339
|
+
if (!this.isFunction[y][x] && i < data.length * 8) {
|
|
340
|
+
this.modules[y][x] = getBit(data[i >>> 3], 7 - (i & 7));
|
|
341
|
+
i++;
|
|
342
|
+
}
|
|
343
|
+
// If this QR Code has any remainder bits (0 to 7), they were assigned as
|
|
344
|
+
// 0/false/light by the constructor and are left unchanged by this method
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
assert(i == data.length * 8);
|
|
349
|
+
}
|
|
350
|
+
// XORs the codeword modules in this QR Code with the given mask pattern.
|
|
351
|
+
// The function modules must be marked and the codeword bits must be drawn
|
|
352
|
+
// before masking. Due to the arithmetic of XOR, calling applyMask() with
|
|
353
|
+
// the same mask value a second time will undo the mask. A final well-formed
|
|
354
|
+
// QR Code needs exactly one (not zero, two, etc.) mask applied.
|
|
355
|
+
applyMask(mask) {
|
|
356
|
+
if (mask < 0 || mask > 7)
|
|
357
|
+
throw new RangeError('Mask value out of range');
|
|
358
|
+
for (let y = 0; y < this.size; y++) {
|
|
359
|
+
for (let x = 0; x < this.size; x++) {
|
|
360
|
+
let invert;
|
|
361
|
+
switch (mask) {
|
|
362
|
+
case 0:
|
|
363
|
+
invert = (x + y) % 2 == 0;
|
|
364
|
+
break;
|
|
365
|
+
case 1:
|
|
366
|
+
invert = y % 2 == 0;
|
|
367
|
+
break;
|
|
368
|
+
case 2:
|
|
369
|
+
invert = x % 3 == 0;
|
|
370
|
+
break;
|
|
371
|
+
case 3:
|
|
372
|
+
invert = (x + y) % 3 == 0;
|
|
373
|
+
break;
|
|
374
|
+
case 4:
|
|
375
|
+
invert = (Math.floor(x / 3) + Math.floor(y / 2)) % 2 == 0;
|
|
376
|
+
break;
|
|
377
|
+
case 5:
|
|
378
|
+
invert = ((x * y) % 2) + ((x * y) % 3) == 0;
|
|
379
|
+
break;
|
|
380
|
+
case 6:
|
|
381
|
+
invert = (((x * y) % 2) + ((x * y) % 3)) % 2 == 0;
|
|
382
|
+
break;
|
|
383
|
+
case 7:
|
|
384
|
+
invert = (((x + y) % 2) + ((x * y) % 3)) % 2 == 0;
|
|
385
|
+
break;
|
|
386
|
+
default:
|
|
387
|
+
throw new Error('Unreachable');
|
|
388
|
+
}
|
|
389
|
+
if (!this.isFunction[y][x] && invert)
|
|
390
|
+
this.modules[y][x] = !this.modules[y][x];
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
// Calculates and returns the penalty score based on state of this QR Code's current modules.
|
|
395
|
+
// This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score.
|
|
396
|
+
getPenaltyScore() {
|
|
397
|
+
let result = 0;
|
|
398
|
+
// Adjacent modules in row having same color, and finder-like patterns
|
|
399
|
+
for (let y = 0; y < this.size; y++) {
|
|
400
|
+
let runColor = false;
|
|
401
|
+
let runX = 0;
|
|
402
|
+
let runHistory = [0, 0, 0, 0, 0, 0, 0];
|
|
403
|
+
for (let x = 0; x < this.size; x++) {
|
|
404
|
+
if (this.modules[y][x] == runColor) {
|
|
405
|
+
runX++;
|
|
406
|
+
if (runX == 5)
|
|
407
|
+
result += QrCode.PENALTY_N1;
|
|
408
|
+
else if (runX > 5)
|
|
409
|
+
result++;
|
|
410
|
+
}
|
|
411
|
+
else {
|
|
412
|
+
this.finderPenaltyAddHistory(runX, runHistory);
|
|
413
|
+
if (!runColor)
|
|
414
|
+
result += this.finderPenaltyCountPatterns(runHistory) * QrCode.PENALTY_N3;
|
|
415
|
+
runColor = this.modules[y][x];
|
|
416
|
+
runX = 1;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
result += this.finderPenaltyTerminateAndCount(runColor, runX, runHistory) * QrCode.PENALTY_N3;
|
|
420
|
+
}
|
|
421
|
+
// Adjacent modules in column having same color, and finder-like patterns
|
|
422
|
+
for (let x = 0; x < this.size; x++) {
|
|
423
|
+
let runColor = false;
|
|
424
|
+
let runY = 0;
|
|
425
|
+
let runHistory = [0, 0, 0, 0, 0, 0, 0];
|
|
426
|
+
for (let y = 0; y < this.size; y++) {
|
|
427
|
+
if (this.modules[y][x] == runColor) {
|
|
428
|
+
runY++;
|
|
429
|
+
if (runY == 5)
|
|
430
|
+
result += QrCode.PENALTY_N1;
|
|
431
|
+
else if (runY > 5)
|
|
432
|
+
result++;
|
|
433
|
+
}
|
|
434
|
+
else {
|
|
435
|
+
this.finderPenaltyAddHistory(runY, runHistory);
|
|
436
|
+
if (!runColor)
|
|
437
|
+
result += this.finderPenaltyCountPatterns(runHistory) * QrCode.PENALTY_N3;
|
|
438
|
+
runColor = this.modules[y][x];
|
|
439
|
+
runY = 1;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
result += this.finderPenaltyTerminateAndCount(runColor, runY, runHistory) * QrCode.PENALTY_N3;
|
|
443
|
+
}
|
|
444
|
+
// 2*2 blocks of modules having same color
|
|
445
|
+
for (let y = 0; y < this.size - 1; y++) {
|
|
446
|
+
for (let x = 0; x < this.size - 1; x++) {
|
|
447
|
+
const color = this.modules[y][x];
|
|
448
|
+
if (color == this.modules[y][x + 1] && color == this.modules[y + 1][x] && color == this.modules[y + 1][x + 1])
|
|
449
|
+
result += QrCode.PENALTY_N2;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
// Balance of dark and light modules
|
|
453
|
+
let dark = 0;
|
|
454
|
+
for (const row of this.modules)
|
|
455
|
+
dark = row.reduce((sum, color) => sum + (color ? 1 : 0), dark);
|
|
456
|
+
const total = this.size * this.size; // Note that size is odd, so dark/total != 1/2
|
|
457
|
+
// Compute the smallest integer k >= 0 such that (45-5k)% <= dark/total <= (55+5k)%
|
|
458
|
+
const k = Math.ceil(Math.abs(dark * 20 - total * 10) / total) - 1;
|
|
459
|
+
assert(k >= 0 && k <= 9);
|
|
460
|
+
result += k * QrCode.PENALTY_N4;
|
|
461
|
+
assert(result >= 0 && result <= 2568888); // Non-tight upper bound based on default values of PENALTY_N1, ..., N4
|
|
462
|
+
return result;
|
|
463
|
+
}
|
|
464
|
+
/*-- Private helper functions --*/
|
|
465
|
+
// Returns an ascending list of positions of alignment patterns for this version number.
|
|
466
|
+
// Each position is in the range [0,177), and are used on both the x and y axes.
|
|
467
|
+
// This could be implemented as lookup table of 40 variable-length lists of integers.
|
|
468
|
+
getAlignmentPatternPositions() {
|
|
469
|
+
if (this.version == 1)
|
|
470
|
+
return [];
|
|
471
|
+
else {
|
|
472
|
+
const numAlign = Math.floor(this.version / 7) + 2;
|
|
473
|
+
const step = this.version == 32 ? 26 : Math.ceil((this.version * 4 + 4) / (numAlign * 2 - 2)) * 2;
|
|
474
|
+
let result = [6];
|
|
475
|
+
for (let pos = this.size - 7; result.length < numAlign; pos -= step)
|
|
476
|
+
result.splice(1, 0, pos);
|
|
477
|
+
return result;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
// Returns the number of data bits that can be stored in a QR Code of the given version number, after
|
|
481
|
+
// all function modules are excluded. This includes remainder bits, so it might not be a multiple of 8.
|
|
482
|
+
// The result is in the range [208, 29648]. This could be implemented as a 40-entry lookup table.
|
|
483
|
+
static getNumRawDataModules(ver) {
|
|
484
|
+
if (ver < QrCode.MIN_VERSION || ver > QrCode.MAX_VERSION)
|
|
485
|
+
throw new RangeError('Version number out of range');
|
|
486
|
+
let result = (16 * ver + 128) * ver + 64;
|
|
487
|
+
if (ver >= 2) {
|
|
488
|
+
const numAlign = Math.floor(ver / 7) + 2;
|
|
489
|
+
result -= (25 * numAlign - 10) * numAlign - 55;
|
|
490
|
+
if (ver >= 7)
|
|
491
|
+
result -= 36;
|
|
492
|
+
}
|
|
493
|
+
assert(result >= 208 && result <= 29648);
|
|
494
|
+
return result;
|
|
495
|
+
}
|
|
496
|
+
// Returns the number of 8-bit data (i.e. not error correction) codewords contained in any
|
|
497
|
+
// QR Code of the given version number and error correction level, with remainder bits discarded.
|
|
498
|
+
// This stateless pure function could be implemented as a (40*4)-cell lookup table.
|
|
499
|
+
static getNumDataCodewords(ver, ecl) {
|
|
500
|
+
return (Math.floor(QrCode.getNumRawDataModules(ver) / 8) -
|
|
501
|
+
QrCode.ECC_CODEWORDS_PER_BLOCK[ecl.ordinal][ver] * QrCode.NUM_ERROR_CORRECTION_BLOCKS[ecl.ordinal][ver]);
|
|
502
|
+
}
|
|
503
|
+
// Returns a Reed-Solomon ECC generator polynomial for the given degree. This could be
|
|
504
|
+
// implemented as a lookup table over all possible parameter values, instead of as an algorithm.
|
|
505
|
+
static reedSolomonComputeDivisor(degree) {
|
|
506
|
+
if (degree < 1 || degree > 255)
|
|
507
|
+
throw new RangeError('Degree out of range');
|
|
508
|
+
// Polynomial coefficients are stored from highest to lowest power, excluding the leading term which is always 1.
|
|
509
|
+
// For example the polynomial x^3 + 255x^2 + 8x + 93 is stored as the uint8 array [255, 8, 93].
|
|
510
|
+
let result = [];
|
|
511
|
+
for (let i = 0; i < degree - 1; i++)
|
|
512
|
+
result.push(0);
|
|
513
|
+
result.push(1); // Start off with the monomial x^0
|
|
514
|
+
// Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}),
|
|
515
|
+
// and drop the highest monomial term which is always 1x^degree.
|
|
516
|
+
// Note that r = 0x02, which is a generator element of this field GF(2^8/0x11D).
|
|
517
|
+
let root = 1;
|
|
518
|
+
for (let i = 0; i < degree; i++) {
|
|
519
|
+
// Multiply the current product by (x - r^i)
|
|
520
|
+
for (let j = 0; j < result.length; j++) {
|
|
521
|
+
result[j] = QrCode.reedSolomonMultiply(result[j], root);
|
|
522
|
+
if (j + 1 < result.length)
|
|
523
|
+
result[j] ^= result[j + 1];
|
|
524
|
+
}
|
|
525
|
+
root = QrCode.reedSolomonMultiply(root, 0x02);
|
|
526
|
+
}
|
|
527
|
+
return result;
|
|
528
|
+
}
|
|
529
|
+
// Returns the Reed-Solomon error correction codeword for the given data and divisor polynomials.
|
|
530
|
+
static reedSolomonComputeRemainder(data, divisor) {
|
|
531
|
+
let result = divisor.map(_ => 0);
|
|
532
|
+
for (const b of data) {
|
|
533
|
+
// Polynomial division
|
|
534
|
+
const factor = b ^ result.shift();
|
|
535
|
+
result.push(0);
|
|
536
|
+
divisor.forEach((coef, i) => (result[i] ^= QrCode.reedSolomonMultiply(coef, factor)));
|
|
537
|
+
}
|
|
538
|
+
return result;
|
|
539
|
+
}
|
|
540
|
+
// Returns the product of the two given field elements modulo GF(2^8/0x11D). The arguments and result
|
|
541
|
+
// are unsigned 8-bit integers. This could be implemented as a lookup table of 256*256 entries of uint8.
|
|
542
|
+
static reedSolomonMultiply(x, y) {
|
|
543
|
+
if (x >>> 8 != 0 || y >>> 8 != 0)
|
|
544
|
+
throw new RangeError('Byte out of range');
|
|
545
|
+
// Russian peasant multiplication
|
|
546
|
+
let z = 0;
|
|
547
|
+
for (let i = 7; i >= 0; i--) {
|
|
548
|
+
z = (z << 1) ^ ((z >>> 7) * 0x11d);
|
|
549
|
+
z ^= ((y >>> i) & 1) * x;
|
|
550
|
+
}
|
|
551
|
+
assert(z >>> 8 == 0);
|
|
552
|
+
return z;
|
|
553
|
+
}
|
|
554
|
+
// Can only be called immediately after a light run is added, and
|
|
555
|
+
// returns either 0, 1, or 2. A helper function for getPenaltyScore().
|
|
556
|
+
finderPenaltyCountPatterns(runHistory) {
|
|
557
|
+
const n = runHistory[1];
|
|
558
|
+
assert(n <= this.size * 3);
|
|
559
|
+
const core = n > 0 && runHistory[2] == n && runHistory[3] == n * 3 && runHistory[4] == n && runHistory[5] == n;
|
|
560
|
+
return ((core && runHistory[0] >= n * 4 && runHistory[6] >= n ? 1 : 0) +
|
|
561
|
+
(core && runHistory[6] >= n * 4 && runHistory[0] >= n ? 1 : 0));
|
|
562
|
+
}
|
|
563
|
+
// Must be called at the end of a line (row or column) of modules. A helper function for getPenaltyScore().
|
|
564
|
+
finderPenaltyTerminateAndCount(currentRunColor, currentRunLength, runHistory) {
|
|
565
|
+
if (currentRunColor) {
|
|
566
|
+
// Terminate dark run
|
|
567
|
+
this.finderPenaltyAddHistory(currentRunLength, runHistory);
|
|
568
|
+
currentRunLength = 0;
|
|
569
|
+
}
|
|
570
|
+
currentRunLength += this.size; // Add light border to final run
|
|
571
|
+
this.finderPenaltyAddHistory(currentRunLength, runHistory);
|
|
572
|
+
return this.finderPenaltyCountPatterns(runHistory);
|
|
573
|
+
}
|
|
574
|
+
// Pushes the given value to the front and drops the last value. A helper function for getPenaltyScore().
|
|
575
|
+
finderPenaltyAddHistory(currentRunLength, runHistory) {
|
|
576
|
+
if (runHistory[0] == 0)
|
|
577
|
+
currentRunLength += this.size; // Add light border to initial run
|
|
578
|
+
runHistory.pop();
|
|
579
|
+
runHistory.unshift(currentRunLength);
|
|
580
|
+
}
|
|
581
|
+
/*-- Constants and tables --*/
|
|
582
|
+
// The minimum version number supported in the QR Code Model 2 standard.
|
|
583
|
+
static { this.MIN_VERSION = 1; }
|
|
584
|
+
// The maximum version number supported in the QR Code Model 2 standard.
|
|
585
|
+
static { this.MAX_VERSION = 40; }
|
|
586
|
+
// For use in getPenaltyScore(), when evaluating which mask is best.
|
|
587
|
+
static { this.PENALTY_N1 = 3; }
|
|
588
|
+
static { this.PENALTY_N2 = 3; }
|
|
589
|
+
static { this.PENALTY_N3 = 40; }
|
|
590
|
+
static { this.PENALTY_N4 = 10; }
|
|
591
|
+
static { this.ECC_CODEWORDS_PER_BLOCK = [
|
|
592
|
+
// Version: (note that index 0 is for padding, and is set to an illegal value)
|
|
593
|
+
//0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level
|
|
594
|
+
[
|
|
595
|
+
-1, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, 28, 28, 30, 30, 26, 28, 30,
|
|
596
|
+
30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
|
|
597
|
+
], // Low
|
|
598
|
+
[
|
|
599
|
+
-1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, 26, 28, 28, 28, 28, 28, 28,
|
|
600
|
+
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
|
601
|
+
], // Medium
|
|
602
|
+
[
|
|
603
|
+
-1, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30, 28, 30, 30, 30, 30, 28, 30,
|
|
604
|
+
30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
|
|
605
|
+
], // Quartile
|
|
606
|
+
[
|
|
607
|
+
-1, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, 30, 24, 30, 30, 30, 30, 30,
|
|
608
|
+
30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
|
|
609
|
+
], // High
|
|
610
|
+
]; }
|
|
611
|
+
static { this.NUM_ERROR_CORRECTION_BLOCKS = [
|
|
612
|
+
// Version: (note that index 0 is for padding, and is set to an illegal value)
|
|
613
|
+
//0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level
|
|
614
|
+
[
|
|
615
|
+
-1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18,
|
|
616
|
+
19, 19, 20, 21, 22, 24, 25,
|
|
617
|
+
], // Low
|
|
618
|
+
[
|
|
619
|
+
-1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, 25, 26, 28, 29,
|
|
620
|
+
31, 33, 35, 37, 38, 40, 43, 45, 47, 49,
|
|
621
|
+
], // Medium
|
|
622
|
+
[
|
|
623
|
+
-1, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, 35, 38, 40,
|
|
624
|
+
43, 45, 48, 51, 53, 56, 59, 62, 65, 68,
|
|
625
|
+
], // Quartile
|
|
626
|
+
[
|
|
627
|
+
-1, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45,
|
|
628
|
+
48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81,
|
|
629
|
+
], // High
|
|
630
|
+
]; }
|
|
631
|
+
}
|
|
632
|
+
qrcodegen.QrCode = QrCode;
|
|
633
|
+
// Appends the given number of low-order bits of the given value
|
|
634
|
+
// to the given buffer. Requires 0 <= len <= 31 and 0 <= val < 2^len.
|
|
635
|
+
function appendBits(val, len, bb) {
|
|
636
|
+
if (len < 0 || len > 31 || val >>> len != 0)
|
|
637
|
+
throw new RangeError('Value out of range');
|
|
638
|
+
for (let i = len - 1; i >= 0; i-- // Append bit by bit
|
|
639
|
+
)
|
|
640
|
+
bb.push((val >>> i) & 1);
|
|
641
|
+
}
|
|
642
|
+
// Returns true iff the i'th bit of x is set to 1.
|
|
643
|
+
function getBit(x, i) {
|
|
644
|
+
return ((x >>> i) & 1) != 0;
|
|
645
|
+
}
|
|
646
|
+
// Throws an exception if the given condition is false.
|
|
647
|
+
function assert(cond) {
|
|
648
|
+
if (!cond)
|
|
649
|
+
throw new Error('Assertion error');
|
|
650
|
+
}
|
|
651
|
+
/*---- Data segment class ----*/
|
|
652
|
+
/*
|
|
653
|
+
* A segment of character/binary/control data in a QR Code symbol.
|
|
654
|
+
* Instances of this class are immutable.
|
|
655
|
+
* The mid-level way to create a segment is to take the payload data
|
|
656
|
+
* and call a static factory function such as QrSegment.makeNumeric().
|
|
657
|
+
* The low-level way to create a segment is to custom-make the bit buffer
|
|
658
|
+
* and call the QrSegment() constructor with appropriate values.
|
|
659
|
+
* This segment class imposes no length restrictions, but QR Codes have restrictions.
|
|
660
|
+
* Even in the most favorable conditions, a QR Code can only hold 7089 characters of data.
|
|
661
|
+
* Any segment longer than this is meaningless for the purpose of generating QR Codes.
|
|
662
|
+
*/
|
|
663
|
+
class QrSegment {
|
|
664
|
+
/*-- Static factory functions (mid level) --*/
|
|
665
|
+
// Returns a segment representing the given binary data encoded in
|
|
666
|
+
// byte mode. All input byte arrays are acceptable. Any text string
|
|
667
|
+
// can be converted to UTF-8 bytes and encoded as a byte mode segment.
|
|
668
|
+
static makeBytes(data) {
|
|
669
|
+
let bb = [];
|
|
670
|
+
for (const b of data)
|
|
671
|
+
appendBits(b, 8, bb);
|
|
672
|
+
return new QrSegment(QrSegment.Mode.BYTE, data.length, bb);
|
|
673
|
+
}
|
|
674
|
+
// Returns a segment representing the given string of decimal digits encoded in numeric mode.
|
|
675
|
+
static makeNumeric(digits) {
|
|
676
|
+
if (!QrSegment.isNumeric(digits))
|
|
677
|
+
throw new RangeError('String contains non-numeric characters');
|
|
678
|
+
let bb = [];
|
|
679
|
+
for (let i = 0; i < digits.length;) {
|
|
680
|
+
// Consume up to 3 digits per iteration
|
|
681
|
+
const n = Math.min(digits.length - i, 3);
|
|
682
|
+
appendBits(parseInt(digits.substring(i, i + n), 10), n * 3 + 1, bb);
|
|
683
|
+
i += n;
|
|
684
|
+
}
|
|
685
|
+
return new QrSegment(QrSegment.Mode.NUMERIC, digits.length, bb);
|
|
686
|
+
}
|
|
687
|
+
// Returns a segment representing the given text string encoded in alphanumeric mode.
|
|
688
|
+
// The characters allowed are: 0 to 9, A to Z (uppercase only), space,
|
|
689
|
+
// dollar, percent, asterisk, plus, hyphen, period, slash, colon.
|
|
690
|
+
static makeAlphanumeric(text) {
|
|
691
|
+
if (!QrSegment.isAlphanumeric(text))
|
|
692
|
+
throw new RangeError('String contains unencodable characters in alphanumeric mode');
|
|
693
|
+
let bb = [];
|
|
694
|
+
let i;
|
|
695
|
+
for (i = 0; i + 2 <= text.length; i += 2) {
|
|
696
|
+
// Process groups of 2
|
|
697
|
+
let temp = QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)) * 45;
|
|
698
|
+
temp += QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i + 1));
|
|
699
|
+
appendBits(temp, 11, bb);
|
|
700
|
+
}
|
|
701
|
+
if (i < text.length)
|
|
702
|
+
// 1 character remaining
|
|
703
|
+
appendBits(QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)), 6, bb);
|
|
704
|
+
return new QrSegment(QrSegment.Mode.ALPHANUMERIC, text.length, bb);
|
|
705
|
+
}
|
|
706
|
+
// Returns a new mutable list of zero or more segments to represent the given Unicode text string.
|
|
707
|
+
// The result may use various segment modes and switch modes to optimize the length of the bit stream.
|
|
708
|
+
static makeSegments(text) {
|
|
709
|
+
// Select the most efficient segment encoding automatically
|
|
710
|
+
if (text == '')
|
|
711
|
+
return [];
|
|
712
|
+
else if (QrSegment.isNumeric(text))
|
|
713
|
+
return [QrSegment.makeNumeric(text)];
|
|
714
|
+
else if (QrSegment.isAlphanumeric(text))
|
|
715
|
+
return [QrSegment.makeAlphanumeric(text)];
|
|
716
|
+
else
|
|
717
|
+
return [QrSegment.makeBytes(QrSegment.toUtf8ByteArray(text))];
|
|
718
|
+
}
|
|
719
|
+
// Returns a segment representing an Extended Channel Interpretation
|
|
720
|
+
// (ECI) designator with the given assignment value.
|
|
721
|
+
static makeEci(assignVal) {
|
|
722
|
+
let bb = [];
|
|
723
|
+
if (assignVal < 0)
|
|
724
|
+
throw new RangeError('ECI assignment value out of range');
|
|
725
|
+
else if (assignVal < 1 << 7)
|
|
726
|
+
appendBits(assignVal, 8, bb);
|
|
727
|
+
else if (assignVal < 1 << 14) {
|
|
728
|
+
appendBits(0b10, 2, bb);
|
|
729
|
+
appendBits(assignVal, 14, bb);
|
|
730
|
+
}
|
|
731
|
+
else if (assignVal < 1000000) {
|
|
732
|
+
appendBits(0b110, 3, bb);
|
|
733
|
+
appendBits(assignVal, 21, bb);
|
|
734
|
+
}
|
|
735
|
+
else
|
|
736
|
+
throw new RangeError('ECI assignment value out of range');
|
|
737
|
+
return new QrSegment(QrSegment.Mode.ECI, 0, bb);
|
|
738
|
+
}
|
|
739
|
+
// Tests whether the given string can be encoded as a segment in numeric mode.
|
|
740
|
+
// A string is encodable iff each character is in the range 0 to 9.
|
|
741
|
+
static isNumeric(text) {
|
|
742
|
+
return QrSegment.NUMERIC_REGEX.test(text);
|
|
743
|
+
}
|
|
744
|
+
// Tests whether the given string can be encoded as a segment in alphanumeric mode.
|
|
745
|
+
// A string is encodable iff each character is in the following set: 0 to 9, A to Z
|
|
746
|
+
// (uppercase only), space, dollar, percent, asterisk, plus, hyphen, period, slash, colon.
|
|
747
|
+
static isAlphanumeric(text) {
|
|
748
|
+
return QrSegment.ALPHANUMERIC_REGEX.test(text);
|
|
749
|
+
}
|
|
750
|
+
/*-- Constructor (low level) and fields --*/
|
|
751
|
+
// Creates a new QR Code segment with the given attributes and data.
|
|
752
|
+
// The character count (numChars) must agree with the mode and the bit buffer length,
|
|
753
|
+
// but the constraint isn't checked. The given bit buffer is cloned and stored.
|
|
754
|
+
constructor(
|
|
755
|
+
// The mode indicator of this segment.
|
|
756
|
+
mode,
|
|
757
|
+
// The length of this segment's unencoded data. Measured in characters for
|
|
758
|
+
// numeric/alphanumeric/kanji mode, bytes for byte mode, and 0 for ECI mode.
|
|
759
|
+
// Always zero or positive. Not the same as the data's bit length.
|
|
760
|
+
numChars,
|
|
761
|
+
// The data bits of this segment. Accessed through getData().
|
|
762
|
+
bitData) {
|
|
763
|
+
this.mode = mode;
|
|
764
|
+
this.numChars = numChars;
|
|
765
|
+
this.bitData = bitData;
|
|
766
|
+
if (numChars < 0)
|
|
767
|
+
throw new RangeError('Invalid argument');
|
|
768
|
+
this.bitData = bitData.slice(); // Make defensive copy
|
|
769
|
+
}
|
|
770
|
+
/*-- Methods --*/
|
|
771
|
+
// Returns a new copy of the data bits of this segment.
|
|
772
|
+
getData() {
|
|
773
|
+
return this.bitData.slice(); // Make defensive copy
|
|
774
|
+
}
|
|
775
|
+
// (Package-private) Calculates and returns the number of bits needed to encode the given segments at
|
|
776
|
+
// the given version. The result is infinity if a segment has too many characters to fit its length field.
|
|
777
|
+
static getTotalBits(segs, version) {
|
|
778
|
+
let result = 0;
|
|
779
|
+
for (const seg of segs) {
|
|
780
|
+
const ccbits = seg.mode.numCharCountBits(version);
|
|
781
|
+
if (seg.numChars >= 1 << ccbits)
|
|
782
|
+
return Infinity; // The segment's length doesn't fit the field's bit width
|
|
783
|
+
result += 4 + ccbits + seg.bitData.length;
|
|
784
|
+
}
|
|
785
|
+
return result;
|
|
786
|
+
}
|
|
787
|
+
// Returns a new array of bytes representing the given string encoded in UTF-8.
|
|
788
|
+
static toUtf8ByteArray(str) {
|
|
789
|
+
str = encodeURI(str);
|
|
790
|
+
let result = [];
|
|
791
|
+
for (let i = 0; i < str.length; i++) {
|
|
792
|
+
if (str.charAt(i) != '%')
|
|
793
|
+
result.push(str.charCodeAt(i));
|
|
794
|
+
else {
|
|
795
|
+
result.push(parseInt(str.substring(i + 1, i + 3), 16));
|
|
796
|
+
i += 2;
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
return result;
|
|
800
|
+
}
|
|
801
|
+
/*-- Constants --*/
|
|
802
|
+
// Describes precisely all strings that are encodable in numeric mode.
|
|
803
|
+
static { this.NUMERIC_REGEX = /^[0-9]*$/; }
|
|
804
|
+
// Describes precisely all strings that are encodable in alphanumeric mode.
|
|
805
|
+
static { this.ALPHANUMERIC_REGEX = /^[A-Z0-9 $%*+.\/:-]*$/; }
|
|
806
|
+
// The set of all legal characters in alphanumeric mode,
|
|
807
|
+
// where each character value maps to the index in the string.
|
|
808
|
+
static { this.ALPHANUMERIC_CHARSET = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:'; }
|
|
809
|
+
}
|
|
810
|
+
qrcodegen.QrSegment = QrSegment;
|
|
811
|
+
})(qrcodegen || (qrcodegen = {}));
|
|
812
|
+
/*---- Public helper enumeration ----*/
|
|
813
|
+
(function (qrcodegen) {
|
|
814
|
+
var QrCode;
|
|
815
|
+
(function (QrCode) {
|
|
816
|
+
/*
|
|
817
|
+
* The error correction level in a QR Code symbol. Immutable.
|
|
818
|
+
*/
|
|
819
|
+
class Ecc {
|
|
820
|
+
/*-- Constants --*/
|
|
821
|
+
static { this.LOW = new Ecc(0, 1); } // The QR Code can tolerate about 7% erroneous codewords
|
|
822
|
+
static { this.MEDIUM = new Ecc(1, 0); } // The QR Code can tolerate about 15% erroneous codewords
|
|
823
|
+
static { this.QUARTILE = new Ecc(2, 3); } // The QR Code can tolerate about 25% erroneous codewords
|
|
824
|
+
static { this.HIGH = new Ecc(3, 2); } // The QR Code can tolerate about 30% erroneous codewords
|
|
825
|
+
/*-- Constructor and fields --*/
|
|
826
|
+
constructor(
|
|
827
|
+
// In the range 0 to 3 (unsigned 2-bit integer).
|
|
828
|
+
ordinal,
|
|
829
|
+
// (Package-private) In the range 0 to 3 (unsigned 2-bit integer).
|
|
830
|
+
formatBits) {
|
|
831
|
+
this.ordinal = ordinal;
|
|
832
|
+
this.formatBits = formatBits;
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
QrCode.Ecc = Ecc;
|
|
836
|
+
})(QrCode = qrcodegen.QrCode || (qrcodegen.QrCode = {}));
|
|
837
|
+
})(qrcodegen || (qrcodegen = {}));
|
|
838
|
+
/*---- Public helper enumeration ----*/
|
|
839
|
+
(function (qrcodegen) {
|
|
840
|
+
var QrSegment;
|
|
841
|
+
(function (QrSegment) {
|
|
842
|
+
/*
|
|
843
|
+
* Describes how a segment's data bits are interpreted. Immutable.
|
|
844
|
+
*/
|
|
845
|
+
class Mode {
|
|
846
|
+
/*-- Constants --*/
|
|
847
|
+
static { this.NUMERIC = new Mode(0x1, [10, 12, 14]); }
|
|
848
|
+
static { this.ALPHANUMERIC = new Mode(0x2, [9, 11, 13]); }
|
|
849
|
+
static { this.BYTE = new Mode(0x4, [8, 16, 16]); }
|
|
850
|
+
static { this.KANJI = new Mode(0x8, [8, 10, 12]); }
|
|
851
|
+
static { this.ECI = new Mode(0x7, [0, 0, 0]); }
|
|
852
|
+
/*-- Constructor and fields --*/
|
|
853
|
+
constructor(
|
|
854
|
+
// The mode indicator bits, which is a uint4 value (range 0 to 15).
|
|
855
|
+
modeBits,
|
|
856
|
+
// Number of character count bits for three different version ranges.
|
|
857
|
+
numBitsCharCount) {
|
|
858
|
+
this.modeBits = modeBits;
|
|
859
|
+
this.numBitsCharCount = numBitsCharCount;
|
|
860
|
+
}
|
|
861
|
+
/*-- Method --*/
|
|
862
|
+
// (Package-private) Returns the bit width of the character count field for a segment in
|
|
863
|
+
// this mode in a QR Code at the given version number. The result is in the range [0, 16].
|
|
864
|
+
numCharCountBits(ver) {
|
|
865
|
+
return this.numBitsCharCount[Math.floor((ver + 7) / 17)];
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
QrSegment.Mode = Mode;
|
|
869
|
+
})(QrSegment = qrcodegen.QrSegment || (qrcodegen.QrSegment = {}));
|
|
870
|
+
})(qrcodegen || (qrcodegen = {}));
|
|
871
|
+
export default qrcodegen;
|
|
872
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXJjb2RlZ2VuLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvbGliL3FyL3FyY29kZWdlbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBcUJHO0FBRUgsWUFBWSxDQUFDO0FBRWIsSUFBVSxTQUFTLENBMjFCbEI7QUEzMUJELFdBQVUsU0FBUztJQUtqQixrQ0FBa0M7SUFFbEM7Ozs7Ozs7Ozs7Ozs7OztPQWVHO0lBQ0gsTUFBYSxNQUFNO1FBQ2pCLCtDQUErQztRQUUvQyxvR0FBb0c7UUFDcEcsMkdBQTJHO1FBQzNHLCtHQUErRztRQUMvRyw2R0FBNkc7UUFDN0csaUVBQWlFO1FBQzFELE1BQU0sQ0FBQyxVQUFVLENBQUMsSUFBWSxFQUFFLEdBQWU7WUFDcEQsTUFBTSxJQUFJLEdBQXFCLFNBQVMsQ0FBQyxTQUFTLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ3RFLE9BQU8sTUFBTSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDMUMsQ0FBQztRQUVELDRGQUE0RjtRQUM1Rix1R0FBdUc7UUFDdkcsdUdBQXVHO1FBQ3ZHLG9IQUFvSDtRQUM3RyxNQUFNLENBQUMsWUFBWSxDQUFDLElBQTJCLEVBQUUsR0FBZTtZQUNyRSxNQUFNLEdBQUcsR0FBYyxTQUFTLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUMzRCxPQUFPLE1BQU0sQ0FBQyxjQUFjLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUMzQyxDQUFDO1FBRUQsOENBQThDO1FBRTlDLHdGQUF3RjtRQUN4RixnRkFBZ0Y7UUFDaEYsZ0ZBQWdGO1FBQ2hGLCtFQUErRTtRQUMvRSw4RUFBOEU7UUFDOUUsK0VBQStFO1FBQy9FLHNGQUFzRjtRQUN0Riw4RUFBOEU7UUFDOUUsa0ZBQWtGO1FBQzNFLE1BQU0sQ0FB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RSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUU7Z0JBQzdHLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUU7YUFDbkQsRUFBRSxNQUFNO1lBQ1Q7Z0JBQ0UsQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFO2dCQUM5RyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFO2FBQ25ELEVBQUUsU0FBUztZQUNaO2dCQUNFLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRTtnQkFDOUcsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRTthQUNuRCxFQUFFLFdBQVc7WUFDZDtnQkFDRSxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUU7Z0JBQzlHLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUU7YUFDbkQsRUFBRSxPQUFPO1NBQ1gsQUFuQjhDLENBbUI3QztpQkFFc0IsZ0NBQTJCLEdBQXNCO1lBQ3ZFLDhFQUE4RTtZQUM5RSxtTEFBbUw7WUFDbkw7Z0JBQ0UsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFO2dCQUMvRyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFO2FBQzNCLEVBQUUsTUFBTTtZQUNUO2dCQUNFLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRTtnQkFDNUcsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRTthQUN2QyxFQUFFLFNBQVM7WUFDWjtnQkFDRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FB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U0FBSSxHQUFHLElBQUksSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztxQkFDbEMsVUFBSyxHQUFHLElBQUksSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztxQkFDbkMsUUFBRyxHQUFHLElBQUksSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUV0RCxnQ0FBZ0M7WUFFaEM7WUFDRSxtRUFBbUU7WUFDbkQsUUFBYTtZQUM3QixxRUFBcUU7WUFDcEQsZ0JBQWlDO2dCQUZsQyxhQUFRLEdBQVIsUUFBUSxDQUFLO2dCQUVaLHFCQUFnQixHQUFoQixnQkFBZ0IsQ0FBaUI7WUFDakQsQ0FBQztZQUVKLGdCQUFnQjtZQUVoQix3RkFBd0Y7WUFDeEYsMEZBQTBGO1lBQ25GLGdCQUFnQixDQUFDLEdBQVE7Z0JBQzlCLE9BQU8sSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUMzRCxDQUFDOztRQXhCVSxjQUFJLE9BeUJoQixDQUFBO0lBQ0gsQ0FBQyxFQWhDbUIsU0FBUyxHQUFULG1CQUFTLEtBQVQsbUJBQVMsUUFnQzVCO0FBQUQsQ0FBQyxFQWhDUyxTQUFTLEtBQVQsU0FBUyxRQWdDbEI7QUFFRCxlQUFlLFNBQVMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBRUiBDb2RlIGdlbmVyYXRvciBsaWJyYXJ5IChUeXBlU2NyaXB0KVxuICpcbiAqIENvcHlyaWdodCAoYykgUHJvamVjdCBOYXl1a2kuIChNSVQgTGljZW5zZSlcbiAqIGh0dHBzOi8vd3d3Lm5heXVraS5pby9wYWdlL3FyLWNvZGUtZ2VuZXJhdG9yLWxpYnJhcnlcbiAqXG4gKiBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5IG9mXG4gKiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluXG4gKiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvXG4gKiB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsIGNvcGllcyBvZlxuICogdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLFxuICogc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4gKiAtIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4gKiAgIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuICogLSBUaGUgU29mdHdhcmUgaXMgcHJvdmlkZWQgXCJhcyBpc1wiLCB3aXRob3V0IHdhcnJhbnR5IG9mIGFueSBraW5kLCBleHByZXNzIG9yXG4gKiAgIGltcGxpZWQsIGluY2x1ZGluZyBidXQgbm90IGxpbWl0ZWQgdG8gdGhlIHdhcnJhbnRpZXMgb2YgbWVyY2hhbnRhYmlsaXR5LFxuICogICBmaXRuZXNzIGZvciBhIHBhcnRpY3VsYXIgcHVycG9zZSBhbmQgbm9uaW5mcmluZ2VtZW50LiBJbiBubyBldmVudCBzaGFsbCB0aGVcbiAqICAgYXV0aG9ycyBvciBjb3B5cmlnaHQgaG9sZGVycyBiZSBsaWFibGUgZm9yIGFueSBjbGFpbSwgZGFtYWdlcyBvciBvdGhlclxuICogICBsaWFiaWxpdHksIHdoZXRoZXIgaW4gYW4gYWN0aW9uIG9mIGNvbnRyYWN0LCB0b3J0IG9yIG90aGVyd2lzZSwgYXJpc2luZyBmcm9tLFxuICogICBvdXQgb2Ygb3IgaW4gY29ubmVjdGlvbiB3aXRoIHRoZSBTb2Z0d2FyZSBvciB0aGUgdXNlIG9yIG90aGVyIGRlYWxpbmdzIGluIHRoZVxuICogICBTb2Z0d2FyZS5cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbm5hbWVzcGFjZSBxcmNvZGVnZW4ge1xuICB0eXBlIGJpdCA9IG51bWJlcjtcbiAgdHlwZSBieXRlID0gbnVtYmVyO1xuICB0eXBlIGludCA9IG51bWJlcjtcblxuICAvKi0tLS0gUVIgQ29kZSBzeW1ib2wgY2xhc3MgLS0tLSovXG5cbiAgLypcbiAgICogQSBRUiBDb2RlIHN5bWJvbCwgd2hpY2ggaXMgYSB0eXBlIG9mIHR3by1kaW1lbnNpb24gYmFyY29kZS5cbiAgICogSW52ZW50ZWQgYnkgRGVuc28gV2F2ZSBhbmQgZGVzY3JpYmVkIGluIHRoZSBJU08vSUVDIDE4MDA0IHN0YW5kYXJkLlxuICAgKiBJbnN0YW5jZXMgb2YgdGhpcyBjbGFzcyByZXByZXNlbnQgYW4gaW1tdXRhYmxlIHNxdWFyZSBncmlkIG9mIGRhcmsgYW5kIGxpZ2h0IGNlbGxzLlxuICAgKiBUaGUgY2xhc3MgcHJvdmlkZXMgc3RhdGljIGZhY3RvcnkgZnVuY3Rpb25zIHRvIGNyZWF0ZSBhIFFSIENvZGUgZnJvbSB0ZXh0IG9yIGJpbmFyeSBkYXRhLlxuICAgKiBUaGUgY2xhc3MgY292ZXJzIHRoZSBRUiBDb2RlIE1vZGVsIDIgc3BlY2lmaWNhdGlvbiwgc3VwcG9ydGluZyBhbGwgdmVyc2lvbnMgKHNpemVzKVxuICAgKiBmcm9tIDEgdG8gNDAsIGFsbCA0IGVycm9yIGNvcnJlY3Rpb24gbGV2ZWxzLCBhbmQgNCBjaGFyYWN0ZXIgZW5jb2RpbmcgbW9kZXMuXG4gICAqXG4gICAqIFdheXMgdG8gY3JlYXRlIGEgUVIgQ29kZSBvYmplY3Q6XG4gICAqIC0gSGlnaCBsZXZlbDogVGFrZSB0aGUgcGF5bG9hZCBkYXRhIGFuZCBjYWxsIFFyQ29kZS5lbmNvZGVUZXh0KCkgb3IgUXJDb2RlLmVuY29kZUJpbmFyeSgpLlxuICAgKiAtIE1pZCBsZXZlbDogQ3VzdG9tLW1ha2UgdGhlIGxpc3Qgb2Ygc2VnbWVudHMgYW5kIGNhbGwgUXJDb2RlLmVuY29kZVNlZ21lbnRzKCkuXG4gICAqIC0gTG93IGxldmVsOiBDdXN0b20tbWFrZSB0aGUgYXJyYXkgb2YgZGF0YSBjb2Rld29yZCBieXRlcyAoaW5jbHVkaW5nXG4gICAqICAgc2VnbWVudCBoZWFkZXJzIGFuZCBmaW5hbCBwYWRkaW5nLCBleGNsdWRpbmcgZXJyb3IgY29ycmVjdGlvbiBjb2Rld29yZHMpLFxuICAgKiAgIHN1cHBseSB0aGUgYXBwcm9wcmlhdGUgdmVyc2lvbiBudW1iZXIsIGFuZCBjYWxsIHRoZSBRckNvZGUoKSBjb25zdHJ1Y3Rvci5cbiAgICogKE5vdGUgdGhhdCBhbGwgd2F5cyByZXF1aXJlIHN1cHBseWluZyB0aGUgZGVzaXJlZCBlcnJvciBjb3JyZWN0aW9uIGxldmVsLilcbiAgICovXG4gIGV4cG9ydCBjbGFzcyBRckNvZGUge1xuICAgIC8qLS0gU3RhdGljIGZhY3RvcnkgZnVuY3Rpb25zIChoaWdoIGxldmVsKSAtLSovXG5cbiAgICAvLyBSZXR1cm5zIGEgUVIgQ29kZSByZXByZXNlbnRpbmcgdGhlIGdpdmVuIFVuaWNvZGUgdGV4dCBzdHJpbmcgYXQgdGhlIGdpdmVuIGVycm9yIGNvcnJlY3Rpb24gbGV2ZWwuXG4gICAgLy8gQXMgYSBjb25zZXJ2YXRpdmUgdXBwZXIgYm91bmQsIHRoaXMgZnVuY3Rpb24gaXMgZ3VhcmFudGVlZCB0byBzdWNjZWVkIGZvciBzdHJpbmdzIHRoYXQgaGF2ZSA3Mzggb3IgZmV3ZXJcbiAgICAvLyBVbmljb2RlIGNvZGUgcG9pbnRzIChub3QgVVRGLTE2IGNvZGUgdW5pdHMpIGlmIHRoZSBsb3cgZXJyb3IgY29ycmVjdGlvbiBsZXZlbCBpcyB1c2VkLiBUaGUgc21hbGxlc3QgcG9zc2libGVcbiAgICAvLyBRUiBDb2RlIHZlcnNpb24gaXMgYXV0b21hdGljYWxseSBjaG9zZW4gZm9yIHRoZSBvdXRwdXQuIFRoZSBFQ0MgbGV2ZWwgb2YgdGhlIHJlc3VsdCBtYXkgYmUgaGlnaGVyIHRoYW4gdGhlXG4gICAgLy8gZWNsIGFyZ3VtZW50IGlmIGl0IGNhbiBiZSBkb25lIHdpdGhvdXQgaW5jcmVhc2luZyB0aGUgdmVyc2lvbi5cbiAgICBwdWJsaWMgc3RhdGljIGVuY29kZVRleHQodGV4dDogc3RyaW5nLCBlY2w6IFFyQ29kZS5FY2MpOiBRckNvZGUge1xuICAgICAgY29uc3Qgc2VnczogQXJyYXk8UXJTZWdtZW50PiA9IHFyY29kZWdlbi5RclNlZ21lbnQubWFrZVNlZ21lbnRzKHRleHQpO1xuICAgICAgcmV0dXJuIFFyQ29kZS5lbmNvZGVTZWdtZW50cyhzZWdzLCBlY2wpO1xuICAgIH1cblxuICAgIC8vIFJldHVybnMgYSBRUiBDb2RlIHJlcHJlc2VudGluZyB0aGUgZ2l2ZW4gYmluYXJ5IGRhdGEgYXQgdGhlIGdpdmVuIGVycm9yIGNvcnJlY3Rpb24gbGV2ZWwuXG4gICAgLy8gVGhpcyBmdW5jdGlvbiBhbHdheXMgZW5jb2RlcyB1c2luZyB0aGUgYmluYXJ5IHNlZ21lbnQgbW9kZSwgbm90IGFueSB0ZXh0IG1vZGUuIFRoZSBtYXhpbXVtIG51bWJlciBvZlxuICAgIC8vIGJ5dGVzIGFsbG93ZWQgaXMgMjk1My4gVGhlIHNtYWxsZXN0IHBvc3NpYmxlIFFSIENvZGUgdmVyc2lvbiBpcyBhdXRvbWF0aWNhbGx5IGNob3NlbiBmb3IgdGhlIG91dHB1dC5cbiAgICAvLyBUaGUgRUNDIGxldmVsIG9mIHRoZSByZXN1bHQgbWF5IGJlIGhpZ2hlciB0aGFuIHRoZSBlY2wgYXJndW1lbnQgaWYgaXQgY2FuIGJlIGRvbmUgd2l0aG91dCBpbmNyZWFzaW5nIHRoZSB2ZXJzaW9uLlxuICAgIHB1YmxpYyBzdGF0aWMgZW5jb2RlQmluYXJ5KGRhdGE6IFJlYWRvbmx5PEFycmF5PGJ5dGU+PiwgZWNsOiBRckNvZGUuRWNjKTogUXJDb2RlIHtcbiAgICAgIGNvbnN0IHNlZzogUXJTZWdtZW50ID0gcXJjb2RlZ2VuLlFyU2VnbWVudC5tYWtlQnl0ZXMoZGF0YSk7XG4gICAgICByZXR1cm4gUXJDb2RlLmVuY29kZVNlZ21lbnRzKFtzZWddLCBlY2wpO1xuICAgIH1cblxuICAgIC8qLS0gU3RhdGljIGZhY3RvcnkgZnVuY3Rpb25zIChtaWQgbGV2ZWwpIC0tKi9cblxuICAgIC8vIFJldHVybnMgYSBRUiBDb2RlIHJlcHJlc2VudGluZyB0aGUgZ2l2ZW4gc2VnbWVudHMgd2l0aCB0aGUgZ2l2ZW4gZW5jb2RpbmcgcGFyYW1ldGVycy5cbiAgICAvLyBUaGUgc21hbGxlc3QgcG9zc2libGUgUVIgQ29kZSB2ZXJzaW9uIHdpdGhpbiB0aGUgZ2l2ZW4gcmFuZ2UgaXMgYXV0b21hdGljYWxseVxuICAgIC8vIGNob3NlbiBmb3IgdGhlIG91dHB1dC4gSWZmIGJvb3N0RWNsIGlzIHRydWUsIHRoZW4gdGhlIEVDQyBsZXZlbCBvZiB0aGUgcmVzdWx0XG4gICAgLy8gbWF5IGJlIGhpZ2hlciB0aGFuIHRoZSBlY2wgYXJndW1lbnQgaWYgaXQgY2FuIGJlIGRvbmUgd2l0aG91dCBpbmNyZWFzaW5nIHRoZVxuICAgIC8vIHZlcnNpb24uIFRoZSBtYXNrIG51bWJlciBpcyBlaXRoZXIgYmV0d2VlbiAwIHRvIDcgKGluY2x1c2l2ZSkgdG8gZm9yY2UgdGhhdFxuICAgIC8vIG1hc2ssIG9yIC0xIHRvIGF1dG9tYXRpY2FsbHkgY2hvb3NlIGFuIGFwcHJvcHJpYXRlIG1hc2sgKHdoaWNoIG1heSBiZSBzbG93KS5cbiAgICAvLyBUaGlzIGZ1bmN0aW9uIGFsbG93cyB0aGUgdXNlciB0byBjcmVhdGUgYSBjdXN0b20gc2VxdWVuY2Ugb2Ygc2VnbWVudHMgdGhhdCBzd2l0Y2hlc1xuICAgIC8vIGJldHdlZW4gbW9kZXMgKHN1Y2ggYXMgYWxwaGFudW1lcmljIGFuZCBieXRlKSB0byBlbmNvZGUgdGV4dCBpbiBsZXNzIHNwYWNlLlxuICAgIC8vIFRoaXMgaXMgYSBtaWQtbGV2ZWwgQVBJOyB0aGUgaGlnaC1sZXZlbCBBUEkgaXMgZW5jb2RlVGV4dCgpIGFuZCBlbmNvZGVCaW5hcnkoKS5cbiAgICBwdWJsaWMgc3RhdGljIGVuY29kZVNlZ21lbnRzKFxuICAgICAgc2VnczogUmVhZG9ubHk8QXJyYXk8UXJTZWdtZW50Pj4sXG4gICAgICBlY2w6IFFyQ29kZS5FY2MsXG4gICAgICBtaW5WZXJzaW9uOiBpbnQgPSAxLFxuICAgICAgbWF4VmVyc2lvbjogaW50ID0gNDAsXG4gICAgICBtYXNrOiBpbnQgPSAtMSxcbiAgICAgIGJvb3N0RWNsOiBib29sZWFuID0gdHJ1ZVxuICAgICk6IFFyQ29kZSB7XG4gICAgICBpZiAoXG4gICAgICAgICEoUXJDb2RlLk1JTl9WRVJTSU9OIDw9IG1pblZlcnNpb24gJiYgbWluVmVyc2lvbiA8PSBtYXhWZXJzaW9uICYmIG1heFZlcnNpb24gPD0gUXJDb2RlLk1BWF9WRVJTSU9OKSB8fFxuICAgICAgICBtYXNrIDwgLTEgfHxcbiAgICAgICAgbWFzayA+IDdcbiAgICAgIClcbiAgICAgICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0ludmFsaWQgdmFsdWUnKTtcblxuICAgICAgLy8gRmluZCB0aGUgbWluaW1hbCB2ZXJzaW9uIG51bWJlciB0byB1c2VcbiAgICAgIGxldCB2ZXJzaW9uOiBpbnQ7XG4gICAgICBsZXQgZGF0YVVzZWRCaXRzOiBpbnQ7XG4gICAgICBmb3IgKHZlcnNpb24gPSBtaW5WZXJzaW9uOyA7IHZlcnNpb24rKykge1xuICAgICAgICBjb25zdCBkYXRhQ2FwYWNpdHlCaXRzOiBpbnQgPSBRckNvZGUuZ2V0TnVtRGF0YUNvZGV3b3Jkcyh2ZXJzaW9uLCBlY2wpICogODsgLy8gTnVtYmVyIG9mIGRhdGEgYml0cyBhdmFpbGFibGVcbiAgICAgICAgY29uc3QgdXNlZEJpdHM6IG51bWJlciA9IFFyU2VnbWVudC5nZXRUb3RhbEJpdHMoc2VncywgdmVyc2lvbik7XG4gICAgICAgIGlmICh1c2VkQml0cyA8PSBkYXRhQ2FwYWNpdHlCaXRzKSB7XG4gICAgICAgICAgZGF0YVVzZWRCaXRzID0gdXNlZEJpdHM7XG4gICAgICAgICAgYnJlYWs7IC8vIFRoaXMgdmVyc2lvbiBudW1iZXIgaXMgZm91bmQgdG8gYmUgc3VpdGFibGVcbiAgICAgICAgfVxuICAgICAgICBpZiAodmVyc2lvbiA+PSBtYXhWZXJzaW9uKVxuICAgICAgICAgIC8vIEFsbCB2ZXJzaW9ucyBpbiB0aGUgcmFuZ2UgY291bGQgbm90IGZpdCB0aGUgZ2l2ZW4gZGF0YVxuICAgICAgICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdEYXRhIHRvbyBsb25nJyk7XG4gICAgICB9XG5cbiAgICAgIC8vIEluY3JlYXNlIHRoZSBlcnJvciBjb3JyZWN0aW9uIGxldmVsIHdoaWxlIHRoZSBkYXRhIHN0aWxsIGZpdHMgaW4gdGhlIGN1cnJlbnQgdmVyc2lvbiBudW1iZXJcbiAgICAgIGZvciAoY29uc3QgbmV3RWNsIG9mIFtRckNvZGUuRWNjLk1FRElVTSwgUXJDb2RlLkVjYy5RVUFSVElMRSwgUXJDb2RlLkVjYy5ISUdIXSkge1xuICAgICAgICAvLyBGcm9tIGxvdyB0byBoaWdoXG4gICAgICAgIGlmIChib29zdEVjbCAmJiBkYXRhVXNlZEJpdHMgPD0gUXJDb2RlLmdldE51bURhdGFDb2Rld29yZHModmVyc2lvbiwgbmV3RWNsKSAqIDgpIGVjbCA9IG5ld0VjbDtcbiAgICAgIH1cblxuICAgICAgLy8gQ29uY2F0ZW5hdGUgYWxsIHNlZ21lbnRzIHRvIGNyZWF0ZSB0aGUgZGF0YSBiaXQgc3RyaW5nXG4gICAgICBsZXQgYmI6IEFycmF5PGJpdD4gPSBbXTtcbiAgICAgIGZvciAoY29uc3Qgc2VnIG9mIHNlZ3MpIHtcbiAgICAgICAgYXBwZW5kQml0cyhzZWcubW9kZS5tb2RlQml0cywgNCwgYmIpO1xuICAgICAgICBhcHBlbmRCaXRzKHNlZy5udW1DaGFycywgc2VnLm1vZGUubnVtQ2hhckNvdW50Qml0cyh2ZXJzaW9uKSwgYmIpO1xuICAgICAgICBmb3IgKGNvbnN0IGIgb2Ygc2VnLmdldERhdGEoKSkgYmIucHVzaChiKTtcbiAgICAgIH1cbiAgICAgIGFzc2VydChiYi5sZW5ndGggPT0gZGF0YVVzZWRCaXRzKTtcblxuICAgICAgLy8gQWRkIHRlcm1pbmF0b3IgYW5kIHBhZCB1cCB0byBhIGJ5dGUgaWYgYXBwbGljYWJsZVxuICAgICAgY29uc3QgZGF0YUNhcGFjaXR5Qml0czogaW50ID0gUXJDb2RlLmdldE51bURhdGFDb2Rld29yZHModmVyc2lvbiwgZWNsKSAqIDg7XG4gICAgICBhc3NlcnQoYmIubGVuZ3RoIDw9IGRhdGFDYXBhY2l0eUJpdHMpO1xuICAgICAgYXBwZW5kQml0cygwLCBNYXRoLm1pbig0LCBkYXRhQ2FwYWNpdHlCaXRzIC0gYmIubGVuZ3RoKSwgYmIpO1xuICAgICAgYXBwZW5kQml0cygwLCAoOCAtIChiYi5sZW5ndGggJSA4KSkgJSA4LCBiYik7XG4gICAgICBhc3NlcnQoYmIubGVuZ3RoICUgOCA9PSAwKTtcblxuICAgICAgLy8gUGFkIHdpdGggYWx0ZXJuYXRpbmcgYnl0ZXMgdW50aWwgZGF0YSBjYXBhY2l0eSBpcyByZWFjaGVkXG4gICAgICBmb3IgKGxldCBwYWRCeXRlID0gMHhlYzsgYmIubGVuZ3RoIDwgZGF0YUNhcGFjaXR5Qml0czsgcGFkQnl0ZSBePSAweGVjIF4gMHgxMSkgYXBwZW5kQml0cyhwYWRCeXRlLCA4LCBiYik7XG5cbiAgICAgIC8vIFBhY2sgYml0cyBpbnRvIGJ5dGVzIGluIGJpZyBlbmRpYW5cbiAgICAgIGxldCBkYXRhQ29kZXdvcmRzOiBBcnJheTxieXRlPiA9IFtdO1xuICAgICAgd2hpbGUgKGRhdGFDb2Rld29yZHMubGVuZ3RoICogOCA8IGJiLmxlbmd0aCkgZGF0YUNvZGV3b3Jkcy5wdXNoKDApO1xuICAgICAgYmIuZm9yRWFjaCgoYjogYml0LCBpOiBpbnQpID0+IChkYXRhQ29kZXdvcmRzW2kgPj4+IDNdIHw9IGIgPDwgKDcgLSAoaSAmIDcpKSkpO1xuXG4gICAgICAvLyBDcmVhdGUgdGhlIFFSIENvZGUgb2JqZWN0XG4gICAgICByZXR1cm4gbmV3IFFyQ29kZSh2ZXJzaW9uLCBlY2wsIGRhdGFDb2Rld29yZHMsIG1hc2spO1xuICAgIH1cblxuICAgIC8qLS0gRmllbGRzIC0tKi9cblxuICAgIC8vIFRoZSB3aWR0aCBhbmQgaGVpZ2h0IG9mIHRoaXMgUVIgQ29kZSwgbWVhc3VyZWQgaW4gbW9kdWxlcywgYmV0d2VlblxuICAgIC8vIDIxIGFuZCAxNzcgKGluY2x1c2l2ZSkuIFRoaXMgaXMgZXF1YWwgdG8gdmVyc2lvbiAqIDQgKyAxNy5cbiAgICBwdWJsaWMgcmVhZG9ubHkgc2l6ZTogaW50O1xuXG4gICAgLy8gVGhlIGluZGV4IG9mIHRoZSBtYXNrIHBhdHRlcm4gdXNlZCBpbiB0aGlzIFFSIENvZGUsIHdoaWNoIGlzIGJldHdlZW4gMCBhbmQgNyAoaW5jbHVzaXZlKS5cbiAgICAvLyBFdmVuIGlmIGEgUVIgQ29kZSBpcyBjcmVhdGVkIHdpdGggYXV0b21hdGljIG1hc2tpbmcgcmVxdWVzdGVkIChtYXNrID0gLTEpLFxuICAgIC8vIHRoZSByZXN1bHRpbmcgb2JqZWN0IHN0aWxsIGhhcyBhIG1hc2sgdmFsdWUgYmV0d2VlbiAwIGFuZCA3LlxuICAgIHB1YmxpYyByZWFkb25seSBtYXNrOiBpbnQ7XG5cbiAgICAvLyBUaGUgbW9kdWxlcyBvZiB0aGlzIFFSIENvZGUgKGZhbHNlID0gbGlnaHQsIHRydWUgPSBkYXJrKS5cbiAgICAvLyBJbW11dGFibGUgYWZ0ZXIgY29uc3RydWN0b3IgZmluaXNoZXMuIEFjY2Vzc2VkIHRocm91Z2ggZ2V0TW9kdWxlKCkuXG4gICAgcHJpdmF0ZSByZWFkb25seSBtb2R1bGVzOiBBcnJheTxBcnJheTxib29sZWFuPj4gPSBbXTtcblxuICAgIC8vIEluZGljYXRlcyBmdW5jdGlvbiBtb2R1bGVzIHRoYXQgYXJlIG5vdCBzdWJqZWN0ZWQgdG8gbWFza2luZy4gRGlzY2FyZGVkIHdoZW4gY29uc3RydWN0b3IgZmluaXNoZXMuXG4gICAgcHJpdmF0ZSByZWFkb25seSBpc0Z1bmN0aW9uOiBBcnJheTxBcnJheTxib29sZWFuPj4gPSBbXTtcblxuICAgIC8qLS0gQ29uc3RydWN0b3IgKGxvdyBsZXZlbCkgYW5kIGZpZWxkcyAtLSovXG5cbiAgICAvLyBDcmVhdGVzIGEgbmV3IFFSIENvZGUgd2l0aCB0aGUgZ2l2ZW4gdmVyc2lvbiBudW1iZXIsXG4gICAgLy8gZXJyb3IgY29ycmVjdGlvbiBsZXZlbCwgZGF0YSBjb2Rld29yZCBieXRlcywgYW5kIG1hc2sgbnVtYmVyLlxuICAgIC8vIFRoaXMgaXMgYSBsb3ctbGV2ZWwgQVBJIHRoYXQgbW9zdCB1c2VycyBzaG91bGQgbm90IHVzZSBkaXJlY3RseS5cbiAgICAvLyBBIG1pZC1sZXZlbCBBUEkgaXMgdGhlIGVuY29kZVNlZ21lbnRzKCkgZnVuY3Rpb24uXG4gICAgcHVibGljIGNvbnN0cnVjdG9yKFxuICAgICAgLy8gVGhlIHZlcnNpb24gbnVtYmVyIG9mIHRoaXMgUVIgQ29kZSwgd2hpY2ggaXMgYmV0d2VlbiAxIGFuZCA0MCAoaW5jbHVzaXZlKS5cbiAgICAgIC8vIFRoaXMgZGV0ZXJtaW5lcyB0aGUgc2l6ZSBvZiB0aGlzIGJhcmNvZGUuXG4gICAgICBwdWJsaWMgcmVhZG9ubHkgdmVyc2lvbjogaW50LFxuXG4gICAgICAvLyBUaGUgZXJyb3IgY29ycmVjdGlvbiBsZXZlbCB1c2VkIGluIHRoaXMgUVIgQ29kZS5cbiAgICAgIHB1YmxpYyByZWFkb25seSBlcnJvckNvcnJlY3Rpb25MZXZlbDogUXJDb2RlLkVjYyxcblxuICAgICAgZGF0YUNvZGV3b3JkczogUmVhZG9ubHk8QXJyYXk8Ynl0ZT4+LFxuXG4gICAgICBtc2s6IGludFxuICAgICkge1xuICAgICAgLy8gQ2hlY2sgc2NhbGFyIGFyZ3VtZW50c1xuICAgICAgaWYgKHZlcnNpb24gPCBRckNvZGUuTUlOX1ZFUlNJT04gfHwgdmVyc2lvbiA+IFFyQ29kZS5NQVhfVkVSU0lPTilcbiAgICAgICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ1ZlcnNpb24gdmFsdWUgb3V0IG9mIHJhbmdlJyk7XG4gICAgICBpZiAobXNrIDwgLTEgfHwgbXNrID4gNykgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ01hc2sgdmFsdWUgb3V0IG9mIHJhbmdlJyk7XG4gICAgICB0aGlzLnNpemUgPSB2ZXJzaW9uICogNCArIDE3O1xuXG4gICAgICAvLyBJbml0aWFsaXplIGJvdGggZ3JpZHMgdG8gYmUgc2l6ZSpzaXplIGFycmF5cyBvZiBCb29sZWFuIGZhbHNlXG4gICAgICBsZXQgcm93OiBBcnJheTxib29sZWFuPiA9IFtdO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNpemU7IGkrKykgcm93LnB1c2goZmFsc2UpO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNpemU7IGkrKykge1xuICAgICAgICB0aGlzLm1vZHVsZXMucHVzaChyb3cuc2xpY2UoKSk7IC8vIEluaXRpYWxseSBhbGwgbGlnaHRcbiAgICAgICAgdGhpcy5pc0Z1bmN0aW9uLnB1c2gocm93LnNsaWNlKCkpO1xuICAgICAgfVxuXG4gICAgICAvLyBDb21wdXRlIEVDQywgZHJhdyBtb2R1bGVzXG4gICAgICB0aGlzLmRyYXdGdW5jdGlvblBhdHRlcm5zKCk7XG4gICAgICBjb25zdCBhbGxDb2Rld29yZHM6IEFycmF5PGJ5dGU+ID0gdGhpcy5hZGRFY2NBbmRJbnRlcmxlYXZlKGRhdGFDb2Rld29yZHMpO1xuICAgICAgdGhpcy5kcmF3Q29kZXdvcmRzKGFsbENvZGV3b3Jkcyk7XG5cbiAgICAgIC8vIERvIG1hc2tpbmdcbiAgICAgIGlmIChtc2sgPT0gLTEpIHtcbiAgICAgICAgLy8gQXV0b21hdGljYWxseSBjaG9vc2UgYmVzdCBtYXNrXG4gICAgICAgIGxldCBtaW5QZW5hbHR5OiBpbnQgPSAxMDAwMDAwMDAwO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDg7IGkrKykge1xuICAgICAgICAgIHRoaXMuYXBwbHlNYXNrKGkpO1xuICAgICAgICAgIHRoaXMuZHJhd0Zvcm1hdEJpdHMoaSk7XG4gICAgICAgICAgY29uc3QgcGVuYWx0eTogaW50ID0gdGhpcy5nZXRQZW5hbHR5U2NvcmUoKTtcbiAgICAgICAgICBpZiAocGVuYWx0eSA8IG1pblBlbmFsdHkpIHtcbiAgICAgICAgICAgIG1zayA9IGk7XG4gICAgICAgICAgICBtaW5QZW5hbHR5ID0gcGVuYWx0eTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5hcHBseU1hc2soaSk7IC8vIFVuZG9lcyB0aGUgbWFzayBkdWUgdG8gWE9SXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGFzc2VydChtc2sgPj0gMCAmJiBtc2sgPD0gNyk7XG4gICAgICB0aGlzLm1hc2sgPSBtc2s7XG4gICAgICB0aGlzLmFwcGx5TWFzayhtc2spOyAvLyBBcHBseSB0aGUgZmluYWwgY2hvaWNlIG9mIG1hc2tcbiAgICAgIHRoaXMuZHJhd0Zvcm1hdEJpdHMobXNrKTsgLy8gT3ZlcndyaXRlIG9sZCBmb3JtYXQgYml0c1xuXG4gICAgICB0aGlzLmlzRnVuY3Rpb24gPSBbXTtcbiAgICB9XG5cbiAgICAvKi0tIEFjY2Vzc29yIG1ldGhvZHMgLS0qL1xuXG4gICAgLy8gUmV0dXJucyB0aGUgY29sb3Igb2YgdGhlIG1vZHVsZSAocGl4ZWwpIGF0IHRoZSBnaXZlbiBjb29yZGluYXRlcywgd2hpY2ggaXMgZmFsc2VcbiAgICAvLyBmb3IgbGlnaHQgb3IgdHJ1ZSBmb3IgZGFyay4gVGhlIHRvcCBsZWZ0IGNvcm5lciBoYXMgdGhlIGNvb3JkaW5hdGVzICh4PTAsIHk9MCkuXG4gICAgLy8gSWYgdGhlIGdpdmVuIGNvb3JkaW5hdGVzIGFyZSBvdXQgb2YgYm91bmRzLCB0aGVuIGZhbHNlIChsaWdodCkgaXMgcmV0dXJuZWQuXG4gICAgcHVibGljIGdldE1vZHVsZSh4OiBpbnQsIHk6IGludCk6IGJvb2xlYW4ge1xuICAgICAgcmV0dXJuIHggPj0gMCAmJiB4IDwgdGhpcy5zaXplICYmIHkgPj0gMCAmJiB5IDwgdGhpcy5zaXplICYmIHRoaXMubW9kdWxlc1t5XVt4XTtcbiAgICB9XG5cbiAgICAvKi0tIFByaXZhdGUgaGVscGVyIG1ldGhvZHMgZm9yIGNvbnN0cnVjdG9yOiBEcmF3aW5nIGZ1bmN0aW9uIG1vZHVsZXMgLS0qL1xuXG4gICAgLy8gUmVhZHMgdGhpcyBvYmplY3QncyB2ZXJzaW9uIGZpZWxkLCBhbmQgZHJhd3MgYW5kIG1hcmtzIGFsbCBmdW5jdGlvbiBtb2R1bGVzLlxuICAgIHByaXZhdGUgZHJhd0Z1bmN0aW9uUGF0dGVybnMoKTogdm9pZCB7XG4gICAgICAvLyBEcmF3IGhvcml6b250YWwgYW5kIHZlcnRpY2FsIHRpbWluZyBwYXR0ZXJuc1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNpemU7IGkrKykge1xuICAgICAgICB0aGlzLnNldEZ1bmN0aW9uTW9kdWxlKDYsIGksIGkgJSAyID09IDApO1xuICAgICAgICB0aGlzLnNldEZ1bmN0aW9uTW9kdWxlKGksIDYsIGkgJSAyID09IDApO1xuICAgICAgfVxuXG4gICAgICAvLyBEcmF3IDMgZmluZGVyIHBhdHRlcm5zIChhbGwgY29ybmVycyBleGNlcHQgYm90dG9tIHJpZ2h0OyBvdmVyd3JpdGVzIHNvbWUgdGltaW5nIG1vZHVsZXMpXG4gICAgICB0aGlzLmRyYXdGaW5kZXJQYXR0ZXJuKDMsIDMpO1xuICAgICAgdGhpcy5kcmF3RmluZGVyUGF0dGVybih0aGlzLnNpemUgLSA0LCAzKTtcbiAgICAgIHRoaXMuZHJhd0ZpbmRlclBhdHRlcm4oMywgdGhpcy5zaXplIC0gNCk7XG5cbiAgICAgIC8vIERyYXcgbnVtZXJvdXMgYWxpZ25tZW50IHBhdHRlcm5zXG4gICAgICBjb25zdCBhbGlnblBhdFBvczogQXJyYXk8aW50PiA9IHRoaXMuZ2V0QWxpZ25tZW50UGF0dGVyblBvc2l0aW9ucygpO1xuICAgICAgY29uc3QgbnVtQWxpZ246IGludCA9IGFsaWduUGF0UG9zLmxlbmd0aDtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtQWxpZ247IGkrKykge1xuICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IG51bUFsaWduOyBqKyspIHtcbiAgICAgICAgICAvLyBEb24ndCBkcmF3IG9uIHRoZSB0aHJlZSBmaW5kZXIgY29ybmVyc1xuICAgICAgICAgIGlmICghKChpID09IDAgJiYgaiA9PSAwKSB8fCAoaSA9PSAwICYmIGogPT0gbnVtQWxpZ24gLSAxKSB8fCAoaSA9PSBudW1BbGlnbiAtIDEgJiYgaiA9PSAwKSkpXG4gICAgICAgICAgICB0aGlzLmRyYXdBbGlnbm1lbnRQYXR0ZXJuKGFsaWduUGF0UG9zW2ldLCBhbGlnblBhdFBvc1tqXSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gRHJhdyBjb25maWd1cmF0aW9uIGRhdGFcbiAgICAgIHRoaXMuZHJhd0Zvcm1hdEJpdHMoMCk7IC8vIER1bW15IG1hc2sgdmFsdWU7IG92ZXJ3cml0dGVuIGxhdGVyIGluIHRoZSBjb25zdHJ1Y3RvclxuICAgICAgdGhpcy5kcmF3VmVyc2lvbigpO1xuICAgIH1cblxuICAgIC8vIERyYXdzIHR3byBjb3BpZXMgb2YgdGhlIGZvcm1hdCBiaXRzICh3aXRoIGl0cyBvd24gZXJyb3IgY29ycmVjdGlvbiBjb2RlKVxuICAgIC8vIGJhc2VkIG9uIHRoZSBnaXZlbiBtYXNrIGFuZCB0aGlzIG9iamVjdCdzIGVycm9yIGNvcnJlY3Rpb24gbGV2ZWwgZmllbGQuXG4gICAgcHJpdmF0ZSBkcmF3Rm9ybWF0Qml0cyhtYXNrOiBpbnQpOiB2b2lkIHtcbiAgICAgIC8vIENhbGN1bGF0ZSBlcnJvciBjb3JyZWN0aW9uIGNvZGUgYW5kIHBhY2sgYml0c1xuICAgICAgY29uc3QgZGF0YTogaW50ID0gKHRoaXMuZXJyb3JDb3JyZWN0aW9uTGV2ZWwuZm9ybWF0Qml0cyA8PCAzKSB8IG1hc2s7IC8vIGVyckNvcnJMdmwgaXMgdWludDIsIG1hc2sgaXMgdWludDNcbiAgICAgIGxldCByZW06IGludCA9IGRhdGE7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDEwOyBpKyspIHJlbSA9IChyZW0gPDwgMSkgXiAoKHJlbSA+Pj4gOSkgKiAweDUzNyk7XG4gICAgICBjb25zdCBiaXRzID0gKChkYXRhIDw8IDEwKSB8IHJlbSkgXiAweDU0MTI7IC8vIHVpbnQxNVxuICAgICAgYXNzZXJ0KGJpdHMgPj4+IDE1ID09IDApO1xuXG4gICAgICAvLyBEcmF3IGZpcnN0IGNvcHlcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDw9IDU7IGkrKykgdGhpcy5zZXRGdW5jdGlvbk1vZHVsZSg4LCBpLCBnZXRCaXQoYml0cywgaSkpO1xuICAgICAgdGhpcy5zZXRGdW5jdGlvbk1vZHVsZSg4LCA3LCBnZXRCaXQoYml0cywgNikpO1xuICAgICAgdGhpcy5zZXRGdW5jdGlvbk1vZHVsZSg4LCA4LCBnZXRCaXQoYml0cywgNykpO1xuICAgICAgdGhpcy5zZXRGdW5jdGlvbk1vZHVsZSg3LCA4LCBnZXRCaXQoYml0cywgOCkpO1xuICAgICAgZm9yIChsZXQgaSA9IDk7IGkgPCAxNTsgaSsrKSB0aGlzLnNldEZ1bmN0aW9uTW9kdWxlKDE0IC0gaSwgOCwgZ2V0Qml0KGJpdHMsIGkpKTtcblxuICAgICAgLy8gRHJhdyBzZWNvbmQgY29weVxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCA4OyBpKyspIHRoaXMuc2V0RnVuY3Rpb25Nb2R1bGUodGhpcy5zaXplIC0gMSAtIGksIDgsIGdldEJpdChiaXRzLCBpKSk7XG4gICAgICBmb3IgKGxldCBpID0gODsgaSA8IDE1OyBpKyspIHRoaXMuc2V0RnVuY3Rpb25Nb2R1bGUoOCwgdGhpcy5zaXplIC0gMTUgKyBpLCBnZXRCaXQoYml0cywgaSkpO1xuICAgICAgdGhpcy5zZXRGdW5jdGlvbk1vZHVsZSg4LCB0aGlzLnNpemUgLSA4LCB0cnVlKTsgLy8gQWx3YXlzIGRhcmtcbiAgICB9XG5cbiAgICAvLyBEcmF3cyB0d28gY29waWVzIG9mIHRoZSB2ZXJzaW9uIGJpdHMgKHdpdGggaXRzIG93biBlcnJvciBjb3JyZWN0aW9uIGNvZGUpLFxuICAgIC8vIGJhc2VkIG9uIHRoaXMgb2JqZWN0J3MgdmVyc2lvbiBmaWVsZCwgaWZmIDcgPD0gdmVyc2lvbiA8PSA0MC5cbiAgICBwcml2YXRlIGRyYXdWZXJzaW9uKCk6IHZvaWQge1xuICAgICAgaWYgKHRoaXMudmVyc2lvbiA8IDcpIHJldHVybjtcblxuICAgICAgLy8gQ2FsY3VsYXRlIGVycm9yIGNvcnJlY3Rpb24gY29kZSBhbmQgcGFjayBiaXRzXG4gICAgICBsZXQgcmVtOiBpbnQgPSB0aGlzLnZlcnNpb247IC8vIHZlcnNpb24gaXMgdWludDYsIGluIHRoZSByYW5nZSBbNywgNDBdXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDEyOyBpKyspIHJlbSA9IChyZW0gPDwgMSkgXiAoKHJlbSA+Pj4gMTEpICogMHgxZjI1KTtcbiAgICAgIGNvbnN0IGJpdHM6IGludCA9ICh0aGlzLnZlcnNpb24gPDwgMTIpIHwgcmVtOyAvLyB1aW50MThcbiAgICAgIGFzc2VydChiaXRzID4+PiAxOCA9PSAwKTtcblxuICAgICAgLy8gRHJhdyB0d28gY29waWVzXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDE4OyBpKyspIHtcbiAgICAgICAgY29uc3QgY29sb3I6IGJvb2xlYW4gPSBnZXRCaXQoYml0cywgaSk7XG4gICAgICAgIGNvbnN0IGE6IGludCA9IHRoaXMuc2l6ZSAtIDExICsgKGkgJSAzKTtcbiAgICAgICAgY29uc3QgYjogaW50ID0gTWF0aC5mbG9vcihpIC8gMyk7XG4gICAgICAgIHRoaXMuc2V0RnVuY3Rpb25Nb2R1bGUoYSwgYiwgY29sb3IpO1xuICAgICAgICB0aGlzLnNldEZ1bmN0aW9uTW9kdWxlKGIsIGEsIGNvbG9yKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBEcmF3cyBhIDkqOSBmaW5kZXIgcGF0dGVybiBpbmNsdWRpbmcgdGhlIGJvcmRlciBzZXBhcmF0b3IsXG4gICAgLy8gd2l0aCB0aGUgY2VudGVyIG1vZHVsZSBhdCAoeCwgeSkuIE1vZHVsZXMgY2FuIGJlIG91dCBvZiBib3VuZHMuXG4gICAgcHJpdmF0ZSBkcmF3RmluZGVyUGF0dGVybih4OiBpbnQsIHk6IGludCk6IHZvaWQge1xuICAgICAgZm9yIChsZXQgZHkgPSAtNDsgZHkgPD0gNDsgZHkrKykge1xuICAgICAgICBmb3IgKGxldCBkeCA9IC00OyBkeCA8PSA0OyBkeCsrKSB7XG4gICAgICAgICAgY29uc3QgZGlzdDogaW50ID0gTWF0aC5tYXgoTWF0aC5hYnMoZHgpLCBNYXRoLmFicyhkeSkpOyAvLyBDaGVieXNoZXYvaW5maW5pdHkgbm9ybVxuICAgICAgICAgIGNvbnN0IHh4OiBpbnQgPSB4ICsgZHg7XG4gICAgICAgICAgY29uc3QgeXk6IGludCA9IHkgKyBkeTtcbiAgICAgICAgICBpZiAoeHggPj0gMCAmJiB4eCA8IHRoaXMuc2l6ZSAmJiB5eSA+PSAwICYmIHl5IDwgdGhpcy5zaXplKVxuICAgICAgICAgICAgdGhpcy5zZXRGdW5jdGlvbk1vZHVsZSh4eCwgeXksIGRpc3QgIT0gMiAmJiBkaXN0ICE9IDQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gRHJhd3MgYSA1KjUgYWxpZ25tZW50IHBhdHRlcm4sIHdpdGggdGhlIGNlbnRlciBtb2R1bGVcbiAgICAvLyBhdCAoeCwgeSkuIEFsbCBtb2R1bGVzIG11c3QgYmUgaW4gYm91bmRzLlxuICAgIHByaXZhdGUgZHJhd0FsaWdubWVudFBhdHRlcm4oeDogaW50LCB5OiBpbnQpOiB2b2lkIHtcbiAgICAgIGZvciAobGV0IGR5ID0gLTI7IGR5IDw9IDI7IGR5KyspIHtcbiAgICAgICAgZm9yIChsZXQgZHggPSAtMjsgZHggPD0gMjsgZHgrKylcbiAgICAgICAgICB0aGlzLnNldEZ1bmN0aW9uTW9kdWxlKHggKyBkeCwgeSArIGR5LCBNYXRoLm1heChNYXRoLmFicyhkeCksIE1hdGguYWJzKGR5KSkgIT0gMSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gU2V0cyB0aGUgY29sb3Igb2YgYSBtb2R1bGUgYW5kIG1hcmtzIGl0IGFzIGEgZnVuY3Rpb24gbW9kdWxlLlxuICAgIC8vIE9ubHkgdXNlZCBieSB0aGUgY29uc3RydWN0b3IuIENvb3JkaW5hdGVzIG11c3QgYmUgaW4gYm91bmRzLlxuICAgIHByaXZhdGUgc2V0RnVuY3Rpb25Nb2R1bGUoeDogaW50LCB5OiBpbnQsIGlzRGFyazogYm9vbGVhbik6IHZvaWQge1xuICAgICAgdGhpcy5tb2R1bGVzW3ldW3hdID0gaXNEYXJrO1xuICAgICAgdGhpcy5pc0Z1bmN0aW9uW3ldW3hdID0gdHJ1ZTtcbiAgICB9XG5cbiAgICAvKi0tIFByaXZhdGUgaGVscGVyIG1ldGhvZHMgZm9yIGNvbnN0cnVjdG9yOiBDb2Rld29yZHMgYW5kIG1hc2tpbmcgLS0qL1xuXG4gICAgLy8gUmV0dXJucyBhIG5ldyBieXRlIHN0cmluZyByZXByZXNlbnRpbmcgdGhlIGdpdmVuIGRhdGEgd2l0aCB0aGUgYXBwcm9wcmlhdGUgZXJyb3IgY29ycmVjdGlvblxuICAgIC8vIGNvZGV3b3JkcyBhcHBlbmRlZCB0byBpdCwgYmFzZWQgb24gdGhpcyBvYmplY3QncyB2ZXJzaW9uIGFuZCBlcnJvciBjb3JyZWN0aW9uIGxldmVsLlxuICAgIHByaXZhdGUgYWRkRWNjQW5kSW50ZXJsZWF2ZShkYXRhOiBSZWFkb25seTxBcnJheTxieXRlPj4pOiBBcnJheTxieXRlPiB7XG4gICAgICBjb25zdCB2ZXI6IGludCA9IHRoaXMudmVyc2lvbjtcbiAgICAgIGNvbnN0IGVjbDogUXJDb2RlLkVjYyA9IHRoaXMuZXJyb3JDb3JyZWN0aW9uTGV2ZWw7XG4gICAgICBpZiAoZGF0YS5sZW5ndGggIT0gUXJDb2RlLmdldE51bURhdGFDb2Rld29yZHModmVyLCBlY2wpKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignSW52YWxpZCBhcmd1bWVudCcpO1xuXG4gICAgICAvLyBDYWxjdWxhdGUgcGFyYW1ldGVyIG51bWJlcnNcbiAgICAgIGNvbnN0IG51bUJsb2NrczogaW50ID0gUXJDb2RlLk5VTV9FUlJPUl9DT1JSRUNUSU9OX0JMT0NLU1tlY2wub3JkaW5hbF1bdmVyXTtcbiAgICAgIGNvbnN0IGJsb2NrRWNjTGVuOiBpbnQgPSBRckNvZGUuRUNDX0NPREVXT1JEU19QRVJfQkxPQ0tbZWNsLm9yZGluYWxdW3Zlcl07XG4gICAgICBjb25zdCByYXdDb2Rld29yZHM6IGludCA9IE1hdGguZmxvb3IoUXJDb2RlLmdldE51bVJhd0RhdGFNb2R1bGVzKHZlcikgLyA4KTtcbiAgICAgIGNvbnN0IG51bVNob3J0QmxvY2tzOiBpbnQgPSBudW1CbG9ja3MgLSAocmF3Q29kZXdvcmRzICUgbnVtQmxvY2tzKTtcbiAgICAgIGNvbnN0IHNob3J0QmxvY2tMZW46IGludCA9IE1hdGguZmxvb3IocmF3Q29kZXdvcmRzIC8gbnVtQmxvY2tzKTtcblxuICAgICAgLy8gU3BsaXQgZGF0YSBpbnRvIGJsb2NrcyBhbmQgYXBwZW5kIEVDQyB0byBlYWNoIGJsb2NrXG4gICAgICBsZXQgYmxvY2tzOiBBcnJheTxBcnJheTxieXRlPj4gPSBbXTtcbiAgICAgIGNvbnN0IHJzRGl2OiBBcnJheTxieXRlPiA9IFFyQ29kZS5yZWVkU29sb21vbkNvbXB1dGVEaXZpc29yKGJsb2NrRWNjTGVuKTtcbiAgICAgIGZvciAobGV0IGkgPSAwLCBrID0gMDsgaSA8IG51bUJsb2NrczsgaSsrKSB7XG4gICAgICAgIGxldCBkYXQ6IEFycmF5PGJ5dGU+ID0gZGF0YS5zbGljZShrLCBrICsgc2hvcnRCbG9ja0xlbiAtIGJsb2NrRWNjTGVuICsgKGkgPCBudW1TaG9ydEJsb2NrcyA/IDAgOiAxKSk7XG4gICAgICAgIGsgKz0gZGF0Lmxlbmd0aDtcbiAgICAgICAgY29uc3QgZWNjOiBBcnJheTxieXRlPiA9IFFyQ29kZS5yZWVkU29sb21vbkNvbXB1dGVSZW1haW5kZXIoZGF0LCByc0Rpdik7XG4gICAgICAgIGlmIChpIDwgbnVtU2hvcnRCbG9ja3MpIGRhdC5wdXNoKDApO1xuICAgICAgICBibG9ja3MucHVzaChkYXQuY29uY2F0KGVjYykpO1xuICAgICAgfVxuXG4gICAgICAvLyBJbnRlcmxlYXZlIChub3QgY29uY2F0ZW5hdGUpIHRoZSBieXRlcyBmcm9tIGV2ZXJ5IGJsb2NrIGludG8gYSBzaW5nbGUgc2VxdWVuY2VcbiAgICAgIGxldCByZXN1bHQ6IEFycmF5PGJ5dGU+ID0gW107XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGJsb2Nrc1swXS5sZW5ndGg7IGkrKykge1xuICAgICAgICBibG9ja3MuZm9yRWFjaCgoYmxvY2ssIGopID0+IHtcbiAgICAgICAgICAvLyBTa2lwIHRoZSBwYWRkaW5nIGJ5dGUgaW4gc2hvcnQgYmxvY2tzXG4gICAgICAgICAgaWYgKGkgIT0gc2hvcnRCbG9ja0xlbiAtIGJsb2NrRWNjTGVuIHx8IGogPj0gbnVtU2hvcnRCbG9ja3MpIHJlc3VsdC5wdXNoKGJsb2NrW2ldKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICBhc3NlcnQocmVzdWx0Lmxlbmd0aCA9PSByYXdDb2Rld29yZHMpO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvLyBEcmF3cyB0aGUgZ2l2ZW4gc2VxdWVuY2Ugb2YgOC1iaXQgY29kZXdvcmRzIChkYXRhIGFuZCBlcnJvciBjb3JyZWN0aW9uKSBvbnRvIHRoZSBlbnRpcmVcbiAgICAvLyBkYXRhIGFyZWEgb2YgdGhpcyBRUiBDb2RlLiBGdW5jdGlvbiBtb2R1bGVzIG5lZWQgdG8gYmUgbWFya2VkIG9mZiBiZWZvcmUgdGhpcyBpcyBjYWxsZWQuXG4gICAgcHJpdmF0ZSBkcmF3Q29kZXdvcmRzKGRhdGE6IFJlYWRvbmx5PEFycmF5PGJ5dGU+Pik6IHZvaWQge1xuICAgICAgaWYgKGRhdGEubGVuZ3RoICE9IE1hdGguZmxvb3IoUXJDb2RlLmdldE51bVJhd0RhdGFNb2R1bGVzKHRoaXMudmVyc2lvbikgLyA4KSlcbiAgICAgICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0ludmFsaWQgYXJndW1lbnQnKTtcbiAgICAgIGxldCBpOiBpbnQgPSAwOyAvLyBCaXQgaW5kZXggaW50byB0aGUgZGF0YVxuICAgICAgLy8gRG8gdGhlIGZ1bm55IHppZ3phZyBzY2FuXG4gICAgICBmb3IgKGxldCByaWdodCA9IHRoaXMuc2l6ZSAtIDE7IHJpZ2h0ID49IDE7IHJpZ2h0IC09IDIpIHtcbiAgICAgICAgLy8gSW5kZXggb2YgcmlnaHQgY29sdW1uIGluIGVhY2ggY29sdW1uIHBhaXJcbiAgICAgICAgaWYgKHJpZ2h0ID09IDYpIHJpZ2h0ID0gNTtcbiAgICAgICAgZm9yIChsZXQgdmVydCA9IDA7IHZlcnQgPCB0aGlzLnNpemU7IHZlcnQrKykge1xuICAgICAgICAgIC8vIFZlcnRpY2FsIGNvdW50ZXJcbiAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IDI7IGorKykge1xuICAgICAgICAgICAgY29uc3QgeDogaW50ID0gcmlnaHQgLSBqOyAvLyBBY3R1YWwgeCBjb29yZGluYXRlXG4gICAgICAgICAgICBjb25zdCB1cHdhcmQ6IGJvb2xlYW4gPSAoKHJpZ2h0ICsgMSkgJiAyKSA9PSAwO1xuICAgICAgICAgICAgY29uc3QgeTogaW50ID0gdXB3YXJkID8gdGhpcy5zaXplIC0gMSAtIHZlcnQgOiB2ZXJ0OyAvLyBBY3R1YWwgeSBjb29yZGluYXRlXG4gICAgICAgICAgICBpZiAoIXRoaXMuaXNGdW5jdGlvblt5XVt4XSAmJiBpIDwgZGF0YS5sZW5ndGggKiA4KSB7XG4gICAgICAgICAgICAgIHRoaXMubW9kdWxlc1t5XVt4XSA9IGdldEJpdChkYXRhW2kgPj4+IDNdLCA3IC0gKGkgJiA3KSk7XG4gICAgICAgICAgICAgIGkrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIElmIHRoaXMgUVIgQ29kZSBoYXMgYW55IHJlbWFpbmRlciBiaXRzICgwIHRvIDcpLCB0aGV5IHdlcmUgYXNzaWduZWQgYXNcbiAgICAgICAgICAgIC8vIDAvZmFsc2UvbGlnaHQgYnkgdGhlIGNvbnN0cnVjdG9yIGFuZCBhcmUgbGVmdCB1bmNoYW5nZWQgYnkgdGhpcyBtZXRob2RcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGFzc2VydChpID09IGRhdGEubGVuZ3RoICogOCk7XG4gICAgfVxuXG4gICAgLy8gWE9ScyB0aGUgY29kZXdvcmQgbW9kdWxlcyBpbiB0aGlzIFFSIENvZGUgd2l0aCB0aGUgZ2l2ZW4gbWFzayBwYXR0ZXJuLlxuICAgIC8vIFRoZSBmdW5jdGlvbiBtb2R1bGVzIG11c3QgYmUgbWFya2VkIGFuZCB0aGUgY29kZXdvcmQgYml0cyBtdXN0IGJlIGRyYXduXG4gICAgLy8gYmVmb3JlIG1hc2tpbmcuIER1ZSB0byB0aGUgYXJpdGhtZXRpYyBvZiBYT1IsIGNhbGxpbmcgYXBwbHlNYXNrKCkgd2l0aFxuICAgIC8vIHRoZSBzYW1lIG1hc2sgdmFsdWUgYSBzZWNvbmQgdGltZSB3aWxsIHVuZG8gdGhlIG1hc2suIEEgZmluYWwgd2VsbC1mb3JtZWRcbiAgICAvLyBRUiBDb2RlIG5lZWRzIGV4YWN0bHkgb25lIChub3QgemVybywgdHdvLCBldGMuKSBtYXNrIGFwcGxpZWQuXG4gICAgcHJpdmF0ZSBhcHBseU1hc2sobWFzazogaW50KTogdm9pZCB7XG4gICAgICBpZiAobWFzayA8IDAgfHwgbWFzayA+IDcpIHRocm93IG5ldyBSYW5nZUVycm9yKCdNYXNrIHZhbHVlIG91dCBvZiByYW5nZScpO1xuICAgICAgZm9yIChsZXQgeSA9IDA7IHkgPCB0aGlzLnNpemU7IHkrKykge1xuICAgICAgICBmb3IgKGxldCB4ID0gMDsgeCA8IHRoaXMuc2l6ZTsgeCsrKSB7XG4gICAgICAgICAgbGV0IGludmVydDogYm9vbGVhbjtcbiAgICAgICAgICBzd2l0Y2ggKG1hc2spIHtcbiAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgaW52ZXJ0ID0gKHggKyB5KSAlIDIgPT0gMDtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgIGludmVydCA9IHkgJSAyID09IDA7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICBpbnZlcnQgPSB4ICUgMyA9PSAwO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgaW52ZXJ0ID0gKHggKyB5KSAlIDMgPT0gMDtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgIGludmVydCA9IChNYXRoLmZsb29yKHggLyAzKSArIE1hdGguZmxvb3IoeSAvIDIpKSAlIDIgPT0gMDtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgIGludmVydCA9ICgoeCAqIHkpICUgMikgKyAoKHggKiB5KSAlIDMpID09IDA7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgICBpbnZlcnQgPSAoKCh4ICogeSkgJSAyKSArICgoeCAqIHkpICUgMykpICUgMiA9PSAwO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgNzpcbiAgICAgICAgICAgICAgaW52ZXJ0ID0gKCgoeCArIHkpICUgMikgKyAoKHggKiB5KSAlIDMpKSAlIDIgPT0gMDtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VucmVhY2hhYmxlJyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICghdGhpcy5pc0Z1bmN0aW9uW3ldW3hdICYmIGludmVydCkgdGhpcy5tb2R1bGVzW3ldW3hdID0gIXRoaXMubW9kdWxlc1t5XVt4XTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIC8vIENhbGN1bGF0ZXMgYW5kIHJldHVybnMgdGhlIHBlbmFsdHkgc2NvcmUgYmFzZWQgb24gc3RhdGUgb2YgdGhpcyBRUiBDb2RlJ3MgY3VycmVudCBtb2R1bGVzLlxuICAgIC8vIFRoaXMgaXMgdXNlZCBieSB0aGUgYXV0b21hdGljIG1hc2sgY2hvaWNlIGFsZ29yaXRobSB0byBmaW5kIHRoZSBtYXNrIHBhdHRlcm4gdGhhdCB5aWVsZHMgdGhlIGxvd2VzdCBzY29yZS5cbiAgICBwcml2YXRlIGdldFBlbmFsdHlTY29yZSgpOiBpbnQge1xuICAgICAgbGV0IHJlc3VsdDogaW50ID0gMDtcblxuICAgICAgLy8gQWRqYWNlbnQgbW9kdWxlcyBpbiByb3cgaGF2aW5nIHNhbWUgY29sb3IsIGFuZCBmaW5kZXItbGlrZSBwYXR0ZXJuc1xuICAgICAgZm9yIChsZXQgeSA9IDA7IHkgPCB0aGlzLnNpemU7IHkrKykge1xuICAgICAgICBsZXQgcnVuQ29sb3IgPSBmYWxzZTtcbiAgICAgICAgbGV0IHJ1blggPSAwO1xuICAgICAgICBsZXQgcnVuSGlzdG9yeSA9IFswLCAwLCAwLCAwLCAwLCAwLCAwXTtcbiAgICAgICAgZm9yIChsZXQgeCA9IDA7IHggPCB0aGlzLnNpemU7IHgrKykge1xuICAgICAgICAgIGlmICh0aGlzLm1vZHVsZXNbeV1beF0gPT0gcnVuQ29sb3IpIHtcbiAgICAgICAgICAgIHJ1blgrKztcbiAgICAgICAgICAgIGlmIChydW5YID09IDUpIHJlc3VsdCArPSBRckNvZGUuUEVOQUxUWV9OMTtcbiAgICAgICAgICAgIGVsc2UgaWYgKHJ1blggPiA1KSByZXN1bHQrKztcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5maW5kZXJQZW5hbHR5QWRkSGlzdG9yeShydW5YLCBydW5IaXN0b3J5KTtcbiAgICAgICAgICAgIGlmICghcnVuQ29sb3IpIHJlc3VsdCArPSB0aGlzLmZpbmRlclBlbmFsdHlDb3VudFBhdHRlcm5zKHJ1bkhpc3RvcnkpICogUXJDb2RlLlBFTkFMVFlfTjM7XG4gICAgICAgICAgICBydW5Db2xvciA9IHRoaXMubW9kdWxlc1t5XVt4XTtcbiAgICAgICAgICAgIHJ1blggPSAxO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXN1bHQgKz0gdGhpcy5maW5kZXJQZW5hbHR5VGVybWluYXRlQW5kQ291bnQocnVuQ29sb3IsIHJ1blgsIHJ1bkhpc3RvcnkpICogUXJDb2RlLlBFTkFMVFlfTjM7XG4gICAgICB9XG4gICAgICAvLyBBZGphY2VudCBtb2R1bGVzIGluIGNvbHVtbiBoYXZpbmcgc2FtZSBjb2xvciwgYW5kIGZpbmRlci1saWtlIHBhdHRlcm5zXG4gICAgICBmb3IgKGxldCB4ID0gMDsgeCA8IHRoaXMuc2l6ZTsgeCsrKSB7XG4gICAgICAgIGxldCBydW5Db2xvciA9IGZhbHNlO1xuICAgICAgICBsZXQgcnVuWSA9IDA7XG4gICAgICAgIGxldCBydW5IaXN0b3J5ID0gWzAsIDAsIDAsIDAsIDAsIDAsIDBdO1xuICAgICAgICBmb3IgKGxldCB5ID0gMDsgeSA8IHRoaXMuc2l6ZTsgeSsrKSB7XG4gICAgICAgICAgaWYgKHRoaXMubW9kdWxlc1t5XVt4XSA9PSBydW5Db2xvcikge1xuICAgICAgICAgICAgcnVuWSsrO1xuICAgICAgICAgICAgaWYgKHJ1blkgPT0gNSkgcmVzdWx0ICs9IFFyQ29kZS5QRU5BTFRZX04xO1xuICAgICAgICAgICAgZWxzZSBpZiAocnVuWSA+IDUpIHJlc3VsdCsrO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmZpbmRlclBlbmFsdHlBZGRIaXN0b3J5KHJ1blksIHJ1bkhpc3RvcnkpO1xuICAgICAgICAgICAgaWYgKCFydW5Db2xvcikgcmVzdWx0ICs9IHRoaXMuZmluZGVyUGVuYWx0eUNvdW50UGF0dGVybnMocnVuSGlzdG9yeSkgKiBRckNvZGUuUEVOQUxUWV9OMztcbiAgICAgICAgICAgIHJ1bkNvbG9yID0gdGhpcy5tb2R1bGVzW3ldW3hdO1xuICAgICAgICAgICAgcnVuWSA9IDE7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJlc3VsdCArPSB0aGlzLmZpbmRlclBlbmFsdHlUZXJtaW5hdGVBbmRDb3VudChydW5Db2xvciwgcnVuWSwgcnVuSGlzdG9yeSkgKiBRckNvZGUuUEVOQUxUWV9OMztcbiAgICAgIH1cblxuICAgICAgLy8gMioyIGJsb2NrcyBvZiBtb2R1bGVzIGhhdmluZyBzYW1lIGNvbG9yXG4gICAgICBmb3IgKGxldCB5ID0gMDsgeSA8IHRoaXMuc2l6ZSAtIDE7IHkrKykge1xuICAgICAgICBmb3IgKGxldCB4ID0gMDsgeCA8IHRoaXMuc2l6ZSAtIDE7IHgrKykge1xuICAgICAgICAgIGNvbnN0IGNvbG9yOiBib29sZWFuID0gdGhpcy5tb2R1bGVzW3ldW3hdO1xuICAgICAgICAgIGlmIChjb2xvciA9PSB0aGlzLm1vZHVsZXNbeV1beCArIDFdICYmIGNvbG9yID09IHRoaXMubW9kdWxlc1t5ICsgMV1beF0gJiYgY29sb3IgPT0gdGhpcy5tb2R1bGVzW3kgKyAxXVt4ICsgMV0pXG4gICAgICAgICAgICByZXN1bHQgKz0gUXJDb2RlLlBFTkFMVFlfTjI7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gQmFsYW5jZSBvZiBkYXJrIGFuZCBsaWdodCBtb2R1bGVzXG4gICAgICBsZXQgZGFyazogaW50ID0gMDtcbiAgICAgIGZvciAoY29uc3Qgcm93IG9mIHRoaXMubW9kdWxlcykgZGFyayA9IHJvdy5yZWR1Y2UoKHN1bSwgY29sb3IpID0+IHN1bSArIChjb2xvciA/IDEgOiAwKSwgZGFyayk7XG4gICAgICBjb25zdCB0b3RhbDogaW50ID0gdGhpcy5zaXplICogdGhpcy5zaXplOyAvLyBOb3RlIHRoYXQgc2l6ZSBpcyBvZGQsIHNvIGRhcmsvdG90YWwgIT0gMS8yXG4gICAgICAvLyBDb21wdXRlIHRoZSBzbWFsbGVzdCBpbnRlZ2VyIGsgPj0gMCBzdWNoIHRoYXQgKDQ1LTVrKSUgPD0gZGFyay90b3RhbCA8PSAoNTUrNWspJVxuICAgICAgY29uc3QgazogaW50ID0gTWF0aC5jZWlsKE1hdGguYWJzKGRhcmsgKiAyMCAtIHRvdGFsICogMTApIC8gdG90YWwpIC0gMTtcbiAgICAgIGFzc2VydChrID49IDAgJiYgayA8PSA5KTtcbiAgICAgIHJlc3VsdCArPSBrICogUXJDb2RlLlBFTkFMVFlfTjQ7XG4gICAgICBhc3NlcnQocmVzdWx0ID49IDAgJiYgcmVzdWx0IDw9IDI1Njg4ODgpOyAvLyBOb24tdGlnaHQgdXBwZXIgYm91bmQgYmFzZWQgb24gZGVmYXVsdCB2YWx1ZXMgb2YgUEVOQUxUWV9OMSwgLi4uLCBONFxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKi0tIFByaXZhdGUgaGVscGVyIGZ1bmN0aW9ucyAtLSovXG5cbiAgICAvLyBSZXR1cm5zIGFuIGFzY2VuZGluZyBsaXN0IG9mIHBvc2l0aW9ucyBvZiBhbGlnbm1lbnQgcGF0dGVybnMgZm9yIHRoaXMgdmVyc2lvbiBudW1iZXIuXG4gICAgLy8gRWFjaCBwb3NpdGlvbiBpcyBpbiB0aGUgcmFuZ2UgWzAsMTc3KSwgYW5kIGFyZSB1c2VkIG9uIGJvdGggdGhlIHggYW5kIHkgYXhlcy5cbiAgICAvLyBUaGlzIGNvdWxkIGJlIGltcGxlbWVudGVkIGFzIGxvb2t1cCB0YWJsZSBvZiA0MCB2YXJpYWJsZS1sZW5ndGggbGlzdHMgb2YgaW50ZWdlcnMuXG4gICAgcHJpdmF0ZSBnZXRBbGlnbm1lbnRQYXR0ZXJuUG9zaXRpb25zKCk6IEFycmF5PGludD4ge1xuICAgICAgaWYgKHRoaXMudmVyc2lvbiA9PSAxKSByZXR1cm4gW107XG4gICAgICBlbHNlIHtcbiAgICAgICAgY29uc3QgbnVtQWxpZ246IGludCA9IE1hdGguZmxvb3IodGhpcy52ZXJzaW9uIC8gNykgKyAyO1xuICAgICAgICBjb25zdCBzdGVwOiBpbnQgPSB0aGlzLnZlcnNpb24gPT0gMzIgPyAyNiA6IE1hdGguY2VpbCgodGhpcy52ZXJzaW9uICogNCArIDQpIC8gKG51bUFsaWduICogMiAtIDIpKSAqIDI7XG4gICAgICAgIGxldCByZXN1bHQ6IEFycmF5PGludD4gPSBbNl07XG4gICAgICAgIGZvciAobGV0IHBvcyA9IHRoaXMuc2l6ZSAtIDc7IHJlc3VsdC5sZW5ndGggPCBudW1BbGlnbjsgcG9zIC09IHN0ZXApIHJlc3VsdC5zcGxpY2UoMSwgMCwgcG9zKTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBSZXR1cm5zIHRoZSBudW1iZXIgb2YgZGF0YSBiaXRzIHRoYXQgY2FuIGJlIHN0b3JlZCBpbiBhIFFSIENvZGUgb2YgdGhlIGdpdmVuIHZlcnNpb24gbnVtYmVyLCBhZnRlclxuICAgIC8vIGFsbCBmdW5jdGlvbiBtb2R1bGVzIGFyZSBleGNsdWRlZC4gVGhpcyBpbmNsdWRlcyByZW1haW5kZXIgYml0cywgc28gaXQgbWlnaHQgbm90IGJlIGEgbXVsdGlwbGUgb2YgOC5cbiAgICAvLyBUaGUgcmVzdWx0IGlzIGluIHRoZSByYW5nZSBbMjA4LCAyOTY0OF0uIFRoaXMgY291bGQgYmUgaW1wbGVtZW50ZWQgYXMgYSA0MC1lbnRyeSBsb29rdXAgdGFibGUuXG4gICAgcHJpdmF0ZSBzdGF0aWMgZ2V0TnVtUmF3RGF0YU1vZHVsZXModmVyOiBpbnQpOiBpbnQge1xuICAgICAgaWYgKHZlciA8IFFyQ29kZS5NSU5fVkVSU0lPTiB8fCB2ZXIgPiBRckNvZGUuTUFYX1ZFUlNJT04pIHRocm93IG5ldyBSYW5nZUVycm9yKCdWZXJzaW9uIG51bWJlciBvdXQgb2YgcmFuZ2UnKTtcbiAgICAgIGxldCByZXN1bHQ6IGludCA9ICgxNiAqIHZlciArIDEyOCkgKiB2ZXIgKyA2NDtcbiAgICAgIGlmICh2ZXIgPj0gMikge1xuICAgICAgICBjb25zdCBudW1BbGlnbjogaW50ID0gTWF0aC5mbG9vcih2ZXIgLyA3KSArIDI7XG4gICAgICAgIHJlc3VsdCAtPSAoMjUgKiBudW1BbGlnbiAtIDEwKSAqIG51bUFsaWduIC0gNTU7XG4gICAgICAgIGlmICh2ZXIgPj0gNykgcmVzdWx0IC09IDM2O1xuICAgICAgfVxuICAgICAgYXNzZXJ0KHJlc3VsdCA+PSAyMDggJiYgcmVzdWx0IDw9IDI5NjQ4KTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLy8gUmV0dXJucyB0aGUgbnVtYmVyIG9mIDgtYml0IGRhdGEgKGkuZS4gbm90IGVycm9yIGNvcnJlY3Rpb24pIGNvZGV3b3JkcyBjb250YWluZWQgaW4gYW55XG4gICAgLy8gUVIgQ29kZSBvZiB0aGUgZ2l2ZW4gdmVyc2lvbiBudW1iZXIgYW5kIGVycm9yIGNvcnJlY3Rpb24gbGV2ZWwsIHdpdGggcmVtYWluZGVyIGJpdHMgZGlzY2FyZGVkLlxuICAgIC8vIFRoaXMgc3RhdGVsZXNzIHB1cmUgZnVuY3Rpb24gY291bGQgYmUgaW1wbGVtZW50ZWQgYXMgYSAoNDAqNCktY2VsbCBsb29rdXAgdGFibGUuXG4gICAgcHJpdmF0ZSBzdGF0aWMgZ2V0TnVtRGF0YUNvZGV3b3Jkcyh2ZXI6IGludCwgZWNsOiBRckNvZGUuRWNjKTogaW50IHtcbiAgICAgIHJldHVybiAoXG4gICAgICAgIE1hdGguZmxvb3IoUXJDb2RlLmdldE51bVJhd0RhdGFNb2R1bGVzKHZlcikgLyA4KSAtXG4gICAgICAgIFFyQ29kZS5FQ0NfQ09ERVdPUkRTX1BFUl9CTE9DS1tlY2wub3JkaW5hbF1bdmVyXSAqIFFyQ29kZS5OVU1fRVJST1JfQ09SUkVDVElPTl9CTE9DS1NbZWNsLm9yZGluYWxdW3Zlcl1cbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gUmV0dXJucyBhIFJlZWQtU29sb21vbiBFQ0MgZ2VuZXJhdG9yIHBvbHlub21pYWwgZm9yIHRoZSBnaXZlbiBkZWdyZWUuIFRoaXMgY291bGQgYmVcbiAgICAvLyBpbXBsZW1lbnRlZCBhcyBhIGxvb2t1cCB0YWJsZSBvdmVyIGFsbCBwb3NzaWJsZSBwYXJhbWV0ZXIgdmFsdWVzLCBpbnN0ZWFkIG9mIGFzIGFuIGFsZ29yaXRobS5cbiAgICBwcml2YXRlIHN0YXRpYyByZWVkU29sb21vbkNvbXB1dGVEaXZpc29yKGRlZ3JlZTogaW50KTogQXJyYXk8Ynl0ZT4ge1xuICAgICAgaWYgKGRlZ3JlZSA8IDEgfHwgZGVncmVlID4gMjU1KSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignRGVncmVlIG91dCBvZiByYW5nZScpO1xuICAgICAgLy8gUG9seW5vbWlhbCBjb2VmZmljaWVudHMgYXJlIHN0b3JlZCBmcm9tIGhpZ2hlc3QgdG8gbG93ZXN0IHBvd2VyLCBleGNsdWRpbmcgdGhlIGxlYWRpbmcgdGVybSB3aGljaCBpcyBhbHdheXMgMS5cbiAgICAgIC8vIEZvciBleGFtcGxlIHRoZSBwb2x5bm9taWFsIHheMyArIDI1NXheMiArIDh4ICsgOTMgaXMgc3RvcmVkIGFzIHRoZSB1aW50OCBhcnJheSBbMjU1LCA4LCA5M10uXG4gICAgICBsZXQgcmVzdWx0OiBBcnJheTxieXRlPiA9IFtdO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkZWdyZWUgLSAxOyBpKyspIHJlc3VsdC5wdXNoKDApO1xuICAgICAgcmVzdWx0LnB1c2goMSk7IC8vIFN0YXJ0IG9mZiB3aXRoIHRoZSBtb25vbWlhbCB4XjBcblxuICAgICAgLy8gQ29tcHV0ZSB0aGUgcHJvZHVjdCBwb2x5bm9taWFsICh4IC0gcl4wKSAqICh4IC0gcl4xKSAqICh4IC0gcl4yKSAqIC4uLiAqICh4IC0gcl57ZGVncmVlLTF9KSxcbiAgICAgIC8vIGFuZCBkcm9wIHRoZSBoaWdoZXN0IG1vbm9taWFsIHRlcm0gd2hpY2ggaXMgYWx3YXlzIDF4XmRlZ3JlZS5cbiAgICAgIC8vIE5vdGUgdGhhdCByID0gMHgwMiwgd2hpY2ggaXMgYSBnZW5lcmF0b3IgZWxlbWVudCBvZiB0aGlzIGZpZWxkIEdGKDJeOC8weDExRCkuXG4gICAgICBsZXQgcm9vdCA9IDE7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGRlZ3JlZTsgaSsrKSB7XG4gICAgICAgIC8vIE11bHRpcGx5IHRoZSBjdXJyZW50IHByb2R1Y3QgYnkgKHggLSByXmkpXG4gICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgcmVzdWx0Lmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgcmVzdWx0W2pdID0gUXJDb2RlLnJlZWRTb2xvbW9uTXVsdGlwbHkocmVzdWx0W2pdLCByb290KTtcbiAgICAgICAgICBpZiAoaiArIDEgPCByZXN1bHQubGVuZ3RoKSByZXN1bHRbal0gXj0gcmVzdWx0W2ogKyAxXTtcbiAgICAgICAgfVxuICAgICAgICByb290ID0gUXJDb2RlLnJlZWRTb2xvbW9uTXVsdGlwbHkocm9vdCwgMHgwMik7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8vIFJldHVybnMgdGhlIFJlZWQtU29sb21vbiBlcnJvciBjb3JyZWN0aW9uIGNvZGV3b3JkIGZvciB0aGUgZ2l2ZW4gZGF0YSBhbmQgZGl2aXNvciBwb2x5bm9taWFscy5cbiAgICBwcml2YXRlIHN0YXRpYyByZWVkU29sb21vbkNvbXB1dGVSZW1haW5kZXIoXG4gICAgICBkYXRhOiBSZWFkb25seTxBcnJheTxieXRlPj4sXG4gICAgICBkaXZpc29yOiBSZWFkb25seTxBcnJheTxieXRlPj5cbiAgICApOiBBcnJheTxieXRlPiB7XG4gICAgICBsZXQgcmVzdWx0OiBBcnJheTxieXRlPiA9IGRpdmlzb3IubWFwKF8gPT4gMCk7XG4gICAgICBmb3IgKGNvbnN0IGIgb2YgZGF0YSkge1xuICAgICAgICAvLyBQb2x5bm9taWFsIGRpdmlzaW9uXG4gICAgICAgIGNvbnN0IGZhY3RvcjogYnl0ZSA9IGIgXiAocmVzdWx0LnNoaWZ0KCkgYXMgYnl0ZSk7XG4gICAgICAgIHJlc3VsdC5wdXNoKDApO1xuICAgICAgICBkaXZpc29yLmZvckVhY2goKGNvZWYsIGkpID0+IChyZXN1bHRbaV0gXj0gUXJDb2RlLnJlZWRTb2xvbW9uTXVsdGlwbHkoY29lZiwgZmFjdG9yKSkpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvLyBSZXR1cm5zIHRoZSBwcm9kdWN0IG9mIHRoZSB0d28gZ2l2ZW4gZmllbGQgZWxlbWVudHMgbW9kdWxvIEdGKDJeOC8weDExRCkuIFRoZSBhcmd1bWVudHMgYW5kIHJlc3VsdFxuICAgIC8vIGFyZSB1bnNpZ25lZCA4LWJpdCBpbnRlZ2Vycy4gVGhpcyBjb3VsZCBiZSBpbXBsZW1lbnRlZCBhcyBhIGxvb2t1cCB0YWJsZSBvZiAyNTYqMjU2IGVudHJpZXMgb2YgdWludDguXG4gICAgcHJpdmF0ZSBzdGF0aWMgcmVlZFNvbG9tb25NdWx0aXBseSh4OiBieXRlLCB5OiBieXRlKTogYnl0ZSB7XG4gICAgICBpZiAoeCA+Pj4gOCAhPSAwIHx8IHkgPj4+IDggIT0gMCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0J5dGUgb3V0IG9mIHJhbmdlJyk7XG4gICAgICAvLyBSdXNzaWFuIHBlYXNhbnQgbXVsdGlwbGljYXRpb25cbiAgICAgIGxldCB6OiBpbnQgPSAwO1xuICAgICAgZm9yIChsZXQgaSA9IDc7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIHogPSAoeiA8PCAxKSBeICgoeiA+Pj4gNykgKiAweDExZCk7XG4gICAgICAgIHogXj0gKCh5ID4+PiBpKSAmIDEpICogeDtcbiAgICAgIH1cbiAgICAgIGFzc2VydCh6ID4+PiA4ID09IDApO1xuICAgICAgcmV0dXJuIHogYXMgYnl0ZTtcbiAgICB9XG5cbiAgICAvLyBDYW4gb25seSBiZSBjYWxsZWQgaW1tZWRpYXRlbHkgYWZ0ZXIgYSBsaWdodCBydW4gaXMgYWRkZWQsIGFuZFxuICAgIC8vIHJldHVybnMgZWl0aGVyIDAsIDEsIG9yIDIuIEEgaGVscGVyIGZ1bmN0aW9uIGZvciBnZXRQZW5hbHR5U2NvcmUoKS5cbiAgICBwcml2YXRlIGZpbmRlclBlbmFsdHlDb3VudFBhdHRlcm5zKHJ1bkhpc3Rvcnk6IFJlYWRvbmx5PEFycmF5PGludD4+KTogaW50IHtcbiAgICAgIGNvbnN0IG46IGludCA9IHJ1bkhpc3RvcnlbMV07XG4gICAgICBhc3NlcnQobiA8PSB0aGlzLnNpemUgKiAzKTtcbiAgICAgIGNvbnN0IGNvcmU6IGJvb2xlYW4gPVxuICAgICAgICBuID4gMCAmJiBydW5IaXN0b3J5WzJdID09IG4gJiYgcnVuSGlzdG9yeVszXSA9PSBuICogMyAmJiBydW5IaXN0b3J5WzRdID09IG4gJiYgcnVuSGlzdG9yeVs1XSA9PSBuO1xuICAgICAgcmV0dXJuIChcbiAgICAgICAgKGNvcmUgJiYgcnVuSGlzdG9yeVswXSA+PSBuICogNCAmJiBydW5IaXN0b3J5WzZdID49IG4gPyAxIDogMCkgK1xuICAgICAgICAoY29yZSAmJiBydW5IaXN0b3J5WzZdID49IG4gKiA0ICYmIHJ1bkhpc3RvcnlbMF0gPj0gbiA/IDEgOiAwKVxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBNdXN0IGJlIGNhbGxlZCBhdCB0aGUgZW5kIG9mIGEgbGluZSAocm93IG9yIGNvbHVtbikgb2YgbW9kdWxlcy4gQSBoZWxwZXIgZnVuY3Rpb24gZm9yIGdldFBlbmFsdHlTY29yZSgpLlxuICAgIHByaXZhdGUgZmluZGVyUGVuYWx0eVRlcm1pbmF0ZUFuZENvdW50KFxuICAgICAgY3VycmVudFJ1bkNvbG9yOiBib29sZWFuLFxuICAgICAgY3VycmVudFJ1bkxlbmd0aDogaW50LFxuICAgICAgcnVuSGlzdG9yeTogQXJyYXk8aW50PlxuICAgICk6IGludCB7XG4gICAgICBpZiAoY3VycmVudFJ1bkNvbG9yKSB7XG4gICAgICAgIC8vIFRlcm1pbmF0ZSBkYXJrIHJ1blxuICAgICAgICB0aGlzLmZpbmRlclBlbmFsdHlBZGRIaXN0b3J5KGN1cnJlbnRSdW5MZW5ndGgsIHJ1bkhpc3RvcnkpO1xuICAgICAgICBjdXJyZW50UnVuTGVuZ3RoID0gMDtcbiAgICAgIH1cbiAgICAgIGN1cnJlbnRSdW5MZW5ndGggKz0gdGhpcy5zaXplOyAvLyBBZGQgbGlnaHQgYm9yZGVyIHRvIGZpbmFsIHJ1blxuICAgICAgdGhpcy5maW5kZXJQZW5hbHR5QWRkSGlzdG9yeShjdXJyZW50UnVuTGVuZ3RoLCBydW5IaXN0b3J5KTtcbiAgICAgIHJldHVybiB0aGlzLmZpbmRlclBlbmFsdHlDb3VudFBhdHRlcm5zKHJ1bkhpc3RvcnkpO1xuICAgIH1cblxuICAgIC8vIFB1c2hlcyB0aGUgZ2l2ZW4gdmFsdWUgdG8gdGhlIGZyb250IGFuZCBkcm9wcyB0aGUgbGFzdCB2YWx1ZS4gQSBoZWxwZXIgZnVuY3Rpb24gZm9yIGdldFBlbmFsdHlTY29yZSgpLlxuICAgIHByaXZhdGUgZmluZGVyUGVuYWx0eUFkZEhpc3RvcnkoY3VycmVudFJ1bkxlbmd0aDogaW50LCBydW5IaXN0b3J5OiBBcnJheTxpbnQ+KTogdm9pZCB7XG4gICAgICBpZiAocnVuSGlzdG9yeVswXSA9PSAwKSBjdXJyZW50UnVuTGVuZ3RoICs9IHRoaXMuc2l6ZTsgLy8gQWRkIGxpZ2h0IGJvcmRlciB0byBpbml0aWFsIHJ1blxuICAgICAgcnVuSGlzdG9yeS5wb3AoKTtcbiAgICAgIHJ1bkhpc3RvcnkudW5zaGlmdChjdXJyZW50UnVuTGVuZ3RoKTtcbiAgICB9XG5cbiAgICAvKi0tIENvbnN0YW50cyBhbmQgdGFibGVzIC0tKi9cblxuICAgIC8vIFRoZSBtaW5pbXVtIHZlcnNpb24gbnVtYmVyIHN1cHBvcnRlZCBpbiB0aGUgUVIgQ29kZSBNb2RlbCAyIHN0YW5kYXJkLlxuICAgIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgTUlOX1ZFUlNJT046IGludCA9IDE7XG4gICAgLy8gVGhlIG1heGltdW0gdmVyc2lvbiBudW1iZXIgc3VwcG9ydGVkIGluIHRoZSBRUiBDb2RlIE1vZGVsIDIgc3RhbmRhcmQuXG4gICAgcHVibGljIHN0YXRpYyByZWFkb25seSBNQVhfVkVSU0lPTjogaW50ID0gNDA7XG5cbiAgICAvLyBGb3IgdXNlIGluIGdldFBlbmFsdHlTY29yZSgpLCB3aGVuIGV2YWx1YXRpbmcgd2hpY2ggbWFzayBpcyBiZXN0LlxuICAgIHByaXZhdGUgc3RhdGljIHJlYWRvbmx5IFBFTkFMVFlfTjE6IGludCA9IDM7XG4gICAgcHJpdmF0ZSBzdGF0aWMgcmVhZG9ubHkgUEVOQUxUWV9OMjogaW50ID0gMztcbiAgICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBQRU5BTFRZX04zOiBpbnQgPSA0MDtcbiAgICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBQRU5BTFRZX040OiBpbnQgPSAxMDtcblxuICAgIHByaXZhdGUgc3RhdGljIHJlYWRvbmx5IEVDQ19DT0RFV09SRFNfUEVSX0JMT0NLOiBBcnJheTxBcnJheTxpbnQ+PiA9IFtcbiAgICAgIC8vIFZlcnNpb246IChub3RlIHRoYXQgaW5kZXggMCBpcyBmb3IgcGFkZGluZywgYW5kIGlzIHNldCB0byBhbiBpbGxlZ2FsIHZhbHVlKVxuICAgICAgLy8wLCAgMSwgIDIsICAzLCAgNCwgIDUsICA2LCAgNywgIDgsICA5LCAxMCwgMTEsIDEyLCAxMywgMTQsIDE1LCAxNiwgMTcsIDE4LCAxOSwgMjAsIDIxLCAyMiwgMjMsIDI0LCAyNSwgMjYsIDI3LCAyOCwgMjksIDMwLCAzMSwgMzIsIDMzLCAzNCwgMzUsIDM2LCAzNywgMzgsIDM5LCA0MCAgICBFcnJvciBjb3JyZWN0aW9uIGxldmVsXG4gICAgICBbXG4gICAgICAgIC0xLCA3LCAxMCwgMTUsIDIwLCAyNiwgMTgsIDIwLCAyNCwgMzAsIDE4LCAyMCwgMjQsIDI2LCAzMCwgMjIsIDI0LCAyOCwgMzAsIDI4LCAyOCwgMjgsIDI4LCAzMCwgMzAsIDI2LCAyOCwgMzAsXG4gICAgICAgIDMwLCAzMCwgMzAsIDMwLCAzMCwgMzAsIDMwLCAzMCwgMzAsIDMwLCAzMCwgMzAsIDMwLFxuICAgICAgXSwgLy8gTG93XG4gICAgICBbXG4gICAgICAgIC0xLCAxMCwgMTYsIDI2LCAxOCwgMjQsIDE2LCAxOCwgMjIsIDIyLCAyNiwgMzAsIDIyLCAyMiwgMjQsIDI0LCAyOCwgMjgsIDI2LCAyNiwgMjYsIDI2LCAyOCwgMjgsIDI4LCAyOCwgMjgsIDI4LFxuICAgICAgICAyOCwgMjgsIDI4LCAyOCwgMjgsIDI4LCAyOCwgMjgsIDI4LCAyOCwgMjgsIDI4LCAyOCxcbiAgICAgIF0sIC8vIE1lZGl1bVxuICAgICAgW1xuICAgICAgICAtMSwgMTMsIDIyLCAxOCwgMjYsIDE4LCAyNCwgMTgsIDIyLCAyMCwgMjQsIDI4LCAyNiwgMjQsIDIwLCAzMCwgMjQsIDI4LCAyOCwgMjYsIDMwLCAyOCwgMzAsIDMwLCAzMCwgMzAsIDI4LCAzMCxcbiAgICAgICAgMzAsIDMwLCAzMCwgMzAsIDMwLCAzMCwgMzAsIDMwLCAzMCwgMzAsIDMwLCAzMCwgMzAsXG4gICAgICBdLCAvLyBRdWFydGlsZVxuICAgICAgW1xuICAgICAgICAtMSwgMTcsIDI4LCAyMiwgMTYsIDIyLCAyOCwgMjYsIDI2LCAyNCwgMjgsIDI0LCAyOCwgMjIsIDI0LCAyNCwgMzAsIDI4LCAyOCwgMjYsIDI4LCAzMCwgMjQsIDMwLCAzMCwgMzAsIDMwLCAzMCxcbiAgICAgICAgMzAsIDMwLCAzMCwgMzAsIDMwLCAzMCwgMzAsIDMwLCAzMCwgMzAsIDMwLCAzMCwgMzAsXG4gICAgICBdLCAvLyBIaWdoXG4gICAgXTtcblxuICAgIHByaXZhdGUgc3RhdGljIHJlYWRvbmx5IE5VTV9FUlJPUl9DT1JSRUNUSU9OX0JMT0NLUzogQXJyYXk8QXJyYXk8aW50Pj4gPSBbXG4gICAgICAvLyBWZXJzaW9uOiAobm90ZSB0aGF0IGluZGV4IDAgaXMgZm9yIHBhZGRpbmcsIGFuZCBpcyBzZXQgdG8gYW4gaWxsZWdhbCB2YWx1ZSlcbiAgICAgIC8vMCwgMSwgMiwgMywgNCwgNSwgNiwgNywgOCwgOSwxMCwgMTEsIDEyLCAxMywgMTQsIDE1LCAxNiwgMTcsIDE4LCAxOSwgMjAsIDIxLCAyMiwgMjMsIDI0LCAyNSwgMjYsIDI3LCAyOCwgMjksIDMwLCAzMSwgMzIsIDMzLCAzNCwgMzUsIDM2LCAzNywgMzgsIDM5LCA0MCAgICBFcnJvciBjb3JyZWN0aW9uIGxldmVsXG4gICAgICBbXG4gICAgICAgIC0xLCAxLCAxLCAxLCAxLCAxLCAyLCAyLCAyLCAyLCA0LCA0LCA0LCA0LCA0LCA2LCA2LCA2LCA2LCA3LCA4LCA4LCA5LCA5LCAxMCwgMTIsIDEyLCAxMiwgMTMsIDE0LCAxNSwgMTYsIDE3LCAxOCxcbiAgICAgICAgMTksIDE5LCAyMCwgMjEsIDIyLCAyNCwgMjUsXG4gICAgICBdLCAvLyBMb3dcbiAgICAgIFtcbiAgICAgICAgLTEsIDEsIDEsIDEsIDIsIDIsIDQsIDQsIDQsIDUsIDUsIDUsIDgsIDksIDksIDEwLCAxMCwgMTEsIDEzLCAxNCwgMTYsIDE3LCAxNywgMTgsIDIwLCAyMSwgMjMsIDI1LCAyNiwgMjgsIDI5LFxuICAgICAgICAzMSwgMzMsIDM1LCAzNywgMzgsIDQwLCA0MywgNDUsIDQ3LCA0OSxcbiAgICAgIF0sIC8vIE1lZGl1bVxuICAgICAgW1xuICAgICAgICAtMSwgMSwgMSwgMiwgMiwgNCwgNCwgNiwgNiwgOCwgOCwgOCwgMTAsIDEyLCAxNiwgMTIsIDE3LCAxNiwgMTgsIDIxLCAyMCwgMjMsIDIzLCAyNSwgMjcsIDI5LCAzNCwgMzQsIDM1LCAzOCwgNDAsXG4gICAgICAgIDQzLCA0NSwgNDgsIDUxLCA1MywgNTYsIDU5LCA2MiwgNjUsIDY4LFxuICAgICAgXSwgLy8gUXVhcnRpbGVcbiAgICAgIFtcbiAgICAgICAgLTEsIDEsIDEsIDIsIDQsIDQsIDQsIDUsIDYsIDgsIDgsIDExLCAxMSwgMTYsIDE2LCAxOCwgMTYsIDE5LCAyMSwgMjUsIDI1LCAyNSwgMzQsIDMwLCAzMiwgMzUsIDM3LCA0MCwgNDIsIDQ1LFxuICAgICAgICA0OCwgNTEsIDU0LCA1NywgNjAsIDYzLCA2NiwgNzAsIDc0LCA3NywgODEsXG4gICAgICBdLCAvLyBIaWdoXG4gICAgXTtcbiAgfVxuXG4gIC8vIEFwcGVuZHMgdGhlIGdpdmVuIG51bWJlciBvZiBsb3ctb3JkZXIgYml0cyBvZiB0aGUgZ2l2ZW4gdmFsdWVcbiAgLy8gdG8gdGhlIGdpdmVuIGJ1ZmZlci4gUmVxdWlyZXMgMCA8PSBsZW4gPD0gMzEgYW5kIDAgPD0gdmFsIDwgMl5sZW4uXG4gIGZ1bmN0aW9uIGFwcGVuZEJpdHModmFsOiBpbnQsIGxlbjogaW50LCBiYjogQXJyYXk8Yml0Pik6IHZvaWQge1xuICAgIGlmIChsZW4gPCAwIHx8IGxlbiA+IDMxIHx8IHZhbCA+Pj4gbGVuICE9IDApIHRocm93IG5ldyBSYW5nZUVycm9yKCdWYWx1ZSBvdXQgb2YgcmFuZ2UnKTtcbiAgICBmb3IgKFxuICAgICAgbGV0IGkgPSBsZW4gLSAxO1xuICAgICAgaSA+PSAwO1xuICAgICAgaS0tIC8vIEFwcGVuZCBiaXQgYnkgYml0XG4gICAgKVxuICAgICAgYmIucHVzaCgodmFsID4+PiBpKSAmIDEpO1xuICB9XG5cbiAgLy8gUmV0dXJucyB0cnVlIGlmZiB0aGUgaSd0aCBiaXQgb2YgeCBpcyBzZXQgdG8gMS5cbiAgZnVuY3Rpb24gZ2V0Qml0KHg6IGludCwgaTogaW50KTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICgoeCA+Pj4gaSkgJiAxKSAhPSAwO1xuICB9XG5cbiAgLy8gVGhyb3dzIGFuIGV4Y2VwdGlvbiBpZiB0aGUgZ2l2ZW4gY29uZGl0aW9uIGlzIGZhbHNlLlxuICBmdW5jdGlvbiBhc3NlcnQoY29uZDogYm9vbGVhbik6IHZvaWQge1xuICAgIGlmICghY29uZCkgdGhyb3cgbmV3IEVycm9yKCdBc3NlcnRpb24gZXJyb3InKTtcbiAgfVxuXG4gIC8qLS0tLSBEYXRhIHNlZ21lbnQgY2xhc3MgLS0tLSovXG5cbiAgLypcbiAgICogQSBzZWdtZW50IG9mIGNoYXJhY3Rlci9iaW5hcnkvY29udHJvbCBkYXRhIGluIGEgUVIgQ29kZSBzeW1ib2wuXG4gICAqIEluc3RhbmNlcyBvZiB0aGlzIGNsYXNzIGFyZSBpbW11dGFibGUuXG4gICAqIFRoZSBtaWQtbGV2ZWwgd2F5IHRvIGNyZWF0ZSBhIHNlZ21lbnQgaXMgdG8gdGFrZSB0aGUgcGF5bG9hZCBkYXRhXG4gICAqIGFuZCBjYWxsIGEgc3RhdGljIGZhY3RvcnkgZnVuY3Rpb24gc3VjaCBhcyBRclNlZ21lbnQubWFrZU51bWVyaWMoKS5cbiAgICogVGhlIGxvdy1sZXZlbCB3YXkgdG8gY3JlYXRlIGEgc2VnbWVudCBpcyB0byBjdXN0b20tbWFrZSB0aGUgYml0IGJ1ZmZlclxuICAgKiBhbmQgY2FsbCB0aGUgUXJTZWdtZW50KCkgY29uc3RydWN0b3Igd2l0aCBhcHByb3ByaWF0ZSB2YWx1ZXMuXG4gICAqIFRoaXMgc2VnbWVudCBjbGFzcyBpbXBvc2VzIG5vIGxlbmd0aCByZXN0cmljdGlvbnMsIGJ1dCBRUiBDb2RlcyBoYXZlIHJlc3RyaWN0aW9ucy5cbiAgICogRXZlbiBpbiB0aGUgbW9zdCBmYXZvcmFibGUgY29uZGl0aW9ucywgYSBRUiBDb2RlIGNhbiBvbmx5IGhvbGQgNzA4OSBjaGFyYWN0ZXJzIG9mIGRhdGEuXG4gICAqIEFueSBzZWdtZW50IGxvbmdlciB0aGFuIHRoaXMgaXMgbWVhbmluZ2xlc3MgZm9yIHRoZSBwdXJwb3NlIG9mIGdlbmVyYXRpbmcgUVIgQ29kZXMuXG4gICAqL1xuICBleHBvcnQgY2xhc3MgUXJTZWdtZW50IHtcbiAgICAvKi0tIFN0YXRpYyBmYWN0b3J5IGZ1bmN0aW9ucyAobWlkIGxldmVsKSAtLSovXG5cbiAgICAvLyBSZXR1cm5zIGEgc2VnbWVudCByZXByZXNlbnRpbmcgdGhlIGdpdmVuIGJpbmFyeSBkYXRhIGVuY29kZWQgaW5cbiAgICAvLyBieXRlIG1vZGUuIEFsbCBpbnB1dCBieXRlIGFycmF5cyBhcmUgYWNjZXB0YWJsZS4gQW55IHRleHQgc3RyaW5nXG4gICAgLy8gY2FuIGJlIGNvbnZlcnRlZCB0byBVVEYtOCBieXRlcyBhbmQgZW5jb2RlZCBhcyBhIGJ5dGUgbW9kZSBzZWdtZW50LlxuICAgIHB1YmxpYyBzdGF0aWMgbWFrZUJ5dGVzKGRhdGE6IFJlYWRvbmx5PEFycmF5PGJ5dGU+Pik6IFFyU2VnbWVudCB7XG4gICAgICBsZXQgYmI6IEFycmF5PGJpdD4gPSBbXTtcbiAgICAgIGZvciAoY29uc3QgYiBvZiBkYXRhKSBhcHBlbmRCaXRzKGIsIDgsIGJiKTtcbiAgICAgIHJldHVybiBuZXcgUXJTZWdtZW50KFFyU2VnbWVudC5Nb2RlLkJZVEUsIGRhdGEubGVuZ3RoLCBiYik7XG4gICAgfVxuXG4gICAgLy8gUmV0dXJucyBhIHNlZ21lbnQgcmVwcmVzZW50aW5nIHRoZSBnaXZlbiBzdHJpbmcgb2YgZGVjaW1hbCBkaWdpdHMgZW5jb2RlZCBpbiBudW1lcmljIG1vZGUuXG4gICAgcHVibGljIHN0YXRpYyBtYWtlTnVtZXJpYyhkaWdpdHM6IHN0cmluZyk6IFFyU2VnbWVudCB7XG4gICAgICBpZiAoIVFyU2VnbWVudC5pc051bWVyaWMoZGlnaXRzKSkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ1N0cmluZyBjb250YWlucyBub24tbnVtZXJpYyBjaGFyYWN0ZXJzJyk7XG4gICAgICBsZXQgYmI6IEFycmF5PGJpdD4gPSBbXTtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZGlnaXRzLmxlbmd0aDsgKSB7XG4gICAgICAgIC8vIENvbnN1bWUgdXAgdG8gMyBkaWdpdHMgcGVyIGl0ZXJhdGlvblxuICAgICAgICBjb25zdCBuOiBpbnQgPSBNYXRoLm1pbihkaWdpdHMubGVuZ3RoIC0gaSwgMyk7XG4gICAgICAgIGFwcGVuZEJpdHMocGFyc2VJbnQoZGlnaXRzLnN1YnN0cmluZyhpLCBpICsgbiksIDEwKSwgbiAqIDMgKyAxLCBiYik7XG4gICAgICAgIGkgKz0gbjtcbiAgICAgIH1cbiAgICAgIHJldHVybiBuZXcgUXJTZWdtZW50KFFyU2VnbWVudC5Nb2RlLk5VTUVSSUMsIGRpZ2l0cy5sZW5ndGgsIGJiKTtcbiAgICB9XG5cbiAgICAvLyBSZXR1cm5zIGEgc2VnbWVudCByZXByZXNlbnRpbmcgdGhlIGdpdmVuIHRleHQgc3RyaW5nIGVuY29kZWQgaW4gYWxwaGFudW1lcmljIG1vZGUuXG4gICAgLy8gVGhlIGNoYXJhY3RlcnMgYWxsb3dlZCBhcmU6IDAgdG8gOSwgQSB0byBaICh1cHBlcmNhc2Ugb25seSksIHNwYWNlLFxuICAgIC8vIGRvbGxhciwgcGVyY2VudCwgYXN0ZXJpc2ssIHBsdXMsIGh5cGhlbiwgcGVyaW9kLCBzbGFzaCwgY29sb24uXG4gICAgcHVibGljIHN0YXRpYyBtYWtlQWxwaGFudW1lcmljKHRleHQ6IHN0cmluZyk6IFFyU2VnbWVudCB7XG4gICAgICBpZiAoIVFyU2VnbWVudC5pc0FscGhhbnVtZXJpYyh0ZXh0KSlcbiAgICAgICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ1N0cmluZyBjb250YWlucyB1bmVuY29kYWJsZSBjaGFyYWN0ZXJzIGluIGFscGhhbnVtZXJpYyBtb2RlJyk7XG4gICAgICBsZXQgYmI6IEFycmF5PGJpdD4gPSBbXTtcbiAgICAgIGxldCBpOiBpbnQ7XG4gICAgICBmb3IgKGkgPSAwOyBpICsgMiA8PSB0ZXh0Lmxlbmd0aDsgaSArPSAyKSB7XG4gICAgICAgIC8vIFByb2Nlc3MgZ3JvdXBzIG9mIDJcbiAgICAgICAgbGV0IHRlbXA6IGludCA9IFFyU2VnbWVudC5BTFBIQU5VTUVSSUNfQ0hBUlNFVC5pbmRleE9mKHRleHQuY2hhckF0KGkpKSAqIDQ1O1xuICAgICAgICB0ZW1wICs9IFFyU2VnbWVudC5BTFBIQU5VTUVSSUNfQ0hBUlNFVC5pbmRleE9mKHRleHQuY2hhckF0KGkgKyAxKSk7XG4gICAgICAgIGFwcGVuZEJpdHModGVtcCwgMTEsIGJiKTtcbiAgICAgIH1cbiAgICAgIGlmIChpIDwgdGV4dC5sZW5ndGgpXG4gICAgICAgIC8vIDEgY2hhcmFjdGVyIHJlbWFpbmluZ1xuICAgICAgICBhcHBlbmRCaXRzKFFyU2VnbWVudC5BTFBIQU5VTUVSSUNfQ0hBUlNFVC5pbmRleE9mKHRleHQuY2hhckF0KGkpKSwgNiwgYmIpO1xuICAgICAgcmV0dXJuIG5ldyBRclNlZ21lbnQoUXJTZWdtZW50Lk1vZGUuQUxQSEFOVU1FUklDLCB0ZXh0Lmxlbmd0aCwgYmIpO1xuICAgIH1cblxuICAgIC8vIFJldHVybnMgYSBuZXcgbXV0YWJsZSBsaXN0IG9mIHplcm8gb3IgbW9yZSBzZWdtZW50cyB0byByZXByZXNlbnQgdGhlIGdpdmVuIFVuaWNvZGUgdGV4dCBzdHJpbmcuXG4gICAgLy8gVGhlIHJlc3VsdCBtYXkgdXNlIHZhcmlvdXMgc2VnbWVudCBtb2RlcyBhbmQgc3dpdGNoIG1vZGVzIHRvIG9wdGltaXplIHRoZSBsZW5ndGggb2YgdGhlIGJpdCBzdHJlYW0uXG4gICAgcHVibGljIHN0YXRpYyBtYWtlU2VnbWVudHModGV4dDogc3RyaW5nKTogQXJyYXk8UXJTZWdtZW50PiB7XG4gICAgICAvLyBTZWxlY3QgdGhlIG1vc3QgZWZmaWNpZW50IHNlZ21lbnQgZW5jb2RpbmcgYXV0b21hdGljYWxseVxuICAgICAgaWYgKHRleHQgPT0gJycpIHJldHVybiBbXTtcbiAgICAgIGVsc2UgaWYgKFFyU2VnbWVudC5pc051bWVyaWModGV4dCkpIHJldHVybiBbUXJTZWdtZW50Lm1ha2VOdW1lcmljKHRleHQpXTtcbiAgICAgIGVsc2UgaWYgKFFyU2VnbWVudC5pc0FscGhhbnVtZXJpYyh0ZXh0KSkgcmV0dXJuIFtRclNlZ21lbnQubWFrZUFscGhhbnVtZXJpYyh0ZXh0KV07XG4gICAgICBlbHNlIHJldHVybiBbUXJTZWdtZW50Lm1ha2VCeXRlcyhRclNlZ21lbnQudG9VdGY4Qnl0ZUFycmF5KHRleHQpKV07XG4gICAgfVxuXG4gICAgLy8gUmV0dXJucyBhIHNlZ21lbnQgcmVwcmVzZW50aW5nIGFuIEV4dGVuZGVkIENoYW5uZWwgSW50ZXJwcmV0YXRpb25cbiAgICAvLyAoRUNJKSBkZXNpZ25hdG9yIHdpdGggdGhlIGdpdmVuIGFzc2lnbm1lbnQgdmFsdWUuXG4gICAgcHVibGljIHN0YXRpYyBtYWtlRWNpKGFzc2lnblZhbDogaW50KTogUXJTZWdtZW50IHtcbiAgICAgIGxldCBiYjogQXJyYXk8Yml0PiA9IFtdO1xuICAgICAgaWYgKGFzc2lnblZhbCA8IDApIHRocm93IG5ldyBSYW5nZUVycm9yKCdFQ0kgYXNzaWdubWVudCB2YWx1ZSBvdXQgb2YgcmFuZ2UnKTtcbiAgICAgIGVsc2UgaWYgKGFzc2lnblZhbCA8IDEgPDwgNykgYXBwZW5kQml0cyhhc3NpZ25WYWwsIDgsIGJiKTtcbiAgICAgIGVsc2UgaWYgKGFzc2lnblZhbCA8IDEgPDwgMTQpIHtcbiAgICAgICAgYXBwZW5kQml0cygwYjEwLCAyLCBiYik7XG4gICAgICAgIGFwcGVuZEJpdHMoYXNzaWduVmFsLCAxNCwgYmIpO1xuICAgICAgfSBlbHNlIGlmIChhc3NpZ25WYWwgPCAxMDAwMDAwKSB7XG4gICAgICAgIGFwcGVuZEJpdHMoMGIxMTAsIDMsIGJiKTtcbiAgICAgICAgYXBwZW5kQml0cyhhc3NpZ25WYWwsIDIxLCBiYik7XG4gICAgICB9IGVsc2UgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0VDSSBhc3NpZ25tZW50IHZhbHVlIG91dCBvZiByYW5nZScpO1xuICAgICAgcmV0dXJuIG5ldyBRclNlZ21lbnQoUXJTZWdtZW50Lk1vZGUuRUNJLCAwLCBiYik7XG4gICAgfVxuXG4gICAgLy8gVGVzdHMgd2hldGhlciB0aGUgZ2l2ZW4gc3RyaW5nIGNhbiBiZSBlbmNvZGVkIGFzIGEgc2VnbWVudCBpbiBudW1lcmljIG1vZGUuXG4gICAgLy8gQSBzdHJpbmcgaXMgZW5jb2RhYmxlIGlmZiBlYWNoIGNoYXJhY3RlciBpcyBpbiB0aGUgcmFuZ2UgMCB0byA5LlxuICAgIHB1YmxpYyBzdGF0aWMgaXNOdW1lcmljKHRleHQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgICAgcmV0dXJuIFFyU2VnbWVudC5OVU1FUklDX1JFR0VYLnRlc3QodGV4dCk7XG4gICAgfVxuXG4gICAgLy8gVGVzdHMgd2hldGhlciB0aGUgZ2l2ZW4gc3RyaW5nIGNhbiBiZSBlbmNvZGVkIGFzIGEgc2VnbWVudCBpbiBhbHBoYW51bWVyaWMgbW9kZS5cbiAgICAvLyBBIHN0cmluZyBpcyBlbmNvZGFibGUgaWZmIGVhY2ggY2hhcmFjdGVyIGlzIGluIHRoZSBmb2xsb3dpbmcgc2V0OiAwIHRvIDksIEEgdG8gWlxuICAgIC8vICh1cHBlcmNhc2Ugb25seSksIHNwYWNlLCBkb2xsYXIsIHBlcmNlbnQsIGFzdGVyaXNrLCBwbHVzLCBoeXBoZW4sIHBlcmlvZCwgc2xhc2gsIGNvbG9uLlxuICAgIHB1YmxpYyBzdGF0aWMgaXNBbHBoYW51bWVyaWModGV4dDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgICByZXR1cm4gUXJTZWdtZW50LkFMUEhBTlVNRVJJQ19SRUdFWC50ZXN0KHRleHQpO1xuICAgIH1cblxuICAgIC8qLS0gQ29uc3RydWN0b3IgKGxvdyBsZXZlbCkgYW5kIGZpZWxkcyAtLSovXG5cbiAgICAvLyBDcmVhdGVzIGEgbmV3IFFSIENvZGUgc2VnbWVudCB3aXRoIHRoZSBnaXZlbiBhdHRyaWJ1dGVzIGFuZCBkYXRhLlxuICAgIC8vIFRoZSBjaGFyYWN0ZXIgY291bnQgKG51bUNoYXJzKSBtdXN0IGFncmVlIHdpdGggdGhlIG1vZGUgYW5kIHRoZSBiaXQgYnVmZmVyIGxlbmd0aCxcbiAgICAvLyBidXQgdGhlIGNvbnN0cmFpbnQgaXNuJ3QgY2hlY2tlZC4gVGhlIGdpdmVuIGJpdCBidWZmZXIgaXMgY2xvbmVkIGFuZCBzdG9yZWQuXG4gICAgcHVibGljIGNvbnN0cnVjdG9yKFxuICAgICAgLy8gVGhlIG1vZGUgaW5kaWNhdG9yIG9mIHRoaXMgc2VnbWVudC5cbiAgICAgIHB1YmxpYyByZWFkb25seSBtb2RlOiBRclNlZ21lbnQuTW9kZSxcblxuICAgICAgLy8gVGhlIGxlbmd0aCBvZiB0aGlzIHNlZ21lbnQncyB1bmVuY29kZWQgZGF0YS4gTWVhc3VyZWQgaW4gY2hhcmFjdGVycyBmb3JcbiAgICAgIC8vIG51bWVyaWMvYWxwaGFudW1lcmljL2thbmppIG1vZGUsIGJ5dGVzIGZvciBieXRlIG1vZGUsIGFuZCAwIGZvciBFQ0kgbW9kZS5cbiAgICAgIC8vIEFsd2F5cyB6ZXJvIG9yIHBvc2l0aXZlLiBOb3QgdGhlIHNhbWUgYXMgdGhlIGRhdGEncyBiaXQgbGVuZ3RoLlxuICAgICAgcHVibGljIHJlYWRvbmx5IG51bUNoYXJzOiBpbnQsXG5cbiAgICAgIC8vIFRoZSBkYXRhIGJpdHMgb2YgdGhpcyBzZWdtZW50LiBBY2Nlc3NlZCB0aHJvdWdoIGdldERhdGEoKS5cbiAgICAgIHByaXZhdGUgcmVhZG9ubHkgYml0RGF0YTogQXJyYXk8Yml0PlxuICAgICkge1xuICAgICAgaWYgKG51bUNoYXJzIDwgMCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0ludmFsaWQgYXJndW1lbnQnKTtcbiAgICAgIHRoaXMuYml0RGF0YSA9IGJpdERhdGEuc2xpY2UoKTsgLy8gTWFrZSBkZWZlbnNpdmUgY29weVxuICAgIH1cblxuICAgIC8qLS0gTWV0aG9kcyAtLSovXG5cbiAgICAvLyBSZXR1cm5zIGEgbmV3IGNvcHkgb2YgdGhlIGRhdGEgYml0cyBvZiB0aGlzIHNlZ21lbnQuXG4gICAgcHVibGljIGdldERhdGEoKTogQXJyYXk8Yml0PiB7XG4gICAgICByZXR1cm4gdGhpcy5iaXREYXRhLnNsaWNlKCk7IC8vIE1ha2UgZGVmZW5zaXZlIGNvcHlcbiAgICB9XG5cbiAgICAvLyAoUGFja2FnZS1wcml2YXRlKSBDYWxjdWxhdGVzIGFuZCByZXR1cm5zIHRoZSBudW1iZXIgb2YgYml0cyBuZWVkZWQgdG8gZW5jb2RlIHRoZSBnaXZlbiBzZWdtZW50cyBhdFxuICAgIC8vIHRoZSBnaXZlbiB2ZXJzaW9uLiBUaGUgcmVzdWx0IGlzIGluZmluaXR5IGlmIGEgc2VnbWVudCBoYXMgdG9vIG1hbnkgY2hhcmFjdGVycyB0byBmaXQgaXRzIGxlbmd0aCBmaWVsZC5cbiAgICBwdWJsaWMgc3RhdGljIGdldFRvdGFsQml0cyhzZWdzOiBSZWFkb25seTxBcnJheTxRclNlZ21lbnQ+PiwgdmVyc2lvbjogaW50KTogbnVtYmVyIHtcbiAgICAgIGxldCByZXN1bHQgPSAwO1xuICAgICAgZm9yIChjb25zdCBzZWcgb2Ygc2Vncykge1xuICAgICAgICBjb25zdCBjY2JpdHM6IGludCA9IHNlZy5tb2RlLm51bUNoYXJDb3VudEJpdHModmVyc2lvbik7XG4gICAgICAgIGlmIChzZWcubnVtQ2hhcnMgPj0gMSA8PCBjY2JpdHMpIHJldHVybiBJbmZpbml0eTsgLy8gVGhlIHNlZ21lbnQncyBsZW5ndGggZG9lc24ndCBmaXQgdGhlIGZpZWxkJ3MgYml0IHdpZHRoXG4gICAgICAgIHJlc3VsdCArPSA0ICsgY2NiaXRzICsgc2VnLmJpdERhdGEubGVuZ3RoO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvLyBSZXR1cm5zIGEgbmV3IGFycmF5IG9mIGJ5dGVzIHJlcHJlc2VudGluZyB0aGUgZ2l2ZW4gc3RyaW5nIGVuY29kZWQgaW4gVVRGLTguXG4gICAgcHJpdmF0ZSBzdGF0aWMgdG9VdGY4Qnl0ZUFycmF5KHN0cjogc3RyaW5nKTogQXJyYXk8Ynl0ZT4ge1xuICAgICAgc3RyID0gZW5jb2RlVVJJKHN0cik7XG4gICAgICBsZXQgcmVzdWx0OiBBcnJheTxieXRlPiA9IFtdO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYgKHN0ci5jaGFyQXQoaSkgIT0gJyUnKSByZXN1bHQucHVzaChzdHIuY2hhckNvZGVBdChpKSk7XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIHJlc3VsdC5wdXNoKHBhcnNlSW50KHN0ci5zdWJzdHJpbmcoaSArIDEsIGkgKyAzKSwgMTYpKTtcbiAgICAgICAgICBpICs9IDI7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyotLSBDb25zdGFudHMgLS0qL1xuXG4gICAgLy8gRGVzY3JpYmVzIHByZWNpc2VseSBhbGwgc3RyaW5ncyB0aGF0IGFyZSBlbmNvZGFibGUgaW4gbnVtZXJpYyBtb2RlLlxuICAgIHByaXZhdGUgc3RhdGljIHJlYWRvbmx5IE5VTUVSSUNfUkVHRVg6IFJlZ0V4cCA9IC9eWzAtOV0qJC87XG5cbiAgICAvLyBEZXNjcmliZXMgcHJlY2lzZWx5IGFsbCBzdHJpbmdzIHRoYXQgYXJlIGVuY29kYWJsZSBpbiBhbHBoYW51bWVyaWMgbW9kZS5cbiAgICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBBTFBIQU5VTUVSSUNfUkVHRVg6IFJlZ0V4cCA9IC9eW0EtWjAtOSAkJSorLlxcLzotXSokLztcblxuICAgIC8vIFRoZSBzZXQgb2YgYWxsIGxlZ2FsIGNoYXJhY3RlcnMgaW4gYWxwaGFudW1lcmljIG1vZGUsXG4gICAgLy8gd2hlcmUgZWFjaCBjaGFyYWN0ZXIgdmFsdWUgbWFwcyB0byB0aGUgaW5kZXggaW4gdGhlIHN0cmluZy5cbiAgICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBBTFBIQU5VTUVSSUNfQ0hBUlNFVDogc3RyaW5nID0gJzAxMjM0NTY3ODlBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWiAkJSorLS4vOic7XG4gIH1cbn1cblxuLyotLS0tIFB1YmxpYyBoZWxwZXIgZW51bWVyYXRpb24gLS0tLSovXG5cbm5hbWVzcGFjZSBxcmNvZGVnZW4uUXJDb2RlIHtcbiAgdHlwZSBpbnQgPSBudW1iZXI7XG5cbiAgLypcbiAgICogVGhlIGVycm9yIGNvcnJlY3Rpb24gbGV2ZWwgaW4gYSBRUiBDb2RlIHN5bWJvbC4gSW1tdXRhYmxlLlxuICAgKi9cbiAgZXhwb3J0IGNsYXNzIEVjYyB7XG4gICAgLyotLSBDb25zdGFudHMgLS0qL1xuXG4gICAgcHVibGljIHN0YXRpYyByZWFkb25seSBMT1cgPSBuZXcgRWNjKDAsIDEpOyAvLyBUaGUgUVIgQ29kZSBjYW4gdG9sZXJhdGUgYWJvdXQgIDclIGVycm9uZW91cyBjb2Rld29yZHNcbiAgICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IE1FRElVTSA9IG5ldyBFY2MoMSwgMCk7IC8vIFRoZSBRUiBDb2RlIGNhbiB0b2xlcmF0ZSBhYm91dCAxNSUgZXJyb25lb3VzIGNvZGV3b3Jkc1xuICAgIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgUVVBUlRJTEUgPSBuZXcgRWNjKDIsIDMpOyAvLyBUaGUgUVIgQ29kZSBjYW4gdG9sZXJhdGUgYWJvdXQgMjUlIGVycm9uZW91cyBjb2Rld29yZHNcbiAgICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IEhJR0ggPSBuZXcgRWNjKDMsIDIpOyAvLyBUaGUgUVIgQ29kZSBjYW4gdG9sZXJhdGUgYWJvdXQgMzAlIGVycm9uZW91cyBjb2Rld29yZHNcblxuICAgIC8qLS0gQ29uc3RydWN0b3IgYW5kIGZpZWxkcyAtLSovXG5cbiAgICBwcml2YXRlIGNvbnN0cnVjdG9yKFxuICAgICAgLy8gSW4gdGhlIHJhbmdlIDAgdG8gMyAodW5zaWduZWQgMi1iaXQgaW50ZWdlcikuXG4gICAgICBwdWJsaWMgcmVhZG9ubHkgb3JkaW5hbDogaW50LFxuICAgICAgLy8gKFBhY2thZ2UtcHJpdmF0ZSkgSW4gdGhlIHJhbmdlIDAgdG8gMyAodW5zaWduZWQgMi1iaXQgaW50ZWdlcikuXG4gICAgICBwdWJsaWMgcmVhZG9ubHkgZm9ybWF0Qml0czogaW50XG4gICAgKSB7fVxuICB9XG59XG5cbi8qLS0tLSBQdWJsaWMgaGVscGVyIGVudW1lcmF0aW9uIC0tLS0qL1xuXG5uYW1lc3BhY2UgcXJjb2RlZ2VuLlFyU2VnbWVudCB7XG4gIHR5cGUgaW50ID0gbnVtYmVyO1xuXG4gIC8qXG4gICAqIERlc2NyaWJlcyBob3cgYSBzZWdtZW50J3MgZGF0YSBiaXRzIGFyZSBpbnRlcnByZXRlZC4gSW1tdXRhYmxlLlxuICAgKi9cbiAgZXhwb3J0IGNsYXNzIE1vZGUge1xuICAgIC8qLS0gQ29uc3RhbnRzIC0tKi9cblxuICAgIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgTlVNRVJJQyA9IG5ldyBNb2RlKDB4MSwgWzEwLCAxMiwgMTRdKTtcbiAgICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IEFMUEhBTlVNRVJJQyA9IG5ldyBNb2RlKDB4MiwgWzksIDExLCAxM10pO1xuICAgIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgQllURSA9IG5ldyBNb2RlKDB4NCwgWzgsIDE2LCAxNl0pO1xuICAgIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgS0FOSkkgPSBuZXcgTW9kZSgweDgsIFs4LCAxMCwgMTJdKTtcbiAgICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IEVDSSA9IG5ldyBNb2RlKDB4NywgWzAsIDAsIDBdKTtcblxuICAgIC8qLS0gQ29uc3RydWN0b3IgYW5kIGZpZWxkcyAtLSovXG5cbiAgICBwcml2YXRlIGNvbnN0cnVjdG9yKFxuICAgICAgLy8gVGhlIG1vZGUgaW5kaWNhdG9yIGJpdHMsIHdoaWNoIGlzIGEgdWludDQgdmFsdWUgKHJhbmdlIDAgdG8gMTUpLlxuICAgICAgcHVibGljIHJlYWRvbmx5IG1vZGVCaXRzOiBpbnQsXG4gICAgICAvLyBOdW1iZXIgb2YgY2hhcmFjdGVyIGNvdW50IGJpdHMgZm9yIHRocmVlIGRpZmZlcmVudCB2ZXJzaW9uIHJhbmdlcy5cbiAgICAgIHByaXZhdGUgcmVhZG9ubHkgbnVtQml0c0NoYXJDb3VudDogW2ludCwgaW50LCBpbnRdXG4gICAgKSB7fVxuXG4gICAgLyotLSBNZXRob2QgLS0qL1xuXG4gICAgLy8gKFBhY2thZ2UtcHJpdmF0ZSkgUmV0dXJucyB0aGUgYml0IHdpZHRoIG9mIHRoZSBjaGFyYWN0ZXIgY291bnQgZmllbGQgZm9yIGEgc2VnbWVudCBpblxuICAgIC8vIHRoaXMgbW9kZSBpbiBhIFFSIENvZGUgYXQgdGhlIGdpdmVuIHZlcnNpb24gbnVtYmVyLiBUaGUgcmVzdWx0IGlzIGluIHRoZSByYW5nZSBbMCwgMTZdLlxuICAgIHB1YmxpYyBudW1DaGFyQ291bnRCaXRzKHZlcjogaW50KTogaW50IHtcbiAgICAgIHJldHVybiB0aGlzLm51bUJpdHNDaGFyQ291bnRbTWF0aC5mbG9vcigodmVyICsgNykgLyAxNyldO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBxcmNvZGVnZW47XG4iXX0=
|