sakuga 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,237 @@
1
+ import {
2
+ CanvasContextUnavailable,
3
+ DEFAULT_BLOCK_DURATION,
4
+ DEFAULT_FPS,
5
+ DEFAULT_HEIGHT,
6
+ DEFAULT_THEME,
7
+ DEFAULT_TRANSITION_DURATION_MS,
8
+ DEFAULT_WIDTH,
9
+ MissingCanvasFactory,
10
+ NoEncodableVideoCodec,
11
+ OutputBufferMissing,
12
+ WebCodecsUnavailable,
13
+ blendColors,
14
+ buildScene,
15
+ buildTransitionDiff,
16
+ buildTransitionTokens,
17
+ diffLayoutTokens,
18
+ easeInOutCubic,
19
+ parseMarkdownCodeBlocks,
20
+ renderFrame,
21
+ resolveTheme
22
+ } from "./shared/chunk-ks7faw1s.js";
23
+ // src/lib/render-api.ts
24
+ import { Effect as Effect2 } from "effect";
25
+
26
+ // src/lib/browser.ts
27
+ import { Effect, Ref, Stream } from "effect";
28
+ import {
29
+ BufferTarget,
30
+ Mp4OutputFormat,
31
+ Output,
32
+ QUALITY_HIGH,
33
+ VideoSample,
34
+ VideoSampleSource,
35
+ WebMOutputFormat,
36
+ getFirstEncodableVideoCodec
37
+ } from "mediabunny";
38
+ var getCanvasContext = (canvas) => Effect.gen(function* () {
39
+ const context = canvas.getContext("2d");
40
+ if (!context) {
41
+ return yield* Effect.fail(new CanvasContextUnavailable({ reason: "Unable to acquire 2D canvas context." }));
42
+ }
43
+ return context;
44
+ });
45
+ var ensureWebCodecs = () => Effect.gen(function* () {
46
+ if (typeof VideoEncoder === "undefined" || typeof VideoFrame === "undefined") {
47
+ return yield* Effect.fail(new WebCodecsUnavailable({
48
+ reason: "WebCodecs VideoEncoder is not available in this browser."
49
+ }));
50
+ }
51
+ });
52
+ var computeFrameCounts = (transitionDurationMs, fps) => {
53
+ const frameDuration = 1 / fps;
54
+ const blockFrames = Math.max(1, Math.round(DEFAULT_BLOCK_DURATION * fps));
55
+ const transitionFrames = Math.max(1, Math.round(transitionDurationMs / 1000 * fps));
56
+ return {
57
+ blockFrames,
58
+ frameDuration,
59
+ transitionFrames
60
+ };
61
+ };
62
+ var makeOutput = (format) => Effect.sync(() => {
63
+ const resolvedFormat = format === "webm" ? new WebMOutputFormat : new Mp4OutputFormat;
64
+ const target = new BufferTarget;
65
+ const outputInstance = new Output({
66
+ format: resolvedFormat,
67
+ target
68
+ });
69
+ return {
70
+ mimeType: resolvedFormat.mimeType,
71
+ output: outputInstance,
72
+ target
73
+ };
74
+ });
75
+ var makeVideoSource = (codec) => Effect.sync(() => new VideoSampleSource({
76
+ bitrate: QUALITY_HIGH,
77
+ codec
78
+ }));
79
+ var renderAndWriteFrame = (context, videoSource, frameDuration, frameIndexRef, width, height) => (frame) => Effect.gen(function* () {
80
+ const frameIndex = yield* Ref.get(frameIndexRef);
81
+ renderFrame(context, width, height, frame);
82
+ const imageData = context.getImageData(0, 0, width, height);
83
+ const sample = new VideoSample(imageData.data, {
84
+ codedHeight: height,
85
+ codedWidth: width,
86
+ duration: frameDuration,
87
+ format: "RGBA",
88
+ timestamp: frameIndex * frameDuration
89
+ });
90
+ yield* Effect.tryPromise({
91
+ catch: (error) => error instanceof Error ? error : new Error(String(error)),
92
+ try: () => videoSource.add(sample)
93
+ });
94
+ sample.close();
95
+ yield* Ref.set(frameIndexRef, frameIndex + 1);
96
+ });
97
+ var buildSceneFrames = (scene, blockFrames) => Stream.range(1, blockFrames).pipe(Stream.map(() => ({
98
+ background: scene.background,
99
+ kind: "scene",
100
+ opacity: 1,
101
+ positionX: scene.blockX,
102
+ positionY: scene.blockY,
103
+ scene
104
+ })));
105
+ var buildTransitionFrames = (scene, nextScene, transitionFrames) => {
106
+ const diff = buildTransitionDiff(scene, nextScene);
107
+ return Stream.range(1, transitionFrames).pipe(Stream.map((index) => {
108
+ const rawProgress = index / transitionFrames;
109
+ const progress = easeInOutCubic(rawProgress);
110
+ const blendedBackground = blendColors(scene.background, nextScene.background, progress);
111
+ const tokens = buildTransitionTokens(diff, progress);
112
+ return {
113
+ background: blendedBackground,
114
+ kind: "transition",
115
+ tokens
116
+ };
117
+ }));
118
+ };
119
+ var buildFramesStream = (scenes, blockFrames, transitionFrames) => Stream.fromIterable(scenes).pipe(Stream.zipWithIndex, Stream.flatMap(([scene, index]) => {
120
+ const nextScene = scenes[index + 1];
121
+ const base = buildSceneFrames(scene, blockFrames);
122
+ return nextScene ? Stream.concat(base, buildTransitionFrames(scene, nextScene, transitionFrames)) : base;
123
+ }));
124
+ var resolveFormat = (format, height, width) => Effect.gen(function* () {
125
+ if (format !== "auto") {
126
+ return {
127
+ codec: format === "mp4" ? "avc" : "vp9",
128
+ container: format
129
+ };
130
+ }
131
+ const codec = yield* Effect.tryPromise({
132
+ catch: () => new NoEncodableVideoCodec({
133
+ reason: "No encodable video codec available in this browser."
134
+ }),
135
+ try: () => getFirstEncodableVideoCodec(["avc", "vp9", "vp8"], {
136
+ bitrate: QUALITY_HIGH,
137
+ height,
138
+ width
139
+ })
140
+ });
141
+ if (!codec) {
142
+ return yield* Effect.fail(new NoEncodableVideoCodec({
143
+ reason: "No encodable video codec available in this browser."
144
+ }));
145
+ }
146
+ return {
147
+ codec,
148
+ container: codec === "avc" ? "mp4" : "webm"
149
+ };
150
+ });
151
+ var resolveCanvas = (canvas, height, width, createCanvas) => Effect.gen(function* () {
152
+ if (canvas) {
153
+ const context2 = yield* getCanvasContext(canvas);
154
+ return {
155
+ canvas,
156
+ context: context2
157
+ };
158
+ }
159
+ if (!createCanvas) {
160
+ return yield* Effect.fail(new MissingCanvasFactory({
161
+ reason: "Browser canvas factory is required when no canvas is provided."
162
+ }));
163
+ }
164
+ const created = createCanvas(height, width);
165
+ const context = yield* getCanvasContext(created);
166
+ return {
167
+ canvas: created,
168
+ context
169
+ };
170
+ });
171
+ var renderVideoBrowser = (theme, codeBlocks, options = {}) => Effect.gen(function* () {
172
+ yield* ensureWebCodecs();
173
+ const width = options.width ?? DEFAULT_WIDTH;
174
+ const height = options.height ?? DEFAULT_HEIGHT;
175
+ const transitionDurationMs = options.transitionDurationMs ?? DEFAULT_TRANSITION_DURATION_MS;
176
+ const format = options.format ?? "auto";
177
+ const { context } = yield* resolveCanvas(options.canvas, height, width, options.createCanvas);
178
+ const resolved = yield* resolveFormat(format, height, width);
179
+ const outputInfo = yield* makeOutput(resolved.container);
180
+ const frameCounts = computeFrameCounts(transitionDurationMs, DEFAULT_FPS);
181
+ const frameIndexRef = yield* Ref.make(0);
182
+ const scenes = yield* Effect.forEach(codeBlocks, (codeBlock) => buildScene(context, codeBlock, theme, width, height), { concurrency: options.concurrency });
183
+ const videoSource = yield* makeVideoSource(resolved.codec);
184
+ return yield* Effect.scoped(Effect.gen(function* () {
185
+ yield* Effect.sync(() => {
186
+ outputInfo.output.addVideoTrack(videoSource, { frameRate: DEFAULT_FPS });
187
+ });
188
+ yield* Effect.tryPromise({
189
+ catch: (error) => error instanceof Error ? error : new Error(String(error)),
190
+ try: () => outputInfo.output.start()
191
+ });
192
+ const frameStream = buildFramesStream(scenes, frameCounts.blockFrames, frameCounts.transitionFrames);
193
+ yield* Stream.runForEach(frameStream, renderAndWriteFrame(context, videoSource, frameCounts.frameDuration, frameIndexRef, width, height));
194
+ yield* Effect.tryPromise({
195
+ catch: (error) => error instanceof Error ? error : new Error(String(error)),
196
+ try: () => outputInfo.output.finalize()
197
+ });
198
+ videoSource.close();
199
+ const buffer = outputInfo.target.buffer;
200
+ if (!buffer) {
201
+ return yield* Effect.fail(new OutputBufferMissing({
202
+ reason: "Output buffer missing after finalize."
203
+ }));
204
+ }
205
+ const output = {
206
+ data: new Uint8Array(buffer),
207
+ extension: resolved.container,
208
+ mimeType: outputInfo.mimeType
209
+ };
210
+ return output;
211
+ }));
212
+ });
213
+
214
+ // src/lib/render-api.ts
215
+ var render = (options) => Effect2.runPromise(Effect2.gen(function* () {
216
+ const theme = options.theme ?? DEFAULT_THEME;
217
+ const resolvedTheme = yield* resolveTheme(theme);
218
+ const blocks = yield* parseMarkdownCodeBlocks(options.markdown);
219
+ const result = yield* renderVideoBrowser(resolvedTheme, blocks, {
220
+ canvas: options.canvas,
221
+ concurrency: options.concurrency,
222
+ createCanvas: options.createCanvas,
223
+ format: options.format,
224
+ height: options.height,
225
+ transitionDurationMs: options.transitionDurationMs,
226
+ width: options.width
227
+ });
228
+ return result;
229
+ }));
230
+ export {
231
+ render,
232
+ parseMarkdownCodeBlocks,
233
+ diffLayoutTokens
234
+ };
235
+
236
+ //# debugId=30C1AF8D08558A9464756E2164756E21
237
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsic3JjL2xpYi9yZW5kZXItYXBpLnRzIiwgInNyYy9saWIvYnJvd3Nlci50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsKICAgICJpbXBvcnQgeyBFZmZlY3QgfSBmcm9tIFwiZWZmZWN0XCJcbmltcG9ydCB7IHJlbmRlclZpZGVvQnJvd3NlciwgdHlwZSBSZW5kZXJWaWRlb0Jyb3dzZXJPcHRpb25zIH0gZnJvbSBcIi4vYnJvd3NlclwiXG5pbXBvcnQgeyBERUZBVUxUX1RIRU1FIH0gZnJvbSBcIi4vY29uc3RhbnRzXCJcbmltcG9ydCB7IHBhcnNlTWFya2Rvd25Db2RlQmxvY2tzIH0gZnJvbSBcIi4vbWFya2Rvd25cIlxuaW1wb3J0IHsgcmVzb2x2ZVRoZW1lIH0gZnJvbSBcIi4vdGhlbWVcIlxuXG5leHBvcnQgdHlwZSBSZW5kZXJPcHRpb25zID0gUmVuZGVyVmlkZW9Ccm93c2VyT3B0aW9ucyAmIHtcbiAgbWFya2Rvd246IHN0cmluZ1xuICB0aGVtZT86IHN0cmluZ1xufVxuXG5leHBvcnQgdHlwZSBSZW5kZXJSZXN1bHQgPVxuICBSZXR1cm5UeXBlPHR5cGVvZiByZW5kZXJWaWRlb0Jyb3dzZXI+IGV4dGVuZHMgRWZmZWN0LkVmZmVjdDxpbmZlciBBLCB1bmtub3duPiA/IEEgOiBuZXZlclxuXG5leHBvcnQgY29uc3QgcmVuZGVyID0gKG9wdGlvbnM6IFJlbmRlck9wdGlvbnMpID0+XG4gIEVmZmVjdC5ydW5Qcm9taXNlKFxuICAgIEVmZmVjdC5nZW4oZnVuY3Rpb24qICgpIHtcbiAgICAgIGNvbnN0IHRoZW1lID0gb3B0aW9ucy50aGVtZSA/PyBERUZBVUxUX1RIRU1FXG4gICAgICBjb25zdCByZXNvbHZlZFRoZW1lID0geWllbGQqIHJlc29sdmVUaGVtZSh0aGVtZSlcbiAgICAgIGNvbnN0IGJsb2NrcyA9IHlpZWxkKiBwYXJzZU1hcmtkb3duQ29kZUJsb2NrcyhvcHRpb25zLm1hcmtkb3duKVxuXG4gICAgICBjb25zdCByZXN1bHQgPSB5aWVsZCogcmVuZGVyVmlkZW9Ccm93c2VyKHJlc29sdmVkVGhlbWUsIGJsb2Nrcywge1xuICAgICAgICBjYW52YXM6IG9wdGlvbnMuY2FudmFzLFxuICAgICAgICBjb25jdXJyZW5jeTogb3B0aW9ucy5jb25jdXJyZW5jeSxcbiAgICAgICAgY3JlYXRlQ2FudmFzOiBvcHRpb25zLmNyZWF0ZUNhbnZhcyxcbiAgICAgICAgZm9ybWF0OiBvcHRpb25zLmZvcm1hdCxcbiAgICAgICAgaGVpZ2h0OiBvcHRpb25zLmhlaWdodCxcbiAgICAgICAgdHJhbnNpdGlvbkR1cmF0aW9uTXM6IG9wdGlvbnMudHJhbnNpdGlvbkR1cmF0aW9uTXMsXG4gICAgICAgIHdpZHRoOiBvcHRpb25zLndpZHRoLFxuICAgICAgfSlcblxuICAgICAgcmV0dXJuIHJlc3VsdFxuICAgIH0pXG4gIClcbiIsCiAgICAiaW1wb3J0IHsgRWZmZWN0LCBSZWYsIFN0cmVhbSB9IGZyb20gXCJlZmZlY3RcIlxuaW1wb3J0IHtcbiAgQnVmZmVyVGFyZ2V0LFxuICBNcDRPdXRwdXRGb3JtYXQsXG4gIE91dHB1dCxcbiAgUVVBTElUWV9ISUdILFxuICBWaWRlb1NhbXBsZSxcbiAgVmlkZW9TYW1wbGVTb3VyY2UsXG4gIFdlYk1PdXRwdXRGb3JtYXQsXG4gIGdldEZpcnN0RW5jb2RhYmxlVmlkZW9Db2RlYyxcbn0gZnJvbSBcIm1lZGlhYnVubnlcIlxuaW1wb3J0IHR5cGUgeyBDYW52YXNDb250ZXh0IH0gZnJvbSBcIi4vY29udGV4dFwiXG5pbXBvcnQgdHlwZSB7IENvZGVCbG9jaywgUmVuZGVyRnJhbWUsIFNjZW5lIH0gZnJvbSBcIi4vdHlwZXNcIlxuaW1wb3J0IHsgYmxlbmRDb2xvcnMgfSBmcm9tIFwiLi9jb2xvclwiXG5pbXBvcnQge1xuICBERUZBVUxUX0JMT0NLX0RVUkFUSU9OLFxuICBERUZBVUxUX0ZQUyxcbiAgREVGQVVMVF9IRUlHSFQsXG4gIERFRkFVTFRfVFJBTlNJVElPTl9EVVJBVElPTl9NUyxcbiAgREVGQVVMVF9XSURUSCxcbn0gZnJvbSBcIi4vY29uc3RhbnRzXCJcbmltcG9ydCB7XG4gIENhbnZhc0NvbnRleHRVbmF2YWlsYWJsZSxcbiAgTWlzc2luZ0NhbnZhc0ZhY3RvcnksXG4gIE5vRW5jb2RhYmxlVmlkZW9Db2RlYyxcbiAgT3V0cHV0QnVmZmVyTWlzc2luZyxcbiAgV2ViQ29kZWNzVW5hdmFpbGFibGUsXG59IGZyb20gXCIuL2Vycm9yc1wiXG5pbXBvcnQgeyByZW5kZXJGcmFtZSB9IGZyb20gXCIuL3JlbmRlclwiXG5pbXBvcnQgeyBidWlsZFNjZW5lIH0gZnJvbSBcIi4vc2NlbmVcIlxuaW1wb3J0IHsgYnVpbGRUcmFuc2l0aW9uRGlmZiwgYnVpbGRUcmFuc2l0aW9uVG9rZW5zLCBlYXNlSW5PdXRDdWJpYyB9IGZyb20gXCIuL3RyYW5zaXRpb25cIlxuXG5leHBvcnQgdHlwZSBCcm93c2VyRm9ybWF0ID0gXCJtcDRcIiB8IFwid2VibVwiIHwgXCJhdXRvXCJcblxuZXhwb3J0IHR5cGUgQ2FudmFzTGlrZSA9IHtcbiAgZ2V0Q29udGV4dDogKHR5cGU6IFwiMmRcIikgPT4gQ2FudmFzQ29udGV4dCB8IG51bGxcbiAgaGVpZ2h0OiBudW1iZXJcbiAgd2lkdGg6IG51bWJlclxufVxuXG5leHBvcnQgdHlwZSBDYW52YXNGYWN0b3J5ID0gKGhlaWdodDogbnVtYmVyLCB3aWR0aDogbnVtYmVyKSA9PiBDYW52YXNMaWtlXG5cbmV4cG9ydCB0eXBlIEJyb3dzZXJPdXRwdXQgPSB7XG4gIGRhdGE6IFVpbnQ4QXJyYXlcbiAgZXh0ZW5zaW9uOiBcIm1wNFwiIHwgXCJ3ZWJtXCJcbiAgbWltZVR5cGU6IHN0cmluZ1xufVxuXG5leHBvcnQgdHlwZSBSZW5kZXJWaWRlb0Jyb3dzZXJPcHRpb25zID0ge1xuICBjYW52YXM/OiBDYW52YXNMaWtlXG4gIGNvbmN1cnJlbmN5PzogbnVtYmVyXG4gIGNyZWF0ZUNhbnZhcz86IENhbnZhc0ZhY3RvcnlcbiAgZm9ybWF0PzogQnJvd3NlckZvcm1hdFxuICBoZWlnaHQ/OiBudW1iZXJcbiAgdHJhbnNpdGlvbkR1cmF0aW9uTXM/OiBudW1iZXJcbiAgd2lkdGg/OiBudW1iZXJcbn1cblxuY29uc3QgZ2V0Q2FudmFzQ29udGV4dCA9IChjYW52YXM6IENhbnZhc0xpa2UpID0+XG4gIEVmZmVjdC5nZW4oZnVuY3Rpb24qICgpIHtcbiAgICBjb25zdCBjb250ZXh0ID0gY2FudmFzLmdldENvbnRleHQoXCIyZFwiKVxuICAgIGlmICghY29udGV4dCkge1xuICAgICAgcmV0dXJuIHlpZWxkKiBFZmZlY3QuZmFpbChcbiAgICAgICAgbmV3IENhbnZhc0NvbnRleHRVbmF2YWlsYWJsZSh7IHJlYXNvbjogXCJVbmFibGUgdG8gYWNxdWlyZSAyRCBjYW52YXMgY29udGV4dC5cIiB9KVxuICAgICAgKVxuICAgIH1cblxuICAgIHJldHVybiBjb250ZXh0XG4gIH0pXG5cbmNvbnN0IGVuc3VyZVdlYkNvZGVjcyA9ICgpID0+XG4gIEVmZmVjdC5nZW4oZnVuY3Rpb24qICgpIHtcbiAgICBpZiAodHlwZW9mIFZpZGVvRW5jb2RlciA9PT0gXCJ1bmRlZmluZWRcIiB8fCB0eXBlb2YgVmlkZW9GcmFtZSA9PT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgcmV0dXJuIHlpZWxkKiBFZmZlY3QuZmFpbChcbiAgICAgICAgbmV3IFdlYkNvZGVjc1VuYXZhaWxhYmxlKHtcbiAgICAgICAgICByZWFzb246IFwiV2ViQ29kZWNzIFZpZGVvRW5jb2RlciBpcyBub3QgYXZhaWxhYmxlIGluIHRoaXMgYnJvd3Nlci5cIixcbiAgICAgICAgfSlcbiAgICAgIClcbiAgICB9XG4gIH0pXG5cbmNvbnN0IGNvbXB1dGVGcmFtZUNvdW50cyA9ICh0cmFuc2l0aW9uRHVyYXRpb25NczogbnVtYmVyLCBmcHM6IG51bWJlcikgPT4ge1xuICBjb25zdCBmcmFtZUR1cmF0aW9uID0gMSAvIGZwc1xuICBjb25zdCBibG9ja0ZyYW1lcyA9IE1hdGgubWF4KDEsIE1hdGgucm91bmQoREVGQVVMVF9CTE9DS19EVVJBVElPTiAqIGZwcykpXG4gIGNvbnN0IHRyYW5zaXRpb25GcmFtZXMgPSBNYXRoLm1heCgxLCBNYXRoLnJvdW5kKCh0cmFuc2l0aW9uRHVyYXRpb25NcyAvIDEwMDApICogZnBzKSlcblxuICByZXR1cm4ge1xuICAgIGJsb2NrRnJhbWVzLFxuICAgIGZyYW1lRHVyYXRpb24sXG4gICAgdHJhbnNpdGlvbkZyYW1lcyxcbiAgfVxufVxuXG5jb25zdCBtYWtlT3V0cHV0ID0gKGZvcm1hdDogXCJtcDRcIiB8IFwid2VibVwiKSA9PlxuICBFZmZlY3Quc3luYygoKSA9PiB7XG4gICAgY29uc3QgcmVzb2x2ZWRGb3JtYXQgPSBmb3JtYXQgPT09IFwid2VibVwiID8gbmV3IFdlYk1PdXRwdXRGb3JtYXQoKSA6IG5ldyBNcDRPdXRwdXRGb3JtYXQoKVxuICAgIGNvbnN0IHRhcmdldCA9IG5ldyBCdWZmZXJUYXJnZXQoKVxuXG4gICAgY29uc3Qgb3V0cHV0SW5zdGFuY2UgPSBuZXcgT3V0cHV0KHtcbiAgICAgIGZvcm1hdDogcmVzb2x2ZWRGb3JtYXQsXG4gICAgICB0YXJnZXQsXG4gICAgfSlcblxuICAgIHJldHVybiB7XG4gICAgICBtaW1lVHlwZTogcmVzb2x2ZWRGb3JtYXQubWltZVR5cGUsXG4gICAgICBvdXRwdXQ6IG91dHB1dEluc3RhbmNlLFxuICAgICAgdGFyZ2V0LFxuICAgIH1cbiAgfSlcblxuY29uc3QgbWFrZVZpZGVvU291cmNlID0gKGNvZGVjOiBSZXNvbHZlZENvZGVjKSA9PlxuICBFZmZlY3Quc3luYyhcbiAgICAoKSA9PlxuICAgICAgbmV3IFZpZGVvU2FtcGxlU291cmNlKHtcbiAgICAgICAgYml0cmF0ZTogUVVBTElUWV9ISUdILFxuICAgICAgICBjb2RlYyxcbiAgICAgIH0pXG4gIClcblxuY29uc3QgcmVuZGVyQW5kV3JpdGVGcmFtZSA9XG4gIChcbiAgICBjb250ZXh0OiBDYW52YXNDb250ZXh0LFxuICAgIHZpZGVvU291cmNlOiBWaWRlb1NhbXBsZVNvdXJjZSxcbiAgICBmcmFtZUR1cmF0aW9uOiBudW1iZXIsXG4gICAgZnJhbWVJbmRleFJlZjogUmVmLlJlZjxudW1iZXI+LFxuICAgIHdpZHRoOiBudW1iZXIsXG4gICAgaGVpZ2h0OiBudW1iZXJcbiAgKSA9PlxuICAoZnJhbWU6IFJlbmRlckZyYW1lKSA9PlxuICAgIEVmZmVjdC5nZW4oZnVuY3Rpb24qICgpIHtcbiAgICAgIGNvbnN0IGZyYW1lSW5kZXggPSB5aWVsZCogUmVmLmdldChmcmFtZUluZGV4UmVmKVxuICAgICAgcmVuZGVyRnJhbWUoY29udGV4dCwgd2lkdGgsIGhlaWdodCwgZnJhbWUpXG5cbiAgICAgIGNvbnN0IGltYWdlRGF0YSA9IGNvbnRleHQuZ2V0SW1hZ2VEYXRhKDAsIDAsIHdpZHRoLCBoZWlnaHQpXG4gICAgICBjb25zdCBzYW1wbGUgPSBuZXcgVmlkZW9TYW1wbGUoaW1hZ2VEYXRhLmRhdGEsIHtcbiAgICAgICAgY29kZWRIZWlnaHQ6IGhlaWdodCxcbiAgICAgICAgY29kZWRXaWR0aDogd2lkdGgsXG4gICAgICAgIGR1cmF0aW9uOiBmcmFtZUR1cmF0aW9uLFxuICAgICAgICBmb3JtYXQ6IFwiUkdCQVwiLFxuICAgICAgICB0aW1lc3RhbXA6IGZyYW1lSW5kZXggKiBmcmFtZUR1cmF0aW9uLFxuICAgICAgfSlcblxuICAgICAgeWllbGQqIEVmZmVjdC50cnlQcm9taXNlKHtcbiAgICAgICAgY2F0Y2g6IChlcnJvcikgPT4gKGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvciA6IG5ldyBFcnJvcihTdHJpbmcoZXJyb3IpKSksXG4gICAgICAgIHRyeTogKCkgPT4gdmlkZW9Tb3VyY2UuYWRkKHNhbXBsZSksXG4gICAgICB9KVxuXG4gICAgICBzYW1wbGUuY2xvc2UoKVxuICAgICAgeWllbGQqIFJlZi5zZXQoZnJhbWVJbmRleFJlZiwgZnJhbWVJbmRleCArIDEpXG4gICAgfSlcblxuY29uc3QgYnVpbGRTY2VuZUZyYW1lcyA9IChzY2VuZTogU2NlbmUsIGJsb2NrRnJhbWVzOiBudW1iZXIpID0+XG4gIFN0cmVhbS5yYW5nZSgxLCBibG9ja0ZyYW1lcykucGlwZShcbiAgICBTdHJlYW0ubWFwKFxuICAgICAgKCkgPT5cbiAgICAgICAgKHtcbiAgICAgICAgICBiYWNrZ3JvdW5kOiBzY2VuZS5iYWNrZ3JvdW5kLFxuICAgICAgICAgIGtpbmQ6IFwic2NlbmVcIixcbiAgICAgICAgICBvcGFjaXR5OiAxLFxuICAgICAgICAgIHBvc2l0aW9uWDogc2NlbmUuYmxvY2tYLFxuICAgICAgICAgIHBvc2l0aW9uWTogc2NlbmUuYmxvY2tZLFxuICAgICAgICAgIHNjZW5lLFxuICAgICAgICB9KSBzYXRpc2ZpZXMgUmVuZGVyRnJhbWVcbiAgICApXG4gIClcblxuY29uc3QgYnVpbGRUcmFuc2l0aW9uRnJhbWVzID0gKHNjZW5lOiBTY2VuZSwgbmV4dFNjZW5lOiBTY2VuZSwgdHJhbnNpdGlvbkZyYW1lczogbnVtYmVyKSA9PiB7XG4gIGNvbnN0IGRpZmYgPSBidWlsZFRyYW5zaXRpb25EaWZmKHNjZW5lLCBuZXh0U2NlbmUpXG5cbiAgcmV0dXJuIFN0cmVhbS5yYW5nZSgxLCB0cmFuc2l0aW9uRnJhbWVzKS5waXBlKFxuICAgIFN0cmVhbS5tYXAoKGluZGV4KSA9PiB7XG4gICAgICBjb25zdCByYXdQcm9ncmVzcyA9IGluZGV4IC8gdHJhbnNpdGlvbkZyYW1lc1xuICAgICAgY29uc3QgcHJvZ3Jlc3MgPSBlYXNlSW5PdXRDdWJpYyhyYXdQcm9ncmVzcylcbiAgICAgIGNvbnN0IGJsZW5kZWRCYWNrZ3JvdW5kID0gYmxlbmRDb2xvcnMoc2NlbmUuYmFja2dyb3VuZCwgbmV4dFNjZW5lLmJhY2tncm91bmQsIHByb2dyZXNzKVxuICAgICAgY29uc3QgdG9rZW5zID0gYnVpbGRUcmFuc2l0aW9uVG9rZW5zKGRpZmYsIHByb2dyZXNzKVxuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBiYWNrZ3JvdW5kOiBibGVuZGVkQmFja2dyb3VuZCxcbiAgICAgICAga2luZDogXCJ0cmFuc2l0aW9uXCIsXG4gICAgICAgIHRva2VucyxcbiAgICAgIH0gc2F0aXNmaWVzIFJlbmRlckZyYW1lXG4gICAgfSlcbiAgKVxufVxuXG5jb25zdCBidWlsZEZyYW1lc1N0cmVhbSA9IChzY2VuZXM6IFNjZW5lW10sIGJsb2NrRnJhbWVzOiBudW1iZXIsIHRyYW5zaXRpb25GcmFtZXM6IG51bWJlcikgPT5cbiAgU3RyZWFtLmZyb21JdGVyYWJsZShzY2VuZXMpLnBpcGUoXG4gICAgU3RyZWFtLnppcFdpdGhJbmRleCxcbiAgICBTdHJlYW0uZmxhdE1hcCgoW3NjZW5lLCBpbmRleF0pID0+IHtcbiAgICAgIGNvbnN0IG5leHRTY2VuZSA9IHNjZW5lc1tpbmRleCArIDFdXG4gICAgICBjb25zdCBiYXNlID0gYnVpbGRTY2VuZUZyYW1lcyhzY2VuZSwgYmxvY2tGcmFtZXMpXG4gICAgICByZXR1cm4gbmV4dFNjZW5lXG4gICAgICAgID8gU3RyZWFtLmNvbmNhdChiYXNlLCBidWlsZFRyYW5zaXRpb25GcmFtZXMoc2NlbmUsIG5leHRTY2VuZSwgdHJhbnNpdGlvbkZyYW1lcykpXG4gICAgICAgIDogYmFzZVxuICAgIH0pXG4gIClcblxudHlwZSBSZXNvbHZlZENvZGVjID0gXCJhdmNcIiB8IFwidnA5XCIgfCBcInZwOFwiIHwgXCJoZXZjXCIgfCBcImF2MVwiXG5cbnR5cGUgUmVzb2x2ZWRGb3JtYXQgPSB7XG4gIGNvZGVjOiBSZXNvbHZlZENvZGVjXG4gIGNvbnRhaW5lcjogXCJtcDRcIiB8IFwid2VibVwiXG59XG5cbmNvbnN0IHJlc29sdmVGb3JtYXQgPSAoZm9ybWF0OiBCcm93c2VyRm9ybWF0LCBoZWlnaHQ6IG51bWJlciwgd2lkdGg6IG51bWJlcikgPT5cbiAgRWZmZWN0LmdlbihmdW5jdGlvbiogKCkge1xuICAgIGlmIChmb3JtYXQgIT09IFwiYXV0b1wiKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBjb2RlYzogZm9ybWF0ID09PSBcIm1wNFwiID8gXCJhdmNcIiA6IFwidnA5XCIsXG4gICAgICAgIGNvbnRhaW5lcjogZm9ybWF0LFxuICAgICAgfSBzYXRpc2ZpZXMgUmVzb2x2ZWRGb3JtYXRcbiAgICB9XG5cbiAgICBjb25zdCBjb2RlYyA9IHlpZWxkKiBFZmZlY3QudHJ5UHJvbWlzZSh7XG4gICAgICBjYXRjaDogKCkgPT5cbiAgICAgICAgbmV3IE5vRW5jb2RhYmxlVmlkZW9Db2RlYyh7XG4gICAgICAgICAgcmVhc29uOiBcIk5vIGVuY29kYWJsZSB2aWRlbyBjb2RlYyBhdmFpbGFibGUgaW4gdGhpcyBicm93c2VyLlwiLFxuICAgICAgICB9KSxcbiAgICAgIHRyeTogKCkgPT5cbiAgICAgICAgZ2V0Rmlyc3RFbmNvZGFibGVWaWRlb0NvZGVjKFtcImF2Y1wiLCBcInZwOVwiLCBcInZwOFwiXSwge1xuICAgICAgICAgIGJpdHJhdGU6IFFVQUxJVFlfSElHSCxcbiAgICAgICAgICBoZWlnaHQsXG4gICAgICAgICAgd2lkdGgsXG4gICAgICAgIH0pLFxuICAgIH0pXG5cbiAgICBpZiAoIWNvZGVjKSB7XG4gICAgICByZXR1cm4geWllbGQqIEVmZmVjdC5mYWlsKFxuICAgICAgICBuZXcgTm9FbmNvZGFibGVWaWRlb0NvZGVjKHtcbiAgICAgICAgICByZWFzb246IFwiTm8gZW5jb2RhYmxlIHZpZGVvIGNvZGVjIGF2YWlsYWJsZSBpbiB0aGlzIGJyb3dzZXIuXCIsXG4gICAgICAgIH0pXG4gICAgICApXG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGNvZGVjLFxuICAgICAgY29udGFpbmVyOiBjb2RlYyA9PT0gXCJhdmNcIiA/IFwibXA0XCIgOiBcIndlYm1cIixcbiAgICB9IHNhdGlzZmllcyBSZXNvbHZlZEZvcm1hdFxuICB9KVxuXG5jb25zdCByZXNvbHZlQ2FudmFzID0gKFxuICBjYW52YXM6IENhbnZhc0xpa2UgfCB1bmRlZmluZWQsXG4gIGhlaWdodDogbnVtYmVyLFxuICB3aWR0aDogbnVtYmVyLFxuICBjcmVhdGVDYW52YXM/OiBDYW52YXNGYWN0b3J5XG4pID0+XG4gIEVmZmVjdC5nZW4oZnVuY3Rpb24qICgpIHtcbiAgICBpZiAoY2FudmFzKSB7XG4gICAgICBjb25zdCBjb250ZXh0ID0geWllbGQqIGdldENhbnZhc0NvbnRleHQoY2FudmFzKVxuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBjYW52YXMsXG4gICAgICAgIGNvbnRleHQsXG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKCFjcmVhdGVDYW52YXMpIHtcbiAgICAgIHJldHVybiB5aWVsZCogRWZmZWN0LmZhaWwoXG4gICAgICAgIG5ldyBNaXNzaW5nQ2FudmFzRmFjdG9yeSh7XG4gICAgICAgICAgcmVhc29uOiBcIkJyb3dzZXIgY2FudmFzIGZhY3RvcnkgaXMgcmVxdWlyZWQgd2hlbiBubyBjYW52YXMgaXMgcHJvdmlkZWQuXCIsXG4gICAgICAgIH0pXG4gICAgICApXG4gICAgfVxuXG4gICAgY29uc3QgY3JlYXRlZCA9IGNyZWF0ZUNhbnZhcyhoZWlnaHQsIHdpZHRoKVxuICAgIGNvbnN0IGNvbnRleHQgPSB5aWVsZCogZ2V0Q2FudmFzQ29udGV4dChjcmVhdGVkKVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGNhbnZhczogY3JlYXRlZCxcbiAgICAgIGNvbnRleHQsXG4gICAgfVxuICB9KVxuXG5leHBvcnQgY29uc3QgcmVuZGVyVmlkZW9Ccm93c2VyID0gKFxuICB0aGVtZTogc3RyaW5nLFxuICBjb2RlQmxvY2tzOiBDb2RlQmxvY2tbXSxcbiAgb3B0aW9uczogUmVuZGVyVmlkZW9Ccm93c2VyT3B0aW9ucyA9IHt9XG4pID0+XG4gIEVmZmVjdC5nZW4oZnVuY3Rpb24qICgpIHtcbiAgICB5aWVsZCogZW5zdXJlV2ViQ29kZWNzKClcblxuICAgIGNvbnN0IHdpZHRoID0gb3B0aW9ucy53aWR0aCA/PyBERUZBVUxUX1dJRFRIXG4gICAgY29uc3QgaGVpZ2h0ID0gb3B0aW9ucy5oZWlnaHQgPz8gREVGQVVMVF9IRUlHSFRcbiAgICBjb25zdCB0cmFuc2l0aW9uRHVyYXRpb25NcyA9IG9wdGlvbnMudHJhbnNpdGlvbkR1cmF0aW9uTXMgPz8gREVGQVVMVF9UUkFOU0lUSU9OX0RVUkFUSU9OX01TXG4gICAgY29uc3QgZm9ybWF0ID0gb3B0aW9ucy5mb3JtYXQgPz8gXCJhdXRvXCJcblxuICAgIGNvbnN0IHsgY29udGV4dCB9ID0geWllbGQqIHJlc29sdmVDYW52YXMob3B0aW9ucy5jYW52YXMsIGhlaWdodCwgd2lkdGgsIG9wdGlvbnMuY3JlYXRlQ2FudmFzKVxuICAgIGNvbnN0IHJlc29sdmVkID0geWllbGQqIHJlc29sdmVGb3JtYXQoZm9ybWF0LCBoZWlnaHQsIHdpZHRoKVxuICAgIGNvbnN0IG91dHB1dEluZm8gPSB5aWVsZCogbWFrZU91dHB1dChyZXNvbHZlZC5jb250YWluZXIpXG4gICAgY29uc3QgZnJhbWVDb3VudHMgPSBjb21wdXRlRnJhbWVDb3VudHModHJhbnNpdGlvbkR1cmF0aW9uTXMsIERFRkFVTFRfRlBTKVxuICAgIGNvbnN0IGZyYW1lSW5kZXhSZWYgPSB5aWVsZCogUmVmLm1ha2UoMClcblxuICAgIGNvbnN0IHNjZW5lcyA9IHlpZWxkKiBFZmZlY3QuZm9yRWFjaChcbiAgICAgIGNvZGVCbG9ja3MsXG4gICAgICAoY29kZUJsb2NrKSA9PiBidWlsZFNjZW5lKGNvbnRleHQsIGNvZGVCbG9jaywgdGhlbWUgYXMgbmV2ZXIsIHdpZHRoLCBoZWlnaHQpLFxuICAgICAgeyBjb25jdXJyZW5jeTogb3B0aW9ucy5jb25jdXJyZW5jeSB9XG4gICAgKVxuXG4gICAgY29uc3QgdmlkZW9Tb3VyY2UgPSB5aWVsZCogbWFrZVZpZGVvU291cmNlKHJlc29sdmVkLmNvZGVjKVxuXG4gICAgcmV0dXJuIHlpZWxkKiBFZmZlY3Quc2NvcGVkKFxuICAgICAgRWZmZWN0LmdlbihmdW5jdGlvbiogKCkge1xuICAgICAgICB5aWVsZCogRWZmZWN0LnN5bmMoKCkgPT4ge1xuICAgICAgICAgIG91dHB1dEluZm8ub3V0cHV0LmFkZFZpZGVvVHJhY2sodmlkZW9Tb3VyY2UsIHsgZnJhbWVSYXRlOiBERUZBVUxUX0ZQUyB9KVxuICAgICAgICB9KVxuXG4gICAgICAgIHlpZWxkKiBFZmZlY3QudHJ5UHJvbWlzZSh7XG4gICAgICAgICAgY2F0Y2g6IChlcnJvcikgPT4gKGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvciA6IG5ldyBFcnJvcihTdHJpbmcoZXJyb3IpKSksXG4gICAgICAgICAgdHJ5OiAoKSA9PiBvdXRwdXRJbmZvLm91dHB1dC5zdGFydCgpLFxuICAgICAgICB9KVxuXG4gICAgICAgIGNvbnN0IGZyYW1lU3RyZWFtID0gYnVpbGRGcmFtZXNTdHJlYW0oXG4gICAgICAgICAgc2NlbmVzLFxuICAgICAgICAgIGZyYW1lQ291bnRzLmJsb2NrRnJhbWVzLFxuICAgICAgICAgIGZyYW1lQ291bnRzLnRyYW5zaXRpb25GcmFtZXNcbiAgICAgICAgKVxuXG4gICAgICAgIHlpZWxkKiBTdHJlYW0ucnVuRm9yRWFjaChcbiAgICAgICAgICBmcmFtZVN0cmVhbSxcbiAgICAgICAgICByZW5kZXJBbmRXcml0ZUZyYW1lKFxuICAgICAgICAgICAgY29udGV4dCxcbiAgICAgICAgICAgIHZpZGVvU291cmNlLFxuICAgICAgICAgICAgZnJhbWVDb3VudHMuZnJhbWVEdXJhdGlvbixcbiAgICAgICAgICAgIGZyYW1lSW5kZXhSZWYsXG4gICAgICAgICAgICB3aWR0aCxcbiAgICAgICAgICAgIGhlaWdodFxuICAgICAgICAgIClcbiAgICAgICAgKVxuXG4gICAgICAgIHlpZWxkKiBFZmZlY3QudHJ5UHJvbWlzZSh7XG4gICAgICAgICAgY2F0Y2g6IChlcnJvcikgPT4gKGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvciA6IG5ldyBFcnJvcihTdHJpbmcoZXJyb3IpKSksXG4gICAgICAgICAgdHJ5OiAoKSA9PiBvdXRwdXRJbmZvLm91dHB1dC5maW5hbGl6ZSgpLFxuICAgICAgICB9KVxuXG4gICAgICAgIHZpZGVvU291cmNlLmNsb3NlKClcblxuICAgICAgICBjb25zdCBidWZmZXIgPSBvdXRwdXRJbmZvLnRhcmdldC5idWZmZXJcbiAgICAgICAgaWYgKCFidWZmZXIpIHtcbiAgICAgICAgICByZXR1cm4geWllbGQqIEVmZmVjdC5mYWlsKFxuICAgICAgICAgICAgbmV3IE91dHB1dEJ1ZmZlck1pc3Npbmcoe1xuICAgICAgICAgICAgICByZWFzb246IFwiT3V0cHV0IGJ1ZmZlciBtaXNzaW5nIGFmdGVyIGZpbmFsaXplLlwiLFxuICAgICAgICAgICAgfSlcbiAgICAgICAgICApXG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBvdXRwdXQ6IEJyb3dzZXJPdXRwdXQgPSB7XG4gICAgICAgICAgZGF0YTogbmV3IFVpbnQ4QXJyYXkoYnVmZmVyKSxcbiAgICAgICAgICBleHRlbnNpb246IHJlc29sdmVkLmNvbnRhaW5lcixcbiAgICAgICAgICBtaW1lVHlwZTogb3V0cHV0SW5mby5taW1lVHlwZSxcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBvdXRwdXRcbiAgICAgIH0pXG4gICAgKVxuICB9KVxuIgogIF0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxtQkFBUzs7O0FDQVQ7QUFDQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQXlEQSxJQUFNLG1CQUFtQixDQUFDLFdBQ3hCLE9BQU8sSUFBSSxVQUFVLEdBQUc7QUFBQSxFQUN0QixNQUFNLFVBQVUsT0FBTyxXQUFXLElBQUk7QUFBQSxFQUN0QyxJQUFJLENBQUMsU0FBUztBQUFBLElBQ1osT0FBTyxPQUFPLE9BQU8sS0FDbkIsSUFBSSx5QkFBeUIsRUFBRSxRQUFRLHVDQUF1QyxDQUFDLENBQ2pGO0FBQUEsRUFDRjtBQUFBLEVBRUEsT0FBTztBQUFBLENBQ1I7QUFFSCxJQUFNLGtCQUFrQixNQUN0QixPQUFPLElBQUksVUFBVSxHQUFHO0FBQUEsRUFDdEIsSUFBSSxPQUFPLGlCQUFpQixlQUFlLE9BQU8sZUFBZSxhQUFhO0FBQUEsSUFDNUUsT0FBTyxPQUFPLE9BQU8sS0FDbkIsSUFBSSxxQkFBcUI7QUFBQSxNQUN2QixRQUFRO0FBQUEsSUFDVixDQUFDLENBQ0g7QUFBQSxFQUNGO0FBQUEsQ0FDRDtBQUVILElBQU0scUJBQXFCLENBQUMsc0JBQThCLFFBQWdCO0FBQUEsRUFDeEUsTUFBTSxnQkFBZ0IsSUFBSTtBQUFBLEVBQzFCLE1BQU0sY0FBYyxLQUFLLElBQUksR0FBRyxLQUFLLE1BQU0seUJBQXlCLEdBQUcsQ0FBQztBQUFBLEVBQ3hFLE1BQU0sbUJBQW1CLEtBQUssSUFBSSxHQUFHLEtBQUssTUFBTyx1QkFBdUIsT0FBUSxHQUFHLENBQUM7QUFBQSxFQUVwRixPQUFPO0FBQUEsSUFDTDtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsRUFDRjtBQUFBO0FBR0YsSUFBTSxhQUFhLENBQUMsV0FDbEIsT0FBTyxLQUFLLE1BQU07QUFBQSxFQUNoQixNQUFNLGlCQUFpQixXQUFXLFNBQVMsSUFBSSxtQkFBcUIsSUFBSTtBQUFBLEVBQ3hFLE1BQU0sU0FBUyxJQUFJO0FBQUEsRUFFbkIsTUFBTSxpQkFBaUIsSUFBSSxPQUFPO0FBQUEsSUFDaEMsUUFBUTtBQUFBLElBQ1I7QUFBQSxFQUNGLENBQUM7QUFBQSxFQUVELE9BQU87QUFBQSxJQUNMLFVBQVUsZUFBZTtBQUFBLElBQ3pCLFFBQVE7QUFBQSxJQUNSO0FBQUEsRUFDRjtBQUFBLENBQ0Q7QUFFSCxJQUFNLGtCQUFrQixDQUFDLFVBQ3ZCLE9BQU8sS0FDTCxNQUNFLElBQUksa0JBQWtCO0FBQUEsRUFDcEIsU0FBUztBQUFBLEVBQ1Q7QUFDRixDQUFDLENBQ0w7QUFFRixJQUFNLHNCQUNKLENBQ0UsU0FDQSxhQUNBLGVBQ0EsZUFDQSxPQUNBLFdBRUYsQ0FBQyxVQUNDLE9BQU8sSUFBSSxVQUFVLEdBQUc7QUFBQSxFQUN0QixNQUFNLGFBQWEsT0FBTyxJQUFJLElBQUksYUFBYTtBQUFBLEVBQy9DLFlBQVksU0FBUyxPQUFPLFFBQVEsS0FBSztBQUFBLEVBRXpDLE1BQU0sWUFBWSxRQUFRLGFBQWEsR0FBRyxHQUFHLE9BQU8sTUFBTTtBQUFBLEVBQzFELE1BQU0sU0FBUyxJQUFJLFlBQVksVUFBVSxNQUFNO0FBQUEsSUFDN0MsYUFBYTtBQUFBLElBQ2IsWUFBWTtBQUFBLElBQ1osVUFBVTtBQUFBLElBQ1YsUUFBUTtBQUFBLElBQ1IsV0FBVyxhQUFhO0FBQUEsRUFDMUIsQ0FBQztBQUFBLEVBRUQsT0FBTyxPQUFPLFdBQVc7QUFBQSxJQUN2QixPQUFPLENBQUMsVUFBVyxpQkFBaUIsUUFBUSxRQUFRLElBQUksTUFBTSxPQUFPLEtBQUssQ0FBQztBQUFBLElBQzNFLEtBQUssTUFBTSxZQUFZLElBQUksTUFBTTtBQUFBLEVBQ25DLENBQUM7QUFBQSxFQUVELE9BQU8sTUFBTTtBQUFBLEVBQ2IsT0FBTyxJQUFJLElBQUksZUFBZSxhQUFhLENBQUM7QUFBQSxDQUM3QztBQUVMLElBQU0sbUJBQW1CLENBQUMsT0FBYyxnQkFDdEMsT0FBTyxNQUFNLEdBQUcsV0FBVyxFQUFFLEtBQzNCLE9BQU8sSUFDTCxPQUNHO0FBQUEsRUFDQyxZQUFZLE1BQU07QUFBQSxFQUNsQixNQUFNO0FBQUEsRUFDTixTQUFTO0FBQUEsRUFDVCxXQUFXLE1BQU07QUFBQSxFQUNqQixXQUFXLE1BQU07QUFBQSxFQUNqQjtBQUNGLEVBQ0osQ0FDRjtBQUVGLElBQU0sd0JBQXdCLENBQUMsT0FBYyxXQUFrQixxQkFBNkI7QUFBQSxFQUMxRixNQUFNLE9BQU8sb0JBQW9CLE9BQU8sU0FBUztBQUFBLEVBRWpELE9BQU8sT0FBTyxNQUFNLEdBQUcsZ0JBQWdCLEVBQUUsS0FDdkMsT0FBTyxJQUFJLENBQUMsVUFBVTtBQUFBLElBQ3BCLE1BQU0sY0FBYyxRQUFRO0FBQUEsSUFDNUIsTUFBTSxXQUFXLGVBQWUsV0FBVztBQUFBLElBQzNDLE1BQU0sb0JBQW9CLFlBQVksTUFBTSxZQUFZLFVBQVUsWUFBWSxRQUFRO0FBQUEsSUFDdEYsTUFBTSxTQUFTLHNCQUFzQixNQUFNLFFBQVE7QUFBQSxJQUVuRCxPQUFPO0FBQUEsTUFDTCxZQUFZO0FBQUEsTUFDWixNQUFNO0FBQUEsTUFDTjtBQUFBLElBQ0Y7QUFBQSxHQUNELENBQ0g7QUFBQTtBQUdGLElBQU0sb0JBQW9CLENBQUMsUUFBaUIsYUFBcUIscUJBQy9ELE9BQU8sYUFBYSxNQUFNLEVBQUUsS0FDMUIsT0FBTyxjQUNQLE9BQU8sUUFBUSxFQUFFLE9BQU8sV0FBVztBQUFBLEVBQ2pDLE1BQU0sWUFBWSxPQUFPLFFBQVE7QUFBQSxFQUNqQyxNQUFNLE9BQU8saUJBQWlCLE9BQU8sV0FBVztBQUFBLEVBQ2hELE9BQU8sWUFDSCxPQUFPLE9BQU8sTUFBTSxzQkFBc0IsT0FBTyxXQUFXLGdCQUFnQixDQUFDLElBQzdFO0FBQUEsQ0FDTCxDQUNIO0FBU0YsSUFBTSxnQkFBZ0IsQ0FBQyxRQUF1QixRQUFnQixVQUM1RCxPQUFPLElBQUksVUFBVSxHQUFHO0FBQUEsRUFDdEIsSUFBSSxXQUFXLFFBQVE7QUFBQSxJQUNyQixPQUFPO0FBQUEsTUFDTCxPQUFPLFdBQVcsUUFBUSxRQUFRO0FBQUEsTUFDbEMsV0FBVztBQUFBLElBQ2I7QUFBQSxFQUNGO0FBQUEsRUFFQSxNQUFNLFFBQVEsT0FBTyxPQUFPLFdBQVc7QUFBQSxJQUNyQyxPQUFPLE1BQ0wsSUFBSSxzQkFBc0I7QUFBQSxNQUN4QixRQUFRO0FBQUEsSUFDVixDQUFDO0FBQUEsSUFDSCxLQUFLLE1BQ0gsNEJBQTRCLENBQUMsT0FBTyxPQUFPLEtBQUssR0FBRztBQUFBLE1BQ2pELFNBQVM7QUFBQSxNQUNUO0FBQUEsTUFDQTtBQUFBLElBQ0YsQ0FBQztBQUFBLEVBQ0wsQ0FBQztBQUFBLEVBRUQsSUFBSSxDQUFDLE9BQU87QUFBQSxJQUNWLE9BQU8sT0FBTyxPQUFPLEtBQ25CLElBQUksc0JBQXNCO0FBQUEsTUFDeEIsUUFBUTtBQUFBLElBQ1YsQ0FBQyxDQUNIO0FBQUEsRUFDRjtBQUFBLEVBRUEsT0FBTztBQUFBLElBQ0w7QUFBQSxJQUNBLFdBQVcsVUFBVSxRQUFRLFFBQVE7QUFBQSxFQUN2QztBQUFBLENBQ0Q7QUFFSCxJQUFNLGdCQUFnQixDQUNwQixRQUNBLFFBQ0EsT0FDQSxpQkFFQSxPQUFPLElBQUksVUFBVSxHQUFHO0FBQUEsRUFDdEIsSUFBSSxRQUFRO0FBQUEsSUFDVixNQUFNLFdBQVUsT0FBTyxpQkFBaUIsTUFBTTtBQUFBLElBRTlDLE9BQU87QUFBQSxNQUNMO0FBQUEsTUFDQTtBQUFBLElBQ0Y7QUFBQSxFQUNGO0FBQUEsRUFFQSxJQUFJLENBQUMsY0FBYztBQUFBLElBQ2pCLE9BQU8sT0FBTyxPQUFPLEtBQ25CLElBQUkscUJBQXFCO0FBQUEsTUFDdkIsUUFBUTtBQUFBLElBQ1YsQ0FBQyxDQUNIO0FBQUEsRUFDRjtBQUFBLEVBRUEsTUFBTSxVQUFVLGFBQWEsUUFBUSxLQUFLO0FBQUEsRUFDMUMsTUFBTSxVQUFVLE9BQU8saUJBQWlCLE9BQU87QUFBQSxFQUUvQyxPQUFPO0FBQUEsSUFDTCxRQUFRO0FBQUEsSUFDUjtBQUFBLEVBQ0Y7QUFBQSxDQUNEO0FBRUksSUFBTSxxQkFBcUIsQ0FDaEMsT0FDQSxZQUNBLFVBQXFDLENBQUMsTUFFdEMsT0FBTyxJQUFJLFVBQVUsR0FBRztBQUFBLEVBQ3RCLE9BQU8sZ0JBQWdCO0FBQUEsRUFFdkIsTUFBTSxRQUFRLFFBQVEsU0FBUztBQUFBLEVBQy9CLE1BQU0sU0FBUyxRQUFRLFVBQVU7QUFBQSxFQUNqQyxNQUFNLHVCQUF1QixRQUFRLHdCQUF3QjtBQUFBLEVBQzdELE1BQU0sU0FBUyxRQUFRLFVBQVU7QUFBQSxFQUVqQyxRQUFRLFlBQVksT0FBTyxjQUFjLFFBQVEsUUFBUSxRQUFRLE9BQU8sUUFBUSxZQUFZO0FBQUEsRUFDNUYsTUFBTSxXQUFXLE9BQU8sY0FBYyxRQUFRLFFBQVEsS0FBSztBQUFBLEVBQzNELE1BQU0sYUFBYSxPQUFPLFdBQVcsU0FBUyxTQUFTO0FBQUEsRUFDdkQsTUFBTSxjQUFjLG1CQUFtQixzQkFBc0IsV0FBVztBQUFBLEVBQ3hFLE1BQU0sZ0JBQWdCLE9BQU8sSUFBSSxLQUFLLENBQUM7QUFBQSxFQUV2QyxNQUFNLFNBQVMsT0FBTyxPQUFPLFFBQzNCLFlBQ0EsQ0FBQyxjQUFjLFdBQVcsU0FBUyxXQUFXLE9BQWdCLE9BQU8sTUFBTSxHQUMzRSxFQUFFLGFBQWEsUUFBUSxZQUFZLENBQ3JDO0FBQUEsRUFFQSxNQUFNLGNBQWMsT0FBTyxnQkFBZ0IsU0FBUyxLQUFLO0FBQUEsRUFFekQsT0FBTyxPQUFPLE9BQU8sT0FDbkIsT0FBTyxJQUFJLFVBQVUsR0FBRztBQUFBLElBQ3RCLE9BQU8sT0FBTyxLQUFLLE1BQU07QUFBQSxNQUN2QixXQUFXLE9BQU8sY0FBYyxhQUFhLEVBQUUsV0FBVyxZQUFZLENBQUM7QUFBQSxLQUN4RTtBQUFBLElBRUQsT0FBTyxPQUFPLFdBQVc7QUFBQSxNQUN2QixPQUFPLENBQUMsVUFBVyxpQkFBaUIsUUFBUSxRQUFRLElBQUksTUFBTSxPQUFPLEtBQUssQ0FBQztBQUFBLE1BQzNFLEtBQUssTUFBTSxXQUFXLE9BQU8sTUFBTTtBQUFBLElBQ3JDLENBQUM7QUFBQSxJQUVELE1BQU0sY0FBYyxrQkFDbEIsUUFDQSxZQUFZLGFBQ1osWUFBWSxnQkFDZDtBQUFBLElBRUEsT0FBTyxPQUFPLFdBQ1osYUFDQSxvQkFDRSxTQUNBLGFBQ0EsWUFBWSxlQUNaLGVBQ0EsT0FDQSxNQUNGLENBQ0Y7QUFBQSxJQUVBLE9BQU8sT0FBTyxXQUFXO0FBQUEsTUFDdkIsT0FBTyxDQUFDLFVBQVcsaUJBQWlCLFFBQVEsUUFBUSxJQUFJLE1BQU0sT0FBTyxLQUFLLENBQUM7QUFBQSxNQUMzRSxLQUFLLE1BQU0sV0FBVyxPQUFPLFNBQVM7QUFBQSxJQUN4QyxDQUFDO0FBQUEsSUFFRCxZQUFZLE1BQU07QUFBQSxJQUVsQixNQUFNLFNBQVMsV0FBVyxPQUFPO0FBQUEsSUFDakMsSUFBSSxDQUFDLFFBQVE7QUFBQSxNQUNYLE9BQU8sT0FBTyxPQUFPLEtBQ25CLElBQUksb0JBQW9CO0FBQUEsUUFDdEIsUUFBUTtBQUFBLE1BQ1YsQ0FBQyxDQUNIO0FBQUEsSUFDRjtBQUFBLElBRUEsTUFBTSxTQUF3QjtBQUFBLE1BQzVCLE1BQU0sSUFBSSxXQUFXLE1BQU07QUFBQSxNQUMzQixXQUFXLFNBQVM7QUFBQSxNQUNwQixVQUFVLFdBQVc7QUFBQSxJQUN2QjtBQUFBLElBRUEsT0FBTztBQUFBLEdBQ1IsQ0FDSDtBQUFBLENBQ0Q7OztBRHBWSSxJQUFNLFNBQVMsQ0FBQyxZQUNyQixRQUFPLFdBQ0wsUUFBTyxJQUFJLFVBQVUsR0FBRztBQUFBLEVBQ3RCLE1BQU0sUUFBUSxRQUFRLFNBQVM7QUFBQSxFQUMvQixNQUFNLGdCQUFnQixPQUFPLGFBQWEsS0FBSztBQUFBLEVBQy9DLE1BQU0sU0FBUyxPQUFPLHdCQUF3QixRQUFRLFFBQVE7QUFBQSxFQUU5RCxNQUFNLFNBQVMsT0FBTyxtQkFBbUIsZUFBZSxRQUFRO0FBQUEsSUFDOUQsUUFBUSxRQUFRO0FBQUEsSUFDaEIsYUFBYSxRQUFRO0FBQUEsSUFDckIsY0FBYyxRQUFRO0FBQUEsSUFDdEIsUUFBUSxRQUFRO0FBQUEsSUFDaEIsUUFBUSxRQUFRO0FBQUEsSUFDaEIsc0JBQXNCLFFBQVE7QUFBQSxJQUM5QixPQUFPLFFBQVE7QUFBQSxFQUNqQixDQUFDO0FBQUEsRUFFRCxPQUFPO0FBQUEsQ0FDUixDQUNIOyIsCiAgImRlYnVnSWQiOiAiMzBDMUFGOEQwODU1OEE5NDY0NzU2RTIxNjQ3NTZFMjEiLAogICJuYW1lcyI6IFtdCn0=