footprintjs 10.0.1 → 10.2.0
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/AGENTS.md +2 -1
- package/CLAUDE.md +61 -7
- package/README.md +136 -312
- package/dist/esm/index.d.ts +62 -2
- package/dist/esm/index.js +13 -6
- package/dist/esm/lib/attempt/anySignal.d.ts +19 -0
- package/dist/esm/lib/attempt/anySignal.js +39 -0
- package/dist/esm/lib/attempt/call.d.ts +88 -0
- package/dist/esm/lib/attempt/call.js +129 -0
- package/dist/esm/lib/attempt/category.d.ts +37 -0
- package/dist/esm/lib/attempt/category.js +131 -0
- package/dist/esm/lib/attempt/correlation.d.ts +95 -0
- package/dist/esm/lib/attempt/correlation.js +178 -0
- package/dist/esm/lib/attempt/deadline.d.ts +44 -0
- package/dist/esm/lib/attempt/deadline.js +101 -0
- package/dist/esm/lib/attempt/decision.d.ts +52 -0
- package/dist/esm/lib/attempt/decision.js +134 -0
- package/dist/esm/lib/attempt/effect.d.ts +76 -0
- package/dist/esm/lib/attempt/effect.js +160 -0
- package/dist/esm/lib/attempt/errors.d.ts +41 -0
- package/dist/esm/lib/attempt/errors.js +44 -0
- package/dist/esm/lib/attempt/index.d.ts +18 -0
- package/dist/esm/lib/attempt/index.js +15 -0
- package/dist/esm/lib/attempt/name.d.ts +21 -0
- package/dist/esm/lib/attempt/name.js +43 -0
- package/dist/esm/lib/attempt/observed.d.ts +66 -0
- package/dist/esm/lib/attempt/observed.js +171 -0
- package/dist/esm/lib/attempt/policy.d.ts +45 -0
- package/dist/esm/lib/attempt/policy.js +83 -0
- package/dist/esm/lib/attempt/record.d.ts +11 -0
- package/dist/esm/lib/attempt/record.js +24 -0
- package/dist/esm/lib/attempt/retryLoopContext.d.ts +18 -0
- package/dist/esm/lib/attempt/retryLoopContext.js +24 -0
- package/dist/esm/lib/attempt/retryLoopTypes.d.ts +18 -0
- package/dist/esm/lib/attempt/retryLoopTypes.js +2 -0
- package/dist/esm/lib/attempt/runner.d.ts +157 -0
- package/dist/esm/lib/attempt/runner.js +523 -0
- package/dist/esm/lib/attempt/standalone.d.ts +47 -0
- package/dist/esm/lib/attempt/standalone.js +126 -0
- package/dist/esm/lib/attempt/types.d.ts +453 -0
- package/dist/esm/lib/attempt/types.js +16 -0
- package/dist/esm/lib/budget/index.d.ts +9 -0
- package/dist/esm/lib/budget/index.js +9 -0
- package/dist/esm/lib/budget/timeBudget.d.ts +136 -0
- package/dist/esm/lib/budget/timeBudget.js +666 -0
- package/dist/esm/lib/builder/FlowChartBuilder.d.ts +88 -3
- package/dist/esm/lib/builder/FlowChartBuilder.js +199 -9
- package/dist/esm/lib/builder/retryLoop.d.ts +56 -0
- package/dist/esm/lib/builder/retryLoop.js +283 -0
- package/dist/esm/lib/builder/types.d.ts +35 -1
- package/dist/esm/lib/builder/types.js +1 -1
- package/dist/esm/lib/decide/decide.js +2 -2
- package/dist/esm/lib/decide/index.d.ts +1 -1
- package/dist/esm/lib/decide/index.js +2 -2
- package/dist/esm/lib/decide/types.d.ts +3 -0
- package/dist/esm/lib/decide/types.js +1 -8
- package/dist/esm/lib/engine/graph/StageNode.d.ts +11 -1
- package/dist/esm/lib/engine/graph/StageNode.js +1 -1
- package/dist/esm/lib/engine/graph/prefixNodeTree.js +5 -1
- package/dist/esm/lib/engine/handlers/ChildrenExecutor.js +36 -6
- package/dist/esm/lib/engine/handlers/DeciderHandler.js +9 -5
- package/dist/esm/lib/engine/handlers/ResumeEntry.js +3 -1
- package/dist/esm/lib/engine/handlers/SelectorHandler.js +6 -5
- package/dist/esm/lib/engine/handlers/StageRunner.d.ts +8 -1
- package/dist/esm/lib/engine/handlers/StageRunner.js +36 -9
- package/dist/esm/lib/engine/handlers/SubflowExecutor.js +24 -5
- package/dist/esm/lib/engine/handlers/commitStage.d.ts +7 -0
- package/dist/esm/lib/engine/handlers/commitStage.js +22 -4
- package/dist/esm/lib/engine/handlers/stageError.d.ts +9 -0
- package/dist/esm/lib/engine/handlers/stageError.js +23 -1
- package/dist/esm/lib/engine/index.d.ts +2 -2
- package/dist/esm/lib/engine/index.js +1 -1
- package/dist/esm/lib/engine/narrative/CombinedNarrativeRecorder.d.ts +27 -13
- package/dist/esm/lib/engine/narrative/CombinedNarrativeRecorder.js +68 -40
- package/dist/esm/lib/engine/narrative/FlowRecorderDispatcher.d.ts +4 -1
- package/dist/esm/lib/engine/narrative/FlowRecorderDispatcher.js +19 -2
- package/dist/esm/lib/engine/narrative/NarrativeFlowRecorder.d.ts +22 -3
- package/dist/esm/lib/engine/narrative/NarrativeFlowRecorder.js +61 -9
- package/dist/esm/lib/engine/narrative/NullControlFlowNarrativeGenerator.d.ts +1 -0
- package/dist/esm/lib/engine/narrative/NullControlFlowNarrativeGenerator.js +2 -1
- package/dist/esm/lib/engine/narrative/formatting/sentences.d.ts +23 -0
- package/dist/esm/lib/engine/narrative/formatting/sentences.js +127 -1
- package/dist/esm/lib/engine/narrative/index.d.ts +2 -2
- package/dist/esm/lib/engine/narrative/index.js +1 -1
- package/dist/esm/lib/engine/narrative/narrativeTypes.d.ts +27 -21
- package/dist/esm/lib/engine/narrative/narrativeTypes.js +1 -1
- package/dist/esm/lib/engine/narrative/recorders/ManifestFlowRecorder.d.ts +45 -2
- package/dist/esm/lib/engine/narrative/recorders/ManifestFlowRecorder.js +55 -2
- package/dist/esm/lib/engine/narrative/recorders/index.d.ts +1 -1
- package/dist/esm/lib/engine/narrative/recorders/index.js +1 -1
- package/dist/esm/lib/engine/narrative/types.d.ts +74 -5
- package/dist/esm/lib/engine/narrative/types.js +1 -1
- package/dist/esm/lib/engine/traversal/FlowchartTraverser.d.ts +59 -19
- package/dist/esm/lib/engine/traversal/FlowchartTraverser.js +194 -118
- package/dist/esm/lib/engine/traversalContext.d.ts +7 -2
- package/dist/esm/lib/engine/traversalContext.js +6 -3
- package/dist/esm/lib/engine/types.d.ts +52 -57
- package/dist/esm/lib/engine/types.js +1 -1
- package/dist/esm/lib/errors/terminalFailure.d.ts +29 -0
- package/dist/esm/lib/errors/terminalFailure.js +60 -0
- package/dist/esm/lib/{decide → filter}/evaluator.d.ts +7 -2
- package/dist/esm/lib/filter/evaluator.js +135 -0
- package/dist/esm/lib/ids/idempotencyKey.d.ts +14 -0
- package/dist/esm/lib/ids/idempotencyKey.js +24 -0
- package/dist/esm/lib/memory/StageContext.d.ts +123 -3
- package/dist/esm/lib/memory/StageContext.js +245 -4
- package/dist/esm/lib/memory/attention.d.ts +26 -0
- package/dist/esm/lib/memory/attention.js +171 -0
- package/dist/esm/lib/memory/borrowedMutation.d.ts +8 -0
- package/dist/esm/lib/memory/borrowedMutation.js +14 -1
- package/dist/esm/lib/memory/frameTypes.d.ts +38 -0
- package/dist/esm/lib/memory/frameTypes.js +3 -1
- package/dist/esm/lib/memory/redaction.d.ts +12 -0
- package/dist/esm/lib/memory/redaction.js +54 -5
- package/dist/esm/lib/pause/record.js +10 -1
- package/dist/esm/lib/pause/types.d.ts +19 -0
- package/dist/esm/lib/pause/types.js +17 -1
- package/dist/esm/lib/reactive/createTypedScope.js +3 -1
- package/dist/esm/lib/reactive/types.d.ts +36 -4
- package/dist/esm/lib/reactive/types.js +3 -1
- package/dist/esm/lib/recorder/AttemptRecorder.d.ts +141 -0
- package/dist/esm/lib/recorder/AttemptRecorder.js +412 -0
- package/dist/esm/lib/recorder/ControlDepRecorder.d.ts +36 -2
- package/dist/esm/lib/recorder/ControlDepRecorder.js +50 -2
- package/dist/esm/lib/recorder/EmitRecorder.d.ts +3 -0
- package/dist/esm/lib/recorder/EmitRecorder.js +1 -1
- package/dist/esm/lib/recorder/InOutRecorder.d.ts +37 -1
- package/dist/esm/lib/recorder/InOutRecorder.js +75 -6
- package/dist/esm/lib/recorder/QualityRecorder.d.ts +32 -5
- package/dist/esm/lib/recorder/QualityRecorder.js +87 -29
- package/dist/esm/lib/recorder/TopologyRecorder.d.ts +35 -5
- package/dist/esm/lib/recorder/TopologyRecorder.js +76 -2
- package/dist/esm/lib/recorder/attemptMetricRows.d.ts +11 -0
- package/dist/esm/lib/recorder/attemptMetricRows.js +202 -0
- package/dist/esm/lib/recorder/attemptMetrics.d.ts +7 -0
- package/dist/esm/lib/recorder/attemptMetrics.js +165 -0
- package/dist/esm/lib/recorder/attemptMetricsTypes.d.ts +114 -0
- package/dist/esm/lib/recorder/attemptMetricsTypes.js +2 -0
- package/dist/esm/lib/recorder/attemptOTel.d.ts +78 -0
- package/dist/esm/lib/recorder/attemptOTel.js +107 -0
- package/dist/esm/lib/recorder/attemptSeries.d.ts +81 -0
- package/dist/esm/lib/recorder/attemptSeries.js +103 -0
- package/dist/esm/lib/recorder/hooks.d.ts +9 -0
- package/dist/esm/lib/recorder/hooks.js +4 -1
- package/dist/esm/lib/runner/DeferredObserverTier.js +13 -1
- package/dist/esm/lib/runner/ExecutionRuntime.d.ts +54 -6
- package/dist/esm/lib/runner/ExecutionRuntime.js +57 -5
- package/dist/esm/lib/runner/FlowChartExecutor.d.ts +46 -2
- package/dist/esm/lib/runner/FlowChartExecutor.js +330 -101
- package/dist/esm/lib/runner/RunnableChart.d.ts +6 -0
- package/dist/esm/lib/runner/RunnableChart.js +5 -1
- package/dist/esm/lib/runner/attach.d.ts +2 -1
- package/dist/esm/lib/runner/attach.js +8 -2
- package/dist/esm/lib/runner/checkpoint.js +3 -1
- package/dist/esm/lib/runner/deadline.d.ts +42 -0
- package/dist/esm/lib/runner/deadline.js +90 -0
- package/dist/esm/lib/runner/index.d.ts +3 -1
- package/dist/esm/lib/runner/index.js +2 -1
- package/dist/esm/lib/runner/options.d.ts +17 -0
- package/dist/esm/lib/runner/options.js +3 -1
- package/dist/esm/lib/runner/recordSink.d.ts +128 -0
- package/dist/esm/lib/runner/recordSink.js +296 -0
- package/dist/esm/lib/runner/resume.d.ts +3 -0
- package/dist/esm/lib/runner/resume.js +22 -2
- package/dist/esm/lib/runner/snapshot.d.ts +2 -2
- package/dist/esm/lib/runner/snapshot.js +6 -2
- package/dist/esm/lib/scope/ScopeFacade.d.ts +118 -4
- package/dist/esm/lib/scope/ScopeFacade.js +304 -7
- package/dist/esm/lib/scope/recorders/DebugRecorder.d.ts +17 -3
- package/dist/esm/lib/scope/recorders/DebugRecorder.js +79 -13
- package/dist/esm/lib/scope/recorders/MetricRecorder.d.ts +10 -0
- package/dist/esm/lib/scope/recorders/MetricRecorder.js +15 -2
- package/dist/esm/lib/scope/runtime.d.ts +3 -0
- package/dist/esm/lib/scope/runtime.js +1 -1
- package/dist/esm/lib/scope/types.d.ts +6 -0
- package/dist/esm/lib/scope/types.js +1 -1
- package/dist/esm/lib/sinks/fileSink.d.ts +135 -0
- package/dist/esm/lib/sinks/fileSink.js +387 -0
- package/dist/esm/recorders.d.ts +8 -2
- package/dist/esm/recorders.js +7 -1
- package/dist/esm/sinks.d.ts +23 -0
- package/dist/esm/sinks.js +23 -0
- package/dist/esm/trace.d.ts +2 -2
- package/dist/esm/trace.js +1 -1
- package/dist/index.js +77 -60
- package/dist/lib/attempt/anySignal.js +43 -0
- package/dist/lib/attempt/call.js +134 -0
- package/dist/lib/attempt/category.js +136 -0
- package/dist/lib/attempt/correlation.js +186 -0
- package/dist/lib/attempt/deadline.js +112 -0
- package/dist/lib/attempt/decision.js +139 -0
- package/dist/lib/attempt/effect.js +174 -0
- package/dist/lib/attempt/errors.js +49 -0
- package/dist/lib/attempt/index.js +26 -0
- package/dist/lib/attempt/name.js +48 -0
- package/dist/lib/attempt/observed.js +177 -0
- package/dist/lib/attempt/policy.js +92 -0
- package/dist/lib/attempt/record.js +29 -0
- package/dist/lib/attempt/retryLoopContext.js +31 -0
- package/dist/lib/attempt/retryLoopTypes.js +3 -0
- package/dist/lib/attempt/runner.js +530 -0
- package/dist/lib/attempt/standalone.js +130 -0
- package/dist/lib/attempt/types.js +17 -0
- package/dist/lib/budget/index.js +17 -0
- package/dist/lib/budget/timeBudget.js +674 -0
- package/dist/lib/builder/FlowChartBuilder.js +199 -9
- package/dist/lib/builder/retryLoop.js +287 -0
- package/dist/lib/builder/types.js +1 -1
- package/dist/lib/decide/decide.js +2 -2
- package/dist/lib/decide/index.js +2 -2
- package/dist/lib/decide/types.js +1 -8
- package/dist/lib/engine/graph/StageNode.js +1 -1
- package/dist/lib/engine/graph/prefixNodeTree.js +5 -1
- package/dist/lib/engine/handlers/ChildrenExecutor.js +36 -6
- package/dist/lib/engine/handlers/DeciderHandler.js +7 -3
- package/dist/lib/engine/handlers/ResumeEntry.js +3 -1
- package/dist/lib/engine/handlers/SelectorHandler.js +4 -3
- package/dist/lib/engine/handlers/StageRunner.js +36 -9
- package/dist/lib/engine/handlers/SubflowExecutor.js +24 -5
- package/dist/lib/engine/handlers/commitStage.js +24 -5
- package/dist/lib/engine/handlers/stageError.js +26 -2
- package/dist/lib/engine/index.js +1 -1
- package/dist/lib/engine/narrative/CombinedNarrativeRecorder.js +67 -39
- package/dist/lib/engine/narrative/FlowRecorderDispatcher.js +19 -2
- package/dist/lib/engine/narrative/NarrativeFlowRecorder.js +60 -8
- package/dist/lib/engine/narrative/NullControlFlowNarrativeGenerator.js +2 -1
- package/dist/lib/engine/narrative/formatting/sentences.js +131 -2
- package/dist/lib/engine/narrative/index.js +1 -1
- package/dist/lib/engine/narrative/narrativeTypes.js +1 -1
- package/dist/lib/engine/narrative/recorders/ManifestFlowRecorder.js +55 -2
- package/dist/lib/engine/narrative/recorders/index.js +1 -1
- package/dist/lib/engine/narrative/types.js +1 -1
- package/dist/lib/engine/traversal/FlowchartTraverser.js +192 -116
- package/dist/lib/engine/traversalContext.js +6 -3
- package/dist/lib/engine/types.js +1 -1
- package/dist/lib/errors/terminalFailure.js +64 -0
- package/dist/lib/filter/evaluator.js +139 -0
- package/dist/lib/ids/idempotencyKey.js +28 -0
- package/dist/lib/memory/StageContext.js +246 -5
- package/dist/lib/memory/attention.js +175 -0
- package/dist/lib/memory/borrowedMutation.js +16 -2
- package/dist/lib/memory/frameTypes.js +3 -1
- package/dist/lib/memory/redaction.js +54 -5
- package/dist/lib/pause/record.js +10 -1
- package/dist/lib/pause/types.js +17 -1
- package/dist/lib/reactive/createTypedScope.js +3 -1
- package/dist/lib/reactive/types.js +3 -1
- package/dist/lib/recorder/AttemptRecorder.js +417 -0
- package/dist/lib/recorder/ControlDepRecorder.js +50 -2
- package/dist/lib/recorder/EmitRecorder.js +1 -1
- package/dist/lib/recorder/InOutRecorder.js +75 -6
- package/dist/lib/recorder/QualityRecorder.js +87 -29
- package/dist/lib/recorder/TopologyRecorder.js +76 -2
- package/dist/lib/recorder/attemptMetricRows.js +209 -0
- package/dist/lib/recorder/attemptMetrics.js +174 -0
- package/dist/lib/recorder/attemptMetricsTypes.js +3 -0
- package/dist/lib/recorder/attemptOTel.js +111 -0
- package/dist/lib/recorder/attemptSeries.js +113 -0
- package/dist/lib/recorder/hooks.js +4 -1
- package/dist/lib/runner/DeferredObserverTier.js +13 -1
- package/dist/lib/runner/ExecutionRuntime.js +57 -5
- package/dist/lib/runner/FlowChartExecutor.js +330 -101
- package/dist/lib/runner/RunnableChart.js +5 -1
- package/dist/lib/runner/attach.js +8 -2
- package/dist/lib/runner/checkpoint.js +3 -1
- package/dist/lib/runner/deadline.js +94 -0
- package/dist/lib/runner/index.js +4 -2
- package/dist/lib/runner/options.js +3 -1
- package/dist/lib/runner/recordSink.js +302 -0
- package/dist/lib/runner/resume.js +22 -2
- package/dist/lib/runner/snapshot.js +6 -2
- package/dist/lib/scope/ScopeFacade.js +303 -6
- package/dist/lib/scope/recorders/DebugRecorder.js +79 -13
- package/dist/lib/scope/recorders/MetricRecorder.js +15 -2
- package/dist/lib/scope/runtime.js +1 -1
- package/dist/lib/scope/types.js +1 -1
- package/dist/lib/sinks/fileSink.js +392 -0
- package/dist/recorders.js +10 -2
- package/dist/sinks.js +32 -0
- package/dist/trace.js +1 -1
- package/dist/types/index.d.ts +62 -2
- package/dist/types/lib/attempt/anySignal.d.ts +19 -0
- package/dist/types/lib/attempt/call.d.ts +88 -0
- package/dist/types/lib/attempt/category.d.ts +37 -0
- package/dist/types/lib/attempt/correlation.d.ts +95 -0
- package/dist/types/lib/attempt/deadline.d.ts +44 -0
- package/dist/types/lib/attempt/decision.d.ts +52 -0
- package/dist/types/lib/attempt/effect.d.ts +76 -0
- package/dist/types/lib/attempt/errors.d.ts +41 -0
- package/dist/types/lib/attempt/index.d.ts +18 -0
- package/dist/types/lib/attempt/name.d.ts +21 -0
- package/dist/types/lib/attempt/observed.d.ts +66 -0
- package/dist/types/lib/attempt/policy.d.ts +45 -0
- package/dist/types/lib/attempt/record.d.ts +11 -0
- package/dist/types/lib/attempt/retryLoopContext.d.ts +18 -0
- package/dist/types/lib/attempt/retryLoopTypes.d.ts +18 -0
- package/dist/types/lib/attempt/runner.d.ts +157 -0
- package/dist/types/lib/attempt/standalone.d.ts +47 -0
- package/dist/types/lib/attempt/types.d.ts +453 -0
- package/dist/types/lib/budget/index.d.ts +9 -0
- package/dist/types/lib/budget/timeBudget.d.ts +136 -0
- package/dist/types/lib/builder/FlowChartBuilder.d.ts +88 -3
- package/dist/types/lib/builder/retryLoop.d.ts +56 -0
- package/dist/types/lib/builder/types.d.ts +35 -1
- package/dist/types/lib/decide/index.d.ts +1 -1
- package/dist/types/lib/decide/types.d.ts +3 -0
- package/dist/types/lib/engine/graph/StageNode.d.ts +11 -1
- package/dist/types/lib/engine/handlers/StageRunner.d.ts +8 -1
- package/dist/types/lib/engine/handlers/commitStage.d.ts +7 -0
- package/dist/types/lib/engine/handlers/stageError.d.ts +9 -0
- package/dist/types/lib/engine/index.d.ts +2 -2
- package/dist/types/lib/engine/narrative/CombinedNarrativeRecorder.d.ts +27 -13
- package/dist/types/lib/engine/narrative/FlowRecorderDispatcher.d.ts +4 -1
- package/dist/types/lib/engine/narrative/NarrativeFlowRecorder.d.ts +22 -3
- package/dist/types/lib/engine/narrative/NullControlFlowNarrativeGenerator.d.ts +1 -0
- package/dist/types/lib/engine/narrative/formatting/sentences.d.ts +23 -0
- package/dist/types/lib/engine/narrative/index.d.ts +2 -2
- package/dist/types/lib/engine/narrative/narrativeTypes.d.ts +27 -21
- package/dist/types/lib/engine/narrative/recorders/ManifestFlowRecorder.d.ts +45 -2
- package/dist/types/lib/engine/narrative/recorders/index.d.ts +1 -1
- package/dist/types/lib/engine/narrative/types.d.ts +74 -5
- package/dist/types/lib/engine/traversal/FlowchartTraverser.d.ts +59 -19
- package/dist/types/lib/engine/traversalContext.d.ts +7 -2
- package/dist/types/lib/engine/types.d.ts +52 -57
- package/dist/types/lib/errors/terminalFailure.d.ts +29 -0
- package/dist/types/lib/{decide → filter}/evaluator.d.ts +7 -2
- package/dist/types/lib/ids/idempotencyKey.d.ts +14 -0
- package/dist/types/lib/memory/StageContext.d.ts +123 -3
- package/dist/types/lib/memory/attention.d.ts +26 -0
- package/dist/types/lib/memory/borrowedMutation.d.ts +8 -0
- package/dist/types/lib/memory/frameTypes.d.ts +38 -0
- package/dist/types/lib/memory/redaction.d.ts +12 -0
- package/dist/types/lib/pause/types.d.ts +19 -0
- package/dist/types/lib/reactive/types.d.ts +36 -4
- package/dist/types/lib/recorder/AttemptRecorder.d.ts +141 -0
- package/dist/types/lib/recorder/ControlDepRecorder.d.ts +36 -2
- package/dist/types/lib/recorder/EmitRecorder.d.ts +3 -0
- package/dist/types/lib/recorder/InOutRecorder.d.ts +37 -1
- package/dist/types/lib/recorder/QualityRecorder.d.ts +32 -5
- package/dist/types/lib/recorder/TopologyRecorder.d.ts +35 -5
- package/dist/types/lib/recorder/attemptMetricRows.d.ts +11 -0
- package/dist/types/lib/recorder/attemptMetrics.d.ts +7 -0
- package/dist/types/lib/recorder/attemptMetricsTypes.d.ts +114 -0
- package/dist/types/lib/recorder/attemptOTel.d.ts +78 -0
- package/dist/types/lib/recorder/attemptSeries.d.ts +81 -0
- package/dist/types/lib/recorder/hooks.d.ts +9 -0
- package/dist/types/lib/runner/ExecutionRuntime.d.ts +54 -6
- package/dist/types/lib/runner/FlowChartExecutor.d.ts +46 -2
- package/dist/types/lib/runner/RunnableChart.d.ts +6 -0
- package/dist/types/lib/runner/attach.d.ts +2 -1
- package/dist/types/lib/runner/deadline.d.ts +42 -0
- package/dist/types/lib/runner/index.d.ts +3 -1
- package/dist/types/lib/runner/options.d.ts +17 -0
- package/dist/types/lib/runner/recordSink.d.ts +128 -0
- package/dist/types/lib/runner/resume.d.ts +3 -0
- package/dist/types/lib/runner/snapshot.d.ts +2 -2
- package/dist/types/lib/scope/ScopeFacade.d.ts +118 -4
- package/dist/types/lib/scope/recorders/DebugRecorder.d.ts +17 -3
- package/dist/types/lib/scope/recorders/MetricRecorder.d.ts +10 -0
- package/dist/types/lib/scope/runtime.d.ts +3 -0
- package/dist/types/lib/scope/types.d.ts +6 -0
- package/dist/types/lib/sinks/fileSink.d.ts +135 -0
- package/dist/types/recorders.d.ts +8 -2
- package/dist/types/sinks.d.ts +23 -0
- package/dist/types/trace.d.ts +2 -2
- package/package.json +20 -6
- package/dist/esm/lib/decide/evaluator.js +0 -130
- package/dist/lib/decide/evaluator.js +0 -134
|
@@ -0,0 +1,666 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* budget/timeBudget.ts — `timeBudget(chart)`: the slowest a chart can take, from what it declares (design
|
|
3
|
+
* docs/design/2026-10-time-and-failure-evidence.md §3.2, packet P5).
|
|
4
|
+
*
|
|
5
|
+
* WHY: a retry policy is a promise about time. `{ attempts: 4, timeoutMs: 40_000, backoffMs: 1_000 }` allows
|
|
6
|
+
* 4 × 40 000 + 3 × 1 000 = 163 000 ms, and a caller who gave the chart 120 s is not served by it — which is
|
|
7
|
+
* knowable before a single stage runs. `.budget(ms)` declares the caller's contract on the chart; `build()` refuses
|
|
8
|
+
* a chart whose declared policies already allow longer (owner ruling Q2) and warns, by name, about every stage it
|
|
9
|
+
* cannot bound. An unbounded stage is never guessed around: it is counted as 0 and named.
|
|
10
|
+
*
|
|
11
|
+
* THE RULES (one walk of the built StageNode graph; each chain of `next` pointers is computed once per start):
|
|
12
|
+
* - a stage with a function: `attempts × timeoutMs` plus the waits between its attempts, as the runner waits them
|
|
13
|
+
* (`attempt/policy.ts`). A number `backoffMs` is arithmetic, under `maxBackoffMs` when declared. A FUNCTION is
|
|
14
|
+
* never asked: it may read the error (a stated `Retry-After`) and no error exists here, so asking it with none
|
|
15
|
+
* could UNDERESTIMATE. It counts at its declared ceiling, `maxBackoffMs` per wait (the runner enforces it); with
|
|
16
|
+
* no ceiling the stage is unbounded `'backoff'`. No `timeoutMs` → unbounded `'no-timeout'`;
|
|
17
|
+
* - a sequence: the sum. A decider, a selector, a fork: the node's own stage plus its slowest child (a fork's
|
|
18
|
+
* children, and a selector's picks, run at once);
|
|
19
|
+
* - a mounted subflow: its chart, walked the same way, under the ids the run gives its stages (`pay/charge`);
|
|
20
|
+
* a lazy one is unbounded `'lazy-subflow'` unless `assume.lazy[subflowId]` names the chart it resolves to;
|
|
21
|
+
* - `parallelForEach`: ONE branch — the branches run at once and `maxBranches` truncates, so the item count never
|
|
22
|
+
* adds time. The branch chart is built at run time, so it is unbounded `'items'` unless
|
|
23
|
+
* `assume.branches[stageId]` names it (its stages are reported under the first branch, `review~0/score`);
|
|
24
|
+
* - a loop is NEVER iterated. With no assumption it is unbounded `'loop'`, named by its target, and counted once.
|
|
25
|
+
* `assume.loops[targetId] = n` bounds it: each time the chart reaches the loop, every stage from the target to
|
|
26
|
+
* the loop's furthest source runs at most `n` times, each at its slowest. Nested loops multiply; two loops that
|
|
27
|
+
* overlap without nesting are one region bounded by the product of their passes (each can re-enter the other).
|
|
28
|
+
*
|
|
29
|
+
* TWO NUMBERS. `knownMs` counts what is bounded (an unbounded stage as 0, an unassumed loop once). Without
|
|
30
|
+
* assumptions it is a time the declared policies ALLOW a run to take (`retryOn` is not read: it may only end a series
|
|
31
|
+
* sooner), so a budget below it cannot be promised — `over` and the build refusal read it, on an unbounded path too.
|
|
32
|
+
* `worstCaseMs` is `knownMs` when every path is bounded, `null` otherwise; with an assumed loop it is an upper bound
|
|
33
|
+
* under that assumption (every pass is counted at its slowest branch).
|
|
34
|
+
*
|
|
35
|
+
* THREAT MODEL. The walk terminates on any graph: a chain is walked with a visited set (a `next` that closes on
|
|
36
|
+
* itself is a loop), nesting is an explicit stack (no recursion — a 5 000-deep subflow nesting walks), a chain that
|
|
37
|
+
* reaches itself through its children or a subflow is a loop, and every chain is computed once per start however
|
|
38
|
+
* often it is mounted. The walk is CAPPED: past `MAX_WALK` node visits it stops with a `RangeError` — a builder chart
|
|
39
|
+
* visits each node at most twice, but a hand-built graph whose chains share their tails is walked once per chain.
|
|
40
|
+
* Sums and products saturate at `Number.MAX_SAFE_INTEGER` — never `Infinity` or `NaN`. Assumptions are copied ONCE,
|
|
41
|
+
* own enumerable properties only, into fresh null-prototype records, and only that copy is read.
|
|
42
|
+
*
|
|
43
|
+
* What it does NOT count: the engine's own work between stages, a stage function that blocks the thread (a timeout
|
|
44
|
+
* stops the WAITING, see the attempt runner), and a StageNode a stage returns at run time — any stage may grow the
|
|
45
|
+
* graph that way, so the budget is of the graph the chart DECLARES.
|
|
46
|
+
*/
|
|
47
|
+
import { joinPath } from 'foottrace';
|
|
48
|
+
import { attemptCeiling, attemptTimeoutMs, backoffCeilingMs, cappedWaitMs } from '../attempt/policy.js';
|
|
49
|
+
import { retryLoopBudget } from '../attempt/retryLoopContext.js';
|
|
50
|
+
import { resolveBackoffMs } from '../attempt/runner.js';
|
|
51
|
+
import { isDevMode } from '../devMode.js';
|
|
52
|
+
import { buildBranchSegment } from '../ids/branchSegment.js';
|
|
53
|
+
/**
|
|
54
|
+
* The most node visits one walk makes. A builder chart visits each node at most twice, so 250 000 is far past any
|
|
55
|
+
* real chart; a hand-built graph whose chains share their tails can need more (each chain walks the shared tail),
|
|
56
|
+
* and the check stops there with a `RangeError` rather than grow without bound.
|
|
57
|
+
*/
|
|
58
|
+
export const MAX_WALK = 250_000;
|
|
59
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
60
|
+
// The entry points
|
|
61
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
62
|
+
/**
|
|
63
|
+
* The slowest the chart can take, computed from its declared retry policies — and every stage that makes a path
|
|
64
|
+
* unbounded, by name. See the module header for the rules.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```ts
|
|
68
|
+
* const report = timeBudget(chart, { budgetMs: 120_000, assume: { loops: { 'ask-again': 3 } } });
|
|
69
|
+
* report.worstCaseMs; // number, or null when a path is unbounded
|
|
70
|
+
* report.criticalPath; // [{ stageId, attempts, timeoutMs, backoffMs, worstMs, passes }]
|
|
71
|
+
* report.unbounded; // [{ stageId, why: 'no-timeout' | 'backoff' | 'loop' | 'lazy-subflow' | 'items' }]
|
|
72
|
+
* report.over; // true when the declared policies allow longer than budgetMs
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
export function timeBudget(chart, options) {
|
|
76
|
+
if (!isChart(chart)) {
|
|
77
|
+
throw new TypeError('timeBudget(chart): pass a built chart — the result of flowChart(...).build().');
|
|
78
|
+
}
|
|
79
|
+
if (options?.budgetMs !== undefined && !isPositiveMs(options.budgetMs)) {
|
|
80
|
+
throw new TypeError('timeBudget: budgetMs must be a number of milliseconds > 0, at most Number.MAX_SAFE_INTEGER ' +
|
|
81
|
+
`(got ${shown(options.budgetMs)}).`);
|
|
82
|
+
}
|
|
83
|
+
const budgetMs = options?.budgetMs ?? declaredBudget(chart);
|
|
84
|
+
const walk = new BudgetWalk(admitAssumptions(options?.assume));
|
|
85
|
+
const ctx = walk.ctxOf(chart, '');
|
|
86
|
+
const root = walk.evaluate({ ctx, start: chart.root });
|
|
87
|
+
// A loop whose target the chart does not hold cannot be bounded by any assumption.
|
|
88
|
+
const rootFlags = [...root.open].map((target) => ({ stageId: reported(ctx, target), why: 'loop' }));
|
|
89
|
+
const bounded = root.bounded && root.open.size === 0;
|
|
90
|
+
return Object.freeze({
|
|
91
|
+
worstCaseMs: bounded ? root.known : null,
|
|
92
|
+
knownMs: root.known,
|
|
93
|
+
criticalPath: Object.freeze(criticalPathOf(root, walk.computed)),
|
|
94
|
+
unbounded: Object.freeze(unboundedOf(root, rootFlags)),
|
|
95
|
+
...(budgetMs !== undefined && { budgetMs }),
|
|
96
|
+
over: budgetMs !== undefined && root.known > budgetMs,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
/** The chart's declared budget (`.budget(ms)`, the spec root's `budgetMs`), or `undefined`. */
|
|
100
|
+
export function declaredBudget(chart) {
|
|
101
|
+
const budgetMs = chart.buildTimeStructure?.budgetMs;
|
|
102
|
+
return isPositiveMs(budgetMs) ? budgetMs : undefined;
|
|
103
|
+
}
|
|
104
|
+
/** `build()`'s refusal for a declared budget the chart can already exceed, or `undefined` when it can keep it. */
|
|
105
|
+
export function budgetRefusal(report) {
|
|
106
|
+
if (!report.over || report.budgetMs === undefined)
|
|
107
|
+
return undefined;
|
|
108
|
+
const counted = report.criticalPath.filter((step) => contribution(step) > 0);
|
|
109
|
+
const shownSteps = slowestInPathOrder(counted, 5).map(stepText);
|
|
110
|
+
const more = counted.length > shownSteps.length ? `, and ${counted.length - shownSteps.length} more` : '';
|
|
111
|
+
const uncounted = report.unbounded.length > 0 ? ` Not counted, having no bound: ${unboundedText(report.unbounded)}.` : '';
|
|
112
|
+
return (`budget(${report.budgetMs}): its declared policies allow ${report.knownMs} ms, over its budget by ` +
|
|
113
|
+
`${report.knownMs - report.budgetMs} ms. Slowest path: ${shownSteps.join('; ')}${more}. Lower attempts or ` +
|
|
114
|
+
`timeoutMs on these stages, or raise the budget.${uncounted}`);
|
|
115
|
+
}
|
|
116
|
+
/** `build()`'s dev-mode warning for a declared budget it cannot check on every path, or `undefined`. */
|
|
117
|
+
export function budgetWarning(report, chartName) {
|
|
118
|
+
if (report.budgetMs === undefined || report.unbounded.length === 0)
|
|
119
|
+
return undefined;
|
|
120
|
+
return (`[footprint] chart '${chartName}' declares a budget of ${report.budgetMs} ms, but the check cannot bound ` +
|
|
121
|
+
`every path: ${unboundedText(report.unbounded)}. Give a stage a retry({ timeoutMs }) and a function backoff a ` +
|
|
122
|
+
'maxBackoffMs; bound a loop, a lazy subflow or a parallelForEach with timeBudget(chart, { assume }).');
|
|
123
|
+
}
|
|
124
|
+
/** Charts already warned at run start — the warning is said once per chart. */
|
|
125
|
+
const warnedAtRunStart = new WeakSet();
|
|
126
|
+
/**
|
|
127
|
+
* The run-start warning (dev mode, once per chart): the run's deadline leaves the chart less time than its declared
|
|
128
|
+
* budget, so a run that takes the time the chart declares will be cut short. `startedAt` is read BEFORE the run's
|
|
129
|
+
* deadline is armed, so `timeoutMs` equal to the budget never warns.
|
|
130
|
+
*/
|
|
131
|
+
export function warnDeadlineUnderBudget(chart, deadline, startedAt) {
|
|
132
|
+
if (deadline === undefined || !isDevMode())
|
|
133
|
+
return;
|
|
134
|
+
const budgetMs = declaredBudget(chart);
|
|
135
|
+
if (budgetMs === undefined)
|
|
136
|
+
return;
|
|
137
|
+
const leftMs = deadline - startedAt;
|
|
138
|
+
if (leftMs >= budgetMs || warnedAtRunStart.has(chart))
|
|
139
|
+
return;
|
|
140
|
+
warnedAtRunStart.add(chart);
|
|
141
|
+
// eslint-disable-next-line no-console
|
|
142
|
+
console.warn(`[footprint] this run's deadline leaves ${Math.max(0, leftMs)} ms, less than the chart's declared budget of ` +
|
|
143
|
+
`${budgetMs} ms ('${chart.root.name}'): a run that takes the time the chart declares will be cut short. Give ` +
|
|
144
|
+
'the run its budget, or declare a smaller one.');
|
|
145
|
+
}
|
|
146
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
147
|
+
// The walk
|
|
148
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
149
|
+
const IN_PROGRESS = Symbol('in-progress');
|
|
150
|
+
const NONE = { kind: 'none' };
|
|
151
|
+
const EMPTY = new Set();
|
|
152
|
+
class BudgetWalk {
|
|
153
|
+
assume;
|
|
154
|
+
/** Every chain, in the order computed: each one after every chain it runs inside itself. */
|
|
155
|
+
computed = [];
|
|
156
|
+
ctxs = new Map();
|
|
157
|
+
/** Node visits so far — capped at `MAX_WALK`. */
|
|
158
|
+
walked = 0;
|
|
159
|
+
constructor(assume) {
|
|
160
|
+
this.assume = assume;
|
|
161
|
+
}
|
|
162
|
+
/** The chain from `start` — every node visit counted against `MAX_WALK`. */
|
|
163
|
+
chainOf(start) {
|
|
164
|
+
const nodes = [];
|
|
165
|
+
const seen = new Set();
|
|
166
|
+
let cur = start;
|
|
167
|
+
while (isNode(cur)) {
|
|
168
|
+
if (cur.isLoopRef)
|
|
169
|
+
return { nodes, backId: String(cur.id) };
|
|
170
|
+
if (seen.has(cur))
|
|
171
|
+
return { nodes, backTo: cur };
|
|
172
|
+
if (++this.walked > MAX_WALK) {
|
|
173
|
+
throw new RangeError(`timeBudget: the walk passed ${MAX_WALK} node visits and stopped. A builder chart visits each node at ` +
|
|
174
|
+
'most twice; a hand-built graph whose chains share their tails walks the shared tail once per chain. ' +
|
|
175
|
+
'The budget of this graph cannot be computed.');
|
|
176
|
+
}
|
|
177
|
+
seen.add(cur);
|
|
178
|
+
nodes.push(cur);
|
|
179
|
+
cur = cur.next;
|
|
180
|
+
}
|
|
181
|
+
return { nodes };
|
|
182
|
+
}
|
|
183
|
+
ctxOf(owner, prefix) {
|
|
184
|
+
let byPrefix = this.ctxs.get(owner);
|
|
185
|
+
if (byPrefix === undefined) {
|
|
186
|
+
byPrefix = new Map();
|
|
187
|
+
this.ctxs.set(owner, byPrefix);
|
|
188
|
+
}
|
|
189
|
+
let ctx = byPrefix.get(prefix);
|
|
190
|
+
if (ctx === undefined) {
|
|
191
|
+
ctx = { subflows: owner.subflows, stageMap: owner.stageMap, prefix, memo: new Map() };
|
|
192
|
+
byPrefix.set(prefix, ctx);
|
|
193
|
+
}
|
|
194
|
+
return ctx;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Compute `root` and every chain it runs — an explicit stack, never recursion. A chain is marked in progress on
|
|
198
|
+
* its first visit and pushes the chains it needs; it is computed on its second, when they are done. A chain that
|
|
199
|
+
* needs one still in progress needs itself: an object cycle, counted as a loop.
|
|
200
|
+
*/
|
|
201
|
+
evaluate(root) {
|
|
202
|
+
const stack = [root];
|
|
203
|
+
while (stack.length > 0) {
|
|
204
|
+
const ref = stack[stack.length - 1];
|
|
205
|
+
const state = ref.ctx.memo.get(ref.start);
|
|
206
|
+
if (state !== undefined && state !== IN_PROGRESS) {
|
|
207
|
+
stack.pop();
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
const nodes = this.chainOf(ref.start);
|
|
211
|
+
const insides = nodes.nodes.map((node) => this.insideOf(node, ref.ctx));
|
|
212
|
+
if (state === undefined) {
|
|
213
|
+
ref.ctx.memo.set(ref.start, IN_PROGRESS);
|
|
214
|
+
const before = stack.length;
|
|
215
|
+
for (const inside of insides) {
|
|
216
|
+
if (inside.kind !== 'chains')
|
|
217
|
+
continue;
|
|
218
|
+
for (const dep of inside.refs)
|
|
219
|
+
if (!dep.ctx.memo.has(dep.start))
|
|
220
|
+
stack.push(dep);
|
|
221
|
+
}
|
|
222
|
+
if (stack.length > before)
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
stack.pop();
|
|
226
|
+
const chain = this.chainResult(ref.ctx, nodes, insides);
|
|
227
|
+
ref.ctx.memo.set(ref.start, chain);
|
|
228
|
+
this.computed.push(chain);
|
|
229
|
+
}
|
|
230
|
+
return root.ctx.memo.get(root.start);
|
|
231
|
+
}
|
|
232
|
+
insideOf(node, ctx) {
|
|
233
|
+
if (node.isDynamicParallel) {
|
|
234
|
+
const stageId = reported(ctx, node.id);
|
|
235
|
+
const chart = own(this.assume.branches, stageId);
|
|
236
|
+
if (chart === undefined)
|
|
237
|
+
return { kind: 'unbounded', why: 'items', stageId };
|
|
238
|
+
const branch = buildBranchSegment(stageId, 0);
|
|
239
|
+
return { kind: 'chains', refs: [{ ctx: this.ctxOf(chart, branch), start: chart.root }], boundary: true };
|
|
240
|
+
}
|
|
241
|
+
if (isMount(node))
|
|
242
|
+
return this.mountOf(node, ctx);
|
|
243
|
+
const children = childrenOf(node);
|
|
244
|
+
if (children.length > 0)
|
|
245
|
+
return { kind: 'chains', refs: children.map((start) => ({ ctx, start })), boundary: false };
|
|
246
|
+
return NONE;
|
|
247
|
+
}
|
|
248
|
+
/** A subflow mount — resolved the way the engine resolves it (`NodeResolver · resolveSubflowReference`). */
|
|
249
|
+
mountOf(node, ctx) {
|
|
250
|
+
const subflowId = reported(ctx, String(node.subflowId));
|
|
251
|
+
if (node.subflowResolver !== undefined) {
|
|
252
|
+
const chart = own(this.assume.lazy, subflowId);
|
|
253
|
+
if (chart === undefined)
|
|
254
|
+
return { kind: 'unbounded', why: 'lazy-subflow', stageId: subflowId };
|
|
255
|
+
return { kind: 'chains', refs: [{ ctx: this.ctxOf(chart, subflowId), start: chart.root }], boundary: true };
|
|
256
|
+
}
|
|
257
|
+
const inline = node.subflowDef;
|
|
258
|
+
if (inline?.root !== undefined) {
|
|
259
|
+
return {
|
|
260
|
+
kind: 'chains',
|
|
261
|
+
refs: [{ ctx: this.ctxOf(inline, ctx.prefix), start: inline.root }],
|
|
262
|
+
boundary: true,
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
const def = subflowDefOf(ctx.subflows, node);
|
|
266
|
+
return def === undefined ? NONE : { kind: 'chains', refs: [{ ctx, start: def.root }], boundary: true };
|
|
267
|
+
}
|
|
268
|
+
chainResult(ctx, shape, insides) {
|
|
269
|
+
const { nodes } = shape;
|
|
270
|
+
const at = new Map();
|
|
271
|
+
nodes.forEach((node, i) => {
|
|
272
|
+
if (!at.has(node.id))
|
|
273
|
+
at.set(node.id, i);
|
|
274
|
+
});
|
|
275
|
+
const backEdges = [];
|
|
276
|
+
const open = new Set();
|
|
277
|
+
// A jump to a target this chain holds at or before `from` is a loop over [target, from]; a forward jump repeats
|
|
278
|
+
// nothing; a target the chain does not hold is the enclosing chain's to resolve.
|
|
279
|
+
const jump = (target, from) => {
|
|
280
|
+
const j = at.get(target);
|
|
281
|
+
if (j === undefined)
|
|
282
|
+
open.add(target);
|
|
283
|
+
else if (j <= from)
|
|
284
|
+
backEdges.push([j, from]);
|
|
285
|
+
};
|
|
286
|
+
let bounded = true;
|
|
287
|
+
const positions = nodes.map((node, q) => {
|
|
288
|
+
const stageId = reported(ctx, node.id);
|
|
289
|
+
const flags = [];
|
|
290
|
+
// A mount runs its subflow in place of a function of its own (the engine never asks its stage map).
|
|
291
|
+
const cost = !isMount(node) && hasFunction(node, ctx) ? helperCost(retryLoopBudget(node), node.retry) : undefined;
|
|
292
|
+
if (cost?.why !== undefined)
|
|
293
|
+
flags.push({ stageId, why: cost.why });
|
|
294
|
+
const inner = this.innerOf(insides[q], flags);
|
|
295
|
+
for (const target of inner.open)
|
|
296
|
+
jump(target, q);
|
|
297
|
+
if (cost?.worstMs === null || !inner.bounded)
|
|
298
|
+
bounded = false;
|
|
299
|
+
return {
|
|
300
|
+
stageId,
|
|
301
|
+
cost,
|
|
302
|
+
innerKnown: inner.known,
|
|
303
|
+
via: inner.via,
|
|
304
|
+
deps: inner.deps,
|
|
305
|
+
flags,
|
|
306
|
+
multiplier: 1,
|
|
307
|
+
declaredPasses: retryLoopBudget(node)?.passes,
|
|
308
|
+
};
|
|
309
|
+
});
|
|
310
|
+
if (shape.backTo !== undefined)
|
|
311
|
+
backEdges.push([nodes.indexOf(shape.backTo), nodes.length - 1]);
|
|
312
|
+
if (shape.backId !== undefined)
|
|
313
|
+
jump(shape.backId, nodes.length - 1);
|
|
314
|
+
if (!this.applyLoops(positions, backEdges))
|
|
315
|
+
bounded = false;
|
|
316
|
+
let known = 0;
|
|
317
|
+
for (const p of positions)
|
|
318
|
+
known = add(known, mul(p.multiplier, add(p.cost?.knownMs ?? 0, p.innerKnown)));
|
|
319
|
+
return { known, bounded, open, positions };
|
|
320
|
+
}
|
|
321
|
+
/** The slowest of the chains a node runs inside itself (they are alternatives, or run at once). */
|
|
322
|
+
innerOf(inside, flags) {
|
|
323
|
+
if (inside.kind === 'none')
|
|
324
|
+
return { known: 0, bounded: true, deps: [], open: EMPTY };
|
|
325
|
+
if (inside.kind === 'unbounded') {
|
|
326
|
+
flags.push({ stageId: inside.stageId, why: inside.why });
|
|
327
|
+
return { known: 0, bounded: false, deps: [], open: EMPTY };
|
|
328
|
+
}
|
|
329
|
+
let via;
|
|
330
|
+
let bounded = true;
|
|
331
|
+
const deps = [];
|
|
332
|
+
const open = new Set();
|
|
333
|
+
for (const ref of inside.refs) {
|
|
334
|
+
const chain = ref.ctx.memo.get(ref.start);
|
|
335
|
+
if (chain === undefined || chain === IN_PROGRESS) {
|
|
336
|
+
flags.push({ stageId: reported(ref.ctx, ref.start.id), why: 'loop' });
|
|
337
|
+
bounded = false;
|
|
338
|
+
continue;
|
|
339
|
+
}
|
|
340
|
+
deps.push(chain);
|
|
341
|
+
if (!chain.bounded)
|
|
342
|
+
bounded = false;
|
|
343
|
+
for (const target of chain.open) {
|
|
344
|
+
if (!inside.boundary) {
|
|
345
|
+
open.add(target);
|
|
346
|
+
continue;
|
|
347
|
+
}
|
|
348
|
+
// A subflow's own traverser looks its loop targets up in its own chart: one it does not hold never resolves.
|
|
349
|
+
flags.push({ stageId: reported(ref.ctx, target), why: 'loop' });
|
|
350
|
+
bounded = false;
|
|
351
|
+
}
|
|
352
|
+
if (via === undefined || chain.known > via.known)
|
|
353
|
+
via = chain;
|
|
354
|
+
}
|
|
355
|
+
return { known: via?.known ?? 0, bounded, ...(via !== undefined && { via }), deps, open };
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Turn a chain's back-edges into each position's multiplier. One loop per target, spanning to its furthest
|
|
359
|
+
* source. Loops are taken in start order on a stack of nested ones; a loop that overlaps the one it starts inside
|
|
360
|
+
* without nesting merges with it (the product of their passes — each can re-enter the other), so what is left is
|
|
361
|
+
* laminar, and one sweep multiplies every position by the loops around it. Returns false when a loop has no
|
|
362
|
+
* assumed passes (it is flagged on its target and counted once).
|
|
363
|
+
*/
|
|
364
|
+
applyLoops(positions, backEdges) {
|
|
365
|
+
if (backEdges.length === 0)
|
|
366
|
+
return true;
|
|
367
|
+
const ends = new Map();
|
|
368
|
+
for (const [target, source] of backEdges)
|
|
369
|
+
ends.set(target, Math.max(ends.get(target) ?? target, source));
|
|
370
|
+
let bounded = true;
|
|
371
|
+
const done = [];
|
|
372
|
+
const active = [];
|
|
373
|
+
for (const [start, end] of [...ends].sort((a, b) => a[0] - b[0])) {
|
|
374
|
+
const target = positions[start];
|
|
375
|
+
const assumed = own(this.assume.loops, target.stageId);
|
|
376
|
+
const passes = target.declaredPasses === undefined ? assumed : Math.max(target.declaredPasses, assumed ?? 1);
|
|
377
|
+
if (passes === undefined) {
|
|
378
|
+
target.flags.push({ stageId: target.stageId, why: 'loop' });
|
|
379
|
+
bounded = false;
|
|
380
|
+
}
|
|
381
|
+
// The active loops nest (each inside the one below it): the innermost ends first.
|
|
382
|
+
let top = lastOf(active);
|
|
383
|
+
while (top !== undefined && top.end < start) {
|
|
384
|
+
done.push(top);
|
|
385
|
+
active.pop();
|
|
386
|
+
top = lastOf(active);
|
|
387
|
+
}
|
|
388
|
+
// Starts inside `top` and ends past it: they overlap without nesting — one region, the product of passes.
|
|
389
|
+
let loop = { start, end, passes: passes ?? 1 };
|
|
390
|
+
while (top !== undefined && top.end < loop.end) {
|
|
391
|
+
active.pop();
|
|
392
|
+
loop = { start: top.start, end: loop.end, passes: mul(top.passes, loop.passes) };
|
|
393
|
+
top = lastOf(active);
|
|
394
|
+
}
|
|
395
|
+
active.push(loop);
|
|
396
|
+
}
|
|
397
|
+
done.push(...active);
|
|
398
|
+
done.sort((a, b) => a.start - b.start || b.end - a.end);
|
|
399
|
+
const around = [];
|
|
400
|
+
let next = 0;
|
|
401
|
+
for (let q = 0; q < positions.length; q++) {
|
|
402
|
+
while (around.length > 0 && around[around.length - 1].end < q)
|
|
403
|
+
around.pop();
|
|
404
|
+
while (next < done.length && done[next].start === q) {
|
|
405
|
+
const outer = around.length > 0 ? around[around.length - 1].product : 1;
|
|
406
|
+
around.push({ end: done[next].end, product: mul(outer, done[next].passes) });
|
|
407
|
+
next++;
|
|
408
|
+
}
|
|
409
|
+
positions[q].multiplier = around.length > 0 ? around[around.length - 1].product : 1;
|
|
410
|
+
}
|
|
411
|
+
return bounded;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
415
|
+
// One stage
|
|
416
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
417
|
+
/**
|
|
418
|
+
* The engine's mount test (`FlowchartTraverser` Phase 0 with `NodeResolver · resolveSubflowReference`): a subflow
|
|
419
|
+
* root with a subflow id runs its subflow — a lazy one always, an eager one when it has no function of its OWN and no
|
|
420
|
+
* children (the resolver never asks the stage map). Anything else is a node like any other.
|
|
421
|
+
*/
|
|
422
|
+
function isMount(node) {
|
|
423
|
+
if (node.isSubflowRoot !== true || typeof node.subflowId !== 'string' || node.subflowId === '')
|
|
424
|
+
return false;
|
|
425
|
+
return node.subflowResolver !== undefined || (typeof node.fn !== 'function' && childrenOf(node).length === 0);
|
|
426
|
+
}
|
|
427
|
+
/** A node's children that are nodes — a hand-built `null` is skipped, never dereferenced. */
|
|
428
|
+
function childrenOf(node) {
|
|
429
|
+
return Array.isArray(node.children) ? node.children.filter(isNode) : [];
|
|
430
|
+
}
|
|
431
|
+
const isNode = (value) => value !== null && typeof value === 'object';
|
|
432
|
+
/** The engine's lookup (`FlowchartTraverser · getStageFn`): the node's own function, else the map's by id or name. */
|
|
433
|
+
function hasFunction(node, ctx) {
|
|
434
|
+
if (typeof node.fn === 'function')
|
|
435
|
+
return true;
|
|
436
|
+
const map = ctx.stageMap;
|
|
437
|
+
return map !== undefined && (map.get(node.id) !== undefined || map.get(node.name) !== undefined);
|
|
438
|
+
}
|
|
439
|
+
/** A stage's worst case under its policy — read by the engine's own readings of it (`attempt/policy.ts`). */
|
|
440
|
+
function helperCost(budget, policy) {
|
|
441
|
+
if (budget === undefined)
|
|
442
|
+
return stageCost(policy);
|
|
443
|
+
if (budget.role === 'callback')
|
|
444
|
+
return stageCost({ attempts: 1, timeoutMs: budget.timeoutMs });
|
|
445
|
+
const ms = budget.role === 'control' ? 0 : budget.waitMs;
|
|
446
|
+
return {
|
|
447
|
+
attempts: 1,
|
|
448
|
+
timeoutMs: ms ?? 0,
|
|
449
|
+
backoffMs: 0,
|
|
450
|
+
knownMs: ms ?? 0,
|
|
451
|
+
worstMs: ms ?? null,
|
|
452
|
+
...(ms === undefined ? { why: 'backoff' } : {}),
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
function stageCost(policy) {
|
|
456
|
+
const attempts = policy === undefined ? 1 : attemptCeiling(policy.attempts);
|
|
457
|
+
const timeoutMs = policy === undefined ? undefined : attemptTimeoutMs(policy.timeoutMs);
|
|
458
|
+
const waits = waitsOf(policy, attempts);
|
|
459
|
+
const knownMs = add(timeoutMs === undefined ? 0 : mul(attempts, timeoutMs), waits.ms);
|
|
460
|
+
const why = timeoutMs === undefined ? 'no-timeout' : waits.known ? undefined : 'backoff';
|
|
461
|
+
return {
|
|
462
|
+
attempts,
|
|
463
|
+
...(timeoutMs !== undefined && { timeoutMs }),
|
|
464
|
+
backoffMs: waits.ms,
|
|
465
|
+
knownMs,
|
|
466
|
+
worstMs: why === undefined ? knownMs : null,
|
|
467
|
+
...(why !== undefined && { why }),
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* The waits between `attempts` attempts, as the runner waits them (`attempt/policy.ts · cappedWaitMs`). A number
|
|
472
|
+
* backoff is arithmetic, under the declared ceiling. A function backoff is NEVER asked — its answer may depend on the
|
|
473
|
+
* error, and no error exists here — so it counts at its declared ceiling per wait, or, with none, is not known
|
|
474
|
+
* (its waits count 0 and the stage is unbounded).
|
|
475
|
+
*/
|
|
476
|
+
function waitsOf(policy, attempts) {
|
|
477
|
+
const waits = attempts - 1;
|
|
478
|
+
const backoffMs = policy?.backoffMs;
|
|
479
|
+
if (waits <= 0 || backoffMs === undefined)
|
|
480
|
+
return { ms: 0, known: true };
|
|
481
|
+
if (typeof backoffMs === 'function') {
|
|
482
|
+
const ceiling = backoffCeilingMs(policy?.maxBackoffMs);
|
|
483
|
+
return ceiling === undefined ? { ms: 0, known: false } : { ms: mul(waits, ceiling), known: true };
|
|
484
|
+
}
|
|
485
|
+
return { ms: mul(waits, cappedWaitMs(resolveBackoffMs(backoffMs, 1), policy?.maxBackoffMs)), known: true };
|
|
486
|
+
}
|
|
487
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
488
|
+
// The report
|
|
489
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
490
|
+
/**
|
|
491
|
+
* The slowest path: how many times each chain on it runs (parents before children — the reverse of the order they
|
|
492
|
+
* were computed in), then its stages in the order a run first reaches them. Each chain is visited once, so a
|
|
493
|
+
* definition mounted twice at every level of a deep nesting is one step with its passes multiplied.
|
|
494
|
+
*/
|
|
495
|
+
function criticalPathOf(root, computed) {
|
|
496
|
+
const runs = new Map([[root, 1]]);
|
|
497
|
+
for (let i = computed.length - 1; i >= 0; i--) {
|
|
498
|
+
const chain = computed[i];
|
|
499
|
+
const count = runs.get(chain);
|
|
500
|
+
if (count === undefined)
|
|
501
|
+
continue;
|
|
502
|
+
for (const p of chain.positions) {
|
|
503
|
+
if (p.via !== undefined)
|
|
504
|
+
runs.set(p.via, add(runs.get(p.via) ?? 0, mul(count, p.multiplier)));
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
const steps = new Map();
|
|
508
|
+
walkPositions(root, (p) => p.via, (chain, p) => {
|
|
509
|
+
if (p.cost === undefined)
|
|
510
|
+
return;
|
|
511
|
+
const passes = mul(runs.get(chain) ?? 0, p.multiplier);
|
|
512
|
+
const step = steps.get(p.stageId);
|
|
513
|
+
if (step !== undefined) {
|
|
514
|
+
step.passes = add(step.passes, passes);
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
517
|
+
steps.set(p.stageId, {
|
|
518
|
+
stageId: p.stageId,
|
|
519
|
+
attempts: p.cost.attempts,
|
|
520
|
+
...(p.cost.timeoutMs !== undefined && { timeoutMs: p.cost.timeoutMs }),
|
|
521
|
+
backoffMs: p.cost.backoffMs,
|
|
522
|
+
worstMs: p.cost.worstMs,
|
|
523
|
+
passes,
|
|
524
|
+
});
|
|
525
|
+
});
|
|
526
|
+
return [...steps.values()].map((step) => Object.freeze(step));
|
|
527
|
+
}
|
|
528
|
+
/** Every unbounded stage, once, in the order a walk of the whole chart reaches it. */
|
|
529
|
+
function unboundedOf(root, rootFlags) {
|
|
530
|
+
const out = [];
|
|
531
|
+
const seen = new Set();
|
|
532
|
+
const note = (flag) => {
|
|
533
|
+
const key = `${flag.why}\u0000${flag.stageId}`;
|
|
534
|
+
if (seen.has(key))
|
|
535
|
+
return;
|
|
536
|
+
seen.add(key);
|
|
537
|
+
out.push(Object.freeze({ stageId: flag.stageId, why: flag.why }));
|
|
538
|
+
};
|
|
539
|
+
walkPositions(root, (p) => p.deps, (_chain, p) => p.flags.forEach(note));
|
|
540
|
+
rootFlags.forEach(note);
|
|
541
|
+
return out;
|
|
542
|
+
}
|
|
543
|
+
/** A preorder walk of positions, descending into each chain `next` names the first time it is reached. */
|
|
544
|
+
function walkPositions(root, next, visit) {
|
|
545
|
+
const visited = new Set([root]);
|
|
546
|
+
const stack = [{ chain: root, q: 0 }];
|
|
547
|
+
while (stack.length > 0) {
|
|
548
|
+
const top = stack[stack.length - 1];
|
|
549
|
+
if (top.q >= top.chain.positions.length) {
|
|
550
|
+
stack.pop();
|
|
551
|
+
continue;
|
|
552
|
+
}
|
|
553
|
+
const p = top.chain.positions[top.q++];
|
|
554
|
+
visit(top.chain, p);
|
|
555
|
+
const inner = next(p);
|
|
556
|
+
const chains = inner === undefined ? [] : Array.isArray(inner) ? inner : [inner];
|
|
557
|
+
for (let i = chains.length - 1; i >= 0; i--) {
|
|
558
|
+
if (visited.has(chains[i]))
|
|
559
|
+
continue;
|
|
560
|
+
visited.add(chains[i]);
|
|
561
|
+
stack.push({ chain: chains[i], q: 0 });
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
566
|
+
// Words
|
|
567
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
568
|
+
const contribution = (s) => mul(s.passes, add(mul(s.attempts, s.timeoutMs ?? 0), s.backoffMs));
|
|
569
|
+
/** The `limit` largest contributors, kept in path order. */
|
|
570
|
+
function slowestInPathOrder(steps, limit) {
|
|
571
|
+
const keep = new Set([...steps]
|
|
572
|
+
.sort((a, b) => contribution(b) - contribution(a))
|
|
573
|
+
.slice(0, limit)
|
|
574
|
+
.map((s) => s.stageId));
|
|
575
|
+
return steps.filter((s) => keep.has(s.stageId));
|
|
576
|
+
}
|
|
577
|
+
function stepText(s) {
|
|
578
|
+
const own = s.timeoutMs === undefined
|
|
579
|
+
? `${s.backoffMs} ms of waits (no timeoutMs)`
|
|
580
|
+
: `${s.attempts} × ${s.timeoutMs} ms + ${s.backoffMs} ms of waits = ${add(mul(s.attempts, s.timeoutMs), s.backoffMs)} ms`;
|
|
581
|
+
return `${s.stageId}: ${own}${s.passes > 1 ? `, ${s.passes} passes` : ''}`;
|
|
582
|
+
}
|
|
583
|
+
function unboundedText(stages) {
|
|
584
|
+
const listed = stages.slice(0, 10).map((s) => `${s.stageId} (${s.why})`);
|
|
585
|
+
return stages.length > listed.length
|
|
586
|
+
? `${listed.join(', ')}, and ${stages.length - listed.length} more`
|
|
587
|
+
: listed.join(', ');
|
|
588
|
+
}
|
|
589
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
590
|
+
// Small laws
|
|
591
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
592
|
+
/** Saturating arithmetic on non-negative milliseconds: never past `Number.MAX_SAFE_INTEGER`, never `NaN`. */
|
|
593
|
+
const CEILING = Number.MAX_SAFE_INTEGER;
|
|
594
|
+
const add = (a, b) => Math.min(a + b, CEILING);
|
|
595
|
+
const mul = (a, b) => (a === 0 || b === 0 ? 0 : Math.min(a * b, CEILING));
|
|
596
|
+
const lastOf = (items) => items[items.length - 1];
|
|
597
|
+
/** A budget: a number of milliseconds > 0 and no more than the saturated sums can be compared against. */
|
|
598
|
+
const isPositiveMs = (value) => typeof value === 'number' && value > 0 && value <= Number.MAX_SAFE_INTEGER;
|
|
599
|
+
const shown = (value) => (typeof value === 'number' ? String(value) : typeof value);
|
|
600
|
+
/** An id as the run names it: under the prefix of the chart it lives in (a lazy or branch chart's mount path). */
|
|
601
|
+
const reported = (ctx, id) => (ctx.prefix === '' ? id : joinPath(ctx.prefix, id));
|
|
602
|
+
function isChart(value) {
|
|
603
|
+
if (value === null || typeof value !== 'object')
|
|
604
|
+
return false;
|
|
605
|
+
const root = value.root;
|
|
606
|
+
return root !== null && typeof root === 'object';
|
|
607
|
+
}
|
|
608
|
+
/** An own property only — a prototype member is never an assumption or a subflow. */
|
|
609
|
+
function own(record, key) {
|
|
610
|
+
return record !== undefined && Object.prototype.hasOwnProperty.call(record, key) ? record[key] : undefined;
|
|
611
|
+
}
|
|
612
|
+
/** The engine's subflow lookup: by subflow id, then subflow name, then node name. */
|
|
613
|
+
function subflowDefOf(subflows, node) {
|
|
614
|
+
for (const key of [node.subflowId, node.subflowName, node.name]) {
|
|
615
|
+
if (key === undefined || key === '')
|
|
616
|
+
continue;
|
|
617
|
+
const def = own(subflows, key);
|
|
618
|
+
if (def !== undefined && def !== null && typeof def.root === 'object' && def.root !== null)
|
|
619
|
+
return def;
|
|
620
|
+
}
|
|
621
|
+
return undefined;
|
|
622
|
+
}
|
|
623
|
+
/**
|
|
624
|
+
* Validate the assumptions and COPY them: each own enumerable key is read exactly once, into a fresh null-prototype
|
|
625
|
+
* record. A getter that changes between reads, a Proxy, or a non-enumerable key can therefore never hand the walk
|
|
626
|
+
* a value that was not validated, and no prototype member is ever an assumption.
|
|
627
|
+
*/
|
|
628
|
+
function admitAssumptions(assume) {
|
|
629
|
+
if (assume !== undefined && (assume === null || typeof assume !== 'object')) {
|
|
630
|
+
throw new TypeError('timeBudget: assume must be an object ({ loops?, lazy?, branches? }).');
|
|
631
|
+
}
|
|
632
|
+
const given = (assume ?? {});
|
|
633
|
+
return {
|
|
634
|
+
loops: snapshot(given.loops, 'loops', (key, passes) => {
|
|
635
|
+
if (typeof passes === 'number' && Number.isInteger(passes) && passes >= 1)
|
|
636
|
+
return passes;
|
|
637
|
+
throw new TypeError(`timeBudget: assume.loops['${key}'] must be a whole number of passes >= 1 (got ${shown(passes)}).`);
|
|
638
|
+
}),
|
|
639
|
+
lazy: snapshot(given.lazy, 'lazy', (key, chart) => assumedChart('lazy', key, chart)),
|
|
640
|
+
branches: snapshot(given.branches, 'branches', (key, chart) => assumedChart('branches', key, chart)),
|
|
641
|
+
};
|
|
642
|
+
}
|
|
643
|
+
function snapshot(record, field, admit) {
|
|
644
|
+
const copy = Object.create(null);
|
|
645
|
+
if (record === undefined)
|
|
646
|
+
return copy;
|
|
647
|
+
if (record === null || typeof record !== 'object') {
|
|
648
|
+
throw new TypeError(`timeBudget: assume.${field} must be an object keyed by id.`);
|
|
649
|
+
}
|
|
650
|
+
for (const key of Object.keys(record))
|
|
651
|
+
copy[key] = admit(key, record[key]);
|
|
652
|
+
return Object.freeze(copy);
|
|
653
|
+
}
|
|
654
|
+
function assumedChart(field, key, chart) {
|
|
655
|
+
const root = isChart(chart) ? chart.root : undefined;
|
|
656
|
+
if (!isNode(root)) {
|
|
657
|
+
throw new TypeError(`timeBudget: assume.${field}['${key}'] must be a built chart (flowChart(...).build()).`);
|
|
658
|
+
}
|
|
659
|
+
const { subflows, stageMap } = chart;
|
|
660
|
+
return Object.freeze({
|
|
661
|
+
root,
|
|
662
|
+
...(subflows !== undefined && { subflows: subflows }),
|
|
663
|
+
...(stageMap instanceof Map && { stageMap }),
|
|
664
|
+
});
|
|
665
|
+
}
|
|
666
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGltZUJ1ZGdldC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvYnVkZ2V0L3RpbWVCdWRnZXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTZDRztBQUVILE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFFckMsT0FBTyxFQUFFLGNBQWMsRUFBRSxnQkFBZ0IsRUFBRSxnQkFBZ0IsRUFBRSxZQUFZLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUV4RyxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDakUsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFHeEQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUUxQyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQXFFN0Q7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUM7QUFFaEMsZ0ZBQWdGO0FBQ2hGLG1CQUFtQjtBQUNuQixnRkFBZ0Y7QUFFaEY7Ozs7Ozs7Ozs7OztHQVlHO0FBQ0gsTUFBTSxVQUFVLFVBQVUsQ0FBQyxLQUFnQixFQUFFLE9BQTJCO0lBQ3RFLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUNwQixNQUFNLElBQUksU0FBUyxDQUFDLCtFQUErRSxDQUFDLENBQUM7SUFDdkcsQ0FBQztJQUNELElBQUksT0FBTyxFQUFFLFFBQVEsS0FBSyxTQUFTLElBQUksQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7UUFDdkUsTUFBTSxJQUFJLFNBQVMsQ0FDakIsNkZBQTZGO1lBQzNGLFFBQVEsS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsSUFBSSxD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QUNuQixJQUFJO1FBQ0osR0FBRyxDQUFDLFFBQVEsS0FBSyxTQUFTLElBQUksRUFBRSxRQUFRLEVBQUUsUUFBK0MsRUFBRSxDQUFDO1FBQzVGLEdBQUcsQ0FBQyxRQUFRLFlBQVksR0FBRyxJQUFJLEVBQUUsUUFBUSxFQUFFLENBQUM7S0FDN0MsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogYnVkZ2V0L3RpbWVCdWRnZXQudHMg4oCUIGB0aW1lQnVkZ2V0KGNoYXJ0KWA6IHRoZSBzbG93ZXN0IGEgY2hhcnQgY2FuIHRha2UsIGZyb20gd2hhdCBpdCBkZWNsYXJlcyAoZGVzaWduXG4gKiBkb2NzL2Rlc2lnbi8yMDI2LTEwLXRpbWUtYW5kLWZhaWx1cmUtZXZpZGVuY2UubWQgwqczLjIsIHBhY2tldCBQNSkuXG4gKlxuICogV0hZOiBhIHJldHJ5IHBvbGljeSBpcyBhIHByb21pc2UgYWJvdXQgdGltZS4gYHsgYXR0ZW1wdHM6IDQsIHRpbWVvdXRNczogNDBfMDAwLCBiYWNrb2ZmTXM6IDFfMDAwIH1gIGFsbG93c1xuICogNCDDlyA0MCAwMDAgKyAzIMOXIDEgMDAwID0gMTYzIDAwMCBtcywgYW5kIGEgY2FsbGVyIHdobyBnYXZlIHRoZSBjaGFydCAxMjAgcyBpcyBub3Qgc2VydmVkIGJ5IGl0IOKAlCB3aGljaCBpc1xuICoga25vd2FibGUgYmVmb3JlIGEgc2luZ2xlIHN0YWdlIHJ1bnMuIGAuYnVkZ2V0KG1zKWAgZGVjbGFyZXMgdGhlIGNhbGxlcidzIGNvbnRyYWN0IG9uIHRoZSBjaGFydDsgYGJ1aWxkKClgIHJlZnVzZXNcbiAqIGEgY2hhcnQgd2hvc2UgZGVjbGFyZWQgcG9saWNpZXMgYWxyZWFkeSBhbGxvdyBsb25nZXIgKG93bmVyIHJ1bGluZyBRMikgYW5kIHdhcm5zLCBieSBuYW1lLCBhYm91dCBldmVyeSBzdGFnZSBpdFxuICogY2Fubm90IGJvdW5kLiBBbiB1bmJvdW5kZWQgc3RhZ2UgaXMgbmV2ZXIgZ3Vlc3NlZCBhcm91bmQ6IGl0IGlzIGNvdW50ZWQgYXMgMCBhbmQgbmFtZWQuXG4gKlxuICogVEhFIFJVTEVTIChvbmUgd2FsayBvZiB0aGUgYnVpbHQgU3RhZ2VOb2RlIGdyYXBoOyBlYWNoIGNoYWluIG9mIGBuZXh0YCBwb2ludGVycyBpcyBjb21wdXRlZCBvbmNlIHBlciBzdGFydCk6XG4gKiAgIC0gYSBzdGFnZSB3aXRoIGEgZnVuY3Rpb246IGBhdHRlbXB0cyDDlyB0aW1lb3V0TXNgIHBsdXMgdGhlIHdhaXRzIGJldHdlZW4gaXRzIGF0dGVtcHRzLCBhcyB0aGUgcnVubmVyIHdhaXRzIHRoZW1cbiAqICAgICAoYGF0dGVtcHQvcG9saWN5LnRzYCkuIEEgbnVtYmVyIGBiYWNrb2ZmTXNgIGlzIGFyaXRobWV0aWMsIHVuZGVyIGBtYXhCYWNrb2ZmTXNgIHdoZW4gZGVjbGFyZWQuIEEgRlVOQ1RJT04gaXNcbiAqICAgICBuZXZlciBhc2tlZDogaXQgbWF5IHJlYWQgdGhlIGVycm9yIChhIHN0YXRlZCBgUmV0cnktQWZ0ZXJgKSBhbmQgbm8gZXJyb3IgZXhpc3RzIGhlcmUsIHNvIGFza2luZyBpdCB3aXRoIG5vbmVcbiAqICAgICBjb3VsZCBVTkRFUkVTVElNQVRFLiBJdCBjb3VudHMgYXQgaXRzIGRlY2xhcmVkIGNlaWxpbmcsIGBtYXhCYWNrb2ZmTXNgIHBlciB3YWl0ICh0aGUgcnVubmVyIGVuZm9yY2VzIGl0KTsgd2l0aFxuICogICAgIG5vIGNlaWxpbmcgdGhlIHN0YWdlIGlzIHVuYm91bmRlZCBgJ2JhY2tvZmYnYC4gTm8gYHRpbWVvdXRNc2Ag4oaSIHVuYm91bmRlZCBgJ25vLXRpbWVvdXQnYDtcbiAqICAgLSBhIHNlcXVlbmNlOiB0aGUgc3VtLiBBIGRlY2lkZXIsIGEgc2VsZWN0b3IsIGEgZm9yazogdGhlIG5vZGUncyBvd24gc3RhZ2UgcGx1cyBpdHMgc2xvd2VzdCBjaGlsZCAoYSBmb3JrJ3NcbiAqICAgICBjaGlsZHJlbiwgYW5kIGEgc2VsZWN0b3IncyBwaWNrcywgcnVuIGF0IG9uY2UpO1xuICogICAtIGEgbW91bnRlZCBzdWJmbG93OiBpdHMgY2hhcnQsIHdhbGtlZCB0aGUgc2FtZSB3YXksIHVuZGVyIHRoZSBpZHMgdGhlIHJ1biBnaXZlcyBpdHMgc3RhZ2VzIChgcGF5L2NoYXJnZWApO1xuICogICAgIGEgbGF6eSBvbmUgaXMgdW5ib3VuZGVkIGAnbGF6eS1zdWJmbG93J2AgdW5sZXNzIGBhc3N1bWUubGF6eVtzdWJmbG93SWRdYCBuYW1lcyB0aGUgY2hhcnQgaXQgcmVzb2x2ZXMgdG87XG4gKiAgIC0gYHBhcmFsbGVsRm9yRWFjaGA6IE9ORSBicmFuY2gg4oCUIHRoZSBicmFuY2hlcyBydW4gYXQgb25jZSBhbmQgYG1heEJyYW5jaGVzYCB0cnVuY2F0ZXMsIHNvIHRoZSBpdGVtIGNvdW50IG5ldmVyXG4gKiAgICAgYWRkcyB0aW1lLiBUaGUgYnJhbmNoIGNoYXJ0IGlzIGJ1aWx0IGF0IHJ1biB0aW1lLCBzbyBpdCBpcyB1bmJvdW5kZWQgYCdpdGVtcydgIHVubGVzc1xuICogICAgIGBhc3N1bWUuYnJhbmNoZXNbc3RhZ2VJZF1gIG5hbWVzIGl0IChpdHMgc3RhZ2VzIGFyZSByZXBvcnRlZCB1bmRlciB0aGUgZmlyc3QgYnJhbmNoLCBgcmV2aWV3fjAvc2NvcmVgKTtcbiAqICAgLSBhIGxvb3AgaXMgTkVWRVIgaXRlcmF0ZWQuIFdpdGggbm8gYXNzdW1wdGlvbiBpdCBpcyB1bmJvdW5kZWQgYCdsb29wJ2AsIG5hbWVkIGJ5IGl0cyB0YXJnZXQsIGFuZCBjb3VudGVkIG9uY2UuXG4gKiAgICAgYGFzc3VtZS5sb29wc1t0YXJnZXRJZF0gPSBuYCBib3VuZHMgaXQ6IGVhY2ggdGltZSB0aGUgY2hhcnQgcmVhY2hlcyB0aGUgbG9vcCwgZXZlcnkgc3RhZ2UgZnJvbSB0aGUgdGFyZ2V0IHRvXG4gKiAgICAgdGhlIGxvb3AncyBmdXJ0aGVzdCBzb3VyY2UgcnVucyBhdCBtb3N0IGBuYCB0aW1lcywgZWFjaCBhdCBpdHMgc2xvd2VzdC4gTmVzdGVkIGxvb3BzIG11bHRpcGx5OyB0d28gbG9vcHMgdGhhdFxuICogICAgIG92ZXJsYXAgd2l0aG91dCBuZXN0aW5nIGFyZSBvbmUgcmVnaW9uIGJvdW5kZWQgYnkgdGhlIHByb2R1Y3Qgb2YgdGhlaXIgcGFzc2VzIChlYWNoIGNhbiByZS1lbnRlciB0aGUgb3RoZXIpLlxuICpcbiAqIFRXTyBOVU1CRVJTLiBga25vd25Nc2AgY291bnRzIHdoYXQgaXMgYm91bmRlZCAoYW4gdW5ib3VuZGVkIHN0YWdlIGFzIDAsIGFuIHVuYXNzdW1lZCBsb29wIG9uY2UpLiBXaXRob3V0XG4gKiBhc3N1bXB0aW9ucyBpdCBpcyBhIHRpbWUgdGhlIGRlY2xhcmVkIHBvbGljaWVzIEFMTE9XIGEgcnVuIHRvIHRha2UgKGByZXRyeU9uYCBpcyBub3QgcmVhZDogaXQgbWF5IG9ubHkgZW5kIGEgc2VyaWVzXG4gKiBzb29uZXIpLCBzbyBhIGJ1ZGdldCBiZWxvdyBpdCBjYW5ub3QgYmUgcHJvbWlzZWQg4oCUIGBvdmVyYCBhbmQgdGhlIGJ1aWxkIHJlZnVzYWwgcmVhZCBpdCwgb24gYW4gdW5ib3VuZGVkIHBhdGggdG9vLlxuICogYHdvcnN0Q2FzZU1zYCBpcyBga25vd25Nc2Agd2hlbiBldmVyeSBwYXRoIGlzIGJvdW5kZWQsIGBudWxsYCBvdGhlcndpc2U7IHdpdGggYW4gYXNzdW1lZCBsb29wIGl0IGlzIGFuIHVwcGVyIGJvdW5kXG4gKiB1bmRlciB0aGF0IGFzc3VtcHRpb24gKGV2ZXJ5IHBhc3MgaXMgY291bnRlZCBhdCBpdHMgc2xvd2VzdCBicmFuY2gpLlxuICpcbiAqIFRIUkVBVCBNT0RFTC4gVGhlIHdhbGsgdGVybWluYXRlcyBvbiBhbnkgZ3JhcGg6IGEgY2hhaW4gaXMgd2Fsa2VkIHdpdGggYSB2aXNpdGVkIHNldCAoYSBgbmV4dGAgdGhhdCBjbG9zZXMgb25cbiAqIGl0c2VsZiBpcyBhIGxvb3ApLCBuZXN0aW5nIGlzIGFuIGV4cGxpY2l0IHN0YWNrIChubyByZWN1cnNpb24g4oCUIGEgNSAwMDAtZGVlcCBzdWJmbG93IG5lc3Rpbmcgd2Fsa3MpLCBhIGNoYWluIHRoYXRcbiAqIHJlYWNoZXMgaXRzZWxmIHRocm91Z2ggaXRzIGNoaWxkcmVuIG9yIGEgc3ViZmxvdyBpcyBhIGxvb3AsIGFuZCBldmVyeSBjaGFpbiBpcyBjb21wdXRlZCBvbmNlIHBlciBzdGFydCBob3dldmVyXG4gKiBvZnRlbiBpdCBpcyBtb3VudGVkLiBUaGUgd2FsayBpcyBDQVBQRUQ6IHBhc3QgYE1BWF9XQUxLYCBub2RlIHZpc2l0cyBpdCBzdG9wcyB3aXRoIGEgYFJhbmdlRXJyb3JgIOKAlCBhIGJ1aWxkZXIgY2hhcnRcbiAqIHZpc2l0cyBlYWNoIG5vZGUgYXQgbW9zdCB0d2ljZSwgYnV0IGEgaGFuZC1idWlsdCBncmFwaCB3aG9zZSBjaGFpbnMgc2hhcmUgdGhlaXIgdGFpbHMgaXMgd2Fsa2VkIG9uY2UgcGVyIGNoYWluLlxuICogU3VtcyBhbmQgcHJvZHVjdHMgc2F0dXJhdGUgYXQgYE51bWJlci5NQVhfU0FGRV9JTlRFR0VSYCDigJQgbmV2ZXIgYEluZmluaXR5YCBvciBgTmFOYC4gQXNzdW1wdGlvbnMgYXJlIGNvcGllZCBPTkNFLFxuICogb3duIGVudW1lcmFibGUgcHJvcGVydGllcyBvbmx5LCBpbnRvIGZyZXNoIG51bGwtcHJvdG90eXBlIHJlY29yZHMsIGFuZCBvbmx5IHRoYXQgY29weSBpcyByZWFkLlxuICpcbiAqIFdoYXQgaXQgZG9lcyBOT1QgY291bnQ6IHRoZSBlbmdpbmUncyBvd24gd29yayBiZXR3ZWVuIHN0YWdlcywgYSBzdGFnZSBmdW5jdGlvbiB0aGF0IGJsb2NrcyB0aGUgdGhyZWFkIChhIHRpbWVvdXRcbiAqIHN0b3BzIHRoZSBXQUlUSU5HLCBzZWUgdGhlIGF0dGVtcHQgcnVubmVyKSwgYW5kIGEgU3RhZ2VOb2RlIGEgc3RhZ2UgcmV0dXJucyBhdCBydW4gdGltZSDigJQgYW55IHN0YWdlIG1heSBncm93IHRoZVxuICogZ3JhcGggdGhhdCB3YXksIHNvIHRoZSBidWRnZXQgaXMgb2YgdGhlIGdyYXBoIHRoZSBjaGFydCBERUNMQVJFUy5cbiAqL1xuXG5pbXBvcnQgeyBqb2luUGF0aCB9IGZyb20gJ2Zvb3R0cmFjZSc7XG5cbmltcG9ydCB7IGF0dGVtcHRDZWlsaW5nLCBhdHRlbXB0VGltZW91dE1zLCBiYWNrb2ZmQ2VpbGluZ01zLCBjYXBwZWRXYWl0TXMgfSBmcm9tICcuLi9hdHRlbXB0L3BvbGljeS5qcyc7XG5pbXBvcnQgdHlwZSB7IFJldHJ5TG9vcEJ1ZGdldCB9IGZyb20gJy4uL2F0dGVtcHQvcmV0cnlMb29wQ29udGV4dC5qcyc7XG5pbXBvcnQgeyByZXRyeUxvb3BCdWRnZXQgfSBmcm9tICcuLi9hdHRlbXB0L3JldHJ5TG9vcENvbnRleHQuanMnO1xuaW1wb3J0IHsgcmVzb2x2ZUJhY2tvZmZNcyB9IGZyb20gJy4uL2F0dGVtcHQvcnVubmVyLmpzJztcbmltcG9ydCB0eXBlIHsgUmV0cnlQb2xpY3kgfSBmcm9tICcuLi9hdHRlbXB0L3R5cGVzLmpzJztcbmltcG9ydCB0eXBlIHsgRmxvd0NoYXJ0IH0gZnJvbSAnLi4vYnVpbGRlci90eXBlcy5qcyc7XG5pbXBvcnQgeyBpc0Rldk1vZGUgfSBmcm9tICcuLi9kZXZNb2RlLmpzJztcbmltcG9ydCB0eXBlIHsgU3RhZ2VOb2RlIH0gZnJvbSAnLi4vZW5naW5lL2dyYXBoL1N0YWdlTm9kZS5qcyc7XG5pbXBvcnQgeyBidWlsZEJyYW5jaFNlZ21lbnQgfSBmcm9tICcuLi9pZHMvYnJhbmNoU2VnbWVudC5qcyc7XG5cbi8vIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuLy8gUHVibGljIHNoYXBlc1xuLy8g4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbi8qKlxuICogV2h5IGEgc3RhZ2Uga2VlcHMgYSBwYXRoIHVuYm91bmRlZDogbm8gcGVyLWF0dGVtcHQgY2FwIChgJ25vLXRpbWVvdXQnYCk7IGEgZnVuY3Rpb24gYmFja29mZiB3aXRoIG5vIGRlY2xhcmVkXG4gKiBgbWF4QmFja29mZk1zYCAoYCdiYWNrb2ZmJ2Ag4oCUIGl0cyB3YWl0cyBtYXkgZGVwZW5kIG9uIGFuIGVycm9yIHRoYXQgZG9lcyBub3QgZXhpc3QgYXQgYnVpbGQpOyBhIGxvb3Agd2l0aCBub1xuICogYXNzdW1lZCBwYXNzZXMgKGAnbG9vcCdgLCBuYW1lZCBieSBpdHMgdGFyZ2V0KTsgYSBsYXp5IHN1YmZsb3cgd2hvc2UgY2hhcnQgaXMgdW5rbm93biBhdCBidWlsZCAoYCdsYXp5LXN1YmZsb3cnYCk7XG4gKiBhIGBwYXJhbGxlbEZvckVhY2hgIHdob3NlIGJyYW5jaCBjaGFydCBpcyBidWlsdCBhdCBydW4gdGltZSAoYCdpdGVtcydgKS5cbiAqL1xuZXhwb3J0IHR5cGUgVW5ib3VuZGVkUmVhc29uID0gJ25vLXRpbWVvdXQnIHwgJ2JhY2tvZmYnIHwgJ2xvb3AnIHwgJ2xhenktc3ViZmxvdycgfCAnaXRlbXMnO1xuXG4vKiogQSBzdGFnZSBvbiB0aGUgc2xvd2VzdCBwYXRoLCB3aXRoIHdoYXQgaXQgZGVjbGFyZXMgYW5kIGhvdyBtYW55IHRpbWVzIHRoZSBwYXRoIHJ1bnMgaXQuICovXG5leHBvcnQgaW50ZXJmYWNlIEJ1ZGdldFN0ZXAge1xuICAvKiogVGhlIHN0YWdlIGlkIGFzIHRoZSBydW4gbmFtZXMgaXQg4oCUIGEgc3ViZmxvdydzIHN0YWdlcyB1bmRlciB0aGVpciBtb3VudCAoYHBheS9jaGFyZ2VgKS4gKi9cbiAgcmVhZG9ubHkgc3RhZ2VJZDogc3RyaW5nO1xuICAvKiogSG93IG1hbnkgYXR0ZW1wdHMgaXRzIHBvbGljeSBhbGxvd3MgKDEgd2l0aG91dCBvbmUpLiAqL1xuICByZWFkb25seSBhdHRlbXB0czogbnVtYmVyO1xuICAvKiogVGhlIGNhcCBvbiBvbmUgYXR0ZW1wdDsgYWJzZW50IHdoZW4gdGhlIHN0YWdlIGRlY2xhcmVzIG5vbmUgKHRoZW4gYHdvcnN0TXNgIGlzIGBudWxsYCkuICovXG4gIHJlYWRvbmx5IHRpbWVvdXRNcz86IG51bWJlcjtcbiAgLyoqIFRoZSB3YWl0cyBiZXR3ZWVuIGl0cyBhdHRlbXB0cywgaW4gdG90YWwuICovXG4gIHJlYWRvbmx5IGJhY2tvZmZNczogbnVtYmVyO1xuICAvKiogYGF0dGVtcHRzIMOXIHRpbWVvdXRNcyArIGJhY2tvZmZNc2Ag4oCUIGBudWxsYCB3aGVuIHRoZSBzdGFnZSBpcyB1bmJvdW5kZWQuICovXG4gIHJlYWRvbmx5IHdvcnN0TXM6IG51bWJlciB8IG51bGw7XG4gIC8qKiBIb3cgbWFueSB0aW1lcyB0aGUgcGF0aCBydW5zIGl0IOKAlCBtb3JlIHRoYW4gMSBvbmx5IGluc2lkZSBhbiBhc3N1bWVkIGxvb3AuICovXG4gIHJlYWRvbmx5IHBhc3NlczogbnVtYmVyO1xufVxuXG4vKiogQSBzdGFnZSB0aGUgY2hlY2sgY2Fubm90IGJvdW5kLCBhbmQgd2h5LiAqL1xuZXhwb3J0IGludGVyZmFjZSBVbmJvdW5kZWRTdGFnZSB7XG4gIHJlYWRvbmx5IHN0YWdlSWQ6IHN0cmluZztcbiAgcmVhZG9ubHkgd2h5OiBVbmJvdW5kZWRSZWFzb247XG59XG5cbi8qKiBXaGF0IHRoZSBjYWxsZXIga25vd3MgdGhhdCB0aGUgY2hhcnQgZG9lcyBub3QgZGVjbGFyZS4gS2V5cyBhcmUgaWRzIGFzIHRoZSBydW4gbmFtZXMgdGhlbS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQnVkZ2V0QXNzdW1wdGlvbnMge1xuICAvKiogQSBsb29wJ3MgVEFSR0VUIGlkICh3aGF0IGBsb29wVG9gIG5hbWVzKSDihpIgdGhlIG1vc3QgcGFzc2VzIHRocm91Z2ggaXQgZWFjaCB0aW1lIHRoZSBjaGFydCByZWFjaGVzIGl0ICjiiaUgMSkuICovXG4gIHJlYWRvbmx5IGxvb3BzPzogUmVhZG9ubHk8UmVjb3JkPHN0cmluZywgbnVtYmVyPj47XG4gIC8qKiBBIGxhenkgbW91bnQncyBzdWJmbG93IGlkIOKGkiB0aGUgY2hhcnQgaXQgcmVzb2x2ZXMgdG8uICovXG4gIHJlYWRvbmx5IGxhenk/OiBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCBGbG93Q2hhcnQ+PjtcbiAgLyoqIEEgYHBhcmFsbGVsRm9yRWFjaGAgc3RhZ2UgaWQg4oaSIHRoZSBjaGFydCBvbmUgYnJhbmNoIHJ1bnMuICovXG4gIHJlYWRvbmx5IGJyYW5jaGVzPzogUmVhZG9ubHk8UmVjb3JkPHN0cmluZywgRmxvd0NoYXJ0Pj47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVGltZUJ1ZGdldE9wdGlvbnMge1xuICAvKiogVGhlIGJ1ZGdldCB0byBjaGVjayBhZ2FpbnN0LiBEZWZhdWx0cyB0byB0aGUgY2hhcnQncyBkZWNsYXJlZCBgLmJ1ZGdldChtcylgLiBBIGZpbml0ZSBudW1iZXIgPiAwLiAqL1xuICByZWFkb25seSBidWRnZXRNcz86IG51bWJlcjtcbiAgcmVhZG9ubHkgYXNzdW1lPzogQnVkZ2V0QXNzdW1wdGlvbnM7XG59XG5cbi8qKiBXaGF0IGB0aW1lQnVkZ2V0KGNoYXJ0KWAgcmVwb3J0cy4gSlNPTi1zYWZlIGFuZCBmcm96ZW4uICovXG5leHBvcnQgaW50ZXJmYWNlIFRpbWVCdWRnZXRSZXBvcnQge1xuICAvKiogVGhlIHdvcnN0IGNhc2Ugb2YgdGhlIHNsb3dlc3QgcGF0aCDigJQgYG51bGxgIHdoZW4gYW55IHBhdGggaXMgdW5ib3VuZGVkIChzZWUgYHVuYm91bmRlZGApLiAqL1xuICByZWFkb25seSB3b3JzdENhc2VNczogbnVtYmVyIHwgbnVsbDtcbiAgLyoqIFRoZSB3b3JzdCBjYXNlIG9mIHdoYXQgSVMgYm91bmRlZDogYW4gdW5ib3VuZGVkIHN0YWdlIGNvdW50cyAwLCBhbiB1bmFzc3VtZWQgbG9vcCBvbmUgcGFzcy4gKi9cbiAgcmVhZG9ubHkga25vd25NczogbnVtYmVyO1xuICAvKiogVGhlIHN0YWdlcyBvZiB0aGUgc2xvd2VzdCBwYXRoLCBpbiB0aGUgb3JkZXIgYSBydW4gZmlyc3QgcmVhY2hlcyB0aGVtIOKAlCB0aGUgcGF0aCB0aGF0IG1ha2VzIGB3b3JzdENhc2VNc2AsXG4gICAqICBvciBga25vd25Nc2Agd2hlbiBhIHBhdGggaXMgdW5ib3VuZGVkLiBga25vd25NcyA9IM6jIHBhc3NlcyDDlyAoYXR0ZW1wdHMgw5cgKHRpbWVvdXRNcyA/PyAwKSArIGJhY2tvZmZNcylgLiAqL1xuICByZWFkb25seSBjcml0aWNhbFBhdGg6IHJlYWRvbmx5IEJ1ZGdldFN0ZXBbXTtcbiAgLyoqIEV2ZXJ5IHN0YWdlIHRoYXQga2VlcHMgYSBwYXRoIHVuYm91bmRlZCwgZWFjaCBuYW1lZCBvbmNlLCBpbiBjaGFydCBvcmRlci4gKi9cbiAgcmVhZG9ubHkgdW5ib3VuZGVkOiByZWFkb25seSBVbmJvdW5kZWRTdGFnZVtdO1xuICAvKiogVGhlIGJ1ZGdldCBjaGVja2VkIGFnYWluc3Qg4oCUIGFic2VudCB3aGVuIHRoZXJlIGlzIG5vbmUuICovXG4gIHJlYWRvbmx5IGJ1ZGdldE1zPzogbnVtYmVyO1xuICAvKiogYGtub3duTXMgPiBidWRnZXRNc2A6IHRoZSBkZWNsYXJlZCBwb2xpY2llcyBhbGxvdyBsb25nZXIgdGhhbiB0aGUgYnVkZ2V0LiBBbHdheXMgYGZhbHNlYCB3aXRob3V0IG9uZS4gKi9cbiAgcmVhZG9ubHkgb3ZlcjogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBUaGUgbW9zdCBub2RlIHZpc2l0cyBvbmUgd2FsayBtYWtlcy4gQSBidWlsZGVyIGNoYXJ0IHZpc2l0cyBlYWNoIG5vZGUgYXQgbW9zdCB0d2ljZSwgc28gMjUwIDAwMCBpcyBmYXIgcGFzdCBhbnlcbiAqIHJlYWwgY2hhcnQ7IGEgaGFuZC1idWlsdCBncmFwaCB3aG9zZSBjaGFpbnMgc2hhcmUgdGhlaXIgdGFpbHMgY2FuIG5lZWQgbW9yZSAoZWFjaCBjaGFpbiB3YWxrcyB0aGUgc2hhcmVkIHRhaWwpLFxuICogYW5kIHRoZSBjaGVjayBzdG9wcyB0aGVyZSB3aXRoIGEgYFJhbmdlRXJyb3JgIHJhdGhlciB0aGFuIGdyb3cgd2l0aG91dCBib3VuZC5cbiAqL1xuZXhwb3J0IGNvbnN0IE1BWF9XQUxLID0gMjUwXzAwMDtcblxuLy8g4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG4vLyBUaGUgZW50cnkgcG9pbnRzXG4vLyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuLyoqXG4gKiBUaGUgc2xvd2VzdCB0aGUgY2hhcnQgY2FuIHRha2UsIGNvbXB1dGVkIGZyb20gaXRzIGRlY2xhcmVkIHJldHJ5IHBvbGljaWVzIOKAlCBhbmQgZXZlcnkgc3RhZ2UgdGhhdCBtYWtlcyBhIHBhdGhcbiAqIHVuYm91bmRlZCwgYnkgbmFtZS4gU2VlIHRoZSBtb2R1bGUgaGVhZGVyIGZvciB0aGUgcnVsZXMuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHRzXG4gKiBjb25zdCByZXBvcnQgPSB0aW1lQnVkZ2V0KGNoYXJ0LCB7IGJ1ZGdldE1zOiAxMjBfMDAwLCBhc3N1bWU6IHsgbG9vcHM6IHsgJ2Fzay1hZ2Fpbic6IDMgfSB9IH0pO1xuICogcmVwb3J0LndvcnN0Q2FzZU1zOyAgLy8gbnVtYmVyLCBvciBudWxsIHdoZW4gYSBwYXRoIGlzIHVuYm91bmRlZFxuICogcmVwb3J0LmNyaXRpY2FsUGF0aDsgLy8gW3sgc3RhZ2VJZCwgYXR0ZW1wdHMsIHRpbWVvdXRNcywgYmFja29mZk1zLCB3b3JzdE1zLCBwYXNzZXMgfV1cbiAqIHJlcG9ydC51bmJvdW5kZWQ7ICAgIC8vIFt7IHN0YWdlSWQsIHdoeTogJ25vLXRpbWVvdXQnIHwgJ2JhY2tvZmYnIHwgJ2xvb3AnIHwgJ2xhenktc3ViZmxvdycgfCAnaXRlbXMnIH1dXG4gKiByZXBvcnQub3ZlcjsgICAgICAgICAvLyB0cnVlIHdoZW4gdGhlIGRlY2xhcmVkIHBvbGljaWVzIGFsbG93IGxvbmdlciB0aGFuIGJ1ZGdldE1zXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRpbWVCdWRnZXQoY2hhcnQ6IEZsb3dDaGFydCwgb3B0aW9ucz86IFRpbWVCdWRnZXRPcHRpb25zKTogVGltZUJ1ZGdldFJlcG9ydCB7XG4gIGlmICghaXNDaGFydChjaGFydCkpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd0aW1lQnVkZ2V0KGNoYXJ0KTogcGFzcyBhIGJ1aWx0IGNoYXJ0IOKAlCB0aGUgcmVzdWx0IG9mIGZsb3dDaGFydCguLi4pLmJ1aWxkKCkuJyk7XG4gIH1cbiAgaWYgKG9wdGlvbnM/LmJ1ZGdldE1zICE9PSB1bmRlZmluZWQgJiYgIWlzUG9zaXRpdmVNcyhvcHRpb25zLmJ1ZGdldE1zKSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAndGltZUJ1ZGdldDogYnVkZ2V0TXMgbXVzdCBiZSBhIG51bWJlciBvZiBtaWxsaXNlY29uZHMgPiAwLCBhdCBtb3N0IE51bWJlci5NQVhfU0FGRV9JTlRFR0VSICcgK1xuICAgICAgICBgKGdvdCAke3Nob3duKG9wdGlvbnMuYnVkZ2V0TXMpfSkuYCxcbiAgICApO1xuICB9XG4gIGNvbnN0IGJ1ZGdldE1zID0gb3B0aW9ucz8uYnVkZ2V0TXMgPz8gZGVjbGFyZWRCdWRnZXQoY2hhcnQpO1xuICBjb25zdCB3YWxrID0gbmV3IEJ1ZGdldFdhbGsoYWRtaXRBc3N1bXB0aW9ucyhvcHRpb25zPy5hc3N1bWUpKTtcbiAgY29uc3QgY3R4ID0gd2Fsay5jdHhPZihjaGFydCwgJycpO1xuICBjb25zdCByb290ID0gd2Fsay5ldmFsdWF0ZSh7IGN0eCwgc3RhcnQ6IGNoYXJ0LnJvb3QgfSk7XG5cbiAgLy8gQSBsb29wIHdob3NlIHRhcmdldCB0aGUgY2hhcnQgZG9lcyBub3QgaG9sZCBjYW5ub3QgYmUgYm91bmRlZCBieSBhbnkgYXNzdW1wdGlvbi5cbiAgY29uc3Qgcm9vdEZsYWdzID0gWy4uLnJvb3Qub3Blbl0ubWFwKCh0YXJnZXQpID0+ICh7IHN0YWdlSWQ6IHJlcG9ydGVkKGN0eCwgdGFyZ2V0KSwgd2h5OiAnbG9vcCcgYXMgY29uc3QgfSkpO1xuICBjb25zdCBib3VuZGVkID0gcm9vdC5ib3VuZGVkICYmIHJvb3Qub3Blbi5zaXplID09PSAwO1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh7XG4gICAgd29yc3RDYXNlTXM6IGJvdW5kZWQgPyByb290Lmtub3duIDogbnVsbCxcbiAgICBrbm93bk1zOiByb290Lmtub3duLFxuICAgIGNyaXRpY2FsUGF0aDogT2JqZWN0LmZyZWV6ZShjcml0aWNhbFBhdGhPZihyb290LCB3YWxrLmNvbXB1dGVkKSksXG4gICAgdW5ib3VuZGVkOiBPYmplY3QuZnJlZXplKHVuYm91bmRlZE9mKHJvb3QsIHJvb3RGbGFncykpLFxuICAgIC4uLihidWRnZXRNcyAhPT0gdW5kZWZpbmVkICYmIHsgYnVkZ2V0TXMgfSksXG4gICAgb3ZlcjogYnVkZ2V0TXMgIT09IHVuZGVmaW5lZCAmJiByb290Lmtub3duID4gYnVkZ2V0TXMsXG4gIH0pO1xufVxuXG4vKiogVGhlIGNoYXJ0J3MgZGVjbGFyZWQgYnVkZ2V0IChgLmJ1ZGdldChtcylgLCB0aGUgc3BlYyByb290J3MgYGJ1ZGdldE1zYCksIG9yIGB1bmRlZmluZWRgLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlY2xhcmVkQnVkZ2V0KGNoYXJ0OiBGbG93Q2hhcnQpOiBudW1iZXIgfCB1bmRlZmluZWQge1xuICBjb25zdCBidWRnZXRNcyA9IGNoYXJ0LmJ1aWxkVGltZVN0cnVjdHVyZT8uYnVkZ2V0TXM7XG4gIHJldHVybiBpc1Bvc2l0aXZlTXMoYnVkZ2V0TXMpID8gYnVkZ2V0TXMgOiB1bmRlZmluZWQ7XG59XG5cbi8qKiBgYnVpbGQoKWAncyByZWZ1c2FsIGZvciBhIGRlY2xhcmVkIGJ1ZGdldCB0aGUgY2hhcnQgY2FuIGFscmVhZHkgZXhjZWVkLCBvciBgdW5kZWZpbmVkYCB3aGVuIGl0IGNhbiBrZWVwIGl0LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJ1ZGdldFJlZnVzYWwocmVwb3J0OiBUaW1lQnVkZ2V0UmVwb3J0KTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgaWYgKCFyZXBvcnQub3ZlciB8fCByZXBvcnQuYnVkZ2V0TXMgPT09IHVuZGVmaW5lZCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgY29uc3QgY291bnRlZCA9IHJlcG9ydC5jcml0aWNhbFBhdGguZmlsdGVyKChzdGVwKSA9PiBjb250cmlidXRpb24oc3RlcCkgPiAwKTtcbiAgY29uc3Qgc2hvd25TdGVwcyA9IHNsb3dlc3RJblBhdGhPcmRlcihjb3VudGVkLCA1KS5tYXAoc3RlcFRleHQpO1xuICBjb25zdCBtb3JlID0gY291bnRlZC5sZW5ndGggPiBzaG93blN0ZXBzLmxlbmd0aCA/IGAsIGFuZCAke2NvdW50ZWQubGVuZ3RoIC0gc2hvd25TdGVwcy5sZW5ndGh9IG1vcmVgIDogJyc7XG4gIGNvbnN0IHVuY291bnRlZCA9XG4gICAgcmVwb3J0LnVuYm91bmRlZC5sZW5ndGggPiAwID8gYCBOb3QgY291bnRlZCwgaGF2aW5nIG5vIGJvdW5kOiAke3VuYm91bmRlZFRleHQocmVwb3J0LnVuYm91bmRlZCl9LmAgOiAnJztcbiAgcmV0dXJuIChcbiAgICBgYnVkZ2V0KCR7cmVwb3J0LmJ1ZGdldE1zfSk6IGl0cyBkZWNsYXJlZCBwb2xpY2llcyBhbGxvdyAke3JlcG9ydC5rbm93bk1zfSBtcywgb3ZlciBpdHMgYnVkZ2V0IGJ5IGAgK1xuICAgIGAke3JlcG9ydC5rbm93bk1zIC0gcmVwb3J0LmJ1ZGdldE1zfSBtcy4gU2xvd2VzdCBwYXRoOiAke3Nob3duU3RlcHMuam9pbignOyAnKX0ke21vcmV9LiBMb3dlciBhdHRlbXB0cyBvciBgICtcbiAgICBgdGltZW91dE1zIG9uIHRoZXNlIHN0YWdlcywgb3IgcmFpc2UgdGhlIGJ1ZGdldC4ke3VuY291bnRlZH1gXG4gICk7XG59XG5cbi8qKiBgYnVpbGQoKWAncyBkZXYtbW9kZSB3YXJuaW5nIGZvciBhIGRlY2xhcmVkIGJ1ZGdldCBpdCBjYW5ub3QgY2hlY2sgb24gZXZlcnkgcGF0aCwgb3IgYHVuZGVmaW5lZGAuICovXG5leHBvcnQgZnVuY3Rpb24gYnVkZ2V0V2FybmluZyhyZXBvcnQ6IFRpbWVCdWRnZXRSZXBvcnQsIGNoYXJ0TmFtZTogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgaWYgKHJlcG9ydC5idWRnZXRNcyA9PT0gdW5kZWZpbmVkIHx8IHJlcG9ydC51bmJvdW5kZWQubGVuZ3RoID09PSAwKSByZXR1cm4gdW5kZWZpbmVkO1xuICByZXR1cm4gKFxuICAgIGBbZm9vdHByaW50XSBjaGFydCAnJHtjaGFydE5hbWV9JyBkZWNsYXJlcyBhIGJ1ZGdldCBvZiAke3JlcG9ydC5idWRnZXRNc30gbXMsIGJ1dCB0aGUgY2hlY2sgY2Fubm90IGJvdW5kIGAgK1xuICAgIGBldmVyeSBwYXRoOiAke3VuYm91bmRlZFRleHQocmVwb3J0LnVuYm91bmRlZCl9LiBHaXZlIGEgc3RhZ2UgYSByZXRyeSh7IHRpbWVvdXRNcyB9KSBhbmQgYSBmdW5jdGlvbiBiYWNrb2ZmIGEgYCArXG4gICAgJ21heEJhY2tvZmZNczsgYm91bmQgYSBsb29wLCBhIGxhenkgc3ViZmxvdyBvciBhIHBhcmFsbGVsRm9yRWFjaCB3aXRoIHRpbWVCdWRnZXQoY2hhcnQsIHsgYXNzdW1lIH0pLidcbiAgKTtcbn1cblxuLyoqIENoYXJ0cyBhbHJlYWR5IHdhcm5lZCBhdCBydW4gc3RhcnQg4oCUIHRoZSB3YXJuaW5nIGlzIHNhaWQgb25jZSBwZXIgY2hhcnQuICovXG5jb25zdCB3YXJuZWRBdFJ1blN0YXJ0ID0gbmV3IFdlYWtTZXQ8b2JqZWN0PigpO1xuXG4vKipcbiAqIFRoZSBydW4tc3RhcnQgd2FybmluZyAoZGV2IG1vZGUsIG9uY2UgcGVyIGNoYXJ0KTogdGhlIHJ1bidzIGRlYWRsaW5lIGxlYXZlcyB0aGUgY2hhcnQgbGVzcyB0aW1lIHRoYW4gaXRzIGRlY2xhcmVkXG4gKiBidWRnZXQsIHNvIGEgcnVuIHRoYXQgdGFrZXMgdGhlIHRpbWUgdGhlIGNoYXJ0IGRlY2xhcmVzIHdpbGwgYmUgY3V0IHNob3J0LiBgc3RhcnRlZEF0YCBpcyByZWFkIEJFRk9SRSB0aGUgcnVuJ3NcbiAqIGRlYWRsaW5lIGlzIGFybWVkLCBzbyBgdGltZW91dE1zYCBlcXVhbCB0byB0aGUgYnVkZ2V0IG5ldmVyIHdhcm5zLlxuICovXG5leHBvcnQgZnVuY3Rpb24gd2FybkRlYWRsaW5lVW5kZXJCdWRnZXQoY2hhcnQ6IEZsb3dDaGFydCwgZGVhZGxpbmU6IG51bWJlciB8IHVuZGVmaW5lZCwgc3RhcnRlZEF0OiBudW1iZXIpOiB2b2lkIHtcbiAgaWYgKGRlYWRsaW5lID09PSB1bmRlZmluZWQgfHwgIWlzRGV2TW9kZSgpKSByZXR1cm47XG4gIGNvbnN0IGJ1ZGdldE1zID0gZGVjbGFyZWRCdWRnZXQoY2hhcnQpO1xuICBpZiAoYnVkZ2V0TXMgPT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuICBjb25zdCBsZWZ0TXMgPSBkZWFkbGluZSAtIHN0YXJ0ZWRBdDtcbiAgaWYgKGxlZnRNcyA+PSBidWRnZXRNcyB8fCB3YXJuZWRBdFJ1blN0YXJ0LmhhcyhjaGFydCkpIHJldHVybjtcbiAgd2FybmVkQXRSdW5TdGFydC5hZGQoY2hhcnQpO1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICBjb25zb2xlLndhcm4oXG4gICAgYFtmb290cHJpbnRdIHRoaXMgcnVuJ3MgZGVhZGxpbmUgbGVhdmVzICR7TWF0aC5tYXgoMCwgbGVmdE1zKX0gbXMsIGxlc3MgdGhhbiB0aGUgY2hhcnQncyBkZWNsYXJlZCBidWRnZXQgb2YgYCArXG4gICAgICBgJHtidWRnZXRNc30gbXMgKCcke2NoYXJ0LnJvb3QubmFtZX0nKTogYSBydW4gdGhhdCB0YWtlcyB0aGUgdGltZSB0aGUgY2hhcnQgZGVjbGFyZXMgd2lsbCBiZSBjdXQgc2hvcnQuIEdpdmUgYCArXG4gICAgICAndGhlIHJ1biBpdHMgYnVkZ2V0LCBvciBkZWNsYXJlIGEgc21hbGxlciBvbmUuJyxcbiAgKTtcbn1cblxuLy8g4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG4vLyBUaGUgd2Fsa1xuLy8g4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbmNvbnN0IElOX1BST0dSRVNTID0gU3ltYm9sKCdpbi1wcm9ncmVzcycpO1xuXG4vKiogV2hlcmUgYSBjaGFpbidzIGlkcyBsaXZlOiBpdHMgY2hhcnQncyBzdWJmbG93IGRpY3Rpb25hcnkgYW5kIHN0YWdlIG1hcCwgYW5kIHRoZSBwcmVmaXggdGhlIHJ1biBnaXZlcyB0aGVtLiAqL1xuaW50ZXJmYWNlIEN0eCB7XG4gIHJlYWRvbmx5IHN1YmZsb3dzOiBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCB7IHJvb3Q6IFN0YWdlTm9kZSB9Pj4gfCB1bmRlZmluZWQ7XG4gIHJlYWRvbmx5IHN0YWdlTWFwOiBSZWFkb25seU1hcDxzdHJpbmcsIHVua25vd24+IHwgdW5kZWZpbmVkO1xuICByZWFkb25seSBwcmVmaXg6IHN0cmluZztcbiAgcmVhZG9ubHkgbWVtbzogTWFwPFN0YWdlTm9kZSwgQ2hhaW4gfCB0eXBlb2YgSU5fUFJPR1JFU1M+O1xufVxuXG5pbnRlcmZhY2UgQ2hhaW5SZWYge1xuICByZWFkb25seSBjdHg6IEN0eDtcbiAgcmVhZG9ubHkgc3RhcnQ6IFN0YWdlTm9kZTtcbn1cblxuLyoqIFdoYXQgYSBub2RlIHJ1bnMgaW5zaWRlIGl0c2VsZiwgYmVzaWRlcyBpdHMgb3duIGZ1bmN0aW9uLiAqL1xudHlwZSBJbnNpZGUgPVxuICB8IHsgcmVhZG9ubHkga2luZDogJ25vbmUnIH1cbiAgfCB7IHJlYWRvbmx5IGtpbmQ6ICd1bmJvdW5kZWQnOyByZWFkb25seSB3aHk6IFVuYm91bmRlZFJlYXNvbjsgcmVhZG9ubHkgc3RhZ2VJZDogc3RyaW5nIH1cbiAgLyoqIGBib3VuZGFyeWA6IHRoZSBjaGFpbnMgYXJlIGFub3RoZXIgY2hhcnQgKGEgc3ViZmxvdykg4oCUIGEgbG9vcCBjYW5ub3QgbGVhdmUgdGhlbS4gKi9cbiAgfCB7IHJlYWRvbmx5IGtpbmQ6ICdjaGFpbnMnOyByZWFkb25seSByZWZzOiByZWFkb25seSBDaGFpblJlZltdOyByZWFkb25seSBib3VuZGFyeTogYm9vbGVhbiB9O1xuXG5pbnRlcmZhY2UgU3RhZ2VDb3N0IHtcbiAgcmVhZG9ubHkgYXR0ZW1wdHM6IG51bWJlcjtcbiAgcmVhZG9ubHkgdGltZW91dE1zPzogbnVtYmVyO1xuICByZWFkb25seSBiYWNrb2ZmTXM6IG51bWJlcjtcbiAgcmVhZG9ubHkga25vd25NczogbnVtYmVyO1xuICByZWFkb25seSB3b3JzdE1zOiBudW1iZXIgfCBudWxsO1xuICByZWFkb25seSB3aHk/OiBVbmJvdW5kZWRSZWFzb247XG59XG5cbi8qKiBPbmUgbm9kZSBvZiBhIGNoYWluLiBgbXVsdGlwbGllcmAgaXMgaG93IG1hbnkgdGltZXMgdGhlIGNoYWluIHJ1bnMgaXQgcGVyIHBhc3Mgb2YgdGhlIGNoYWluLiAqL1xuaW50ZXJmYWNlIFBvc2l0aW9uIHtcbiAgcmVhZG9ubHkgc3RhZ2VJZDogc3RyaW5nO1xuICByZWFkb25seSBjb3N0OiBTdGFnZUNvc3QgfCB1bmRlZmluZWQ7XG4gIHJlYWRvbmx5IGlubmVyS25vd246IG51bWJlcjtcbiAgLyoqIFRoZSBzbG93ZXN0IGNoYWluIGl0IHJ1bnMgaW5zaWRlIGl0c2VsZiDigJQgdGhlIGNyaXRpY2FsIHBhdGggZ29lcyB0aHJvdWdoIGl0LiAqL1xuICByZWFkb25seSB2aWE6IENoYWluIHwgdW5kZWZpbmVkO1xuICAvKiogRXZlcnkgY2hhaW4gaXQgcnVucyBpbnNpZGUgaXRzZWxmLCBpbiBvcmRlci4gKi9cbiAgcmVhZG9ubHkgZGVwczogcmVhZG9ubHkgQ2hhaW5bXTtcbiAgcmVhZG9ubHkgZmxhZ3M6IFVuYm91bmRlZFN0YWdlW107XG4gIG11bHRpcGxpZXI6IG51bWJlcjtcbiAgcmVhZG9ubHkgZGVjbGFyZWRQYXNzZXM/OiBudW1iZXI7XG59XG5cbi8qKiBBIGNvbXB1dGVkIGNoYWluOiBhIHJ1biBvZiBgbmV4dGAgcG9pbnRlcnMsIGFuZCB3aGF0IHRoZSBub2RlcyBvbiBpdCBydW4gaW5zaWRlIHRoZW1zZWx2ZXMuICovXG5pbnRlcmZhY2UgQ2hhaW4ge1xuICByZWFkb25seSBrbm93bjogbnVtYmVyO1xuICByZWFkb25seSBib3VuZGVkOiBib29sZWFuO1xuICAvKiogTG9vcCB0YXJnZXRzIChyYXcgaWRzKSB0aGlzIGNoYWluIGp1bXBzIGJhY2sgdG8gYW5kIGRvZXMgbm90IGhvbGQg4oCUIHRoZSBlbmNsb3NpbmcgY2hhaW4gcmVzb2x2ZXMgdGhlbS4gKi9cbiAgcmVhZG9ubHkgb3BlbjogUmVhZG9ubHlTZXQ8c3RyaW5nPjtcbiAgcmVhZG9ubHkgcG9zaXRpb25zOiByZWFkb25seSBQb3NpdGlvbltdO1xufVxuXG5pbnRlcmZhY2UgTG9vcCB7XG4gIHJlYWRvbmx5IHN0YXJ0OiBudW1iZXI7XG4gIHJlYWRvbmx5IGVuZDogbnVtYmVyO1xuICByZWFkb25seSBwYXNzZXM6IG51bWJlcjtcbn1cblxuY29uc3QgTk9ORTogSW5zaWRlID0geyBraW5kOiAnbm9uZScgfTtcbmNvbnN0IEVNUFRZOiBSZWFkb25seVNldDxzdHJpbmc+ID0gbmV3IFNldCgpO1xuXG5jbGFzcyBCdWRnZXRXYWxrIHtcbiAgLyoqIEV2ZXJ5IGNoYWluLCBpbiB0aGUgb3JkZXIgY29tcHV0ZWQ6IGVhY2ggb25lIGFmdGVyIGV2ZXJ5IGNoYWluIGl0IHJ1bnMgaW5zaWRlIGl0c2VsZi4gKi9cbiAgcmVhZG9ubHkgY29tcHV0ZWQ6IENoYWluW10gPSBbXTtcbiAgcHJpdmF0ZSByZWFkb25seSBjdHhzID0gbmV3IE1hcDxvYmplY3QsIE1hcDxzdHJpbmcsIEN0eD4+KCk7XG5cbiAgLyoqIE5vZGUgdmlzaXRzIHNvIGZhciDigJQgY2FwcGVkIGF0IGBNQVhfV0FMS2AuICovXG4gIHByaXZhdGUgd2Fsa2VkID0gMDtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IGFzc3VtZTogQWRtaXR0ZWRBc3N1bXB0aW9ucykge31cblxuICAvKiogVGhlIGNoYWluIGZyb20gYHN0YXJ0YCDigJQgZXZlcnkgbm9kZSB2aXNpdCBjb3VudGVkIGFnYWluc3QgYE1BWF9XQUxLYC4gKi9cbiAgcHJpdmF0ZSBjaGFpbk9mKHN0YXJ0OiBTdGFnZU5vZGUpOiBDaGFpblNoYXBlIHtcbiAgICBjb25zdCBub2RlczogU3RhZ2VOb2RlW10gPSBbXTtcbiAgICBjb25zdCBzZWVuID0gbmV3IFNldDxTdGFnZU5vZGU+KCk7XG4gICAgbGV0IGN1cjogU3RhZ2VOb2RlIHwgdW5kZWZpbmVkID0gc3RhcnQ7XG4gICAgd2hpbGUgKGlzTm9kZShjdXIpKSB7XG4gICAgICBpZiAoY3VyLmlzTG9vcFJlZikgcmV0dXJuIHsgbm9kZXMsIGJhY2tJZDogU3RyaW5nKGN1ci5pZCkgfTtcbiAgICAgIGlmIChzZWVuLmhhcyhjdXIpKSByZXR1cm4geyBub2RlcywgYmFja1RvOiBjdXIgfTtcbiAgICAgIGlmICgrK3RoaXMud2Fsa2VkID4gTUFYX1dBTEspIHtcbiAgICAgICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoXG4gICAgICAgICAgYHRpbWVCdWRnZXQ6IHRoZSB3YWxrIHBhc3NlZCAke01BWF9XQUxLfSBub2RlIHZpc2l0cyBhbmQgc3RvcHBlZC4gQSBidWlsZGVyIGNoYXJ0IHZpc2l0cyBlYWNoIG5vZGUgYXQgYCArXG4gICAgICAgICAgICAnbW9zdCB0d2ljZTsgYSBoYW5kLWJ1aWx0IGdyYXBoIHdob3NlIGNoYWlucyBzaGFyZSB0aGVpciB0YWlscyB3YWxrcyB0aGUgc2hhcmVkIHRhaWwgb25jZSBwZXIgY2hhaW4uICcgK1xuICAgICAgICAgICAgJ1RoZSBidWRnZXQgb2YgdGhpcyBncmFwaCBjYW5ub3QgYmUgY29tcHV0ZWQuJyxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIHNlZW4uYWRkKGN1cik7XG4gICAgICBub2Rlcy5wdXNoKGN1cik7XG4gICAgICBjdXIgPSBjdXIubmV4dDtcbiAgICB9XG4gICAgcmV0dXJuIHsgbm9kZXMgfTtcbiAgfVxuXG4gIGN0eE9mKFxuICAgIG93bmVyOiB7XG4gICAgICByZWFkb25seSBzdWJmbG93cz86IFJlY29yZDxzdHJpbmcsIHsgcm9vdDogU3RhZ2VOb2RlIH0+O1xuICAgICAgcmVhZG9ubHkgc3RhZ2VNYXA/OiBSZWFkb25seU1hcDxzdHJpbmcsIHVua25vd24+O1xuICAgIH0sXG4gICAgcHJlZml4OiBzdHJpbmcsXG4gICk6IEN0eCB7XG4gICAgbGV0IGJ5UHJlZml4ID0gdGhpcy5jdHhzLmdldChvd25lcik7XG4gICAgaWYgKGJ5UHJlZml4ID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGJ5UHJlZml4ID0gbmV3IE1hcCgpO1xuICAgICAgdGhpcy5jdHhzLnNldChvd25lciwgYnlQcmVmaXgpO1xuICAgIH1cbiAgICBsZXQgY3R4ID0gYnlQcmVmaXguZ2V0KHByZWZpeCk7XG4gICAgaWYgKGN0eCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBjdHggPSB7IHN1YmZsb3dzOiBvd25lci5zdWJmbG93cywgc3RhZ2VNYXA6IG93bmVyLnN0YWdlTWFwLCBwcmVmaXgsIG1lbW86IG5ldyBNYXAoKSB9O1xuICAgICAgYnlQcmVmaXguc2V0KHByZWZpeCwgY3R4KTtcbiAgICB9XG4gICAgcmV0dXJuIGN0eDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb21wdXRlIGByb290YCBhbmQgZXZlcnkgY2hhaW4gaXQgcnVucyDigJQgYW4gZXhwbGljaXQgc3RhY2ssIG5ldmVyIHJlY3Vyc2lvbi4gQSBjaGFpbiBpcyBtYXJrZWQgaW4gcHJvZ3Jlc3Mgb25cbiAgICogaXRzIGZpcnN0IHZpc2l0IGFuZCBwdXNoZXMgdGhlIGNoYWlucyBpdCBuZWVkczsgaXQgaXMgY29tcHV0ZWQgb24gaXRzIHNlY29uZCwgd2hlbiB0aGV5IGFyZSBkb25lLiBBIGNoYWluIHRoYXRcbiAgICogbmVlZHMgb25lIHN0aWxsIGluIHByb2dyZXNzIG5lZWRzIGl0c2VsZjogYW4gb2JqZWN0IGN5Y2xlLCBjb3VudGVkIGFzIGEgbG9vcC5cbiAgICovXG4gIGV2YWx1YXRlKHJvb3Q6IENoYWluUmVmKTogQ2hhaW4ge1xuICAgIGNvbnN0IHN0YWNrOiBDaGFpblJlZltdID0gW3Jvb3RdO1xuICAgIHdoaWxlIChzdGFjay5sZW5ndGggPiAwKSB7XG4gICAgICBjb25zdCByZWYgPSBzdGFja1tzdGFjay5sZW5ndGggLSAxXTtcbiAgICAgIGNvbnN0IHN0YXRlID0gcmVmLmN0eC5tZW1vLmdldChyZWYuc3RhcnQpO1xuICAgICAgaWYgKHN0YXRlICE9PSB1bmRlZmluZWQgJiYgc3RhdGUgIT09IElOX1BST0dSRVNTKSB7XG4gICAgICAgIHN0YWNrLnBvcCgpO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IG5vZGVzID0gdGhpcy5jaGFpbk9mKHJlZi5zdGFydCk7XG4gICAgICBjb25zdCBpbnNpZGVzID0gbm9kZXMubm9kZXMubWFwKChub2RlKSA9PiB0aGlzLmluc2lkZU9mKG5vZGUsIHJlZi5jdHgpKTtcbiAgICAgIGlmIChzdGF0ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJlZi5jdHgubWVtby5zZXQocmVmLnN0YXJ0LCBJTl9QUk9HUkVTUyk7XG4gICAgICAgIGNvbnN0IGJlZm9yZSA9IHN0YWNrLmxlbmd0aDtcbiAgICAgICAgZm9yIChjb25zdCBpbnNpZGUgb2YgaW5zaWRlcykge1xuICAgICAgICAgIGlmIChpbnNpZGUua2luZCAhPT0gJ2NoYWlucycpIGNvbnRpbnVlO1xuICAgICAgICAgIGZvciAoY29uc3QgZGVwIG9mIGluc2lkZS5yZWZzKSBpZiAoIWRlcC5jdHgubWVtby5oYXMoZGVwLnN0YXJ0KSkgc3RhY2sucHVzaChkZXApO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzdGFjay5sZW5ndGggPiBiZWZvcmUpIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgc3RhY2sucG9wKCk7XG4gICAgICBjb25zdCBjaGFpbiA9IHRoaXMuY2hhaW5SZXN1bHQocmVmLmN0eCwgbm9kZXMsIGluc2lkZXMpO1xuICAgICAgcmVmLmN0eC5tZW1vLnNldChyZWYuc3RhcnQsIGNoYWluKTtcbiAgICAgIHRoaXMuY29tcHV0ZWQucHVzaChjaGFpbik7XG4gICAgfVxuICAgIHJldHVybiByb290LmN0eC5tZW1vLmdldChyb290LnN0YXJ0KSBhcyBDaGFpbjtcbiAgfVxuXG4gIHByaXZhdGUgaW5zaWRlT2Yobm9kZTogU3RhZ2VOb2RlLCBjdHg6IEN0eCk6IEluc2lkZSB7XG4gICAgaWYgKG5vZGUuaXNEeW5hbWljUGFyYWxsZWwpIHtcbiAgICAgIGNvbnN0IHN0YWdlSWQgPSByZXBvcnRlZChjdHgsIG5vZGUuaWQpO1xuICAgICAgY29uc3QgY2hhcnQgPSBvd24odGhpcy5hc3N1bWUuYnJhbmNoZXMsIHN0YWdlSWQpO1xuICAgICAgaWYgKGNoYXJ0ID09PSB1bmRlZmluZWQpIHJldHVybiB7IGtpbmQ6ICd1bmJvdW5kZWQnLCB3aHk6ICdpdGVtcycsIHN0YWdlSWQgfTtcbiAgICAgIGNvbnN0IGJyYW5jaCA9IGJ1aWxkQnJhbmNoU2VnbWVudChzdGFnZUlkLCAwKTtcbiAgICAgIHJldHVybiB7IGtpbmQ6ICdjaGFpbnMnLCByZWZzOiBbeyBjdHg6IHRoaXMuY3R4T2YoY2hhcnQsIGJyYW5jaCksIHN0YXJ0OiBjaGFydC5yb290IH1dLCBib3VuZGFyeTogdHJ1ZSB9O1xuICAgIH1cbiAgICBpZiAoaXNNb3VudChub2RlKSkgcmV0dXJuIHRoaXMubW91bnRPZihub2RlLCBjdHgpO1xuICAgIGNvbnN0IGNoaWxkcmVuID0gY2hpbGRyZW5PZihub2RlKTtcbiAgICBpZiAoY2hpbGRyZW4ubGVuZ3RoID4gMClcbiAgICAgIHJldHVybiB7IGtpbmQ6ICdjaGFpbnMnLCByZWZzOiBjaGlsZHJlbi5tYXAoKHN0YXJ0KSA9PiAoeyBjdHgsIHN0YXJ0IH0pKSwgYm91bmRhcnk6IGZhbHNlIH07XG4gICAgcmV0dXJuIE5PTkU7XG4gIH1cblxuICAvKiogQSBzdWJmbG93IG1vdW50IOKAlCByZXNvbHZlZCB0aGUgd2F5IHRoZSBlbmdpbmUgcmVzb2x2ZXMgaXQgKGBOb2RlUmVzb2x2ZXIgwrcgcmVzb2x2ZVN1YmZsb3dSZWZlcmVuY2VgKS4gKi9cbiAgcHJpdmF0ZSBtb3VudE9mKG5vZGU6IFN0YWdlTm9kZSwgY3R4OiBDdHgpOiBJbnNpZGUge1xuICAgIGNvbnN0IHN1YmZsb3dJZCA9IHJlcG9ydGVkKGN0eCwgU3RyaW5nKG5vZGUuc3ViZmxvd0lkKSk7XG4gICAgaWYgKG5vZGUuc3ViZmxvd1Jlc29sdmVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGNvbnN0IGNoYXJ0ID0gb3duKHRoaXMuYXNzdW1lLmxhenksIHN1YmZsb3dJZCk7XG4gICAgICBpZiAoY2hhcnQgPT09IHVuZGVmaW5lZCkgcmV0dXJuIHsga2luZDogJ3VuYm91bmRlZCcsIHdoeTogJ2xhenktc3ViZmxvdycsIHN0YWdlSWQ6IHN1YmZsb3dJZCB9O1xuICAgICAgcmV0dXJuIHsga2luZDogJ2NoYWlucycsIHJlZnM6IFt7IGN0eDogdGhpcy5jdHhPZihjaGFydCwgc3ViZmxvd0lkKSwgc3RhcnQ6IGNoYXJ0LnJvb3QgfV0sIGJvdW5kYXJ5OiB0cnVlIH07XG4gICAgfVxuICAgIGNvbnN0IGlubGluZSA9IG5vZGUuc3ViZmxvd0RlZjtcbiAgICBpZiAoaW5saW5lPy5yb290ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGtpbmQ6ICdjaGFpbnMnLFxuICAgICAgICByZWZzOiBbeyBjdHg6IHRoaXMuY3R4T2YoaW5saW5lIGFzIFBhcmFtZXRlcnM8QnVkZ2V0V2Fsa1snY3R4T2YnXT5bMF0sIGN0eC5wcmVmaXgpLCBzdGFydDogaW5saW5lLnJvb3QgfV0sXG4gICAgICAgIGJvdW5kYXJ5OiB0cnVlLFxuICAgICAgfTtcbiAgICB9XG4gICAgY29uc3QgZGVmID0gc3ViZmxvd0RlZk9mKGN0eC5zdWJmbG93cywgbm9kZSk7XG4gICAgcmV0dXJuIGRlZiA9PT0gdW5kZWZpbmVkID8gTk9ORSA6IHsga2luZDogJ2NoYWlucycsIHJlZnM6IFt7IGN0eCwgc3RhcnQ6IGRlZi5yb290IH1dLCBib3VuZGFyeTogdHJ1ZSB9O1xuICB9XG5cbiAgcHJpdmF0ZSBjaGFpblJlc3VsdChjdHg6IEN0eCwgc2hhcGU6IENoYWluU2hhcGUsIGluc2lkZXM6IHJlYWRvbmx5IEluc2lkZVtdKTogQ2hhaW4ge1xuICAgIGNvbnN0IHsgbm9kZXMgfSA9IHNoYXBlO1xuICAgIGNvbnN0IGF0ID0gbmV3IE1hcDxzdHJpbmcsIG51bWJlcj4oKTtcbiAgICBub2Rlcy5mb3JFYWNoKChub2RlLCBpKSA9PiB7XG4gICAgICBpZiAoIWF0Lmhhcyhub2RlLmlkKSkgYXQuc2V0KG5vZGUuaWQsIGkpO1xuICAgIH0pO1xuICAgIGNvbnN0IGJhY2tFZGdlczogQXJyYXk8cmVhZG9ubHkgW251bWJlciwgbnVtYmVyXT4gPSBbXTtcbiAgICBjb25zdCBvcGVuID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgLy8gQSBqdW1wIHRvIGEgdGFyZ2V0IHRoaXMgY2hhaW4gaG9sZHMgYXQgb3IgYmVmb3JlIGBmcm9tYCBpcyBhIGxvb3Agb3ZlciBbdGFyZ2V0LCBmcm9tXTsgYSBmb3J3YXJkIGp1bXAgcmVwZWF0c1xuICAgIC8vIG5vdGhpbmc7IGEgdGFyZ2V0IHRoZSBjaGFpbiBkb2VzIG5vdCBob2xkIGlzIHRoZSBlbmNsb3NpbmcgY2hhaW4ncyB0byByZXNvbHZlLlxuICAgIGNvbnN0IGp1bXAgPSAodGFyZ2V0OiBzdHJpbmcsIGZyb206IG51bWJlcikgPT4ge1xuICAgICAgY29uc3QgaiA9IGF0LmdldCh0YXJnZXQpO1xuICAgICAgaWYgKGogPT09IHVuZGVmaW5lZCkgb3Blbi5hZGQodGFyZ2V0KTtcbiAgICAgIGVsc2UgaWYgKGogPD0gZnJvbSkgYmFja0VkZ2VzLnB1c2goW2osIGZyb21dKTtcbiAgICB9O1xuXG4gICAgbGV0IGJvdW5kZWQgPSB0cnVlO1xuICAgIGNvbnN0IHBvc2l0aW9uczogUG9zaXRpb25bXSA9IG5vZGVzLm1hcCgobm9kZSwgcSkgPT4ge1xuICAgICAgY29uc3Qgc3RhZ2VJZCA9IHJlcG9ydGVkKGN0eCwgbm9kZS5pZCk7XG4gICAgICBjb25zdCBmbGFnczogVW5ib3VuZGVkU3RhZ2VbXSA9IFtdO1xuICAgICAgLy8gQSBtb3VudCBydW5zIGl0cyBzdWJmbG93IGluIHBsYWNlIG9mIGEgZnVuY3Rpb24gb2YgaXRzIG93biAodGhlIGVuZ2luZSBuZXZlciBhc2tzIGl0cyBzdGFnZSBtYXApLlxuICAgICAgY29uc3QgY29zdCA9ICFpc01vdW50KG5vZGUpICYmIGhhc0Z1bmN0aW9uKG5vZGUsIGN0eCkgPyBoZWxwZXJDb3N0KHJldHJ5TG9vcEJ1ZGdldChub2RlKSwgbm9kZS5yZXRyeSkgOiB1bmRlZmluZWQ7XG4gICAgICBpZiAoY29zdD8ud2h5ICE9PSB1bmRlZmluZWQpIGZsYWdzLnB1c2goeyBzdGFnZUlkLCB3aHk6IGNvc3Qud2h5IH0pO1xuICAgICAgY29uc3QgaW5uZXIgPSB0aGlzLmlubmVyT2YoaW5zaWRlc1txXSwgZmxhZ3MpO1xuICAgICAgZm9yIChjb25zdCB0YXJnZXQgb2YgaW5uZXIub3BlbikganVtcCh0YXJnZXQsIHEpO1xuICAgICAgaWYgKGNvc3Q/LndvcnN0TXMgPT09IG51bGwgfHwgIWlubmVyLmJvdW5kZWQpIGJvdW5kZWQgPSBmYWxzZTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHN0YWdlSWQsXG4gICAgICAgIGNvc3QsXG4gICAgICAgIGlubmVyS25vd246IGlubmVyLmtub3duLFxuICAgICAgICB2aWE6IGlubmVyLnZpYSxcbiAgICAgICAgZGVwczogaW5uZXIuZGVwcyxcbiAgICAgICAgZmxhZ3MsXG4gICAgICAgIG11bHRpcGxpZXI6IDEsXG4gICAgICAgIGRlY2xhcmVkUGFzc2VzOiByZXRyeUxvb3BCdWRnZXQobm9kZSk/LnBhc3NlcyxcbiAgICAgIH07XG4gICAgfSk7XG4gICAgaWYgKHNoYXBlLmJhY2tUbyAhPT0gdW5kZWZpbmVkKSBiYWNrRWRnZXMucHVzaChbbm9kZXMuaW5kZXhPZihzaGFwZS5iYWNrVG8pLCBub2Rlcy5sZW5ndGggLSAxXSk7XG4gICAgaWYgKHNoYXBlLmJhY2tJZCAhPT0gdW5kZWZpbmVkKSBqdW1wKHNoYXBlLmJhY2tJZCwgbm9kZXMubGVuZ3RoIC0gMSk7XG5cbiAgICBpZiAoIXRoaXMuYXBwbHlMb29wcyhwb3NpdGlvbnMsIGJhY2tFZGdlcykpIGJvdW5kZWQgPSBmYWxzZTtcbiAgICBsZXQga25vd24gPSAwO1xuICAgIGZvciAoY29uc3QgcCBvZiBwb3NpdGlvbnMpIGtub3duID0gYWRkKGtub3duLCBtdWwocC5tdWx0aXBsaWVyLCBhZGQocC5jb3N0Py5rbm93bk1zID8/IDAsIHAuaW5uZXJLbm93bikpKTtcbiAgICByZXR1cm4geyBrbm93biwgYm91bmRlZCwgb3BlbiwgcG9zaXRpb25zIH07XG4gIH1cblxuICAvKiogVGhlIHNsb3dlc3Qgb2YgdGhlIGNoYWlucyBhIG5vZGUgcnVucyBpbnNpZGUgaXRzZWxmICh0aGV5IGFyZSBhbHRlcm5hdGl2ZXMsIG9yIHJ1biBhdCBvbmNlKS4gKi9cbiAgcHJpdmF0ZSBpbm5lck9mKFxuICAgIGluc2lkZTogSW5zaWRlLFxuICAgIGZsYWdzOiBVbmJvdW5kZWRTdGFnZVtdLFxuICApOiB7IGtub3duOiBudW1iZXI7IGJvdW5kZWQ6IGJvb2xlYW47IHZpYT86IENoYWluOyBkZXBzOiBDaGFpbltdOyBvcGVuOiBSZWFkb25seVNldDxzdHJpbmc+IH0ge1xuICAgIGlmIChpbnNpZGUua2luZCA9PT0gJ25vbmUnKSByZXR1cm4geyBrbm93bjogMCwgYm91bmRlZDogdHJ1ZSwgZGVwczogW10sIG9wZW46IEVNUFRZIH07XG4gICAgaWYgKGluc2lkZS5raW5kID09PSAndW5ib3VuZGVkJykge1xuICAgICAgZmxhZ3MucHVzaCh7IHN0YWdlSWQ6IGluc2lkZS5zdGFnZUlkLCB3aHk6IGluc2lkZS53aHkgfSk7XG4gICAgICByZXR1cm4geyBrbm93bjogMCwgYm91bmRlZDogZmFsc2UsIGRlcHM6IFtdLCBvcGVuOiBFTVBUWSB9O1xuICAgIH1cbiAgICBsZXQgdmlhOiBDaGFpbiB8IHVuZGVmaW5lZDtcbiAgICBsZXQgYm91bmRlZCA9IHRydWU7XG4gICAgY29uc3QgZGVwczogQ2hhaW5bXSA9IFtdO1xuICAgIGNvbnN0IG9wZW4gPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICBmb3IgKGNvbnN0IHJlZiBvZiBpbnNpZGUucmVmcykge1xuICAgICAgY29uc3QgY2hhaW4gPSByZWYuY3R4Lm1lbW8uZ2V0KHJlZi5zdGFydCk7XG4gICAgICBpZiAoY2hhaW4gPT09IHVuZGVmaW5lZCB8fCBjaGFpbiA9PT0gSU5fUFJPR1JFU1MpIHtcbiAgICAgICAgZmxhZ3MucHVzaCh7IHN0YWdlSWQ6IHJlcG9ydGVkKHJlZi5jdHgsIHJlZi5zdGFydC5pZCksIHdoeTogJ2xvb3AnIH0pO1xuICAgICAgICBib3VuZGVkID0gZmFsc2U7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgZGVwcy5wdXNoKGNoYWluKTtcbiAgICAgIGlmICghY2hhaW4uYm91bmRlZCkgYm91bmRlZCA9IGZhbHNlO1xuICAgICAgZm9yIChjb25zdCB0YXJnZXQgb2YgY2hhaW4ub3Blbikge1xuICAgICAgICBpZiAoIWluc2lkZS5ib3VuZGFyeSkge1xuICAgICAgICAgIG9wZW4uYWRkKHRhcmdldCk7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQSBzdWJmbG93J3Mgb3duIHRyYXZlcnNlciBsb29rcyBpdHMgbG9vcCB0YXJnZXRzIHVwIGluIGl0cyBvd24gY2hhcnQ6IG9uZSBpdCBkb2VzIG5vdCBob2xkIG5ldmVyIHJlc29sdmVzLlxuICAgICAgICBmbGFncy5wdXNoKHsgc3RhZ2VJZDogcmVwb3J0ZWQocmVmLmN0eCwgdGFyZ2V0KSwgd2h5OiAnbG9vcCcgfSk7XG4gICAgICAgIGJvdW5kZWQgPSBmYWxzZTtcbiAgICAgIH1cbiAgICAgIGlmICh2aWEgPT09IHVuZGVmaW5lZCB8fCBjaGFpbi5rbm93biA+IHZpYS5rbm93bikgdmlhID0gY2hhaW47XG4gICAgfVxuICAgIHJldHVybiB7IGtub3duOiB2aWE/Lmtub3duID8/IDAsIGJvdW5kZWQsIC4uLih2aWEgIT09IHVuZGVmaW5lZCAmJiB7IHZpYSB9KSwgZGVwcywgb3BlbiB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFR1cm4gYSBjaGFpbidzIGJhY2stZWRnZXMgaW50byBlYWNoIHBvc2l0aW9uJ3MgbXVsdGlwbGllci4gT25lIGxvb3AgcGVyIHRhcmdldCwgc3Bhbm5pbmcgdG8gaXRzIGZ1cnRoZXN0XG4gICAqIHNvdXJjZS4gTG9vcHMgYXJlIHRha2VuIGluIHN0YXJ0IG9yZGVyIG9uIGEgc3RhY2sgb2YgbmVzdGVkIG9uZXM7IGEgbG9vcCB0aGF0IG92ZXJsYXBzIHRoZSBvbmUgaXQgc3RhcnRzIGluc2lkZVxuICAgKiB3aXRob3V0IG5lc3RpbmcgbWVyZ2VzIHdpdGggaXQgKHRoZSBwcm9kdWN0IG9mIHRoZWlyIHBhc3NlcyDigJQgZWFjaCBjYW4gcmUtZW50ZXIgdGhlIG90aGVyKSwgc28gd2hhdCBpcyBsZWZ0IGlzXG4gICAqIGxhbWluYXIsIGFuZCBvbmUgc3dlZXAgbXVsdGlwbGllcyBldmVyeSBwb3NpdGlvbiBieSB0aGUgbG9vcHMgYXJvdW5kIGl0LiBSZXR1cm5zIGZhbHNlIHdoZW4gYSBsb29wIGhhcyBub1xuICAgKiBhc3N1bWVkIHBhc3NlcyAoaXQgaXMgZmxhZ2dlZCBvbiBpdHMgdGFyZ2V0IGFuZCBjb3VudGVkIG9uY2UpLlxuICAgKi9cbiAgcHJpdmF0ZSBhcHBseUxvb3BzKHBvc2l0aW9uczogUG9zaXRpb25bXSwgYmFja0VkZ2VzOiBSZWFkb25seUFycmF5PHJlYWRvbmx5IFtudW1iZXIsIG51bWJlcl0+KTogYm9vbGVhbiB7XG4gICAgaWYgKGJhY2tFZGdlcy5sZW5ndGggPT09IDApIHJldHVybiB0cnVlO1xuICAgIGNvbnN0IGVuZHMgPSBuZXcgTWFwPG51bWJlciwgbnVtYmVyPigpO1xuICAgIGZvciAoY29uc3QgW3RhcmdldCwgc291cmNlXSBvZiBiYWNrRWRnZXMpIGVuZHMuc2V0KHRhcmdldCwgTWF0aC5tYXgoZW5kcy5nZXQodGFyZ2V0KSA/PyB0YXJnZXQsIHNvdXJjZSkpO1xuXG4gICAgbGV0IGJvdW5kZWQgPSB0cnVlO1xuICAgIGNvbnN0IGRvbmU6IExvb3BbXSA9IFtdO1xuICAgIGNvbnN0IGFjdGl2ZTogTG9vcFtdID0gW107XG4gICAgZm9yIChjb25zdCBbc3RhcnQsIGVuZF0gb2YgWy4uLmVuZHNdLnNvcnQoKGEsIGIpID0+IGFbMF0gLSBiWzBdKSkge1xuICAgICAgY29uc3QgdGFyZ2V0ID0gcG9zaXRpb25zW3N0YXJ0XTtcbiAgICAgIGNvbnN0IGFzc3VtZWQgPSBvd24odGhpcy5hc3N1bWUubG9vcHMsIHRhcmdldC5zdGFnZUlkKTtcbiAgICAgIGNvbnN0IHBhc3NlcyA9IHRhcmdldC5kZWNsYXJlZFBhc3NlcyA9PT0gdW5kZWZpbmVkID8gYXNzdW1lZCA6IE1hdGgubWF4KHRhcmdldC5kZWNsYXJlZFBhc3NlcywgYXNzdW1lZCA/PyAxKTtcbiAgICAgIGlmIChwYXNzZXMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0YXJnZXQuZmxhZ3MucHVzaCh7IHN0YWdlSWQ6IHRhcmdldC5zdGFnZUlkLCB3aHk6ICdsb29wJyB9KTtcbiAgICAgICAgYm91bmRlZCA9IGZhbHNlO1xuICAgICAgfVxuICAgICAgLy8gVGhlIGFjdGl2ZSBsb29wcyBuZXN0IChlYWNoIGluc2lkZSB0aGUgb25lIGJlbG93IGl0KTogdGhlIGlubmVybW9zdCBlbmRzIGZpcnN0LlxuICAgICAgbGV0IHRvcCA9IGxhc3RPZihhY3RpdmUpO1xuICAgICAgd2hpbGUgKHRvcCAhPT0gdW5kZWZpbmVkICYmIHRvcC5lbmQgPCBzdGFydCkge1xuICAgICAgICBkb25lLnB1c2godG9wKTtcbiAgICAgICAgYWN0aXZlLnBvcCgpO1xuICAgICAgICB0b3AgPSBsYXN0T2YoYWN0aXZlKTtcbiAgICAgIH1cbiAgICAgIC8vIFN0YXJ0cyBpbnNpZGUgYHRvcGAgYW5kIGVuZHMgcGFzdCBpdDogdGhleSBvdmVybGFwIHdpdGhvdXQgbmVzdGluZyDigJQgb25lIHJlZ2lvbiwgdGhlIHByb2R1Y3Qgb2YgcGFzc2VzLlxuICAgICAgbGV0IGxvb3A6IExvb3AgPSB7IHN0YXJ0LCBlbmQsIHBhc3NlczogcGFzc2VzID8/IDEgfTtcbiAgICAgIHdoaWxlICh0b3AgIT09IHVuZGVmaW5lZCAmJiB0b3AuZW5kIDwgbG9vcC5lbmQpIHtcbiAgICAgICAgYWN0aXZlLnBvcCgpO1xuICAgICAgICBsb29wID0geyBzdGFydDogdG9wLnN0YXJ0LCBlbmQ6IGxvb3AuZW5kLCBwYXNzZXM6IG11bCh0b3AucGFzc2VzLCBsb29wLnBhc3NlcykgfTtcbiAgICAgICAgdG9wID0gbGFzdE9mKGFjdGl2ZSk7XG4gICAgICB9XG4gICAgICBhY3RpdmUucHVzaChsb29wKTtcbiAgICB9XG4gICAgZG9uZS5wdXNoKC4uLmFjdGl2ZSk7XG5cbiAgICBkb25lLnNvcnQoKGEsIGIpID0+IGEuc3RhcnQgLSBiLnN0YXJ0IHx8IGIuZW5kIC0gYS5lbmQpO1xuICAgIGNvbnN0IGFyb3VuZDogQXJyYXk8eyByZWFkb25seSBlbmQ6IG51bWJlcjsgcmVhZG9ubHkgcHJvZHVjdDogbnVtYmVyIH0+ID0gW107XG4gICAgbGV0IG5leHQgPSAwO1xuICAgIGZvciAobGV0IHEgPSAwOyBxIDwgcG9zaXRpb25zLmxlbmd0aDsgcSsrKSB7XG4gICAgICB3aGlsZSAoYXJvdW5kLmxlbmd0aCA+IDAgJiYgYXJvdW5kW2Fyb3VuZC5sZW5ndGggLSAxXS5lbmQgPCBxKSBhcm91bmQucG9wKCk7XG4gICAgICB3aGlsZSAobmV4dCA8IGRvbmUubGVuZ3RoICYmIGRvbmVbbmV4dF0uc3RhcnQgPT09IHEpIHtcbiAgICAgICAgY29uc3Qgb3V0ZXIgPSBhcm91bmQubGVuZ3RoID4gMCA/IGFyb3VuZFthcm91bmQubGVuZ3RoIC0gMV0ucHJvZHVjdCA6IDE7XG4gICAgICAgIGFyb3VuZC5wdXNoKHsgZW5kOiBkb25lW25leHRdLmVuZCwgcHJvZHVjdDogbXVsKG91dGVyLCBkb25lW25leHRdLnBhc3NlcykgfSk7XG4gICAgICAgIG5leHQrKztcbiAgICAgIH1cbiAgICAgIHBvc2l0aW9uc1txXS5tdWx0aXBsaWVyID0gYXJvdW5kLmxlbmd0aCA+IDAgPyBhcm91bmRbYXJvdW5kLmxlbmd0aCAtIDFdLnByb2R1Y3QgOiAxO1xuICAgIH1cbiAgICByZXR1cm4gYm91bmRlZDtcbiAgfVxufVxuXG4vKiogQSBydW4gb2YgYG5leHRgIHBvaW50ZXJzIGZyb20gYHN0YXJ0YDogaXRzIG5vZGVzLCBhbmQgd2hlcmUgaXQganVtcHMgYmFjayB0byAoYSBsb29wIHN0dWIncyBpZCwgb3IgYSBjeWNsZSkuICovXG5pbnRlcmZhY2UgQ2hhaW5TaGFwZSB7XG4gIHJlYWRvbmx5IG5vZGVzOiByZWFkb25seSBTdGFnZU5vZGVbXTtcbiAgcmVhZG9ubHkgYmFja0lkPzogc3RyaW5nO1xuICByZWFkb25seSBiYWNrVG8/OiBTdGFnZU5vZGU7XG59XG5cbi8vIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuLy8gT25lIHN0YWdlXG4vLyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuLyoqXG4gKiBUaGUgZW5naW5lJ3MgbW91bnQgdGVzdCAoYEZsb3djaGFydFRyYXZlcnNlcmAgUGhhc2UgMCB3aXRoIGBOb2RlUmVzb2x2ZXIgwrcgcmVzb2x2ZVN1YmZsb3dSZWZlcmVuY2VgKTogYSBzdWJmbG93XG4gKiByb290IHdpdGggYSBzdWJmbG93IGlkIHJ1bnMgaXRzIHN1YmZsb3cg4oCUIGEgbGF6eSBvbmUgYWx3YXlzLCBhbiBlYWdlciBvbmUgd2hlbiBpdCBoYXMgbm8gZnVuY3Rpb24gb2YgaXRzIE9XTiBhbmQgbm9cbiAqIGNoaWxkcmVuICh0aGUgcmVzb2x2ZXIgbmV2ZXIgYXNrcyB0aGUgc3RhZ2UgbWFwKS4gQW55dGhpbmcgZWxzZSBpcyBhIG5vZGUgbGlrZSBhbnkgb3RoZXIuXG4gKi9cbmZ1bmN0aW9uIGlzTW91bnQobm9kZTogU3RhZ2VOb2RlKTogYm9vbGVhbiB7XG4gIGlmIChub2RlLmlzU3ViZmxvd1Jvb3QgIT09IHRydWUgfHwgdHlwZW9mIG5vZGUuc3ViZmxvd0lkICE9PSAnc3RyaW5nJyB8fCBub2RlLnN1YmZsb3dJZCA9PT0gJycpIHJldHVybiBmYWxzZTtcbiAgcmV0dXJuIG5vZGUuc3ViZmxvd1Jlc29sdmVyICE9PSB1bmRlZmluZWQgfHwgKHR5cGVvZiBub2RlLmZuICE9PSAnZnVuY3Rpb24nICYmIGNoaWxkcmVuT2Yobm9kZSkubGVuZ3RoID09PSAwKTtcbn1cblxuLyoqIEEgbm9kZSdzIGNoaWxkcmVuIHRoYXQgYXJlIG5vZGVzIOKAlCBhIGhhbmQtYnVpbHQgYG51bGxgIGlzIHNraXBwZWQsIG5ldmVyIGRlcmVmZXJlbmNlZC4gKi9cbmZ1bmN0aW9uIGNoaWxkcmVuT2Yobm9kZTogU3RhZ2VOb2RlKTogU3RhZ2VOb2RlW10ge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheShub2RlLmNoaWxkcmVuKSA/IG5vZGUuY2hpbGRyZW4uZmlsdGVyKGlzTm9kZSkgOiBbXTtcbn1cblxuY29uc3QgaXNOb2RlID0gKHZhbHVlOiB1bmtub3duKTogdmFsdWUgaXMgU3RhZ2VOb2RlID0+IHZhbHVlICE9PSBudWxsICYmIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCc7XG5cbi8qKiBUaGUgZW5naW5lJ3MgbG9va3VwIChgRmxvd2NoYXJ0VHJhdmVyc2VyIMK3IGdldFN0YWdlRm5gKTogdGhlIG5vZGUncyBvd24gZnVuY3Rpb24sIGVsc2UgdGhlIG1hcCdzIGJ5IGlkIG9yIG5hbWUuICovXG5mdW5jdGlvbiBoYXNGdW5jdGlvbihub2RlOiBTdGFnZU5vZGUsIGN0eDogQ3R4KTogYm9vbGVhbiB7XG4gIGlmICh0eXBlb2Ygbm9kZS5mbiA9PT0gJ2Z1bmN0aW9uJykgcmV0dXJuIHRydWU7XG4gIGNvbnN0IG1hcCA9IGN0eC5zdGFnZU1hcDtcbiAgcmV0dXJuIG1hcCAhPT0gdW5kZWZpbmVkICYmIChtYXAuZ2V0KG5vZGUuaWQpICE9PSB1bmRlZmluZWQgfHwgbWFwLmdldChub2RlLm5hbWUpICE9PSB1bmRlZmluZWQpO1xufVxuXG4vKiogQSBzdGFnZSdzIHdvcnN0IGNhc2UgdW5kZXIgaXRzIHBvbGljeSDigJQgcmVhZCBieSB0aGUgZW5naW5lJ3Mgb3duIHJlYWRpbmdzIG9mIGl0IChgYXR0ZW1wdC9wb2xpY3kudHNgKS4gKi9cbmZ1bmN0aW9uIGhlbHBlckNvc3QoYnVkZ2V0OiBSZXRyeUxvb3BCdWRnZXQgfCB1bmRlZmluZWQsIHBvbGljeTogUmV0cnlQb2xpY3kgfCB1bmRlZmluZWQpOiBTdGFnZUNvc3Qge1xuICBpZiAoYnVkZ2V0ID09PSB1bmRlZmluZWQpIHJldHVybiBzdGFnZUNvc3QocG9saWN5KTtcbiAgaWYgKGJ1ZGdldC5yb2xlID09PSAnY2FsbGJhY2snKSByZXR1cm4gc3RhZ2VDb3N0KHsgYXR0ZW1wdHM6IDEsIHRpbWVvdXRNczogYnVkZ2V0LnRpbWVvdXRNcyB9KTtcbiAgY29uc3QgbXMgPSBidWRnZXQucm9sZSA9PT0gJ2NvbnRyb2wnID8gMCA6IGJ1ZGdldC53YWl0TXM7XG4gIHJldHVybiB7XG4gICAgYXR0ZW1wdHM6IDEsXG4gICAgdGltZW91dE1zOiBtcyA/PyAwLFxuICAgIGJhY2tvZmZNczogMCxcbiAgICBrbm93bk1zOiBtcyA/PyAwLFxuICAgIHdvcnN0TXM6IG1zID8/IG51bGwsXG4gICAgLi4uKG1zID09PSB1bmRlZmluZWQgPyB7IHdoeTogJ2JhY2tvZmYnIGFzIGNvbnN0IH0gOiB7fSksXG4gIH07XG59XG5cbmZ1bmN0aW9uIHN0YWdlQ29zdChwb2xpY3k6IFJldHJ5UG9saWN5IHwgdW5kZWZpbmVkKTogU3RhZ2VDb3N0IHtcbiAgY29uc3QgYXR0ZW1wdHMgPSBwb2xpY3kgPT09IHVuZGVmaW5lZCA/IDEgOiBhdHRlbXB0Q2VpbGluZyhwb2xpY3kuYXR0ZW1wdHMpO1xuICBjb25zdCB0aW1lb3V0TXMgPSBwb2xpY3kgPT09IHVuZGVmaW5lZCA/IHVuZGVmaW5lZCA6IGF0dGVtcHRUaW1lb3V0TXMocG9saWN5LnRpbWVvdXRNcyk7XG4gIGNvbnN0IHdhaXRzID0gd2FpdHNPZihwb2xpY3ksIGF0dGVtcHRzKTtcbiAgY29uc3Qga25vd25NcyA9IGFkZCh0aW1lb3V0TXMgPT09IHVuZGVmaW5lZCA/IDAgOiBtdWwoYXR0ZW1wdHMsIHRpbWVvdXRNcyksIHdhaXRzLm1zKTtcbiAgY29uc3Qgd2h5OiBVbmJvdW5kZWRSZWFzb24gfCB1bmRlZmluZWQgPSB0aW1lb3V0TXMgPT09IHVuZGVmaW5lZCA/ICduby10aW1lb3V0JyA6IHdhaXRzLmtub3duID8gdW5kZWZpbmVkIDogJ2JhY2tvZmYnO1xuICByZXR1cm4ge1xuICAgIGF0dGVtcHRzLFxuICAgIC4uLih0aW1lb3V0TXMgIT09IHVuZGVmaW5lZCAmJiB7IHRpbWVvdXRNcyB9KSxcbiAgICBiYWNrb2ZmTXM6IHdhaXRzLm1zLFxuICAgIGtub3duTXMsXG4gICAgd29yc3RNczogd2h5ID09PSB1bmRlZmluZWQgPyBrbm93bk1zIDogbnVsbCxcbiAgICAuLi4od2h5ICE9PSB1bmRlZmluZWQgJiYgeyB3aHkgfSksXG4gIH07XG59XG5cbi8qKlxuICogVGhlIHdhaXRzIGJldHdlZW4gYGF0dGVtcHRzYCBhdHRlbXB0cywgYXMgdGhlIHJ1bm5lciB3YWl0cyB0aGVtIChgYXR0ZW1wdC9wb2xpY3kudHMgwrcgY2FwcGVkV2FpdE1zYCkuIEEgbnVtYmVyXG4gKiBiYWNrb2ZmIGlzIGFyaXRobWV0aWMsIHVuZGVyIHRoZSBkZWNsYXJlZCBjZWlsaW5nLiBBIGZ1bmN0aW9uIGJhY2tvZmYgaXMgTkVWRVIgYXNrZWQg4oCUIGl0cyBhbnN3ZXIgbWF5IGRlcGVuZCBvbiB0aGVcbiAqIGVycm9yLCBhbmQgbm8gZXJyb3IgZXhpc3RzIGhlcmUg4oCUIHNvIGl0IGNvdW50cyBhdCBpdHMgZGVjbGFyZWQgY2VpbGluZyBwZXIgd2FpdCwgb3IsIHdpdGggbm9uZSwgaXMgbm90IGtub3duXG4gKiAoaXRzIHdhaXRzIGNvdW50IDAgYW5kIHRoZSBzdGFnZSBpcyB1bmJvdW5kZWQpLlxuICovXG5mdW5jdGlvbiB3YWl0c09mKHBvbGljeTogUmV0cnlQb2xpY3kgfCB1bmRlZmluZWQsIGF0dGVtcHRzOiBudW1iZXIpOiB7IG1zOiBudW1iZXI7IGtub3duOiBib29sZWFuIH0ge1xuICBjb25zdCB3YWl0cyA9IGF0dGVtcHRzIC0gMTtcbiAgY29uc3QgYmFja29mZk1zID0gcG9saWN5Py5iYWNrb2ZmTXM7XG4gIGlmICh3YWl0cyA8PSAwIHx8IGJhY2tvZmZNcyA9PT0gdW5kZWZpbmVkKSByZXR1cm4geyBtczogMCwga25vd246IHRydWUgfTtcbiAgaWYgKHR5cGVvZiBiYWNrb2ZmTXMgPT09ICdmdW5jdGlvbicpIHtcbiAgICBjb25zdCBjZWlsaW5nID0gYmFja29mZkNlaWxpbmdNcyhwb2xpY3k/Lm1heEJhY2tvZmZNcyk7XG4gICAgcmV0dXJuIGNlaWxpbmcgPT09IHVuZGVmaW5lZCA/IHsgbXM6IDAsIGtub3duOiBmYWxzZSB9IDogeyBtczogbXVsKHdhaXRzLCBjZWlsaW5nKSwga25vd246IHRydWUgfTtcbiAgfVxuICByZXR1cm4geyBtczogbXVsKHdhaXRzLCBjYXBwZWRXYWl0TXMocmVzb2x2ZUJhY2tvZmZNcyhiYWNrb2ZmTXMsIDEpLCBwb2xpY3k/Lm1heEJhY2tvZmZNcykpLCBrbm93bjogdHJ1ZSB9O1xufVxuXG4vLyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcbi8vIFRoZSByZXBvcnRcbi8vIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4vKipcbiAqIFRoZSBzbG93ZXN0IHBhdGg6IGhvdyBtYW55IHRpbWVzIGVhY2ggY2hhaW4gb24gaXQgcnVucyAocGFyZW50cyBiZWZvcmUgY2hpbGRyZW4g4oCUIHRoZSByZXZlcnNlIG9mIHRoZSBvcmRlciB0aGV5XG4gKiB3ZXJlIGNvbXB1dGVkIGluKSwgdGhlbiBpdHMgc3RhZ2VzIGluIHRoZSBvcmRlciBhIHJ1biBmaXJzdCByZWFjaGVzIHRoZW0uIEVhY2ggY2hhaW4gaXMgdmlzaXRlZCBvbmNlLCBzbyBhXG4gKiBkZWZpbml0aW9uIG1vdW50ZWQgdHdpY2UgYXQgZXZlcnkgbGV2ZWwgb2YgYSBkZWVwIG5lc3RpbmcgaXMgb25lIHN0ZXAgd2l0aCBpdHMgcGFzc2VzIG11bHRpcGxpZWQuXG4gKi9cbmZ1bmN0aW9uIGNyaXRpY2FsUGF0aE9mKHJvb3Q6IENoYWluLCBjb21wdXRlZDogcmVhZG9ubHkgQ2hhaW5bXSk6IEJ1ZGdldFN0ZXBbXSB7XG4gIGNvbnN0IHJ1bnMgPSBuZXcgTWFwPENoYWluLCBudW1iZXI+KFtbcm9vdCwgMV1dKTtcbiAgZm9yIChsZXQgaSA9IGNvbXB1dGVkLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgY29uc3QgY2hhaW4gPSBjb21wdXRlZFtpXTtcbiAgICBjb25zdCBjb3VudCA9IHJ1bnMuZ2V0KGNoYWluKTtcbiAgICBpZiAoY291bnQgPT09IHVuZGVmaW5lZCkgY29udGludWU7XG4gICAgZm9yIChjb25zdCBwIG9mIGNoYWluLnBvc2l0aW9ucykge1xuICAgICAgaWYgKHAudmlhICE9PSB1bmRlZmluZWQpIHJ1bnMuc2V0KHAudmlhLCBhZGQocnVucy5nZXQocC52aWEpID8/IDAsIG11bChjb3VudCwgcC5tdWx0aXBsaWVyKSkpO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IHN0ZXBzID0gbmV3IE1hcDxzdHJpbmcsIHsgLXJlYWRvbmx5IFtLIGluIGtleW9mIEJ1ZGdldFN0ZXBdOiBCdWRnZXRTdGVwW0tdIH0+KCk7XG4gIHdhbGtQb3NpdGlvbnMoXG4gICAgcm9vdCxcbiAgICAocCkgPT4gcC52aWEsXG4gICAgKGNoYWluLCBwKSA9PiB7XG4gICAgICBpZiAocC5jb3N0ID09PSB1bmRlZmluZWQpIHJldHVybjtcbiAgICAgIGNvbnN0IHBhc3NlcyA9IG11bChydW5zLmdldChjaGFpbikgPz8gMCwgcC5tdWx0aXBsaWVyKTtcbiAgICAgIGNvbnN0IHN0ZXAgPSBzdGVwcy5nZXQocC5zdGFnZUlkKTtcbiAgICAgIGlmIChzdGVwICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgc3RlcC5wYXNzZXMgPSBhZGQoc3RlcC5wYXNzZXMsIHBhc3Nlcyk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHN0ZXBzLnNldChwLnN0YWdlSWQsIHtcbiAgICAgICAgc3RhZ2VJZDogcC5zdGFnZUlkLFxuICAgICAgICBhdHRlbXB0czogcC5jb3N0LmF0dGVtcHRzLFxuICAgICAgICAuLi4ocC5jb3N0LnRpbWVvdXRNcyAhPT0gdW5kZWZpbmVkICYmIHsgdGltZW91dE1zOiBwLmNvc3QudGltZW91dE1zIH0pLFxuICAgICAgICBiYWNrb2ZmTXM6IHAuY29zdC5iYWNrb2ZmTXMsXG4gICAgICAgIHdvcnN0TXM6IHAuY29zdC53b3JzdE1zLFxuICAgICAgICBwYXNzZXMsXG4gICAgICB9KTtcbiAgICB9LFxuICApO1xuICByZXR1cm4gWy4uLnN0ZXBzLnZhbHVlcygpXS5tYXAoKHN0ZXApID0+IE9iamVjdC5mcmVlemUoc3RlcCkpO1xufVxuXG4vKiogRXZlcnkgdW5ib3VuZGVkIHN0YWdlLCBvbmNlLCBpbiB0aGUgb3JkZXIgYSB3YWxrIG9mIHRoZSB3aG9sZSBjaGFydCByZWFjaGVzIGl0LiAqL1xuZnVuY3Rpb24gdW5ib3VuZGVkT2Yocm9vdDogQ2hhaW4sIHJvb3RGbGFnczogcmVhZG9ubHkgVW5ib3VuZGVkU3RhZ2VbXSk6IFVuYm91bmRlZFN0YWdlW10ge1xuICBjb25zdCBvdXQ6IFVuYm91bmRlZFN0YWdlW10gPSBbXTtcbiAgY29uc3Qgc2VlbiA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICBjb25zdCBub3RlID0gKGZsYWc6IFVuYm91bmRlZFN0YWdlKSA9PiB7XG4gICAgY29uc3Qga2V5ID0gYCR7ZmxhZy53aHl9XFx1MDAwMCR7ZmxhZy5zdGFnZUlkfWA7XG4gICAgaWYgKHNlZW4uaGFzKGtleSkpIHJldHVybjtcbiAgICBzZWVuLmFkZChrZXkpO1xuICAgIG91dC5wdXNoKE9iamVjdC5mcmVlemUoeyBzdGFnZUlkOiBmbGFnLnN0YWdlSWQsIHdoeTogZmxhZy53aHkgfSkpO1xuICB9O1xuICB3YWxrUG9zaXRpb25zKFxuICAgIHJvb3QsXG4gICAgKHApID0+IHAuZGVwcyxcbiAgICAoX2NoYWluLCBwKSA9PiBwLmZsYWdzLmZvckVhY2gobm90ZSksXG4gICk7XG4gIHJvb3RGbGFncy5mb3JFYWNoKG5vdGUpO1xuICByZXR1cm4gb3V0O1xufVxuXG4vKiogQSBwcmVvcmRlciB3YWxrIG9mIHBvc2l0aW9ucywgZGVzY2VuZGluZyBpbnRvIGVhY2ggY2hhaW4gYG5leHRgIG5hbWVzIHRoZSBmaXJzdCB0aW1lIGl0IGlzIHJlYWNoZWQuICovXG5mdW5jdGlvbiB3YWxrUG9zaXRpb25zKFxuICByb290OiBDaGFpbixcbiAgbmV4dDogKHA6IFBvc2l0aW9uKSA9PiBDaGFpbiB8IHJlYWRvbmx5IENoYWluW10gfCB1bmRlZmluZWQsXG4gIHZpc2l0OiAoY2hhaW46IENoYWluLCBwOiBQb3NpdGlvbikgPT4gdm9pZCxcbik6IHZvaWQge1xuICBjb25zdCB2aXNpdGVkID0gbmV3IFNldDxDaGFpbj4oW3Jvb3RdKTtcbiAgY29uc3Qgc3RhY2s6IEFycmF5PHsgY2hhaW46IENoYWluOyBxOiBudW1iZXIgfT4gPSBbeyBjaGFpbjogcm9vdCwgcTogMCB9XTtcbiAgd2hpbGUgKHN0YWNrLmxlbmd0aCA+IDApIHtcbiAgICBjb25zdCB0b3AgPSBzdGFja1tzdGFjay5sZW5ndGggLSAxXTtcbiAgICBpZiAodG9wLnEgPj0gdG9wLmNoYWluLnBvc2l0aW9ucy5sZW5ndGgpIHtcbiAgICAgIHN0YWNrLnBvcCgpO1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGNvbnN0IHAgPSB0b3AuY2hhaW4ucG9zaXRpb25zW3RvcC5xKytdO1xuICAgIHZpc2l0KHRvcC5jaGFpbiwgcCk7XG4gICAgY29uc3QgaW5uZXIgPSBuZXh0KHApO1xuICAgIGNvbnN0IGNoYWlucyA9IGlubmVyID09PSB1bmRlZmluZWQgPyBbXSA6IEFycmF5LmlzQXJyYXkoaW5uZXIpID8gaW5uZXIgOiBbaW5uZXIgYXMgQ2hhaW5dO1xuICAgIGZvciAobGV0IGkgPSBjaGFpbnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgIGlmICh2aXNpdGVkLmhhcyhjaGFpbnNbaV0pKSBjb250aW51ZTtcbiAgICAgIHZpc2l0ZWQuYWRkKGNoYWluc1tpXSk7XG4gICAgICBzdGFjay5wdXNoKHsgY2hhaW46IGNoYWluc1tpXSwgcTogMCB9KTtcbiAgICB9XG4gIH1cbn1cblxuLy8g4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG4vLyBXb3Jkc1xuLy8g4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbmNvbnN0IGNvbnRyaWJ1dGlvbiA9IChzOiBCdWRnZXRTdGVwKSA9PiBtdWwocy5wYXNzZXMsIGFkZChtdWwocy5hdHRlbXB0cywgcy50aW1lb3V0TXMgPz8gMCksIHMuYmFja29mZk1zKSk7XG5cbi8qKiBUaGUgYGxpbWl0YCBsYXJnZXN0IGNvbnRyaWJ1dG9ycywga2VwdCBpbiBwYXRoIG9yZGVyLiAqL1xuZnVuY3Rpb24gc2xvd2VzdEluUGF0aE9yZGVyKHN0ZXBzOiByZWFkb25seSBCdWRnZXRTdGVwW10sIGxpbWl0OiBudW1iZXIpOiBCdWRnZXRTdGVwW10ge1xuICBjb25zdCBrZWVwID0gbmV3IFNldChcbiAgICBbLi4uc3RlcHNdXG4gICAgICAuc29ydCgoYSwgYikgPT4gY29udHJpYnV0aW9uKGIpIC0gY29udHJpYnV0aW9uKGEpKVxuICAgICAgLnNsaWNlKDAsIGxpbWl0KVxuICAgICAgLm1hcCgocykgPT4gcy5zdGFnZUlkKSxcbiAgKTtcbiAgcmV0dXJuIHN0ZXBzLmZpbHRlcigocykgPT4ga2VlcC5oYXMocy5zdGFnZUlkKSk7XG59XG5cbmZ1bmN0aW9uIHN0ZXBUZXh0KHM6IEJ1ZGdldFN0ZXApOiBzdHJpbmcge1xuICBjb25zdCBvd24gPVxuICAgIHMudGltZW91dE1zID09PSB1bmRlZmluZWRcbiAgICAgID8gYCR7cy5iYWNrb2ZmTXN9IG1zIG9mIHdhaXRzIChubyB0aW1lb3V0TXMpYFxuICAgICAgOiBgJHtzLmF0dGVtcHRzfSDDlyAke3MudGltZW91dE1zfSBtcyArICR7cy5iYWNrb2ZmTXN9IG1zIG9mIHdhaXRzID0gJHthZGQoXG4gICAgICAgICAgbXVsKHMuYXR0ZW1wdHMsIHMudGltZW91dE1zKSxcbiAgICAgICAgICBzLmJhY2tvZmZNcyxcbiAgICAgICAgKX0gbXNgO1xuICByZXR1cm4gYCR7cy5zdGFnZUlkfTogJHtvd259JHtzLnBhc3NlcyA+IDEgPyBgLCAke3MucGFzc2VzfSBwYXNzZXNgIDogJyd9YDtcbn1cblxuZnVuY3Rpb24gdW5ib3VuZGVkVGV4dChzdGFnZXM6IHJlYWRvbmx5IFVuYm91bmRlZFN0YWdlW10pOiBzdHJpbmcge1xuICBjb25zdCBsaXN0ZWQgPSBzdGFnZXMuc2xpY2UoMCwgMTApLm1hcCgocykgPT4gYCR7cy5zdGFnZUlkfSAoJHtzLndoeX0pYCk7XG4gIHJldHVybiBzdGFnZXMubGVuZ3RoID4gbGlzdGVkLmxlbmd0aFxuICAgID8gYCR7bGlzdGVkLmpvaW4oJywgJyl9LCBhbmQgJHtzdGFnZXMubGVuZ3RoIC0gbGlzdGVkLmxlbmd0aH0gbW9yZWBcbiAgICA6IGxpc3RlZC5qb2luKCcsICcpO1xufVxuXG4vLyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcbi8vIFNtYWxsIGxhd3Ncbi8vIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4vKiogU2F0dXJhdGluZyBhcml0aG1ldGljIG9uIG5vbi1uZWdhdGl2ZSBtaWxsaXNlY29uZHM6IG5ldmVyIHBhc3QgYE51bWJlci5NQVhfU0FGRV9JTlRFR0VSYCwgbmV2ZXIgYE5hTmAuICovXG5jb25zdCBDRUlMSU5HID0gTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVI7XG5jb25zdCBhZGQgPSAoYTogbnVtYmVyLCBiOiBudW1iZXIpOiBudW1iZXIgPT4gTWF0aC5taW4oYSArIGIsIENFSUxJTkcpO1xuY29uc3QgbXVsID0gKGE6IG51bWJlciwgYjogbnVtYmVyKTogbnVtYmVyID0+IChhID09PSAwIHx8IGIgPT09IDAgPyAwIDogTWF0aC5taW4oYSAqIGIsIENFSUxJTkcpKTtcblxuY29uc3QgbGFzdE9mID0gPFQ+KGl0ZW1zOiByZWFkb25seSBUW10pOiBUIHwgdW5kZWZpbmVkID0+IGl0ZW1zW2l0ZW1zLmxlbmd0aCAtIDFdO1xuXG4vKiogQSBidWRnZXQ6IGEgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyA+IDAgYW5kIG5vIG1vcmUgdGhhbiB0aGUgc2F0dXJhdGVkIHN1bXMgY2FuIGJlIGNvbXBhcmVkIGFnYWluc3QuICovXG5jb25zdCBpc1Bvc2l0aXZlTXMgPSAodmFsdWU6IHVua25vd24pOiB2YWx1ZSBpcyBudW1iZXIgPT5cbiAgdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJyAmJiB2YWx1ZSA+IDAgJiYgdmFsdWUgPD0gTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVI7XG5cbmNvbnN0IHNob3duID0gKHZhbHVlOiB1bmtub3duKTogc3RyaW5nID0+ICh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInID8gU3RyaW5nKHZhbHVlKSA6IHR5cGVvZiB2YWx1ZSk7XG5cbi8qKiBBbiBpZCBhcyB0aGUgcnVuIG5hbWVzIGl0OiB1bmRlciB0aGUgcHJlZml4IG9mIHRoZSBjaGFydCBpdCBsaXZlcyBpbiAoYSBsYXp5IG9yIGJyYW5jaCBjaGFydCdzIG1vdW50IHBhdGgpLiAqL1xuY29uc3QgcmVwb3J0ZWQgPSAoY3R4OiBDdHgsIGlkOiBzdHJpbmcpOiBzdHJpbmcgPT4gKGN0eC5wcmVmaXggPT09ICcnID8gaWQgOiBqb2luUGF0aChjdHgucHJlZml4LCBpZCkpO1xuXG5mdW5jdGlvbiBpc0NoYXJ0KHZhbHVlOiB1bmtub3duKTogdmFsdWUgaXMgRmxvd0NoYXJ0IHtcbiAgaWYgKHZhbHVlID09PSBudWxsIHx8IHR5cGVvZiB2YWx1ZSAhPT0gJ29iamVjdCcpIHJldHVybiBmYWxzZTtcbiAgY29uc3Qgcm9vdCA9ICh2YWx1ZSBhcyB7IHJvb3Q/OiB1bmtub3duIH0pLnJvb3Q7XG4gIHJldHVybiByb290ICE9PSBudWxsICYmIHR5cGVvZiByb290ID09PSAnb2JqZWN0Jztcbn1cblxuLyoqIEFuIG93biBwcm9wZXJ0eSBvbmx5IOKAlCBhIHByb3RvdHlwZSBtZW1iZXIgaXMgbmV2ZXIgYW4gYXNzdW1wdGlvbiBvciBhIHN1YmZsb3cuICovXG5mdW5jdGlvbiBvd248VD4ocmVjb3JkOiBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCBUPj4gfCB1bmRlZmluZWQsIGtleTogc3RyaW5nKTogVCB8IHVuZGVmaW5lZCB7XG4gIHJldHVybiByZWNvcmQgIT09IHVuZGVmaW5lZCAmJiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocmVjb3JkLCBrZXkpID8gcmVjb3JkW2tleV0gOiB1bmRlZmluZWQ7XG59XG5cbi8qKiBUaGUgZW5naW5lJ3Mgc3ViZmxvdyBsb29rdXA6IGJ5IHN1YmZsb3cgaWQsIHRoZW4gc3ViZmxvdyBuYW1lLCB0aGVuIG5vZGUgbmFtZS4gKi9cbmZ1bmN0aW9uIHN1YmZsb3dEZWZPZihcbiAgc3ViZmxvd3M6IFJlYWRvbmx5PFJlY29yZDxzdHJpbmcsIHsgcm9vdDogU3RhZ2VOb2RlIH0+PiB8IHVuZGVmaW5lZCxcbiAgbm9kZTogU3RhZ2VOb2RlLFxuKTogeyByb290OiBTdGFnZU5vZGUgfSB8IHVuZGVmaW5lZCB7XG4gIGZvciAoY29uc3Qga2V5IG9mIFtub2RlLnN1YmZsb3dJZCwgbm9kZS5zdWJmbG93TmFtZSwgbm9kZS5uYW1lXSkge1xuICAgIGlmIChrZXkgPT09IHVuZGVmaW5lZCB8fCBrZXkgPT09ICcnKSBjb250aW51ZTtcbiAgICBjb25zdCBkZWYgPSBvd24oc3ViZmxvd3MsIGtleSk7XG4gICAgaWYgKGRlZiAhPT0gdW5kZWZpbmVkICYmIGRlZiAhPT0gbnVsbCAmJiB0eXBlb2YgZGVmLnJvb3QgPT09ICdvYmplY3QnICYmIGRlZi5yb290ICE9PSBudWxsKSByZXR1cm4gZGVmO1xuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbi8qKiBXaGF0IGEgY2hhcnQgYXNzdW1lZCBmb3IgYSBsYXp5IG1vdW50IG9yIGEgYnJhbmNoIGlzLCByZWFkIG9uY2U6IGl0cyByb290LCBpdHMgc3ViZmxvd3MsIGl0cyBzdGFnZSBtYXAuICovXG5pbnRlcmZhY2UgQXNzdW1lZENoYXJ0IHtcbiAgcmVhZG9ubHkgcm9vdDogU3RhZ2VOb2RlO1xuICByZWFkb25seSBzdWJmbG93cz86IFJlY29yZDxzdHJpbmcsIHsgcm9vdDogU3RhZ2VOb2RlIH0+O1xuICByZWFkb25seSBzdGFnZU1hcD86IFJlYWRvbmx5TWFwPHN0cmluZywgdW5rbm93bj47XG59XG5cbi8qKiBUaGUgY2FsbGVyJ3MgYXNzdW1wdGlvbnMsIHZhbGlkYXRlZCBhbmQgY29waWVkIG9uY2Ug4oCUIHRoZSB3YWxrIHJlYWRzIG9ubHkgdGhlc2UgbnVsbC1wcm90b3R5cGUgcmVjb3Jkcy4gKi9cbmludGVyZmFjZSBBZG1pdHRlZEFzc3VtcHRpb25zIHtcbiAgcmVhZG9ubHkgbG9vcHM6IFJlYWRvbmx5PFJlY29yZDxzdHJpbmcsIG51bWJlcj4+O1xuICByZWFkb25seSBsYXp5OiBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCBBc3N1bWVkQ2hhcnQ+PjtcbiAgcmVhZG9ubHkgYnJhbmNoZXM6IFJlYWRvbmx5PFJlY29yZDxzdHJpbmcsIEFzc3VtZWRDaGFydD4+O1xufVxuXG4vKipcbiAqIFZhbGlkYXRlIHRoZSBhc3N1bXB0aW9ucyBhbmQgQ09QWSB0aGVtOiBlYWNoIG93biBlbnVtZXJhYmxlIGtleSBpcyByZWFkIGV4YWN0bHkgb25jZSwgaW50byBhIGZyZXNoIG51bGwtcHJvdG90eXBlXG4gKiByZWNvcmQuIEEgZ2V0dGVyIHRoYXQgY2hhbmdlcyBiZXR3ZWVuIHJlYWRzLCBhIFByb3h5LCBvciBhIG5vbi1lbnVtZXJhYmxlIGtleSBjYW4gdGhlcmVmb3JlIG5ldmVyIGhhbmQgdGhlIHdhbGtcbiAqIGEgdmFsdWUgdGhhdCB3YXMgbm90IHZhbGlkYXRlZCwgYW5kIG5vIHByb3RvdHlwZSBtZW1iZXIgaXMgZXZlciBhbiBhc3N1bXB0aW9uLlxuICovXG5mdW5jdGlvbiBhZG1pdEFzc3VtcHRpb25zKGFzc3VtZTogdW5rbm93bik6IEFkbWl0dGVkQXNzdW1wdGlvbnMge1xuICBpZiAoYXNzdW1lICE9PSB1bmRlZmluZWQgJiYgKGFzc3VtZSA9PT0gbnVsbCB8fCB0eXBlb2YgYXNzdW1lICE9PSAnb2JqZWN0JykpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd0aW1lQnVkZ2V0OiBhc3N1bWUgbXVzdCBiZSBhbiBvYmplY3QgKHsgbG9vcHM/LCBsYXp5PywgYnJhbmNoZXM/IH0pLicpO1xuICB9XG4gIGNvbnN0IGdpdmVuID0gKGFzc3VtZSA/PyB7fSkgYXMgUmVjb3JkPCdsb29wcycgfCAnbGF6eScgfCAnYnJhbmNoZXMnLCB1bmtub3duPjtcbiAgcmV0dXJuIHtcbiAgICBsb29wczogc25hcHNob3QoZ2l2ZW4ubG9vcHMsICdsb29wcycsIChrZXksIHBhc3NlcykgPT4ge1xuICAgICAgaWYgKHR5cGVvZiBwYXNzZXMgPT09ICdudW1iZXInICYmIE51bWJlci5pc0ludGVnZXIocGFzc2VzKSAmJiBwYXNzZXMgPj0gMSkgcmV0dXJuIHBhc3NlcztcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAgIGB0aW1lQnVkZ2V0OiBhc3N1bWUubG9vcHNbJyR7a2V5fSddIG11c3QgYmUgYSB3aG9sZSBudW1iZXIgb2YgcGFzc2VzID49IDEgKGdvdCAke3Nob3duKHBhc3Nlcyl9KS5gLFxuICAgICAgKTtcbiAgICB9KSxcbiAgICBsYXp5OiBzbmFwc2hvdChnaXZlbi5sYXp5LCAnbGF6eScsIChrZXksIGNoYXJ0KSA9PiBhc3N1bWVkQ2hhcnQoJ2xhenknLCBrZXksIGNoYXJ0KSksXG4gICAgYnJhbmNoZXM6IHNuYXBzaG90KGdpdmVuLmJyYW5jaGVzLCAnYnJhbmNoZXMnLCAoa2V5LCBjaGFydCkgPT4gYXNzdW1lZENoYXJ0KCdicmFuY2hlcycsIGtleSwgY2hhcnQpKSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gc25hcHNob3Q8VD4ocmVjb3JkOiB1bmtub3duLCBmaWVsZDogc3RyaW5nLCBhZG1pdDogKGtleTogc3RyaW5nLCB2YWx1ZTogdW5rbm93bikgPT4gVCk6IFJlY29yZDxzdHJpbmcsIFQ+IHtcbiAgY29uc3QgY29weSA9IE9iamVjdC5jcmVhdGUobnVsbCkgYXMgUmVjb3JkPHN0cmluZywgVD47XG4gIGlmIChyZWNvcmQgPT09IHVuZGVmaW5lZCkgcmV0dXJuIGNvcHk7XG4gIGlmIChyZWNvcmQgPT09IG51bGwgfHwgdHlwZW9mIHJlY29yZCAhPT0gJ29iamVjdCcpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGB0aW1lQnVkZ2V0OiBhc3N1bWUuJHtmaWVsZH0gbXVzdCBiZSBhbiBvYmplY3Qga2V5ZWQgYnkgaWQuYCk7XG4gIH1cbiAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMocmVjb3JkKSkgY29weVtrZXldID0gYWRtaXQoa2V5LCAocmVjb3JkIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KVtrZXldKTtcbiAgcmV0dXJuIE9iamVjdC5mcmVlemUoY29weSk7XG59XG5cbmZ1bmN0aW9uIGFzc3VtZWRDaGFydChmaWVsZDogc3RyaW5nLCBrZXk6IHN0cmluZywgY2hhcnQ6IHVua25vd24pOiBBc3N1bWVkQ2hhcnQge1xuICBjb25zdCByb290ID0gaXNDaGFydChjaGFydCkgPyAoY2hhcnQgYXMgeyByb290OiB1bmtub3duIH0pLnJvb3QgOiB1bmRlZmluZWQ7XG4gIGlmICghaXNOb2RlKHJvb3QpKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgdGltZUJ1ZGdldDogYXNzdW1lLiR7ZmllbGR9Wycke2tleX0nXSBtdXN0IGJlIGEgYnVpbHQgY2hhcnQgKGZsb3dDaGFydCguLi4pLmJ1aWxkKCkpLmApO1xuICB9XG4gIGNvbnN0IHsgc3ViZmxvd3MsIHN0YWdlTWFwIH0gPSBjaGFydCBhcyBGbG93Q2hhcnQ7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKHtcbiAgICByb290LFxuICAgIC4uLihzdWJmbG93cyAhPT0gdW5kZWZpbmVkICYmIHsgc3ViZmxvd3M6IHN1YmZsb3dzIGFzIFJlY29yZDxzdHJpbmcsIHsgcm9vdDogU3RhZ2VOb2RlIH0+IH0pLFxuICAgIC4uLihzdGFnZU1hcCBpbnN0YW5jZW9mIE1hcCAmJiB7IHN0YWdlTWFwIH0pLFxuICB9KTtcbn1cbiJdfQ==
|