@jsprismarine/spawning 0.0.0 → 0.16.0-unstable-20261029135432

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.
@@ -0,0 +1,277 @@
1
+ import { FilterParseError, parseFilter } from "@jsprismarine/packs";
2
+ // src/rules.ts
3
+ /**
4
+ * The spawn rule grammar.
5
+ *
6
+ * A file is `{"format_version": "<semver>", "minecraft:spawn_rules": {...}}`,
7
+ * and the body has `description` and `conditions`. Mojang's
8
+ * `Spawn Rules.json` declares 24 condition components; vanilla writes 21 of
9
+ * them. Parsing reports an unknown component rather than refusing the file, so
10
+ * a pack written against a newer game still loads and the report names what
11
+ * the runtime did not read.
12
+ */
13
+ /** The pools `description.population_control` names, each with its own cap. */
14
+ var POPULATION_POOLS = [
15
+ "animal",
16
+ "water_animal",
17
+ "water_ambient",
18
+ "ambient",
19
+ "monster",
20
+ "cat",
21
+ "pillager",
22
+ "villager"
23
+ ];
24
+ /** The difficulty names `minecraft:difficulty_filter` compares, in ascending order. */
25
+ var DIFFICULTIES = [
26
+ "peaceful",
27
+ "easy",
28
+ "normal",
29
+ "hard"
30
+ ];
31
+ /**
32
+ * Every condition component `Spawn Rules.json` declares, in the schema's
33
+ * order. Vanilla writes 21 of the 24; `minecraft:spawns_above_block_filter`,
34
+ * `minecraft:is_persistent` and `minecraft:is_experimental` appear in the
35
+ * schema alone, so this package parses them and leaves their meaning to the
36
+ * caller.
37
+ */
38
+ var SPAWN_RULE_COMPONENTS = [
39
+ "minecraft:biome_filter",
40
+ "minecraft:brightness_filter",
41
+ "minecraft:delay_filter",
42
+ "minecraft:density_limit",
43
+ "minecraft:difficulty_filter",
44
+ "minecraft:disallow_spawns_in_bubble",
45
+ "minecraft:distance_filter",
46
+ "minecraft:height_filter",
47
+ "minecraft:herd",
48
+ "minecraft:is_experimental",
49
+ "minecraft:is_persistent",
50
+ "minecraft:mob_event_filter",
51
+ "minecraft:permute_type",
52
+ "minecraft:player_in_village_filter",
53
+ "minecraft:spawn_event",
54
+ "minecraft:spawns_above_block_filter",
55
+ "minecraft:spawns_lava",
56
+ "minecraft:spawns_on_block_filter",
57
+ "minecraft:spawns_on_block_prevented_filter",
58
+ "minecraft:spawns_on_surface",
59
+ "minecraft:spawns_underground",
60
+ "minecraft:spawns_underwater",
61
+ "minecraft:weight",
62
+ "minecraft:world_age_filter"
63
+ ];
64
+ var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
65
+ var KNOWN_COMPONENTS = new Set(SPAWN_RULE_COMPONENTS);
66
+ var KNOWN_POOLS = new Set(POPULATION_POOLS);
67
+ /** Reads a number, falling back when the key is absent or not a number. */
68
+ var numberAt = (source, key, fallback) => {
69
+ const value = source[key];
70
+ return typeof value === "number" && Number.isFinite(value) ? value : fallback;
71
+ };
72
+ var stringAt = (source, key) => {
73
+ const value = source[key];
74
+ return typeof value === "string" ? value : void 0;
75
+ };
76
+ var bodyOf = (value) => isRecord(value) ? value : {};
77
+ /**
78
+ * Reads a block list written as one name, as a list of names, or as a list of
79
+ * `{name}` objects. All three appear in vanilla.
80
+ */
81
+ var blockList = (value) => {
82
+ const members = Array.isArray(value) ? value : [value];
83
+ const names = [];
84
+ for (const member of members) if (typeof member === "string") names.push(member);
85
+ else if (isRecord(member) && typeof member.name === "string") names.push(member.name);
86
+ return names;
87
+ };
88
+ var difficultyAt = (source, key, fallback, fail) => {
89
+ const value = source[key];
90
+ if (value === void 0) return fallback;
91
+ const name = DIFFICULTIES.find((difficulty) => difficulty === value);
92
+ if (name !== void 0) return name;
93
+ fail(`minecraft:difficulty_filter ${key} is not a difficulty: ${JSON.stringify(value)}`);
94
+ return fallback;
95
+ };
96
+ var parseHerd = (value) => (Array.isArray(value) ? value : [value]).filter(isRecord).map((body) => {
97
+ const rule = {
98
+ minSize: numberAt(body, "min_size", 1),
99
+ maxSize: numberAt(body, "max_size", 1),
100
+ initialEventCount: numberAt(body, "initial_event_count", 0),
101
+ eventSkipCount: numberAt(body, "event_skip_count", 0)
102
+ };
103
+ const initialEvent = stringAt(body, "initial_event");
104
+ if (initialEvent !== void 0) rule.initialEvent = initialEvent;
105
+ const event = stringAt(body, "event");
106
+ if (event !== void 0) rule.event = event;
107
+ return rule;
108
+ });
109
+ var parsePermutations = (value) => (Array.isArray(value) ? value : []).filter(isRecord).map((body) => {
110
+ const permutation = {
111
+ weight: numberAt(body, "weight", 1),
112
+ minGuaranteed: numberAt(body, "min_guaranteed", numberAt(body, "guaranteed_count", 0))
113
+ };
114
+ const entityType = stringAt(body, "entity_type");
115
+ if (entityType !== void 0) permutation.entityType = entityType;
116
+ return permutation;
117
+ });
118
+ var parseCondition = (value, fail) => {
119
+ for (const key of Object.keys(value)) if (!KNOWN_COMPONENTS.has(key)) fail("spawnRule.unknownComponent", `unknown spawn rule component ${key}`);
120
+ const weightBody = bodyOf(value["minecraft:weight"]);
121
+ const condition = {
122
+ weight: {
123
+ default: numberAt(weightBody, "default", 1),
124
+ rarity: numberAt(weightBody, "rarity", 0)
125
+ },
126
+ herd: "minecraft:herd" in value ? parseHerd(value["minecraft:herd"]) : [],
127
+ spawnsOnSurface: "minecraft:spawns_on_surface" in value,
128
+ spawnsUnderground: "minecraft:spawns_underground" in value,
129
+ spawnsUnderwater: "minecraft:spawns_underwater" in value,
130
+ spawnsLava: "minecraft:spawns_lava" in value,
131
+ disallowSpawnsInBubble: "minecraft:disallow_spawns_in_bubble" in value,
132
+ isPersistent: "minecraft:is_persistent" in value,
133
+ isExperimental: "minecraft:is_experimental" in value
134
+ };
135
+ if ("minecraft:biome_filter" in value) try {
136
+ condition.biomeFilter = parseFilter(value["minecraft:biome_filter"]);
137
+ } catch (error) {
138
+ if (!(error instanceof FilterParseError)) throw error;
139
+ fail("spawnRule.badValue", `minecraft:biome_filter does not parse: ${error.message}`);
140
+ }
141
+ if ("minecraft:brightness_filter" in value) {
142
+ const body = bodyOf(value["minecraft:brightness_filter"]);
143
+ condition.brightness = {
144
+ min: numberAt(body, "min", 0),
145
+ max: numberAt(body, "max", 15),
146
+ adjustForWeather: body.adjust_for_weather === true
147
+ };
148
+ }
149
+ if ("minecraft:difficulty_filter" in value) {
150
+ const body = bodyOf(value["minecraft:difficulty_filter"]);
151
+ const report = (message) => fail("spawnRule.badValue", message);
152
+ condition.difficulty = {
153
+ min: difficultyAt(body, "min", "peaceful", report),
154
+ max: difficultyAt(body, "max", "hard", report)
155
+ };
156
+ }
157
+ if ("minecraft:height_filter" in value) {
158
+ const body = bodyOf(value["minecraft:height_filter"]);
159
+ condition.height = {
160
+ min: numberAt(body, "min", 24),
161
+ max: numberAt(body, "max", 128)
162
+ };
163
+ }
164
+ if ("minecraft:distance_filter" in value) {
165
+ const body = bodyOf(value["minecraft:distance_filter"]);
166
+ condition.distance = {
167
+ min: numberAt(body, "min", 24),
168
+ max: numberAt(body, "max", 128)
169
+ };
170
+ }
171
+ if ("minecraft:world_age_filter" in value) {
172
+ const body = bodyOf(value["minecraft:world_age_filter"]);
173
+ condition.worldAge = {
174
+ min: numberAt(body, "min", 0),
175
+ max: numberAt(body, "max", -1)
176
+ };
177
+ }
178
+ if ("minecraft:density_limit" in value) {
179
+ const body = bodyOf(value["minecraft:density_limit"]);
180
+ condition.density = {
181
+ surface: numberAt(body, "surface", -1),
182
+ underground: numberAt(body, "underground", -1)
183
+ };
184
+ }
185
+ if ("minecraft:spawns_on_block_filter" in value) condition.blocks = blockList(value["minecraft:spawns_on_block_filter"]);
186
+ if ("minecraft:spawns_on_block_prevented_filter" in value) condition.preventedBlocks = blockList(value["minecraft:spawns_on_block_prevented_filter"]);
187
+ if ("minecraft:spawns_above_block_filter" in value) {
188
+ const body = bodyOf(value["minecraft:spawns_above_block_filter"]);
189
+ condition.aboveBlocks = {
190
+ blocks: blockList(body.blocks),
191
+ distance: numberAt(body, "distance", 1)
192
+ };
193
+ }
194
+ if ("minecraft:permute_type" in value) condition.permutations = parsePermutations(value["minecraft:permute_type"]);
195
+ if ("minecraft:delay_filter" in value) {
196
+ const body = bodyOf(value["minecraft:delay_filter"]);
197
+ const delay = {
198
+ min: numberAt(body, "min", 0),
199
+ max: numberAt(body, "max", 0),
200
+ spawnChance: numberAt(body, "spawn_chance", 100)
201
+ };
202
+ const identifier = stringAt(body, "identifier");
203
+ if (identifier !== void 0) delay.identifier = identifier;
204
+ condition.delay = delay;
205
+ }
206
+ const mobEvent = stringAt(bodyOf(value["minecraft:mob_event_filter"]), "event");
207
+ if ("minecraft:mob_event_filter" in value && mobEvent !== void 0) condition.mobEvent = mobEvent;
208
+ const spawnEvent = stringAt(bodyOf(value["minecraft:spawn_event"]), "event");
209
+ if ("minecraft:spawn_event" in value && spawnEvent !== void 0) condition.spawnEvent = spawnEvent;
210
+ if ("minecraft:player_in_village_filter" in value) {
211
+ const body = bodyOf(value["minecraft:player_in_village_filter"]);
212
+ condition.playerInVillage = {
213
+ distance: numberAt(body, "distance", 0),
214
+ villageBorderTolerance: numberAt(body, "village_border_tolerance", 10)
215
+ };
216
+ }
217
+ return condition;
218
+ };
219
+ /**
220
+ * Parses one `spawn_rules/*.json` file.
221
+ *
222
+ * @returns The rule, or undefined when the file is not a spawn rule or names
223
+ * no identifier. Everything else loads and reports.
224
+ */
225
+ var parseSpawnRule = (file, options) => {
226
+ const fail = (code, message) => {
227
+ const diagnostic = {
228
+ severity: "error",
229
+ code,
230
+ pack: options.pack,
231
+ message
232
+ };
233
+ if (options.path !== void 0) diagnostic.path = options.path;
234
+ options.report?.(diagnostic);
235
+ };
236
+ const warn = (code, message) => {
237
+ const diagnostic = {
238
+ severity: "warning",
239
+ code,
240
+ pack: options.pack,
241
+ message
242
+ };
243
+ if (options.path !== void 0) diagnostic.path = options.path;
244
+ options.report?.(diagnostic);
245
+ };
246
+ if (!isRecord(file) || !isRecord(file["minecraft:spawn_rules"])) {
247
+ fail("spawnRule.notASpawnRule", "the file has no `minecraft:spawn_rules` body");
248
+ return;
249
+ }
250
+ const body = file["minecraft:spawn_rules"];
251
+ const description = bodyOf(body.description);
252
+ const identifier = stringAt(description, "identifier");
253
+ if (identifier === void 0) {
254
+ fail("spawnRule.missingIdentifier", "`description.identifier` is missing");
255
+ return;
256
+ }
257
+ const rule = {
258
+ identifier,
259
+ conditions: []
260
+ };
261
+ const formatVersion = stringAt(file, "format_version");
262
+ if (formatVersion !== void 0) rule.formatVersion = formatVersion;
263
+ const pool = stringAt(description, "population_control");
264
+ if (pool !== void 0) {
265
+ rule.populationControl = pool;
266
+ if (!KNOWN_POOLS.has(pool)) warn("spawnRule.unknownPool", `unknown population_control ${pool}`);
267
+ }
268
+ const conditions = body.conditions;
269
+ if (conditions !== void 0) {
270
+ if (!Array.isArray(conditions)) fail("spawnRule.badValue", "`conditions` must be an array");
271
+ else rule.conditions = conditions.filter(isRecord).map((condition) => parseCondition(condition, fail));
272
+ }
273
+ return rule;
274
+ };
275
+ export { DIFFICULTIES, POPULATION_POOLS, SPAWN_RULE_COMPONENTS, parseSpawnRule };
276
+
277
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVsZXMuZXMuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vc3JjL3J1bGVzLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgRGlhZ25vc3RpYyB9IGZyb20gJ0Bqc3ByaXNtYXJpbmUvZW50aXRpZXMnO1xuaW1wb3J0IHR5cGUgeyBGaWx0ZXIgfSBmcm9tICdAanNwcmlzbWFyaW5lL3BhY2tzJztcbmltcG9ydCB7IEZpbHRlclBhcnNlRXJyb3IsIHBhcnNlRmlsdGVyIH0gZnJvbSAnQGpzcHJpc21hcmluZS9wYWNrcyc7XG5cbi8qKlxuICogVGhlIHNwYXduIHJ1bGUgZ3JhbW1hci5cbiAqXG4gKiBBIGZpbGUgaXMgYHtcImZvcm1hdF92ZXJzaW9uXCI6IFwiPHNlbXZlcj5cIiwgXCJtaW5lY3JhZnQ6c3Bhd25fcnVsZXNcIjogey4uLn19YCxcbiAqIGFuZCB0aGUgYm9keSBoYXMgYGRlc2NyaXB0aW9uYCBhbmQgYGNvbmRpdGlvbnNgLiBNb2phbmcnc1xuICogYFNwYXduIFJ1bGVzLmpzb25gIGRlY2xhcmVzIDI0IGNvbmRpdGlvbiBjb21wb25lbnRzOyB2YW5pbGxhIHdyaXRlcyAyMSBvZlxuICogdGhlbS4gUGFyc2luZyByZXBvcnRzIGFuIHVua25vd24gY29tcG9uZW50IHJhdGhlciB0aGFuIHJlZnVzaW5nIHRoZSBmaWxlLCBzb1xuICogYSBwYWNrIHdyaXR0ZW4gYWdhaW5zdCBhIG5ld2VyIGdhbWUgc3RpbGwgbG9hZHMgYW5kIHRoZSByZXBvcnQgbmFtZXMgd2hhdFxuICogdGhlIHJ1bnRpbWUgZGlkIG5vdCByZWFkLlxuICovXG5cbi8qKiBUaGUgcG9vbHMgYGRlc2NyaXB0aW9uLnBvcHVsYXRpb25fY29udHJvbGAgbmFtZXMsIGVhY2ggd2l0aCBpdHMgb3duIGNhcC4gKi9cbmV4cG9ydCBjb25zdCBQT1BVTEFUSU9OX1BPT0xTID0gW1xuICAgICdhbmltYWwnLFxuICAgICd3YXRlcl9hbmltYWwnLFxuICAgICd3YXRlcl9hbWJpZW50JyxcbiAgICAnYW1iaWVudCcsXG4gICAgJ21vbnN0ZXInLFxuICAgICdjYXQnLFxuICAgICdwaWxsYWdlcicsXG4gICAgJ3ZpbGxhZ2VyJ1xuXSBhcyBjb25zdDtcblxuLyoqIE9uZSBvZiB7QGxpbmsgUE9QVUxBVElPTl9QT09MU30uICovXG5leHBvcnQgdHlwZSBQb3B1bGF0aW9uUG9vbCA9ICh0eXBlb2YgUE9QVUxBVElPTl9QT09MUylbbnVtYmVyXTtcblxuLyoqIFRoZSBkaWZmaWN1bHR5IG5hbWVzIGBtaW5lY3JhZnQ6ZGlmZmljdWx0eV9maWx0ZXJgIGNvbXBhcmVzLCBpbiBhc2NlbmRpbmcgb3JkZXIuICovXG5leHBvcnQgY29uc3QgRElGRklDVUxUSUVTID0gWydwZWFjZWZ1bCcsICdlYXN5JywgJ25vcm1hbCcsICdoYXJkJ10gYXMgY29uc3Q7XG5cbi8qKiBPbmUgb2Yge0BsaW5rIERJRkZJQ1VMVElFU30uICovXG5leHBvcnQgdHlwZSBEaWZmaWN1bHR5ID0gKHR5cGVvZiBESUZGSUNVTFRJRVMpW251bWJlcl07XG5cbi8qKlxuICogRXZlcnkgY29uZGl0aW9uIGNvbXBvbmVudCBgU3Bhd24gUnVsZXMuanNvbmAgZGVjbGFyZXMsIGluIHRoZSBzY2hlbWEnc1xuICogb3JkZXIuIFZhbmlsbGEgd3JpdGVzIDIxIG9mIHRoZSAyNDsgYG1pbmVjcmFmdDpzcGF3bnNfYWJvdmVfYmxvY2tfZmlsdGVyYCxcbiAqIGBtaW5lY3JhZnQ6aXNfcGVyc2lzdGVudGAgYW5kIGBtaW5lY3JhZnQ6aXNfZXhwZXJpbWVudGFsYCBhcHBlYXIgaW4gdGhlXG4gKiBzY2hlbWEgYWxvbmUsIHNvIHRoaXMgcGFja2FnZSBwYXJzZXMgdGhlbSBhbmQgbGVhdmVzIHRoZWlyIG1lYW5pbmcgdG8gdGhlXG4gKiBjYWxsZXIuXG4gKi9cbmV4cG9ydCBjb25zdCBTUEFXTl9SVUxFX0NPTVBPTkVOVFMgPSBbXG4gICAgJ21pbmVjcmFmdDpiaW9tZV9maWx0ZXInLFxuICAgICdtaW5lY3JhZnQ6YnJpZ2h0bmVzc19maWx0ZXInLFxuICAgICdtaW5lY3JhZnQ6ZGVsYXlfZmlsdGVyJyxcbiAgICAnbWluZWNyYWZ0OmRlbnNpdHlfbGltaXQnLFxuICAgICdtaW5lY3JhZnQ6ZGlmZmljdWx0eV9maWx0ZXInLFxuICAgICdtaW5lY3JhZnQ6ZGlzYWxsb3dfc3Bhd25zX2luX2J1YmJsZScsXG4gICAgJ21pbmVjcmFmdDpkaXN0YW5jZV9maWx0ZXInLFxuICAgICdtaW5lY3JhZnQ6aGVpZ2h0X2ZpbHRlcicsXG4gICAgJ21pbmVjcmFmdDpoZXJkJyxcbiAgICAnbWluZWNyYWZ0OmlzX2V4cGVyaW1lbnRhbCcsXG4gICAgJ21pbmVjcmFmdDppc19wZXJzaXN0ZW50JyxcbiAgICAnbWluZWNyYWZ0Om1vYl9ldmVudF9maWx0ZXInLFxuICAgICdtaW5lY3JhZnQ6cGVybXV0ZV90eXBlJyxcbiAgICAnbWluZWNyYWZ0OnBsYXllcl9pbl92aWxsYWdlX2ZpbHRlcicsXG4gICAgJ21pbmVjcmFmdDpzcGF3bl9ldmVudCcsXG4gICAgJ21pbmVjcmFmdDpzcGF3bnNfYWJvdmVfYmxvY2tfZmlsdGVyJyxcbiAgICAnbWluZWNyYWZ0OnNwYXduc19sYXZhJyxcbiAgICAnbWluZWNyYWZ0OnNwYXduc19vbl9ibG9ja19maWx0ZXInLFxuICAgICdtaW5lY3JhZnQ6c3Bhd25zX29uX2Jsb2NrX3ByZXZlbnRlZF9maWx0ZXInLFxuICAgICdtaW5lY3JhZnQ6c3Bhd25zX29uX3N1cmZhY2UnLFxuICAgICdtaW5lY3JhZnQ6c3Bhd25zX3VuZGVyZ3JvdW5kJyxcbiAgICAnbWluZWNyYWZ0OnNwYXduc191bmRlcndhdGVyJyxcbiAgICAnbWluZWNyYWZ0OndlaWdodCcsXG4gICAgJ21pbmVjcmFmdDp3b3JsZF9hZ2VfZmlsdGVyJ1xuXSBhcyBjb25zdDtcblxuLyoqIE9uZSBvZiB7QGxpbmsgU1BBV05fUlVMRV9DT01QT05FTlRTfS4gKi9cbmV4cG9ydCB0eXBlIFNwYXduUnVsZUNvbXBvbmVudCA9ICh0eXBlb2YgU1BBV05fUlVMRV9DT01QT05FTlRTKVtudW1iZXJdO1xuXG4vKiogQW4gaW5jbHVzaXZlIG51bWVyaWMgcmFuZ2UsIGFzIGV2ZXJ5IGB7bWluLCBtYXh9YCBjb21wb25lbnQgd3JpdGVzIG9uZS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3Bhd25SYW5nZSB7XG4gICAgcmVhZG9ubHkgbWluOiBudW1iZXI7XG4gICAgcmVhZG9ubHkgbWF4OiBudW1iZXI7XG59XG5cbi8qKiBIb3cgb2Z0ZW4gb25lIGNvbmRpdGlvbiBpcyBkcmF3biBhZ2FpbnN0IHRoZSBvdGhlcnMgdGhhdCBwYXNzIGF0IHRoZSBzYW1lIHBvc2l0aW9uLiAqL1xuZXhwb3J0IGludGVyZmFjZSBTcGF3bldlaWdodCB7XG4gICAgLyoqIFRoZSByZWxhdGl2ZSB3ZWlnaHQ7IGEgd2VpZ2h0IG9mIDEwMCBhbW9uZyBhIHRvdGFsIG9mIDEwMDAgaXMgZHJhd24gYSB0ZW50aCBvZiB0aGUgdGltZS4gKi9cbiAgICByZWFkb25seSBkZWZhdWx0OiBudW1iZXI7XG4gICAgLyoqIEFuIGV4dHJhIHJhcml0eSByb2xsIE1vamFuZyBkb2N1bWVudHMgYnkgbmFtZSBvbmx5LiBaZXJvIG1lYW5zIG5vIHJvbGwuICovXG4gICAgcmVhZG9ubHkgcmFyaXR5OiBudW1iZXI7XG59XG5cbi8qKiBPbmUgYG1pbmVjcmFmdDpoZXJkYCBhbHRlcm5hdGl2ZTogaG93IG1hbnkgc3Bhd24gdG9nZXRoZXIgYW5kIHdoaWNoIGV2ZW50cyB0aGV5IHJ1bi4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSGVyZFJ1bGUge1xuICAgIHJlYWRvbmx5IG1pblNpemU6IG51bWJlcjtcbiAgICByZWFkb25seSBtYXhTaXplOiBudW1iZXI7XG4gICAgLyoqIFRoZSBldmVudCB0aGUgZmlyc3Qge0BsaW5rIGluaXRpYWxFdmVudENvdW50fSBtZW1iZXJzIHJ1biBpbnN0ZWFkIG9mIHRoZWlyIHNwYXduIGV2ZW50LiAqL1xuICAgIHJlYWRvbmx5IGluaXRpYWxFdmVudD86IHN0cmluZztcbiAgICByZWFkb25seSBpbml0aWFsRXZlbnRDb3VudDogbnVtYmVyO1xuICAgIC8qKiBUaGUgZXZlbnQgZXZlcnkgbWVtYmVyIHBhc3Qge0BsaW5rIGV2ZW50U2tpcENvdW50fSBydW5zLiAqL1xuICAgIHJlYWRvbmx5IGV2ZW50Pzogc3RyaW5nO1xuICAgIHJlYWRvbmx5IGV2ZW50U2tpcENvdW50OiBudW1iZXI7XG59XG5cbi8qKiBPbmUgYG1pbmVjcmFmdDpwZXJtdXRlX3R5cGVgIGVudHJ5OiBhIHdlaWdodGVkIHN3YXAgb2YgdGhlIGVudGl0eSBhIGhlcmQgbWVtYmVyIHNwYXducyBhcy4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3Bhd25QZXJtdXRhdGlvbiB7XG4gICAgcmVhZG9ubHkgd2VpZ2h0OiBudW1iZXI7XG4gICAgLyoqXG4gICAgICogVGhlIGVudGl0eSB0byBzcGF3biBpbnN0ZWFkLCBvcHRpb25hbGx5IGluIHRoZSBgdHlwZTxldmVudD5gIGZvcm0uIEFic2VudFxuICAgICAqIG1lYW5zIHRoZSBydWxlJ3Mgb3duIGVudGl0eSwgd2hpY2ggaXMgaG93IHZhbmlsbGEgd3JpdGVzIHRoZSBjb21tb24gYnJhbmNoLlxuICAgICAqL1xuICAgIHJlYWRvbmx5IGVudGl0eVR5cGU/OiBzdHJpbmc7XG4gICAgLyoqIEhvdyBtYW55IGhlcmQgbWVtYmVycyB0aGlzIHBlcm11dGF0aW9uIHRha2VzIGJlZm9yZSB0aGUgd2VpZ2h0ZWQgZHJhdyBydW5zLiAqL1xuICAgIHJlYWRvbmx5IG1pbkd1YXJhbnRlZWQ6IG51bWJlcjtcbn1cblxuLyoqIFRoZSBgbWluZWNyYWZ0OmRlbGF5X2ZpbHRlcmAgYm9keTogYSBjb29sZG93biBzaGFyZWQgYnkgZXZlcnkgcnVsZSBuYW1pbmcgdGhlIHNhbWUgaWRlbnRpZmllci4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3Bhd25EZWxheSB7XG4gICAgcmVhZG9ubHkgbWluOiBudW1iZXI7XG4gICAgcmVhZG9ubHkgbWF4OiBudW1iZXI7XG4gICAgLyoqIFRoZSBjb29sZG93bidzIG5hbWUsIHdoaWNoIGlzIGhvdyB0aGUgdGhyZWUgcGlsbGFnZXIgcGF0cm9sIGNvbmRpdGlvbnMga2VlcCBzZXBhcmF0ZSB0aW1lcnMuICovXG4gICAgcmVhZG9ubHkgaWRlbnRpZmllcj86IHN0cmluZztcbiAgICAvKiogVGhlIHBlcmNlbnQgY2hhbmNlIHRoZSBhdHRlbXB0IHRha2VzIG9uY2UgdGhlIGNvb2xkb3duIGhhcyBlbGFwc2VkLiAqL1xuICAgIHJlYWRvbmx5IHNwYXduQ2hhbmNlOiBudW1iZXI7XG59XG5cbi8qKiBUaGUgYG1pbmVjcmFmdDpwbGF5ZXJfaW5fdmlsbGFnZV9maWx0ZXJgIGJvZHkuICovXG5leHBvcnQgaW50ZXJmYWNlIFBsYXllckluVmlsbGFnZUZpbHRlciB7XG4gICAgcmVhZG9ubHkgZGlzdGFuY2U6IG51bWJlcjtcbiAgICByZWFkb25seSB2aWxsYWdlQm9yZGVyVG9sZXJhbmNlOiBudW1iZXI7XG59XG5cbi8qKiBUaGUgYG1pbmVjcmFmdDpzcGF3bnNfYWJvdmVfYmxvY2tfZmlsdGVyYCBib2R5LCB3aGljaCBubyB2YW5pbGxhIHJ1bGUgd3JpdGVzLiAqL1xuZXhwb3J0IGludGVyZmFjZSBBYm92ZUJsb2NrRmlsdGVyIHtcbiAgICByZWFkb25seSBibG9ja3M6IHJlYWRvbmx5IHN0cmluZ1tdO1xuICAgIHJlYWRvbmx5IGRpc3RhbmNlOiBudW1iZXI7XG59XG5cbi8qKlxuICogT25lIG1lbWJlciBvZiBgY29uZGl0aW9uc2A6IGEgY29tcGxldGUgYWx0ZXJuYXRpdmUgc2V0IG9mIHJlcXVpcmVtZW50cyB3aXRoXG4gKiBpdHMgb3duIHdlaWdodCwgaGVyZCBhbmQgcGVybXV0YXRpb25zLiBBIHJ1bGUgcGFzc2VzIGF0IGEgcG9zaXRpb24gd2hlbiBhbnlcbiAqIG9uZSBvZiBpdHMgY29uZGl0aW9ucyBkb2VzLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNwYXduQ29uZGl0aW9uIHtcbiAgICByZWFkb25seSB3ZWlnaHQ6IFNwYXduV2VpZ2h0O1xuICAgIHJlYWRvbmx5IGJpb21lRmlsdGVyPzogRmlsdGVyO1xuICAgIHJlYWRvbmx5IGJyaWdodG5lc3M/OiB7IHJlYWRvbmx5IG1pbjogbnVtYmVyOyByZWFkb25seSBtYXg6IG51bWJlcjsgcmVhZG9ubHkgYWRqdXN0Rm9yV2VhdGhlcjogYm9vbGVhbiB9O1xuICAgIHJlYWRvbmx5IGRpZmZpY3VsdHk/OiB7IHJlYWRvbmx5IG1pbjogRGlmZmljdWx0eTsgcmVhZG9ubHkgbWF4OiBEaWZmaWN1bHR5IH07XG4gICAgcmVhZG9ubHkgaGVpZ2h0PzogU3Bhd25SYW5nZTtcbiAgICAvKiogSG93IGZhciBmcm9tIHRoZSBuZWFyZXN0IHBsYXllciB0aGUgcG9zaXRpb24gbXVzdCBiZS4gKi9cbiAgICByZWFkb25seSBkaXN0YW5jZT86IFNwYXduUmFuZ2U7XG4gICAgLyoqIEhvdyBtYW55IG9mIHRoaXMgZW50aXR5IG1heSBhbHJlYWR5IHN0YW5kIG5lYXJieSwgcGVyIHBhc3M7IC0xIGlzIG5vIGxpbWl0LiAqL1xuICAgIHJlYWRvbmx5IGRlbnNpdHk/OiB7IHJlYWRvbmx5IHN1cmZhY2U6IG51bWJlcjsgcmVhZG9ubHkgdW5kZXJncm91bmQ6IG51bWJlciB9O1xuICAgIHJlYWRvbmx5IHdvcmxkQWdlPzogU3Bhd25SYW5nZTtcbiAgICByZWFkb25seSBzcGF3bnNPblN1cmZhY2U6IGJvb2xlYW47XG4gICAgcmVhZG9ubHkgc3Bhd25zVW5kZXJncm91bmQ6IGJvb2xlYW47XG4gICAgcmVhZG9ubHkgc3Bhd25zVW5kZXJ3YXRlcjogYm9vbGVhbjtcbiAgICByZWFkb25seSBzcGF3bnNMYXZhOiBib29sZWFuO1xuICAgIHJlYWRvbmx5IGRpc2FsbG93U3Bhd25zSW5CdWJibGU6IGJvb2xlYW47XG4gICAgcmVhZG9ubHkgaXNQZXJzaXN0ZW50OiBib29sZWFuO1xuICAgIHJlYWRvbmx5IGlzRXhwZXJpbWVudGFsOiBib29sZWFuO1xuICAgIC8qKiBUaGUgYmxvY2tzIHRoZSBwb3NpdGlvbiBtYXkgc3RhbmQgb247IGFuIGVtcHR5IGxpc3QgbWVhbnMgdGhlIGNvbXBvbmVudCBpcyBhYnNlbnQuICovXG4gICAgcmVhZG9ubHkgYmxvY2tzPzogcmVhZG9ubHkgc3RyaW5nW107XG4gICAgLyoqIFRoZSBibG9ja3MgdGhlIHBvc2l0aW9uIG1heSBub3Qgc3RhbmQgb24uICovXG4gICAgcmVhZG9ubHkgcHJldmVudGVkQmxvY2tzPzogcmVhZG9ubHkgc3RyaW5nW107XG4gICAgcmVhZG9ubHkgYWJvdmVCbG9ja3M/OiBBYm92ZUJsb2NrRmlsdGVyO1xuICAgIHJlYWRvbmx5IGhlcmQ6IHJlYWRvbmx5IEhlcmRSdWxlW107XG4gICAgcmVhZG9ubHkgcGVybXV0YXRpb25zPzogcmVhZG9ubHkgU3Bhd25QZXJtdXRhdGlvbltdO1xuICAgIHJlYWRvbmx5IGRlbGF5PzogU3Bhd25EZWxheTtcbiAgICByZWFkb25seSBtb2JFdmVudD86IHN0cmluZztcbiAgICAvKiogVGhlIGV2ZW50IGEgc3Bhd25lZCBlbnRpdHkgcnVucyBpbnN0ZWFkIG9mIGBtaW5lY3JhZnQ6ZW50aXR5X3NwYXduZWRgLiAqL1xuICAgIHJlYWRvbmx5IHNwYXduRXZlbnQ/OiBzdHJpbmc7XG4gICAgcmVhZG9ubHkgcGxheWVySW5WaWxsYWdlPzogUGxheWVySW5WaWxsYWdlRmlsdGVyO1xufVxuXG4vKiogT25lIHBhcnNlZCBgc3Bhd25fcnVsZXMvKi5qc29uYC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3Bhd25SdWxlIHtcbiAgICByZWFkb25seSBpZGVudGlmaWVyOiBzdHJpbmc7XG4gICAgLyoqIFRoZSBwb29sIHdob3NlIGNhcCBnYXRlcyB0aGlzIGVudGl0eSwgYWJzZW50IHdoZW4gdGhlIGZpbGUgbmFtZXMgbm9uZS4gKi9cbiAgICByZWFkb25seSBwb3B1bGF0aW9uQ29udHJvbD86IHN0cmluZztcbiAgICByZWFkb25seSBmb3JtYXRWZXJzaW9uPzogc3RyaW5nO1xuICAgIHJlYWRvbmx5IGNvbmRpdGlvbnM6IHJlYWRvbmx5IFNwYXduQ29uZGl0aW9uW107XG59XG5cbi8qKiBXaGVyZSBhIHBhcnNlIHJlcG9ydHMgaXRzIGZpbmRpbmdzLiAqL1xuZXhwb3J0IGludGVyZmFjZSBTcGF3blJ1bGVQYXJzZU9wdGlvbnMge1xuICAgIC8qKiBUaGUgcGFjayB0aGUgZmlsZSBjYW1lIGZyb20sIHVzZWQgaW4gdGhlIGRpYWdub3N0aWNzLiAqL1xuICAgIHJlYWRvbmx5IHBhY2s6IHN0cmluZztcbiAgICByZWFkb25seSBwYXRoPzogc3RyaW5nO1xuICAgIHJlYWRvbmx5IHJlcG9ydD86IChkaWFnbm9zdGljOiBEaWFnbm9zdGljKSA9PiB2b2lkO1xufVxuXG5jb25zdCBpc1JlY29yZCA9ICh2YWx1ZTogdW5rbm93bik6IHZhbHVlIGlzIFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0+XG4gICAgdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJiB2YWx1ZSAhPT0gbnVsbCAmJiAhQXJyYXkuaXNBcnJheSh2YWx1ZSk7XG5cbmNvbnN0IEtOT1dOX0NPTVBPTkVOVFM6IFJlYWRvbmx5U2V0PHN0cmluZz4gPSBuZXcgU2V0KFNQQVdOX1JVTEVfQ09NUE9ORU5UUyk7XG5cbmNvbnN0IEtOT1dOX1BPT0xTOiBSZWFkb25seVNldDxzdHJpbmc+ID0gbmV3IFNldChQT1BVTEFUSU9OX1BPT0xTKTtcblxuLyoqIFJlYWRzIGEgbnVtYmVyLCBmYWxsaW5nIGJhY2sgd2hlbiB0aGUga2V5IGlzIGFic2VudCBvciBub3QgYSBudW1iZXIuICovXG5jb25zdCBudW1iZXJBdCA9IChzb3VyY2U6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LCBrZXk6IHN0cmluZywgZmFsbGJhY2s6IG51bWJlcik6IG51bWJlciA9PiB7XG4gICAgY29uc3QgdmFsdWUgPSBzb3VyY2Vba2V5XTtcbiAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJyAmJiBOdW1iZXIuaXNGaW5pdGUodmFsdWUpID8gdmFsdWUgOiBmYWxsYmFjaztcbn07XG5cbmNvbnN0IHN0cmluZ0F0ID0gKHNvdXJjZTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sIGtleTogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkID0+IHtcbiAgICBjb25zdCB2YWx1ZSA9IHNvdXJjZVtrZXldO1xuICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnID8gdmFsdWUgOiB1bmRlZmluZWQ7XG59O1xuXG5jb25zdCBib2R5T2YgPSAodmFsdWU6IHVua25vd24pOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9PiAoaXNSZWNvcmQodmFsdWUpID8gdmFsdWUgOiB7fSk7XG5cbi8qKlxuICogUmVhZHMgYSBibG9jayBsaXN0IHdyaXR0ZW4gYXMgb25lIG5hbWUsIGFzIGEgbGlzdCBvZiBuYW1lcywgb3IgYXMgYSBsaXN0IG9mXG4gKiBge25hbWV9YCBvYmplY3RzLiBBbGwgdGhyZWUgYXBwZWFyIGluIHZhbmlsbGEuXG4gKi9cbmNvbnN0IGJsb2NrTGlzdCA9ICh2YWx1ZTogdW5rbm93bik6IHJlYWRvbmx5IHN0cmluZ1tdID0+IHtcbiAgICBjb25zdCBtZW1iZXJzID0gQXJyYXkuaXNBcnJheSh2YWx1ZSkgPyB2YWx1ZSA6IFt2YWx1ZV07XG4gICAgY29uc3QgbmFtZXM6IHN0cmluZ1tdID0gW107XG4gICAgZm9yIChjb25zdCBtZW1iZXIgb2YgbWVtYmVycykge1xuICAgICAgICBpZiAodHlwZW9mIG1lbWJlciA9PT0gJ3N0cmluZycpIG5hbWVzLnB1c2gobWVtYmVyKTtcbiAgICAgICAgZWxzZSBpZiAoaXNSZWNvcmQobWVtYmVyKSAmJiB0eXBlb2YgbWVtYmVyLm5hbWUgPT09ICdzdHJpbmcnKSBuYW1lcy5wdXNoKG1lbWJlci5uYW1lKTtcbiAgICB9XG4gICAgcmV0dXJuIG5hbWVzO1xufTtcblxuY29uc3QgZGlmZmljdWx0eUF0ID0gKFxuICAgIHNvdXJjZTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4gICAga2V5OiBzdHJpbmcsXG4gICAgZmFsbGJhY2s6IERpZmZpY3VsdHksXG4gICAgZmFpbDogKG1lc3NhZ2U6IHN0cmluZykgPT4gdm9pZFxuKTogRGlmZmljdWx0eSA9PiB7XG4gICAgY29uc3QgdmFsdWUgPSBzb3VyY2Vba2V5XTtcbiAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkgcmV0dXJuIGZhbGxiYWNrO1xuICAgIGNvbnN0IG5hbWUgPSBESUZGSUNVTFRJRVMuZmluZCgoZGlmZmljdWx0eSkgPT4gZGlmZmljdWx0eSA9PT0gdmFsdWUpO1xuICAgIGlmIChuYW1lICE9PSB1bmRlZmluZWQpIHJldHVybiBuYW1lO1xuICAgIGZhaWwoYG1pbmVjcmFmdDpkaWZmaWN1bHR5X2ZpbHRlciAke2tleX0gaXMgbm90IGEgZGlmZmljdWx0eTogJHtKU09OLnN0cmluZ2lmeSh2YWx1ZSl9YCk7XG4gICAgcmV0dXJuIGZhbGxiYWNrO1xufTtcblxuY29uc3QgcGFyc2VIZXJkID0gKHZhbHVlOiB1bmtub3duKTogcmVhZG9ubHkgSGVyZFJ1bGVbXSA9PlxuICAgIChBcnJheS5pc0FycmF5KHZhbHVlKSA/IHZhbHVlIDogW3ZhbHVlXSkuZmlsdGVyKGlzUmVjb3JkKS5tYXAoKGJvZHkpID0+IHtcbiAgICAgICAgY29uc3QgcnVsZToge1xuICAgICAgICAgICAgbWluU2l6ZTogbnVtYmVyO1xuICAgICAgICAgICAgbWF4U2l6ZTogbnVtYmVyO1xuICAgICAgICAgICAgaW5pdGlhbEV2ZW50Pzogc3RyaW5nO1xuICAgICAgICAgICAgaW5pdGlhbEV2ZW50Q291bnQ6IG51bWJlcjtcbiAgICAgICAgICAgIGV2ZW50Pzogc3RyaW5nO1xuICAgICAgICAgICAgZXZlbnRTa2lwQ291bnQ6IG51bWJlcjtcbiAgICAgICAgfSA9IHtcbiAgICAgICAgICAgIG1pblNpemU6IG51bWJlckF0KGJvZHksICdtaW5fc2l6ZScsIDEpLFxuICAgICAgICAgICAgbWF4U2l6ZTogbnVtYmVyQXQoYm9keSwgJ21heF9zaXplJywgMSksXG4gICAgICAgICAgICBpbml0aWFsRXZlbnRDb3VudDogbnVtYmVyQXQoYm9keSwgJ2luaXRpYWxfZXZlbnRfY291bnQnLCAwKSxcbiAgICAgICAgICAgIGV2ZW50U2tpcENvdW50OiBudW1iZXJBdChib2R5LCAnZXZlbnRfc2tpcF9jb3VudCcsIDApXG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IGluaXRpYWxFdmVudCA9IHN0cmluZ0F0KGJvZHksICdpbml0aWFsX2V2ZW50Jyk7XG4gICAgICAgIGlmIChpbml0aWFsRXZlbnQgIT09IHVuZGVmaW5lZCkgcnVsZS5pbml0aWFsRXZlbnQgPSBpbml0aWFsRXZlbnQ7XG4gICAgICAgIGNvbnN0IGV2ZW50ID0gc3RyaW5nQXQoYm9keSwgJ2V2ZW50Jyk7XG4gICAgICAgIGlmIChldmVudCAhPT0gdW5kZWZpbmVkKSBydWxlLmV2ZW50ID0gZXZlbnQ7XG4gICAgICAgIHJldHVybiBydWxlO1xuICAgIH0pO1xuXG5jb25zdCBwYXJzZVBlcm11dGF0aW9ucyA9ICh2YWx1ZTogdW5rbm93bik6IHJlYWRvbmx5IFNwYXduUGVybXV0YXRpb25bXSA9PlxuICAgIChBcnJheS5pc0FycmF5KHZhbHVlKSA/IHZhbHVlIDogW10pLmZpbHRlcihpc1JlY29yZCkubWFwKChib2R5KSA9PiB7XG4gICAgICAgIGNvbnN0IHBlcm11dGF0aW9uOiB7IHdlaWdodDogbnVtYmVyOyBlbnRpdHlUeXBlPzogc3RyaW5nOyBtaW5HdWFyYW50ZWVkOiBudW1iZXIgfSA9IHtcbiAgICAgICAgICAgIHdlaWdodDogbnVtYmVyQXQoYm9keSwgJ3dlaWdodCcsIDEpLFxuICAgICAgICAgICAgLy8gVGhlIHNjaGVtYSBjYWxscyBpdCBgbWluX2d1YXJhbnRlZWRgOyB0aGUgZG9jcyBwYWdlIGNhbGxzIHRoZSBzYW1lXG4gICAgICAgICAgICAvLyBmaWVsZCBgZ3VhcmFudGVlZF9jb3VudGAsIHNvIGJvdGggc3BlbGxpbmdzIHJlYWQuXG4gICAgICAgICAgICBtaW5HdWFyYW50ZWVkOiBudW1iZXJBdChib2R5LCAnbWluX2d1YXJhbnRlZWQnLCBudW1iZXJBdChib2R5LCAnZ3VhcmFudGVlZF9jb3VudCcsIDApKVxuICAgICAgICB9O1xuICAgICAgICBjb25zdCBlbnRpdHlUeXBlID0gc3RyaW5nQXQoYm9keSwgJ2VudGl0eV90eXBlJyk7XG4gICAgICAgIGlmIChlbnRpdHlUeXBlICE9PSB1bmRlZmluZWQpIHBlcm11dGF0aW9uLmVudGl0eVR5cGUgPSBlbnRpdHlUeXBlO1xuICAgICAgICByZXR1cm4gcGVybXV0YXRpb247XG4gICAgfSk7XG5cbmNvbnN0IHBhcnNlQ29uZGl0aW9uID0gKFxuICAgIHZhbHVlOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgICBmYWlsOiAoY29kZTogc3RyaW5nLCBtZXNzYWdlOiBzdHJpbmcpID0+IHZvaWRcbik6IFNwYXduQ29uZGl0aW9uID0+IHtcbiAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyh2YWx1ZSkpIHtcbiAgICAgICAgaWYgKCFLTk9XTl9DT01QT05FTlRTLmhhcyhrZXkpKSBmYWlsKCdzcGF3blJ1bGUudW5rbm93bkNvbXBvbmVudCcsIGB1bmtub3duIHNwYXduIHJ1bGUgY29tcG9uZW50ICR7a2V5fWApO1xuICAgIH1cblxuICAgIGNvbnN0IHdlaWdodEJvZHkgPSBib2R5T2YodmFsdWVbJ21pbmVjcmFmdDp3ZWlnaHQnXSk7XG4gICAgY29uc3QgY29uZGl0aW9uOiB7XG4gICAgICAgIC1yZWFkb25seSBbS2V5IGluIGtleW9mIFNwYXduQ29uZGl0aW9uXTogU3Bhd25Db25kaXRpb25bS2V5XTtcbiAgICB9ID0ge1xuICAgICAgICAvLyBUaGUgc2NoZW1hIG1hcmtzIGBkZWZhdWx0YCByZXF1aXJlZCBhbmQgc2F5cyBub3RoaW5nIGFib3V0IGEgY29uZGl0aW9uXG4gICAgICAgIC8vIHRoYXQgd3JpdGVzIG5vIHdlaWdodCBhdCBhbGwsIHNvIGFuIGFic2VudCB3ZWlnaHQgY291bnRzIG9uY2UuXG4gICAgICAgIHdlaWdodDogeyBkZWZhdWx0OiBudW1iZXJBdCh3ZWlnaHRCb2R5LCAnZGVmYXVsdCcsIDEpLCByYXJpdHk6IG51bWJlckF0KHdlaWdodEJvZHksICdyYXJpdHknLCAwKSB9LFxuICAgICAgICBoZXJkOiAnbWluZWNyYWZ0OmhlcmQnIGluIHZhbHVlID8gcGFyc2VIZXJkKHZhbHVlWydtaW5lY3JhZnQ6aGVyZCddKSA6IFtdLFxuICAgICAgICBzcGF3bnNPblN1cmZhY2U6ICdtaW5lY3JhZnQ6c3Bhd25zX29uX3N1cmZhY2UnIGluIHZhbHVlLFxuICAgICAgICBzcGF3bnNVbmRlcmdyb3VuZDogJ21pbmVjcmFmdDpzcGF3bnNfdW5kZXJncm91bmQnIGluIHZhbHVlLFxuICAgICAgICBzcGF3bnNVbmRlcndhdGVyOiAnbWluZWNyYWZ0OnNwYXduc191bmRlcndhdGVyJyBpbiB2YWx1ZSxcbiAgICAgICAgc3Bhd25zTGF2YTogJ21pbmVjcmFmdDpzcGF3bnNfbGF2YScgaW4gdmFsdWUsXG4gICAgICAgIGRpc2FsbG93U3Bhd25zSW5CdWJibGU6ICdtaW5lY3JhZnQ6ZGlzYWxsb3dfc3Bhd25zX2luX2J1YmJsZScgaW4gdmFsdWUsXG4gICAgICAgIGlzUGVyc2lzdGVudDogJ21pbmVjcmFmdDppc19wZXJzaXN0ZW50JyBpbiB2YWx1ZSxcbiAgICAgICAgaXNFeHBlcmltZW50YWw6ICdtaW5lY3JhZnQ6aXNfZXhwZXJpbWVudGFsJyBpbiB2YWx1ZVxuICAgIH07XG5cbiAgICBpZiAoJ21pbmVjcmFmdDpiaW9tZV9maWx0ZXInIGluIHZhbHVlKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25kaXRpb24uYmlvbWVGaWx0ZXIgPSBwYXJzZUZpbHRlcih2YWx1ZVsnbWluZWNyYWZ0OmJpb21lX2ZpbHRlciddKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIGlmICghKGVycm9yIGluc3RhbmNlb2YgRmlsdGVyUGFyc2VFcnJvcikpIHRocm93IGVycm9yO1xuICAgICAgICAgICAgZmFpbCgnc3Bhd25SdWxlLmJhZFZhbHVlJywgYG1pbmVjcmFmdDpiaW9tZV9maWx0ZXIgZG9lcyBub3QgcGFyc2U6ICR7ZXJyb3IubWVzc2FnZX1gKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmICgnbWluZWNyYWZ0OmJyaWdodG5lc3NfZmlsdGVyJyBpbiB2YWx1ZSkge1xuICAgICAgICBjb25zdCBib2R5ID0gYm9keU9mKHZhbHVlWydtaW5lY3JhZnQ6YnJpZ2h0bmVzc19maWx0ZXInXSk7XG4gICAgICAgIGNvbmRpdGlvbi5icmlnaHRuZXNzID0ge1xuICAgICAgICAgICAgbWluOiBudW1iZXJBdChib2R5LCAnbWluJywgMCksXG4gICAgICAgICAgICBtYXg6IG51bWJlckF0KGJvZHksICdtYXgnLCAxNSksXG4gICAgICAgICAgICBhZGp1c3RGb3JXZWF0aGVyOiBib2R5LmFkanVzdF9mb3Jfd2VhdGhlciA9PT0gdHJ1ZVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIGlmICgnbWluZWNyYWZ0OmRpZmZpY3VsdHlfZmlsdGVyJyBpbiB2YWx1ZSkge1xuICAgICAgICBjb25zdCBib2R5ID0gYm9keU9mKHZhbHVlWydtaW5lY3JhZnQ6ZGlmZmljdWx0eV9maWx0ZXInXSk7XG4gICAgICAgIGNvbnN0IHJlcG9ydCA9IChtZXNzYWdlOiBzdHJpbmcpOiB2b2lkID0+IGZhaWwoJ3NwYXduUnVsZS5iYWRWYWx1ZScsIG1lc3NhZ2UpO1xuICAgICAgICBjb25kaXRpb24uZGlmZmljdWx0eSA9IHtcbiAgICAgICAgICAgIG1pbjogZGlmZmljdWx0eUF0KGJvZHksICdtaW4nLCAncGVhY2VmdWwnLCByZXBvcnQpLFxuICAgICAgICAgICAgbWF4OiBkaWZmaWN1bHR5QXQoYm9keSwgJ21heCcsICdoYXJkJywgcmVwb3J0KVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIGlmICgnbWluZWNyYWZ0OmhlaWdodF9maWx0ZXInIGluIHZhbHVlKSB7XG4gICAgICAgIGNvbnN0IGJvZHkgPSBib2R5T2YodmFsdWVbJ21pbmVjcmFmdDpoZWlnaHRfZmlsdGVyJ10pO1xuICAgICAgICBjb25kaXRpb24uaGVpZ2h0ID0geyBtaW46IG51bWJlckF0KGJvZHksICdtaW4nLCAyNCksIG1heDogbnVtYmVyQXQoYm9keSwgJ21heCcsIDEyOCkgfTtcbiAgICB9XG5cbiAgICBpZiAoJ21pbmVjcmFmdDpkaXN0YW5jZV9maWx0ZXInIGluIHZhbHVlKSB7XG4gICAgICAgIGNvbnN0IGJvZHkgPSBib2R5T2YodmFsdWVbJ21pbmVjcmFmdDpkaXN0YW5jZV9maWx0ZXInXSk7XG4gICAgICAgIGNvbmRpdGlvbi5kaXN0YW5jZSA9IHsgbWluOiBudW1iZXJBdChib2R5LCAnbWluJywgMjQpLCBtYXg6IG51bWJlckF0KGJvZHksICdtYXgnLCAxMjgpIH07XG4gICAgfVxuXG4gICAgaWYgKCdtaW5lY3JhZnQ6d29ybGRfYWdlX2ZpbHRlcicgaW4gdmFsdWUpIHtcbiAgICAgICAgY29uc3QgYm9keSA9IGJvZHlPZih2YWx1ZVsnbWluZWNyYWZ0OndvcmxkX2FnZV9maWx0ZXInXSk7XG4gICAgICAgIGNvbmRpdGlvbi53b3JsZEFnZSA9IHsgbWluOiBudW1iZXJBdChib2R5LCAnbWluJywgMCksIG1heDogbnVtYmVyQXQoYm9keSwgJ21heCcsIC0xKSB9O1xuICAgIH1cblxuICAgIGlmICgnbWluZWNyYWZ0OmRlbnNpdHlfbGltaXQnIGluIHZhbHVlKSB7XG4gICAgICAgIGNvbnN0IGJvZHkgPSBib2R5T2YodmFsdWVbJ21pbmVjcmFmdDpkZW5zaXR5X2xpbWl0J10pO1xuICAgICAgICBjb25kaXRpb24uZGVuc2l0eSA9IHsgc3VyZmFjZTogbnVtYmVyQXQoYm9keSwgJ3N1cmZhY2UnLCAtMSksIHVuZGVyZ3JvdW5kOiBudW1iZXJBdChib2R5LCAndW5kZXJncm91bmQnLCAtMSkgfTtcbiAgICB9XG5cbiAgICBpZiAoJ21pbmVjcmFmdDpzcGF3bnNfb25fYmxvY2tfZmlsdGVyJyBpbiB2YWx1ZSlcbiAgICAgICAgY29uZGl0aW9uLmJsb2NrcyA9IGJsb2NrTGlzdCh2YWx1ZVsnbWluZWNyYWZ0OnNwYXduc19vbl9ibG9ja19maWx0ZXInXSk7XG5cbiAgICBpZiAoJ21pbmVjcmFmdDpzcGF3bnNfb25fYmxvY2tfcHJldmVudGVkX2ZpbHRlcicgaW4gdmFsdWUpXG4gICAgICAgIGNvbmRpdGlvbi5wcmV2ZW50ZWRCbG9ja3MgPSBibG9ja0xpc3QodmFsdWVbJ21pbmVjcmFmdDpzcGF3bnNfb25fYmxvY2tfcHJldmVudGVkX2ZpbHRlciddKTtcblxuICAgIGlmICgnbWluZWNyYWZ0OnNwYXduc19hYm92ZV9ibG9ja19maWx0ZXInIGluIHZhbHVlKSB7XG4gICAgICAgIGNvbnN0IGJvZHkgPSBib2R5T2YodmFsdWVbJ21pbmVjcmFmdDpzcGF3bnNfYWJvdmVfYmxvY2tfZmlsdGVyJ10pO1xuICAgICAgICBjb25kaXRpb24uYWJvdmVCbG9ja3MgPSB7IGJsb2NrczogYmxvY2tMaXN0KGJvZHkuYmxvY2tzKSwgZGlzdGFuY2U6IG51bWJlckF0KGJvZHksICdkaXN0YW5jZScsIDEpIH07XG4gICAgfVxuXG4gICAgaWYgKCdtaW5lY3JhZnQ6cGVybXV0ZV90eXBlJyBpbiB2YWx1ZSkgY29uZGl0aW9uLnBlcm11dGF0aW9ucyA9IHBhcnNlUGVybXV0YXRpb25zKHZhbHVlWydtaW5lY3JhZnQ6cGVybXV0ZV90eXBlJ10pO1xuXG4gICAgaWYgKCdtaW5lY3JhZnQ6ZGVsYXlfZmlsdGVyJyBpbiB2YWx1ZSkge1xuICAgICAgICBjb25zdCBib2R5ID0gYm9keU9mKHZhbHVlWydtaW5lY3JhZnQ6ZGVsYXlfZmlsdGVyJ10pO1xuICAgICAgICBjb25zdCBkZWxheTogeyBtaW46IG51bWJlcjsgbWF4OiBudW1iZXI7IGlkZW50aWZpZXI/OiBzdHJpbmc7IHNwYXduQ2hhbmNlOiBudW1iZXIgfSA9IHtcbiAgICAgICAgICAgIG1pbjogbnVtYmVyQXQoYm9keSwgJ21pbicsIDApLFxuICAgICAgICAgICAgbWF4OiBudW1iZXJBdChib2R5LCAnbWF4JywgMCksXG4gICAgICAgICAgICBzcGF3bkNoYW5jZTogbnVtYmVyQXQoYm9keSwgJ3NwYXduX2NoYW5jZScsIDEwMClcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgaWRlbnRpZmllciA9IHN0cmluZ0F0KGJvZHksICdpZGVudGlmaWVyJyk7XG4gICAgICAgIGlmIChpZGVudGlmaWVyICE9PSB1bmRlZmluZWQpIGRlbGF5LmlkZW50aWZpZXIgPSBpZGVudGlmaWVyO1xuICAgICAgICBjb25kaXRpb24uZGVsYXkgPSBkZWxheTtcbiAgICB9XG5cbiAgICBjb25zdCBtb2JFdmVudCA9IHN0cmluZ0F0KGJvZHlPZih2YWx1ZVsnbWluZWNyYWZ0Om1vYl9ldmVudF9maWx0ZXInXSksICdldmVudCcpO1xuICAgIGlmICgnbWluZWNyYWZ0Om1vYl9ldmVudF9maWx0ZXInIGluIHZhbHVlICYmIG1vYkV2ZW50ICE9PSB1bmRlZmluZWQpIGNvbmRpdGlvbi5tb2JFdmVudCA9IG1vYkV2ZW50O1xuXG4gICAgY29uc3Qgc3Bhd25FdmVudCA9IHN0cmluZ0F0KGJvZHlPZih2YWx1ZVsnbWluZWNyYWZ0OnNwYXduX2V2ZW50J10pLCAnZXZlbnQnKTtcbiAgICBpZiAoJ21pbmVjcmFmdDpzcGF3bl9ldmVudCcgaW4gdmFsdWUgJiYgc3Bhd25FdmVudCAhPT0gdW5kZWZpbmVkKSBjb25kaXRpb24uc3Bhd25FdmVudCA9IHNwYXduRXZlbnQ7XG5cbiAgICBpZiAoJ21pbmVjcmFmdDpwbGF5ZXJfaW5fdmlsbGFnZV9maWx0ZXInIGluIHZhbHVlKSB7XG4gICAgICAgIGNvbnN0IGJvZHkgPSBib2R5T2YodmFsdWVbJ21pbmVjcmFmdDpwbGF5ZXJfaW5fdmlsbGFnZV9maWx0ZXInXSk7XG4gICAgICAgIGNvbmRpdGlvbi5wbGF5ZXJJblZpbGxhZ2UgPSB7XG4gICAgICAgICAgICBkaXN0YW5jZTogbnVtYmVyQXQoYm9keSwgJ2Rpc3RhbmNlJywgMCksXG4gICAgICAgICAgICB2aWxsYWdlQm9yZGVyVG9sZXJhbmNlOiBudW1iZXJBdChib2R5LCAndmlsbGFnZV9ib3JkZXJfdG9sZXJhbmNlJywgMTApXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbmRpdGlvbjtcbn07XG5cbi8qKlxuICogUGFyc2VzIG9uZSBgc3Bhd25fcnVsZXMvKi5qc29uYCBmaWxlLlxuICpcbiAqIEByZXR1cm5zIFRoZSBydWxlLCBvciB1bmRlZmluZWQgd2hlbiB0aGUgZmlsZSBpcyBub3QgYSBzcGF3biBydWxlIG9yIG5hbWVzXG4gKiBubyBpZGVudGlmaWVyLiBFdmVyeXRoaW5nIGVsc2UgbG9hZHMgYW5kIHJlcG9ydHMuXG4gKi9cbmV4cG9ydCBjb25zdCBwYXJzZVNwYXduUnVsZSA9IChmaWxlOiB1bmtub3duLCBvcHRpb25zOiBTcGF3blJ1bGVQYXJzZU9wdGlvbnMpOiBTcGF3blJ1bGUgfCB1bmRlZmluZWQgPT4ge1xuICAgIGNvbnN0IGZhaWwgPSAoY29kZTogc3RyaW5nLCBtZXNzYWdlOiBzdHJpbmcpOiB2b2lkID0+IHtcbiAgICAgICAgY29uc3QgZGlhZ25vc3RpYzogRGlhZ25vc3RpYyA9IHsgc2V2ZXJpdHk6ICdlcnJvcicsIGNvZGUsIHBhY2s6IG9wdGlvbnMucGFjaywgbWVzc2FnZSB9O1xuICAgICAgICBpZiAob3B0aW9ucy5wYXRoICE9PSB1bmRlZmluZWQpIGRpYWdub3N0aWMucGF0aCA9IG9wdGlvbnMucGF0aDtcbiAgICAgICAgb3B0aW9ucy5yZXBvcnQ/LihkaWFnbm9zdGljKTtcbiAgICB9O1xuICAgIGNvbnN0IHdhcm4gPSAoY29kZTogc3RyaW5nLCBtZXNzYWdlOiBzdHJpbmcpOiB2b2lkID0+IHtcbiAgICAgICAgY29uc3QgZGlhZ25vc3RpYzogRGlhZ25vc3RpYyA9IHsgc2V2ZXJpdHk6ICd3YXJuaW5nJywgY29kZSwgcGFjazogb3B0aW9ucy5wYWNrLCBtZXNzYWdlIH07XG4gICAgICAgIGlmIChvcHRpb25zLnBhdGggIT09IHVuZGVmaW5lZCkgZGlhZ25vc3RpYy5wYXRoID0gb3B0aW9ucy5wYXRoO1xuICAgICAgICBvcHRpb25zLnJlcG9ydD8uKGRpYWdub3N0aWMpO1xuICAgIH07XG5cbiAgICBpZiAoIWlzUmVjb3JkKGZpbGUpIHx8ICFpc1JlY29yZChmaWxlWydtaW5lY3JhZnQ6c3Bhd25fcnVsZXMnXSkpIHtcbiAgICAgICAgZmFpbCgnc3Bhd25SdWxlLm5vdEFTcGF3blJ1bGUnLCAndGhlIGZpbGUgaGFzIG5vIGBtaW5lY3JhZnQ6c3Bhd25fcnVsZXNgIGJvZHknKTtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBjb25zdCBib2R5ID0gZmlsZVsnbWluZWNyYWZ0OnNwYXduX3J1bGVzJ107XG4gICAgY29uc3QgZGVzY3JpcHRpb24gPSBib2R5T2YoYm9keS5kZXNjcmlwdGlvbik7XG4gICAgY29uc3QgaWRlbnRpZmllciA9IHN0cmluZ0F0KGRlc2NyaXB0aW9uLCAnaWRlbnRpZmllcicpO1xuICAgIGlmIChpZGVudGlmaWVyID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgZmFpbCgnc3Bhd25SdWxlLm1pc3NpbmdJZGVudGlmaWVyJywgJ2BkZXNjcmlwdGlvbi5pZGVudGlmaWVyYCBpcyBtaXNzaW5nJyk7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgY29uc3QgcnVsZTogeyAtcmVhZG9ubHkgW0tleSBpbiBrZXlvZiBTcGF3blJ1bGVdOiBTcGF3blJ1bGVbS2V5XSB9ID0geyBpZGVudGlmaWVyLCBjb25kaXRpb25zOiBbXSB9O1xuXG4gICAgY29uc3QgZm9ybWF0VmVyc2lvbiA9IHN0cmluZ0F0KGZpbGUsICdmb3JtYXRfdmVyc2lvbicpO1xuICAgIGlmIChmb3JtYXRWZXJzaW9uICE9PSB1bmRlZmluZWQpIHJ1bGUuZm9ybWF0VmVyc2lvbiA9IGZvcm1hdFZlcnNpb247XG5cbiAgICBjb25zdCBwb29sID0gc3RyaW5nQXQoZGVzY3JpcHRpb24sICdwb3B1bGF0aW9uX2NvbnRyb2wnKTtcbiAgICBpZiAocG9vbCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJ1bGUucG9wdWxhdGlvbkNvbnRyb2wgPSBwb29sO1xuICAgICAgICBpZiAoIUtOT1dOX1BPT0xTLmhhcyhwb29sKSkgd2Fybignc3Bhd25SdWxlLnVua25vd25Qb29sJywgYHVua25vd24gcG9wdWxhdGlvbl9jb250cm9sICR7cG9vbH1gKTtcbiAgICB9XG5cbiAgICBjb25zdCBjb25kaXRpb25zID0gYm9keS5jb25kaXRpb25zO1xuICAgIGlmIChjb25kaXRpb25zICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KGNvbmRpdGlvbnMpKSB7XG4gICAgICAgICAgICBmYWlsKCdzcGF3blJ1bGUuYmFkVmFsdWUnLCAnYGNvbmRpdGlvbnNgIG11c3QgYmUgYW4gYXJyYXknKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJ1bGUuY29uZGl0aW9ucyA9IGNvbmRpdGlvbnMuZmlsdGVyKGlzUmVjb3JkKS5tYXAoKGNvbmRpdGlvbikgPT4gcGFyc2VDb25kaXRpb24oY29uZGl0aW9uLCBmYWlsKSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcnVsZTtcbn07XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7QUFnQkEsSUFBYSxtQkFBbUI7Q0FDNUI7Q0FDQTtDQUNBO0NBQ0E7Q0FDQTtDQUNBO0NBQ0E7Q0FDQTtBQUNKOztBQU1BLElBQWEsZUFBZTtDQUFDO0NBQVk7Q0FBUTtDQUFVO0FBQU07Ozs7Ozs7O0FBWWpFLElBQWEsd0JBQXdCO0NBQ2pDO0NBQ0E7Q0FDQTtDQUNBO0NBQ0E7Q0FDQTtDQUNBO0NBQ0E7Q0FDQTtDQUNBO0NBQ0E7Q0FDQTtDQUNBO0NBQ0E7Q0FDQTtDQUNBO0NBQ0E7Q0FDQTtDQUNBO0NBQ0E7Q0FDQTtDQUNBO0NBQ0E7Q0FDQTtBQUNKO0FBdUhBLElBQU0sWUFBWSxVQUNkLE9BQU8sVUFBVSxZQUFZLFVBQVUsUUFBUSxDQUFDLE1BQU0sUUFBUSxLQUFLO0FBRXZFLElBQU0sbUJBQXdDLElBQUksSUFBSSxxQkFBcUI7QUFFM0UsSUFBTSxjQUFtQyxJQUFJLElBQUksZ0JBQWdCOztBQUdqRSxJQUFNLFlB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