@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.
- package/CHANGELOG.md +80 -0
- package/LICENSE +373 -0
- package/README.md +207 -0
- package/dist/conditions.cjs.cjs +190 -0
- package/dist/conditions.d.ts +81 -0
- package/dist/conditions.d.ts.map +1 -0
- package/dist/conditions.es.js +186 -0
- package/dist/constants.cjs.cjs +29 -0
- package/dist/constants.d.ts +73 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.es.js +26 -0
- package/dist/despawn.cjs.cjs +25 -0
- package/dist/despawn.d.ts +33 -0
- package/dist/despawn.d.ts.map +1 -0
- package/dist/despawn.es.js +23 -0
- package/dist/engineRules.cjs.cjs +145 -0
- package/dist/engineRules.d.ts +86 -0
- package/dist/engineRules.d.ts.map +1 -0
- package/dist/engineRules.es.js +138 -0
- package/dist/index.cjs.cjs +32 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.es.js +8 -0
- package/dist/rules.cjs.cjs +282 -0
- package/dist/rules.d.ts +152 -0
- package/dist/rules.d.ts.map +1 -0
- package/dist/rules.es.js +277 -0
- package/dist/spawner.cjs.cjs +280 -0
- package/dist/spawner.d.ts +105 -0
- package/dist/spawner.d.ts.map +1 -0
- package/dist/spawner.es.js +278 -0
- package/dist/tables/spawnConstants.cjs.cjs +111 -0
- package/dist/tables/spawnConstants.d.ts +2 -0
- package/dist/tables/spawnConstants.es.js +89 -0
- package/dist/tables/spawnConstants.json.d.ts +2 -0
- package/dist/world.cjs.cjs +51 -0
- package/dist/world.d.ts +111 -0
- package/dist/world.d.ts.map +1 -0
- package/dist/world.es.js +45 -0
- package/package.json +68 -5
package/dist/rules.es.js
ADDED
|
@@ -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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
|