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/LICENSE +21 -0
- package/README.md +9 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +233 -0
- package/dist/index.d.ts +82 -0
- package/dist/index.js +237 -0
- package/dist/shared/chunk-ks7faw1s.js +1782 -0
- package/package.json +69 -0
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/PyBERUZBVUxUX1dJRFRIXG4gICAgY29uc3QgaGVpZ2h0ID0gb3B0aW9ucy5oZWlnaHQgPz8gREVGQVVMVF9IRUlHSFRcbiAgICBjb25zdCB0cmFuc2l0aW9uRHVyYXRpb25NcyA9IG9wdGlvbnMudHJhbnNpdGlvbkR1cmF0aW9uTXMgPz8gREVGQVVMVF9UUkFOU0lUSU9OX0RVUkFUSU9OX01TXG4gICAgY29uc3QgZm9ybWF0ID0gb3B0aW9ucy5mb3JtYXQgPz8gXCJhdXRvXCJcblxuICAgIGNvbnN0IHsgY29udGV4dCB9ID0geWllbGQqIHJlc29sdmVDYW52YXMob3B0aW9ucy5jYW52YXMsIGhlaWdodCwgd2lkdGgsIG9wdGlvbnMuY3JlYXRlQ2FudmFzKVxuICAgIGNvbnN0IHJlc29sdmVkID0geWllbGQqIHJlc29sdmVGb3JtYXQoZm9ybWF0LCBoZWlnaHQsIHdpZHRoKVxuICAgIGNvbnN0IG91dHB1dEluZm8gPSB5aWVsZCogbWFrZU91dHB1dChyZXNvbHZlZC5jb250YWluZXIpXG4gICAgY29uc3QgZnJhbWVDb3VudHMgPSBjb21wdXRlRnJhbWVDb3VudHModHJhbnNpdGlvbkR1cmF0aW9uTXMsIERFRkFVTFRfRlBTKVxuICAgIGNvbnN0IGZyYW1lSW5kZXhSZWYgPSB5aWVsZCogUmVmLm1ha2UoMClcblxuICAgIGNvbnN0IHNjZW5lcyA9IHlpZWxkKiBFZmZlY3QuZm9yRWFjaChcbiAgICAgIGNvZGVCbG9ja3MsXG4gICAgICAoY29kZUJsb2NrKSA9PiBidWlsZFNjZW5lKGNvbnRleHQsIGNvZGVCbG9jaywgdGhlbWUgYXMgbmV2ZXIsIHdpZHRoLCBoZWlnaHQpLFxuICAgICAgeyBjb25jdXJyZW5jeTogb3B0aW9ucy5jb25jdXJyZW5jeSB9XG4gICAgKVxuXG4gICAgY29uc3QgdmlkZW9Tb3VyY2UgPSB5aWVsZCogbWFrZVZpZGVvU291cmNlKHJlc29sdmVkLmNvZGVjKVxuXG4gICAgcmV0dXJuIHlpZWxkKiBFZmZlY3Quc2NvcGVkKFxuICAgICAgRWZmZWN0LmdlbihmdW5jdGlvbiogKCkge1xuICAgICAgICB5aWVsZCogRWZmZWN0LnN5bmMoKCkgPT4ge1xuICAgICAgICAgIG91dHB1dEluZm8ub3V0cHV0LmFkZFZpZGVvVHJhY2sodmlkZW9Tb3VyY2UsIHsgZnJhbWVSYXRlOiBERUZBVUxUX0ZQUyB9KVxuICAgICAgICB9KVxuXG4gICAgICAgIHlpZWxkKiBFZmZlY3QudHJ5UHJvbWlzZSh7XG4gICAgICAgICAgY2F0Y2g6IChlcnJvcikgPT4gKGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvciA6IG5ldyBFcnJvcihTdHJpbmcoZXJyb3IpKSksXG4gICAgICAgICAgdHJ5OiAoKSA9PiBvdXRwdXRJbmZvLm91dHB1dC5zdGFydCgpLFxuICAgICAgICB9KVxuXG4gICAgICAgIGNvbnN0IGZyYW1lU3RyZWFtID0gYnVpbGRGcmFtZXNTdHJlYW0oXG4gICAgICAgICAgc2NlbmVzLFxuICAgICAgICAgIGZyYW1lQ291bnRzLmJsb2NrRnJhbWVzLFxuICAgICAgICAgIGZyYW1lQ291bnRzLnRyYW5zaXRpb25GcmFtZXNcbiAgICAgICAgKVxuXG4gICAgICAgIHlpZWxkKiBTdHJlYW0ucnVuRm9yRWFjaChcbiAgICAgICAgICBmcmFtZVN0cmVhbSxcbiAgICAgICAgICByZW5kZXJBbmRXcml0ZUZyYW1lKFxuICAgICAgICAgICAgY29udGV4dCxcbiAgICAgICAgICAgIHZpZGVvU291cmNlLFxuICAgICAgICAgICAgZnJhbWVDb3VudHMuZnJhbWVEdXJhdGlvbixcbiAgICAgICAgICAgIGZyYW1lSW5kZXhSZWYsXG4gICAgICAgICAgICB3aWR0aCxcbiAgICAgICAgICAgIGhlaWdodFxuICAgICAgICAgIClcbiAgICAgICAgKVxuXG4gICAgICAgIHlpZWxkKiBFZmZlY3QudHJ5UHJvbWlzZSh7XG4gICAgICAgICAgY2F0Y2g6IChlcnJvcikgPT4gKGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvciA6IG5ldyBFcnJvcihTdHJpbmcoZXJyb3IpKSksXG4gICAgICAgICAgdHJ5OiAoKSA9PiBvdXRwdXRJbmZvLm91dHB1dC5maW5hbGl6ZSgpLFxuICAgICAgICB9KVxuXG4gICAgICAgIHZpZGVvU291cmNlLmNsb3NlKClcblxuICAgICAgICBjb25zdCBidWZmZXIgPSBvdXRwdXRJbmZvLnRhcmdldC5idWZmZXJcbiAgICAgICAgaWYgKCFidWZmZXIpIHtcbiAgICAgICAgICByZXR1cm4geWllbGQqIEVmZmVjdC5mYWlsKFxuICAgICAgICAgICAgbmV3IE91dHB1dEJ1ZmZlck1pc3Npbmcoe1xuICAgICAgICAgICAgICByZWFzb246IFwiT3V0cHV0IGJ1ZmZlciBtaXNzaW5nIGFmdGVyIGZpbmFsaXplLlwiLFxuICAgICAgICAgICAgfSlcbiAgICAgICAgICApXG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBvdXRwdXQ6IEJyb3dzZXJPdXRwdXQgPSB7XG4gICAgICAgICAgZGF0YTogbmV3IFVpbnQ4QXJyYXkoYnVmZmVyKSxcbiAgICAgICAgICBleHRlbnNpb246IHJlc29sdmVkLmNvbnRhaW5lcixcbiAgICAgICAgICBtaW1lVHlwZTogb3V0cHV0SW5mby5taW1lVHlwZSxcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBvdXRwdXRcbiAgICAgIH0pXG4gICAgKVxuICB9KVxuIgogIF0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxtQkFBUzs7O0FDQVQ7QUFDQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQXlEQSxJQUFNLG1CQUFtQixDQUFDLFdBQ3hCLE9BQU8sSUFBSSxVQUFVLEdBQUc7QUFBQSxFQUN0QixNQUFNLFVBQVUsT0FBTyxXQUFXLElBQUk7QUFBQSxFQUN0QyxJQUFJLENBQUMsU0FBUztBQUFBLElBQ1osT0FBTyxPQUFPLE9BQU8sS0FDbkIsSUFBSSx5QkFBeUIsRUFBRSxRQUFRLHVDQUF1QyxDQUFDLENBQ2pGO0FBQUEsRUFDRjtBQUFBLEVBRUEsT0FBTztBQUFBLENBQ1I7QUFFSCxJQUFNLGtCQUFrQixNQUN0QixPQUFPLElBQUksVUFBVSxHQUFHO0FBQUEsRUFDdEIsSUFBSSxPQUFPLGlCQUFpQixlQUFlLE9BQU8sZUFBZSxhQUFhO0FBQUEsSUFDNUUsT0FBTyxPQUFPLE9BQU8sS0FDbkIsSUFBSSxxQkFBcUI7QUFBQSxNQUN2QixRQUFRO0FBQUEsSUFDVixDQUFD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LElBRUEsT0FBTztBQUFBLEdBQ1IsQ0FDSDtBQUFBLENBQ0Q7OztBRHBWSSxJQUFNLFNBQVMsQ0FBQyxZQUNyQixRQUFPLFdBQ0wsUUFBTyxJQUFJLFVBQVUsR0FBRztBQUFBLEVBQ3RCLE1BQU0sUUFBUSxRQUFRLFNBQVM7QUFBQSxFQUMvQixNQUFNLGdCQUFnQixPQUFPLGFBQWEsS0FBSztBQUFBLEVBQy9DLE1BQU0sU0FBUyxPQUFPLHdCQUF3QixRQUFRLFFBQVE7QUFBQSxFQUU5RCxNQUFNLFNBQVMsT0FBTyxtQkFBbUIsZUFBZSxRQUFRO0FBQUEsSUFDOUQsUUFBUSxRQUFRO0FBQUEsSUFDaEIsYUFBYSxRQUFRO0FBQUEsSUFDckIsY0FBYyxRQUFRO0FBQUEsSUFDdEIsUUFBUSxRQUFRO0FBQUEsSUFDaEIsUUFBUSxRQUFRO0FBQUEsSUFDaEIsc0JBQXNCLFFBQVE7QUFBQSxJQUM5QixPQUFPLFFBQVE7QUFBQSxFQUNqQixDQUFDO0FBQUEsRUFFRCxPQUFPO0FBQUEsQ0FDUixDQUNIOyIsCiAgImRlYnVnSWQiOiAiMzBDMUFGOEQwODU1OEE5NDY0NzU2RTIxNjQ3NTZFMjEiLAogICJuYW1lcyI6IFtdCn0=
|