1 | /**
|
2 | * 分词器接口
|
3 | *
|
4 | * @author 老雷<leizongmin@gmail.com>
|
5 | */
|
6 | ;
|
7 | Object.defineProperty(exports, "__esModule", { value: true });
|
8 | const path = require("path");
|
9 | const get_1 = require("./fs/get");
|
10 | const blacklist_1 = require("./table/blacklist");
|
11 | const dict_1 = require("./table/dict");
|
12 | const loader_1 = require("./loader");
|
13 | const stopword_1 = require("./table/stopword");
|
14 | const synonym_1 = require("./table/synonym");
|
15 | const segment_dict_1 = require("segment-dict");
|
16 | const project_config_1 = require("../project.config");
|
17 | const core_1 = require("./segment/core");
|
18 | const defaults_1 = require("./segment/defaults");
|
19 | const index_1 = require("./defaults/index");
|
20 | const useModules2_1 = require("./segment/methods/useModules2");
|
21 | /**
|
22 | * 创建分词器接口
|
23 | */
|
24 | class Segment extends core_1.default {
|
25 | getDictDatabase(type, autocreate, libTableDict) {
|
26 | if ((autocreate || this.inited) && !this.db[type]) {
|
27 | if (type == synonym_1.default.type) {
|
28 | libTableDict = libTableDict || synonym_1.default;
|
29 | }
|
30 | else if (type == stopword_1.TableDictStopword.type) {
|
31 | libTableDict = libTableDict || stopword_1.TableDictStopword;
|
32 | }
|
33 | else if (type == blacklist_1.default.type || type == "BLACKLIST_FOR_OPTIMIZER" /* BLACKLIST_FOR_OPTIMIZER */ || type == "BLACKLIST_FOR_SYNONYM" /* BLACKLIST_FOR_SYNONYM */) {
|
34 | libTableDict = libTableDict || blacklist_1.default;
|
35 | }
|
36 | else {
|
37 | libTableDict = libTableDict || dict_1.TableDict;
|
38 | }
|
39 | this.db[type] = new libTableDict(type, this.options, {
|
40 | TABLE: this.DICT[type],
|
41 | });
|
42 | }
|
43 | return this.db[type];
|
44 | }
|
45 | use(mod, ...argv) {
|
46 | useModules2_1.useModules(this, mod, ...argv);
|
47 | this.inited = true;
|
48 | return this;
|
49 | }
|
50 | _resolveDictFilename(name, pathPlus = [], extPlus = []) {
|
51 | let options = {
|
52 | paths: [
|
53 | '',
|
54 | project_config_1.default.dict_root,
|
55 | ...pathPlus,
|
56 | path.resolve(segment_dict_1.default.DICT_ROOT, 'segment'),
|
57 | ],
|
58 | extensions: [
|
59 | '',
|
60 | ...extPlus,
|
61 | '.utf8',
|
62 | '.txt',
|
63 | ],
|
64 | onlyFile: true,
|
65 | };
|
66 | if (name.indexOf('*') != -1) {
|
67 | let ls = get_1.searchGlobSync(name, options);
|
68 | if (!ls || !ls.length) {
|
69 | throw Error(`Cannot find dict glob file "${name}".`);
|
70 | }
|
71 | return ls;
|
72 | }
|
73 | let filename = get_1.searchFirstSync(name, options);
|
74 | if (!filename) {
|
75 | //console.log(name, pathPlus, extPlus);
|
76 | throw Error(`Cannot find dict file "${name}".`);
|
77 | }
|
78 | return filename;
|
79 | }
|
80 | /**
|
81 | * 载入字典文件
|
82 | *
|
83 | * @param {String} name 字典文件名
|
84 | * @param {String} type 类型
|
85 | * @param {Boolean} convert_to_lower 是否全部转换为小写
|
86 | * @return {Segment}
|
87 | */
|
88 | loadDict(name, type, convert_to_lower, skipExists) {
|
89 | let filename = this._resolveDictFilename(name);
|
90 | if (Array.isArray(filename)) {
|
91 | let self = this;
|
92 | filename.forEach(v => this.loadDict(v, type, convert_to_lower, skipExists));
|
93 | //console.log(filename);
|
94 | return this;
|
95 | }
|
96 | if (!type)
|
97 | type = 'TABLE'; // 默认为TABLE
|
98 | const db = this.getDictDatabase(type, true);
|
99 | const TABLE = this.DICT[type] = db.TABLE;
|
100 | const TABLE2 = this.DICT[type + '2'] = db.TABLE2;
|
101 | /*
|
102 | // 初始化词典
|
103 | if (!this.DICT[type]) this.DICT[type] = {};
|
104 | if (!this.DICT[type + '2']) this.DICT[type + '2'] = {};
|
105 | let TABLE = this.DICT[type]; // 词典表 '词' => {属性}
|
106 | let TABLE2 = this.DICT[type + '2']; // 词典表 '长度' => '词' => 属性
|
107 | */
|
108 | // 导入数据
|
109 | const POSTAG = this.POSTAG;
|
110 | let data = loader_1.default.SegmentDictLoader.loadSync(filename);
|
111 | data.forEach(function (data) {
|
112 | if (convert_to_lower) {
|
113 | data[0] = data[0].toLowerCase();
|
114 | }
|
115 | db.add(data, skipExists);
|
116 | /*
|
117 | let [w, p, f] = data;
|
118 |
|
119 | if (w.length == 0)
|
120 | {
|
121 | throw new Error()
|
122 | }
|
123 |
|
124 | TABLE[w] = { p, f, };
|
125 | if (!TABLE2[w.length]) TABLE2[w.length] = {};
|
126 | TABLE2[w.length][w] = TABLE[w];
|
127 | */
|
128 | });
|
129 | data = undefined;
|
130 | this.inited = true;
|
131 | return this;
|
132 | }
|
133 | /**
|
134 | * 载入同义词词典
|
135 | *
|
136 | * @param {String} name 字典文件名
|
137 | */
|
138 | loadSynonymDict(name, skipExists) {
|
139 | let filename = this._resolveDictFilename(name, [
|
140 | path.resolve(segment_dict_1.default.DICT_ROOT, 'synonym'),
|
141 | ]);
|
142 | if (Array.isArray(filename)) {
|
143 | let self = this;
|
144 | filename.forEach(v => this.loadSynonymDict(v, skipExists));
|
145 | return this;
|
146 | }
|
147 | let type = 'SYNONYM';
|
148 | const db = this.getDictDatabase(type, true);
|
149 | const TABLE = this.DICT[type] = db.TABLE;
|
150 | /*
|
151 | // 初始化词典
|
152 | if (!this.DICT[type]) this.DICT[type] = {};
|
153 | // 词典表 '同义词' => '标准词'
|
154 | let TABLE = this.DICT[type] as IDICT_SYNONYM;
|
155 | // 导入数据
|
156 | */
|
157 | let data = loader_1.default.SegmentSynonymLoader.loadSync(filename);
|
158 | data.forEach(function (blocks) {
|
159 | db.add(blocks, skipExists);
|
160 | /*
|
161 | let [n1, n2] = blocks;
|
162 |
|
163 | TABLE[n1] = n2;
|
164 | if (TABLE[n2] === n1)
|
165 | {
|
166 | delete TABLE[n2];
|
167 | }
|
168 | */
|
169 | });
|
170 | //console.log(TABLE);
|
171 | data = undefined;
|
172 | this.inited = true;
|
173 | return this;
|
174 | }
|
175 | _loadBlacklistDict(name, type) {
|
176 | let filename = this._resolveDictFilename(name, [
|
177 | path.resolve(segment_dict_1.default.DICT_ROOT, 'blacklist'),
|
178 | ]);
|
179 | if (Array.isArray(filename)) {
|
180 | let self = this;
|
181 | filename.forEach(v => this._loadBlacklistDict(v, type));
|
182 | return this;
|
183 | }
|
184 | const db = this.getDictDatabase(type, true);
|
185 | const TABLE = this.DICT[type] = db.TABLE;
|
186 | let data = loader_1.default.SegmentDict
|
187 | .requireLoaderModule('line')
|
188 | .loadSync(filename, {
|
189 | filter(line) {
|
190 | return line.trim();
|
191 | },
|
192 | });
|
193 | data.forEach(v => db.add(v));
|
194 | data = undefined;
|
195 | this.inited = true;
|
196 | return this;
|
197 | }
|
198 | /**
|
199 | * 字典黑名單 在主字典內刪除此字典內有的條目
|
200 | */
|
201 | loadBlacklistDict(name) {
|
202 | return this._loadBlacklistDict(name, "BLACKLIST" /* BLACKLIST */);
|
203 | }
|
204 | /**
|
205 | * 優化器黑名單 會防止部分優化器去組合此字典內的詞
|
206 | * 例如 人名 自動組合之類
|
207 | */
|
208 | loadBlacklistOptimizerDict(name) {
|
209 | return this._loadBlacklistDict(name, "BLACKLIST_FOR_OPTIMIZER" /* BLACKLIST_FOR_OPTIMIZER */);
|
210 | }
|
211 | /**
|
212 | * 轉換黑名單 動態轉換字詞時會忽略此字典內的詞
|
213 | */
|
214 | loadBlacklistSynonymDict(name) {
|
215 | return this._loadBlacklistDict(name, "BLACKLIST_FOR_SYNONYM" /* BLACKLIST_FOR_SYNONYM */);
|
216 | }
|
217 | /**
|
218 | * 载入停止符词典
|
219 | *
|
220 | * @param {String} name 字典文件名
|
221 | */
|
222 | loadStopwordDict(name) {
|
223 | let filename = this._resolveDictFilename(name, [
|
224 | path.resolve(segment_dict_1.default.DICT_ROOT, 'stopword'),
|
225 | ]);
|
226 | if (Array.isArray(filename)) {
|
227 | let self = this;
|
228 | filename.forEach(v => this.loadStopwordDict(v));
|
229 | return this;
|
230 | }
|
231 | const type = "STOPWORD" /* STOPWORD */;
|
232 | const db = this.getDictDatabase(type, true);
|
233 | const TABLE = this.DICT[type] = db.TABLE;
|
234 | let data = loader_1.default.SegmentDict
|
235 | .requireLoaderModule('line')
|
236 | .loadSync(filename, {
|
237 | filter(line) {
|
238 | return line.trim();
|
239 | },
|
240 | });
|
241 | data.forEach(v => db.add(v));
|
242 | data = undefined;
|
243 | this.inited = true;
|
244 | return this;
|
245 | }
|
246 | useDefault(...argv) {
|
247 | index_1.useDefault(this, ...argv);
|
248 | this.inited = true;
|
249 | return this;
|
250 | }
|
251 | /**
|
252 | * 此函數只需執行一次,並且一般狀況下不需要手動呼叫
|
253 | */
|
254 | autoInit(options) {
|
255 | if (!this.inited) {
|
256 | this.inited = true;
|
257 | if (!this.modules.tokenizer.length) {
|
258 | this.useDefault(options);
|
259 | }
|
260 | }
|
261 | return this;
|
262 | }
|
263 | addBlacklist(word, remove) {
|
264 | let me = this;
|
265 | this.autoInit(this.options);
|
266 | const BLACKLIST = me.getDictDatabase("BLACKLIST" /* BLACKLIST */);
|
267 | const TABLE = me.getDictDatabase("TABLE" /* TABLE */);
|
268 | let bool = !remove;
|
269 | if (bool) {
|
270 | BLACKLIST.add(word);
|
271 | TABLE.remove(word);
|
272 | }
|
273 | else {
|
274 | BLACKLIST.remove(word);
|
275 | }
|
276 | return this;
|
277 | }
|
278 | /**
|
279 | * remove key in TABLE by BLACKLIST
|
280 | */
|
281 | doBlacklist() {
|
282 | let me = this;
|
283 | this.autoInit(this.options);
|
284 | const BLACKLIST = me.getDict("BLACKLIST" /* BLACKLIST */);
|
285 | const TABLE = me.getDictDatabase("TABLE" /* TABLE */);
|
286 | Object.entries(BLACKLIST)
|
287 | .forEach(function ([key, bool]) {
|
288 | bool && TABLE.remove(key);
|
289 | });
|
290 | return this;
|
291 | }
|
292 | doSegment(text, options = {}) {
|
293 | this.autoInit(this.options);
|
294 | return super.doSegment(text, options);
|
295 | }
|
296 | }
|
297 | exports.Segment = Segment;
|
298 | Segment.defaultOptionsDoSegment = defaults_1.defaultOptionsDoSegment;
|
299 | exports.default = Segment;
|
300 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU2VnbWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIlNlZ21lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7R0FJRztBQUVILFlBQVksQ0FBQzs7QUFFYiw2QkFBNkI7QUFDN0Isa0NBQTJEO0FBRTNELGlEQUFtRDtBQUVuRCx1Q0FBd0U7QUFFeEUscUNBQThCO0FBRTlCLCtDQUFxRDtBQUNyRCw2Q0FBK0M7QUFDL0MsK0NBQXVDO0FBS3ZDLHNEQUE4QztBQWtCOUMseUNBQXlDO0FBR3pDLGlEQUE2RDtBQUM3RCw0Q0FBa0U7QUFDbEUsK0RBQTJEO0FBRTNEOztHQUVHO0FBQ0gsTUFBYSxPQUFRLFNBQVEsY0FBVztJQWlDdkMsZUFBZSxDQUFDLElBQVksRUFBRSxVQUFvQixFQUFFLFlBQWE7UUFFaEUsSUFBSSxDQUFDLFVBQVUsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUNqRDtZQUNDLElBQUksSUFBSSxJQUFJLGlCQUFnQixDQUFDLElBQUksRUFDakM7Z0JBQ0MsWUFBWSxHQUFHLFlBQVksSUFBSSxpQkFBZ0IsQ0FBQzthQUNoRDtpQkFDSSxJQUFJLElBQUksSUFBSSw0QkFBaUIsQ0FBQyxJQUFJLEVBQ3ZDO2dCQUNDLFlBQVksR0FBRyxZQUFZLElBQUksNEJBQWlCLENBQUM7YUFDakQ7aUJBQ0ksSUFBSSxJQUFJLElBQUksbUJBQWtCLENBQUMsSUFBSSxJQUFJLElBQUksMkRBQTRDLElBQUksSUFBSSx1REFBMEMsRUFDOUk7Z0JBQ0MsWUFBWSxHQUFHLFlBQVksSUFBSSxtQkFBa0IsQ0FBQzthQUNsRDtpQkFFRDtnQkFDQyxZQUFZLEdBQUcsWUFBWSxJQUFJLGdCQUFTLENBQUM7YUFDekM7WUFFRCxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxHQUFHLElBQUksWUFBWSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsT0FBTyxFQUFFO2dC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TyxDQUFRLENBQUE7SUFDN0MsQ0FBQzs7QUFsZEYsMEJBb2RDO0FBamRPLCtCQUF1QixHQUFzQixrQ0FBdUIsQ0FBQztBQTBmN0Usa0JBQWUsT0FBTyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiDliIbor43lmajmjqXlj6NcbiAqXG4gKiBAYXV0aG9yIOiAgembtzxsZWl6b25nbWluQGdtYWlsLmNvbT5cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBzZWFyY2hGaXJzdFN5bmMsIHNlYXJjaEdsb2JTeW5jIH0gZnJvbSAnLi9mcy9nZXQnO1xuaW1wb3J0IFBPU1RBRyBmcm9tICcuL1BPU1RBRyc7XG5pbXBvcnQgVGFibGVEaWN0QmxhY2tsaXN0IGZyb20gJy4vdGFibGUvYmxhY2tsaXN0JztcbmltcG9ydCBBYnN0cmFjdFRhYmxlRGljdENvcmUgZnJvbSAnLi90YWJsZS9jb3JlJztcbmltcG9ydCB7IElPcHRpb25zIGFzIElPcHRpb25zVGFibGVEaWN0LCBUYWJsZURpY3QgfSBmcm9tICcuL3RhYmxlL2RpY3QnO1xuXG5pbXBvcnQgTG9hZGVyIGZyb20gJy4vbG9hZGVyJztcbmltcG9ydCB7IGNybGYgfSBmcm9tICdjcmxmLW5vcm1hbGl6ZSc7XG5pbXBvcnQgeyBUYWJsZURpY3RTdG9wd29yZCB9IGZyb20gJy4vdGFibGUvc3RvcHdvcmQnO1xuaW1wb3J0IFRhYmxlRGljdFN5bm9ueW0gZnJvbSAnLi90YWJsZS9zeW5vbnltJztcbmltcG9ydCBTZWdtZW50RGljdCBmcm9tICdzZWdtZW50LWRpY3QnO1xuaW1wb3J0IHsgSVN1Yk9wdGltaXplciwgSVN1YlRva2VuaXplciwgT3B0aW1pemVyLCBUb2tlbml6ZXIgfSBmcm9tICcuL21vZCc7XG5pbXBvcnQgeyBkZWJ1Z1Rva2VuIH0gZnJvbSAnLi91dGlsL2RlYnVnJztcbmltcG9ydCB7IElXb3JkRGVidWcgfSBmcm9tICcuL3V0aWwvaW5kZXgnO1xuXG5pbXBvcnQgUHJvamVjdENvbmZpZyBmcm9tICcuLi9wcm9qZWN0LmNvbmZpZyc7XG5cbmltcG9ydCBkZWVwbWVyZ2UgZnJvbSAnZGVlcG1lcmdlLXBsdXMvY29yZSc7XG5pbXBvcnQgeyBFbnVtRGljdERhdGFiYXNlIH0gZnJvbSAnLi9jb25zdCc7XG5pbXBvcnQgeyBFTlVNX1NVQk1PRFMsIEVOVU1fU1VCTU9EU19OQU1FLCBFTlVNX1NVQk1PRFNfT1RIRVIgfSBmcm9tICcuL21vZC9pbmRleCc7XG5cbmltcG9ydCB7XG5cdElESUNULFxuXHRJRElDVDIsXG5cdElESUNUX0JMQUNLTElTVCxcblx0SURJQ1RfU1RPUFdPUkQsXG5cdElESUNUX1NZTk9OWU0sXG5cdElPcHRpb25zRG9TZWdtZW50LFxuXHRJT3B0aW9uc1NlZ21lbnQsXG5cdElTUExJVCxcblx0SVNQTElUX0ZJTFRFUixcblx0SVdvcmQsXG59IGZyb20gJy4vc2VnbWVudC90eXBlcyc7XG5pbXBvcnQgU2VnbWVudENvcmUgZnJvbSAnLi9zZWdtZW50L2NvcmUnO1xuaW1wb3J0IHsgX2lzSWdub3JlTW9kdWxlcyB9IGZyb20gJy4vc2VnbWVudC9tZXRob2RzL3VzZU1vZHVsZXMnO1xuaW1wb3J0IHsgSVRTT3ZlcndyaXRlIH0gZnJvbSAndHMtdHlwZSc7XG5pbXBvcnQgeyBkZWZhdWx0T3B0aW9uc0RvU2VnbWVudCB9IGZyb20gJy4vc2VnbWVudC9kZWZhdWx0cyc7XG5pbXBvcnQgeyBJVXNlRGVmYXVsdE9wdGlvbnMsIHVzZURlZmF1bHQgfSBmcm9tICcuL2RlZmF1bHRzL2luZGV4JztcbmltcG9ydCB7IHVzZU1vZHVsZXMgfSBmcm9tICcuL3NlZ21lbnQvbWV0aG9kcy91c2VNb2R1bGVzMic7XG5cbi8qKlxuICog5Yib5bu65YiG6K+N5Zmo5o6l5Y+jXG4gKi9cbmV4cG9ydCBjbGFzcyBTZWdtZW50IGV4dGVuZHMgU2VnbWVudENvcmVcbntcblxuXHRzdGF0aWMgZGVmYXVsdE9wdGlvbnNEb1NlZ21lbnQ6IElPcHRpb25zRG9TZWdtZW50ID0gZGVmYXVsdE9wdGlvbnNEb1NlZ21lbnQ7XG5cblx0Z2V0RGljdERhdGFiYXNlPFIgZXh0ZW5kcyBUYWJsZURpY3RTeW5vbnltPih0eXBlOiBFbnVtRGljdERhdGFiYXNlLlNZTk9OWU0sXG5cdFx0YXV0b2NyZWF0ZT86IGJvb2xlYW4sXG5cdFx0bGliVGFibGVEaWN0PzogeyBuZXcoLi4uYXJndik6IFIgfSxcblx0KTogUlxuXHRnZXREaWN0RGF0YWJhc2U8UiBleHRlbmRzIFRhYmxlRGljdD4odHlwZTogRW51bURpY3REYXRhYmFzZS5UQUJMRSxcblx0XHRhdXRvY3JlYXRlPzogYm9vbGVhbixcblx0XHRsaWJUYWJsZURpY3Q/OiB7IG5ldyguLi5hcmd2KTogUiB9LFxuXHQpOiBSXG5cdGdldERpY3REYXRhYmFzZTxSIGV4dGVuZHMgVGFibGVEaWN0U3RvcHdvcmQ+KHR5cGU6IEVudW1EaWN0RGF0YWJhc2UuU1RPUFdPUkQsXG5cdFx0YXV0b2NyZWF0ZT86IGJvb2xlYW4sXG5cdFx0bGliVGFibGVEaWN0PzogeyBuZXcoLi4uYXJndik6IFIgfSxcblx0KTogUlxuXHRnZXREaWN0RGF0YWJhc2U8UiBleHRlbmRzIFRhYmxlRGljdEJsYWNrbGlzdD4odHlwZTogRW51bURpY3REYXRhYmFzZS5CTEFDS0xJU1QsXG5cdFx0YXV0b2NyZWF0ZT86IGJvb2xlYW4sXG5cdFx0bGliVGFibGVEaWN0PzogeyBuZXcoLi4uYXJndik6IFIgfSxcblx0KTogUlxuXHRnZXREaWN0RGF0YWJhc2U8UiBleHRlbmRzIFRhYmxlRGljdEJsYWNrbGlzdD4odHlwZTogRW51bURpY3REYXRhYmFzZS5CTEFDS0xJU1RfRk9SX09QVElNSVpFUixcblx0XHRhdXRvY3JlYXRlPzogYm9vbGVhbixcblx0XHRsaWJUYWJsZURpY3Q/OiB7IG5ldyguLi5hcmd2KTogUiB9LFxuXHQpOiBSXG5cdGdldERpY3REYXRhYmFzZTxSIGV4dGVuZHMgVGFibGVEaWN0QmxhY2tsaXN0Pih0eXBlOiBFbnVtRGljdERhdGFiYXNlLkJMQUNLTElTVF9GT1JfU1lOT05ZTSxcblx0XHRhdXRvY3JlYXRlPzogYm9vbGVhbixcblx0XHRsaWJUYWJsZURpY3Q/OiB7IG5ldyguLi5hcmd2KTogUiB9LFxuXHQpOiBSXG5cdGdldERpY3REYXRhYmFzZTxSIGV4dGVuZHMgQWJzdHJhY3RUYWJsZURpY3RDb3JlPGFueT4+KHR5cGU6IHN0cmluZyB8IEVudW1EaWN0RGF0YWJhc2UsXG5cdFx0YXV0b2NyZWF0ZT86IGJvb2xlYW4sXG5cdFx0bGliVGFibGVEaWN0PzogeyBuZXcoLi4uYXJndik6IFIgfSxcblx0KTogUlxuXHRnZXREaWN0RGF0YWJhc2UodHlwZTogc3RyaW5nLCBhdXRvY3JlYXRlPzogYm9vbGVhbiwgbGliVGFibGVEaWN0Pylcblx0e1xuXHRcdGlmICgoYXV0b2NyZWF0ZSB8fCB0aGlzLmluaXRlZCkgJiYgIXRoaXMuZGJbdHlwZV0pXG5cdFx0e1xuXHRcdFx0aWYgKHR5cGUgPT0gVGFibGVEaWN0U3lub255bS50eXBlKVxuXHRcdFx0e1xuXHRcdFx0XHRsaWJUYWJsZURpY3QgPSBsaWJUYWJsZURpY3QgfHwgVGFibGVEaWN0U3lub255bTtcblx0XHRcdH1cblx0XHRcdGVsc2UgaWYgKHR5cGUgPT0gVGFibGVEaWN0U3RvcHdvcmQudHlwZSlcblx0XHRcdHtcblx0XHRcdFx0bGliVGFibGVEaWN0ID0gbGliVGFibGVEaWN0IHx8IFRhYmxlRGljdFN0b3B3b3JkO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSBpZiAodHlwZSA9PSBUYWJsZURpY3RCbGFja2xpc3QudHlwZSB8fCB0eXBlID09IEVudW1EaWN0RGF0YWJhc2UuQkxBQ0tMSVNUX0ZPUl9PUFRJTUlaRVIgfHwgdHlwZSA9PSBFbnVtRGljdERhdGFiYXNlLkJMQUNLTElTVF9GT1JfU1lOT05ZTSlcblx0XHRcdHtcblx0XHRcdFx0bGliVGFibGVEaWN0ID0gbGliVGFibGVEaWN0IHx8IFRhYmxlRGljdEJsYWNrbGlzdDtcblx0XHRcdH1cblx0XHRcdGVsc2Vcblx0XHRcdHtcblx0XHRcdFx0bGliVGFibGVEaWN0ID0gbGliVGFibGVEaWN0IHx8IFRhYmxlRGljdDtcblx0XHRcdH1cblxuXHRcdFx0dGhpcy5kYlt0eXBlXSA9IG5ldyBsaWJUYWJsZURpY3QodHlwZSwgdGhpcy5vcHRpb25zLCB7XG5cdFx0XHRcdFRBQkxFOiB0aGlzLkRJQ1RbdHlwZV0sXG5cdFx0XHR9KTtcblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcy5kYlt0eXBlXTtcblx0fVxuXG5cdC8qKlxuXHQgKiDovb3lhaXliIbor43mqKHlnZdcblx0ICpcblx0ICogQHBhcmFtIHtTdHJpbmd8QXJyYXl8T2JqZWN0fSBtb2R1bGUg5qih5Z2X5ZCN56ewKOaVsOe7hCnmiJbmqKHlnZflr7nosaFcblx0ICogQHJldHVybiB7U2VnbWVudH1cblx0ICovXG5cdHVzZShtb2Q6IElTdWJPcHRpbWl6ZXIsIC4uLmFyZ3YpXG5cdHVzZShtb2Q6IElTdWJUb2tlbml6ZXIsIC4uLmFyZ3YpXG5cdHVzZShtb2Q6IEFycmF5PElTdWJUb2tlbml6ZXIgfCBJU3ViT3B0aW1pemVyIHwgc3RyaW5nPiwgLi4uYXJndilcblx0dXNlKG1vZDogc3RyaW5nLCAuLi5hcmd2KVxuXHR1c2UobW9kLCAuLi5hcmd2KVxuXHR1c2UobW9kLCAuLi5hcmd2KVxuXHR7XG5cdFx0dXNlTW9kdWxlcyh0aGlzLCBtb2QsIC4uLmFyZ3YpO1xuXG5cdFx0dGhpcy5pbml0ZWQgPSB0cnVlO1xuXG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHRfcmVzb2x2ZURpY3RGaWxlbmFtZShuYW1lOiBzdHJpbmcsIHBhdGhQbHVzOiBzdHJpbmdbXSA9IFtdLCBleHRQbHVzOiBzdHJpbmdbXSA9IFtdKTogc3RyaW5nIHwgc3RyaW5nW11cblx0e1xuXHRcdGxldCBvcHRpb25zID0ge1xuXHRcdFx0cGF0aHM6IFtcblx0XHRcdFx0JycsXG5cdFx0XHRcdFByb2plY3RDb25maWcuZGljdF9yb290LFxuXG5cdFx0XHRcdC4uLnBhdGhQbHVzLFxuXHRcdFx0XHRwYXRoLnJlc29sdmUoU2VnbWVudERpY3QuRElDVF9ST09ULCAnc2VnbWVudCcpLFxuXHRcdFx0XSxcblx0XHRcdGV4dGVuc2lvbnM6IFtcblx0XHRcdFx0JycsXG5cdFx0XHRcdC4uLmV4dFBsdXMsXG5cdFx0XHRcdCcudXRmOCcsXG5cdFx0XHRcdCcudHh0Jyxcblx0XHRcdF0sXG5cblx0XHRcdG9ubHlGaWxlOiB0cnVlLFxuXHRcdH07XG5cblx0XHRpZiAobmFtZS5pbmRleE9mKCcqJykgIT0gLTEpXG5cdFx0e1xuXHRcdFx0bGV0IGxzID0gc2VhcmNoR2xvYlN5bmMobmFtZSwgb3B0aW9ucyk7XG5cblx0XHRcdGlmICghbHMgfHwgIWxzLmxlbmd0aClcblx0XHRcdHtcblx0XHRcdFx0dGhyb3cgRXJyb3IoYENhbm5vdCBmaW5kIGRpY3QgZ2xvYiBmaWxlIFwiJHtuYW1lfVwiLmApO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gbHM7XG5cdFx0fVxuXG5cdFx0bGV0IGZpbGVuYW1lID0gc2VhcmNoRmlyc3RTeW5jKG5hbWUsIG9wdGlvbnMpO1xuXG5cdFx0aWYgKCFmaWxlbmFtZSlcblx0XHR7XG5cdFx0XHQvL2NvbnNvbGUubG9nKG5hbWUsIHBhdGhQbHVzLCBleHRQbHVzKTtcblxuXHRcdFx0dGhyb3cgRXJyb3IoYENhbm5vdCBmaW5kIGRpY3QgZmlsZSBcIiR7bmFtZX1cIi5gKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gZmlsZW5hbWU7XG5cdH1cblxuXHQvKipcblx0ICog6L295YWl5a2X5YW45paH5Lu2XG5cdCAqXG5cdCAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIOWtl+WFuOaWh+S7tuWQjVxuXHQgKiBAcGFyYW0ge1N0cmluZ30gdHlwZSDnsbvlnotcblx0ICogQHBhcmFtIHtCb29sZWFufSBjb252ZXJ0X3RvX2xvd2VyIOaYr+WQpuWFqOmDqOi9rOaNouS4uuWwj+WGmVxuXHQgKiBAcmV0dXJuIHtTZWdtZW50fVxuXHQgKi9cblx0bG9hZERpY3QobmFtZTogc3RyaW5nLCB0eXBlPzogc3RyaW5nLCBjb252ZXJ0X3RvX2xvd2VyPzogYm9vbGVhbiwgc2tpcEV4aXN0cz86IGJvb2xlYW4pXG5cdHtcblx0XHRsZXQgZmlsZW5hbWUgPSB0aGlzLl9yZXNvbHZlRGljdEZpbGVuYW1lKG5hbWUpO1xuXG5cdFx0aWYgKEFycmF5LmlzQXJyYXkoZmlsZW5hbWUpKVxuXHRcdHtcblx0XHRcdGxldCBzZWxmID0gdGhpcztcblxuXHRcdFx0ZmlsZW5hbWUuZm9yRWFjaCh2ID0+IHRoaXMubG9hZERpY3QodiwgdHlwZSwgY29udmVydF90b19sb3dlciwgc2tpcEV4aXN0cykpO1xuXG5cdFx0XHQvL2NvbnNvbGUubG9nKGZpbGVuYW1lKTtcblxuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fVxuXG5cdFx0aWYgKCF0eXBlKSB0eXBlID0gJ1RBQkxFJzsgICAgIC8vIOm7mOiupOS4ulRBQkxFXG5cblx0XHRjb25zdCBkYiA9IHRoaXMuZ2V0RGljdERhdGFiYXNlKHR5cGUsIHRydWUpO1xuXG5cdFx0Y29uc3QgVEFCTEUgPSB0aGlzLkRJQ1RbdHlwZV0gPSBkYi5UQUJMRTtcblx0XHRjb25zdCBUQUJMRTIgPSB0aGlzLkRJQ1RbdHlwZSArICcyJ10gPSBkYi5UQUJMRTI7XG5cblx0XHQvKlxuXHRcdC8vIOWIneWni+WMluivjeWFuFxuXHRcdGlmICghdGhpcy5ESUNUW3R5cGVdKSB0aGlzLkRJQ1RbdHlwZV0gPSB7fTtcblx0XHRpZiAoIXRoaXMuRElDVFt0eXBlICsgJzInXSkgdGhpcy5ESUNUW3R5cGUgKyAnMiddID0ge307XG5cdFx0bGV0IFRBQkxFID0gdGhpcy5ESUNUW3R5cGVdOyAgICAgICAgLy8g6K+N5YW46KGoICAn6K+NJyA9PiB75bGe5oCnfVxuXHRcdGxldCBUQUJMRTIgPSB0aGlzLkRJQ1RbdHlwZSArICcyJ107IC8vIOivjeWFuOihqCAgJ+mVv+W6picgPT4gJ+ivjScgPT4g5bGe5oCnXG5cdFx0Ki9cblx0XHQvLyDlr7zlhaXmlbDmja5cblx0XHRjb25zdCBQT1NUQUcgPSB0aGlzLlBPU1RBRztcblxuXHRcdGxldCBkYXRhID0gTG9hZGVyLlNlZ21lbnREaWN0TG9hZGVyLmxvYWRTeW5jKGZpbGVuYW1lKTtcblxuXHRcdGRhdGEuZm9yRWFjaChmdW5jdGlvbiAoZGF0YSlcblx0XHR7XG5cdFx0XHRpZiAoY29udmVydF90b19sb3dlcilcblx0XHRcdHtcblx0XHRcdFx0ZGF0YVswXSA9IGRhdGFbMF0udG9Mb3dlckNhc2UoKTtcblx0XHRcdH1cblxuXHRcdFx0ZGIuYWRkKGRhdGEsIHNraXBFeGlzdHMpO1xuXG5cdFx0XHQvKlxuXHRcdFx0bGV0IFt3LCBwLCBmXSA9IGRhdGE7XG5cblx0XHRcdGlmICh3Lmxlbmd0aCA9PSAwKVxuXHRcdFx0e1xuXHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoKVxuXHRcdFx0fVxuXG5cdFx0XHRUQUJMRVt3XSA9IHsgcCwgZiwgfTtcblx0XHRcdGlmICghVEFCTEUyW3cubGVuZ3RoXSkgVEFCTEUyW3cubGVuZ3RoXSA9IHt9O1xuXHRcdFx0VEFCTEUyW3cubGVuZ3RoXVt3XSA9IFRBQkxFW3ddO1xuXHRcdFx0Ki9cblx0XHR9KTtcblxuXHRcdGRhdGEgPSB1bmRlZmluZWQ7XG5cblx0XHR0aGlzLmluaXRlZCA9IHRydWU7XG5cblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiDovb3lhaXlkIzkuYnor43or43lhbhcblx0ICpcblx0ICogQHBhcmFtIHtTdHJpbmd9IG5hbWUg5a2X5YW45paH5Lu25ZCNXG5cdCAqL1xuXHRsb2FkU3lub255bURpY3QobmFtZTogc3RyaW5nLCBza2lwRXhpc3RzPzogYm9vbGVhbilcblx0e1xuXHRcdGxldCBmaWxlbmFtZSA9IHRoaXMuX3Jlc29sdmVEaWN0RmlsZW5hbWUobmFtZSwgW1xuXHRcdFx0cGF0aC5yZXNvbHZlKFNlZ21lbnREaWN0LkRJQ1RfUk9PVCwgJ3N5bm9ueW0nKSxcblx0XHRdKTtcblxuXHRcdGlmIChBcnJheS5pc0FycmF5KGZpbGVuYW1lKSlcblx0XHR7XG5cdFx0XHRsZXQgc2VsZiA9IHRoaXM7XG5cblx0XHRcdGZpbGVuYW1lLmZvckVhY2godiA9PiB0aGlzLmxvYWRTeW5vbnltRGljdCh2LCBza2lwRXhpc3RzKSk7XG5cblx0XHRcdHJldHVybiB0aGlzO1xuXHRcdH1cblxuXHRcdGxldCB0eXBlID0gJ1NZTk9OWU0nO1xuXG5cdFx0Y29uc3QgZGIgPSB0aGlzLmdldERpY3REYXRhYmFzZSh0eXBlLCB0cnVlKTtcblxuXHRcdGNvbnN0IFRBQkxFID0gdGhpcy5ESUNUW3R5cGVdID0gZGIuVEFCTEU7XG5cblx0XHQvKlxuXHRcdC8vIOWIneWni+WMluivjeWFuFxuXHRcdGlmICghdGhpcy5ESUNUW3R5cGVdKSB0aGlzLkRJQ1RbdHlwZV0gPSB7fTtcblx0XHQvLyDor43lhbjooaggICflkIzkuYnor40nID0+ICfmoIflh4bor40nXG5cdFx0bGV0IFRBQkxFID0gdGhpcy5ESUNUW3R5cGVdIGFzIElESUNUX1NZTk9OWU07XG5cdFx0Ly8g5a+85YWl5pWw5o2uXG5cdFx0Ki9cblxuXHRcdGxldCBkYXRhID0gTG9hZGVyLlNlZ21lbnRTeW5vbnltTG9hZGVyLmxvYWRTeW5jKGZpbGVuYW1lKTtcblxuXHRcdGRhdGEuZm9yRWFjaChmdW5jdGlvbiAoYmxvY2tzOiBzdHJpbmdbXSlcblx0XHR7XG5cdFx0XHRkYi5hZGQoYmxvY2tzLCBza2lwRXhpc3RzKTtcblxuXHRcdFx0Lypcblx0XHRcdGxldCBbbjEsIG4yXSA9IGJsb2NrcztcblxuXHRcdFx0VEFCTEVbbjFdID0gbjI7XG5cdFx0XHRpZiAoVEFCTEVbbjJdID09PSBuMSlcblx0XHRcdHtcblx0XHRcdFx0ZGVsZXRlIFRBQkxFW24yXTtcblx0XHRcdH1cblx0XHRcdCovXG5cdFx0fSk7XG5cblx0XHQvL2NvbnNvbGUubG9nKFRBQkxFKTtcblxuXHRcdGRhdGEgPSB1bmRlZmluZWQ7XG5cblx0XHR0aGlzLmluaXRlZCA9IHRydWU7XG5cblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdHByb3RlY3RlZCBfbG9hZEJsYWNrbGlzdERpY3QobmFtZTogc3RyaW5nLCB0eXBlOiBFbnVtRGljdERhdGFiYXNlKVxuXHR7XG5cdFx0bGV0IGZpbGVuYW1lID0gdGhpcy5fcmVzb2x2ZURpY3RGaWxlbmFtZShuYW1lLCBbXG5cdFx0XHRwYXRoLnJlc29sdmUoU2VnbWVudERpY3QuRElDVF9ST09ULCAnYmxhY2tsaXN0JyksXG5cdFx0XSk7XG5cblx0XHRpZiAoQXJyYXkuaXNBcnJheShmaWxlbmFtZSkpXG5cdFx0e1xuXHRcdFx0bGV0IHNlbGYgPSB0aGlzO1xuXG5cdFx0XHRmaWxlbmFtZS5mb3JFYWNoKHYgPT4gdGhpcy5fbG9hZEJsYWNrbGlzdERpY3QodiwgdHlwZSkpO1xuXG5cdFx0XHRyZXR1cm4gdGhpcztcblx0XHR9XG5cblx0XHRjb25zdCBkYiA9IHRoaXMuZ2V0RGljdERhdGFiYXNlKHR5cGUsIHRydWUpO1xuXG5cdFx0Y29uc3QgVEFCTEUgPSB0aGlzLkRJQ1RbdHlwZV0gPSBkYi5UQUJMRTtcblxuXHRcdGxldCBkYXRhID0gTG9hZGVyLlNlZ21lbnREaWN0XG5cdFx0XHQucmVxdWlyZUxvYWRlck1vZHVsZSgnbGluZScpXG5cdFx0XHQubG9hZFN5bmMoZmlsZW5hbWUsIHtcblx0XHRcdFx0ZmlsdGVyKGxpbmU6IHN0cmluZylcblx0XHRcdFx0e1xuXHRcdFx0XHRcdHJldHVybiBsaW5lLnRyaW0oKTtcblx0XHRcdFx0fSxcblx0XHRcdH0pXG5cdFx0O1xuXG5cdFx0ZGF0YS5mb3JFYWNoKHYgPT4gZGIuYWRkKHYpKTtcblxuXHRcdGRhdGEgPSB1bmRlZmluZWQ7XG5cblx0XHR0aGlzLmluaXRlZCA9IHRydWU7XG5cblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiDlrZflhbjpu5HlkI3llq4g5Zyo5Li75a2X5YW45YWn5Yiq6Zmk5q2k5a2X5YW45YWn5pyJ55qE5qKd55uuXG5cdCAqL1xuXHRsb2FkQmxhY2tsaXN0RGljdChuYW1lOiBzdHJpbmcpXG5cdHtcblx0XHRyZXR1cm4gdGhpcy5fbG9hZEJsYWNrbGlzdERpY3QobmFtZSwgRW51bURpY3REYXRhYmFzZS5CTEFDS0xJU1QpXG5cdH1cblxuXHQvKipcblx0ICog5YSq5YyW5Zmo6buR5ZCN5ZauIOacg+mYsuatoumDqOWIhuWEquWMluWZqOWOu+e1hOWQiOatpOWtl+WFuOWFp+eahOipnlxuXHQgKiDkvovlpoIg5Lq65ZCNIOiHquWLlee1hOWQiOS5i+mhnlxuXHQgKi9cblx0bG9hZEJsYWNrbGlzdE9wdGltaXplckRpY3QobmFtZTogc3RyaW5nKVxuXHR7XG5cdFx0cmV0dXJuIHRoaXMuX2xvYWRCbGFja2xpc3REaWN0KG5hbWUsIEVudW1EaWN0RGF0YWJhc2UuQkxBQ0tMSVNUX0ZPUl9PUFRJTUlaRVIpXG5cdH1cblxuXHQvKipcblx0ICog6L2J5o+b6buR5ZCN5ZauIOWLleaFi+i9ieaPm+Wtl+ipnuaZguacg+W/veeVpeatpOWtl+WFuOWFp+eahOipnlxuXHQgKi9cblx0bG9hZEJsYWNrbGlzdFN5bm9ueW1EaWN0KG5hbWU6IHN0cmluZylcblx0e1xuXHRcdHJldHVybiB0aGlzLl9sb2FkQmxhY2tsaXN0RGljdChuYW1lLCBFbnVtRGljdERhdGFiYXNlLkJMQUNLTElTVF9GT1JfU1lOT05ZTSlcblx0fVxuXG5cdC8qKlxuXHQgKiDovb3lhaXlgZzmraLnrKbor43lhbhcblx0ICpcblx0ICogQHBhcmFtIHtTdHJpbmd9IG5hbWUg5a2X5YW45paH5Lu25ZCNXG5cdCAqL1xuXHRsb2FkU3RvcHdvcmREaWN0KG5hbWU6IHN0cmluZylcblx0e1xuXHRcdGxldCBmaWxlbmFtZSA9IHRoaXMuX3Jlc29sdmVEaWN0RmlsZW5hbWUobmFtZSwgW1xuXHRcdFx0cGF0aC5yZXNvbHZlKFNlZ21lbnREaWN0LkRJQ1RfUk9PVCwgJ3N0b3B3b3JkJyksXG5cdFx0XSk7XG5cblx0XHRpZiAoQXJyYXkuaXNBcnJheShmaWxlbmFtZSkpXG5cdFx0e1xuXHRcdFx0bGV0IHNlbGYgPSB0aGlzO1xuXG5cdFx0XHRmaWxlbmFtZS5mb3JFYWNoKHYgPT4gdGhpcy5sb2FkU3RvcHdvcmREaWN0KHYpKTtcblxuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fVxuXG5cdFx0Y29uc3QgdHlwZSA9IEVudW1EaWN0RGF0YWJhc2UuU1RPUFdPUkQ7XG5cblx0XHRjb25zdCBkYiA9IHRoaXMuZ2V0RGljdERhdGFiYXNlKHR5cGUsIHRydWUpO1xuXG5cdFx0Y29uc3QgVEFCTEUgPSB0aGlzLkRJQ1RbdHlwZV0gPSBkYi5UQUJMRTtcblxuXHRcdGxldCBkYXRhID0gTG9hZGVyLlNlZ21lbnREaWN0XG5cdFx0XHQucmVxdWlyZUxvYWRlck1vZHVsZSgnbGluZScpXG5cdFx0XHQubG9hZFN5bmMoZmlsZW5hbWUsIHtcblx0XHRcdFx0ZmlsdGVyKGxpbmU6IHN0cmluZylcblx0XHRcdFx0e1xuXHRcdFx0XHRcdHJldHVybiBsaW5lLnRyaW0oKTtcblx0XHRcdFx0fSxcblx0XHRcdH0pXG5cdFx0O1xuXG5cdFx0ZGF0YS5mb3JFYWNoKHYgPT4gZGIuYWRkKHYpKTtcblxuXHRcdGRhdGEgPSB1bmRlZmluZWQ7XG5cblx0XHR0aGlzLmluaXRlZCA9IHRydWU7XG5cblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiDkvb/nlKjpu5jorqTnmoTor4bliKvmqKHlnZflkozlrZflhbjmlofku7Zcblx0ICog5Zyo5L2/55So6aCQ6Kit5YC855qE5oOF5rOB5LiL77yM5LiN6ZyA6KaB5Li75YuV5ZG85Y+r5q2k5Ye95pW4XG5cdCAqXG5cdCAqIEByZXR1cm4ge1NlZ21lbnR9XG5cdCAqL1xuXHR1c2VEZWZhdWx0KG9wdGlvbnM/OiBJVXNlRGVmYXVsdE9wdGlvbnMsIC4uLmFyZ3YpXG5cdHVzZURlZmF1bHQoLi4uYXJndilcblx0e1xuXHRcdHVzZURlZmF1bHQodGhpcywgLi4uYXJndik7XG5cblx0XHR0aGlzLmluaXRlZCA9IHRydWU7XG5cblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiDmraTlh73mlbjlj6rpnIDln7fooYzkuIDmrKHvvIzkuKbkuJTkuIDoiKzni4Dms4HkuIvkuI3pnIDopoHmiYvli5Xlkbzlj6tcblx0ICovXG5cdGF1dG9Jbml0KG9wdGlvbnM/OiBJVXNlRGVmYXVsdE9wdGlvbnMpXG5cdHtcblx0XHRpZiAoIXRoaXMuaW5pdGVkKVxuXHRcdHtcblx0XHRcdHRoaXMuaW5pdGVkID0gdHJ1ZTtcblxuXHRcdFx0aWYgKCF0aGlzLm1vZHVsZXMudG9rZW5pemVyLmxlbmd0aClcblx0XHRcdHtcblx0XHRcdFx0dGhpcy51c2VEZWZhdWx0KG9wdGlvbnMpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0YWRkQmxhY2tsaXN0KHdvcmQ6IHN0cmluZywgcmVtb3ZlPzogYm9vbGVhbilcblx0e1xuXHRcdGxldCBtZSA9IHRoaXM7XG5cblx0XHR0aGlzLmF1dG9Jbml0KHRoaXMub3B0aW9ucyk7XG5cblx0XHRjb25zdCBCTEFDS0xJU1QgPSBtZS5nZXREaWN0RGF0YWJhc2UoRW51bURpY3REYXRhYmFzZS5CTEFDS0xJU1QpO1xuXHRcdGNvbnN0IFRBQkxFID0gbWUuZ2V0RGljdERhdGFiYXNlKEVudW1EaWN0RGF0YWJhc2UuVEFCTEUpO1xuXG5cdFx0bGV0IGJvb2wgPSAhcmVtb3ZlO1xuXG5cdFx0aWYgKGJvb2wpXG5cdFx0e1xuXHRcdFx0QkxBQ0tMSVNULmFkZCh3b3JkKTtcblx0XHRcdFRBQkxFLnJlbW92ZSh3b3JkKTtcblx0XHR9XG5cdFx0ZWxzZVxuXHRcdHtcblx0XHRcdEJMQUNLTElTVC5yZW1vdmUod29yZClcblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpc1xuXHR9XG5cblx0LyoqXG5cdCAqIHJlbW92ZSBrZXkgaW4gVEFCTEUgYnkgQkxBQ0tMSVNUXG5cdCAqL1xuXHRkb0JsYWNrbGlzdCgpXG5cdHtcblx0XHRsZXQgbWUgPSB0aGlzO1xuXG5cdFx0dGhpcy5hdXRvSW5pdCh0aGlzLm9wdGlvbnMpO1xuXG5cdFx0Y29uc3QgQkxBQ0tMSVNUID0gbWUuZ2V0RGljdChFbnVtRGljdERhdGFiYXNlLkJMQUNLTElTVCk7XG5cdFx0Y29uc3QgVEFCTEUgPSBtZS5nZXREaWN0RGF0YWJhc2UoRW51bURpY3REYXRhYmFzZS5UQUJMRSk7XG5cblx0XHRPYmplY3QuZW50cmllcyhCTEFDS0xJU1QpXG5cdFx0XHQuZm9yRWFjaChmdW5jdGlvbiAoW2tleSwgYm9vbF0pXG5cdFx0XHR7XG5cdFx0XHRcdGJvb2wgJiYgVEFCTEUucmVtb3ZlKGtleSlcblx0XHRcdH0pXG5cdFx0O1xuXG5cdFx0cmV0dXJuIHRoaXNcblx0fVxuXG5cdC8qKlxuXHQgKiDlvIDlp4vliIbor41cblx0ICpcblx0ICogQHBhcmFtIHtTdHJpbmd9IHRleHQg5paH5pysXG5cdCAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIOmAiemhuVxuXHQgKiAgIC0ge0Jvb2xlYW59IHNpbXBsZSDmmK/lkKbku4Xov5Tlm57ljZXor43lhoXlrrlcblx0ICogICAtIHtCb29sZWFufSBzdHJpcFB1bmN0dWF0aW9uIOWOu+mZpOagh+eCueespuWPt1xuXHQgKiAgIC0ge0Jvb2xlYW59IGNvbnZlcnRTeW5vbnltIOi9rOaNouWQjOS5ieivjVxuXHQgKiAgIC0ge0Jvb2xlYW59IHN0cmlwU3RvcHdvcmQg5Y676Zmk5YGc5q2i56ymXG5cdCAqIEByZXR1cm4ge0FycmF5fVxuXHQgKi9cblx0ZG9TZWdtZW50KHRleHQ6IHN0cmluZyB8IEJ1ZmZlciwgb3B0aW9uczogSVRTT3ZlcndyaXRlPElPcHRpb25zRG9TZWdtZW50LCB7XG5cdFx0c2ltcGxlOiB0cnVlLFxuXHR9Pik6IHN0cmluZ1tdXG5cdGRvU2VnbWVudCh0ZXh0OiBzdHJpbmcgfCBCdWZmZXIsIG9wdGlvbnM/OiBJT3B0aW9uc0RvU2VnbWVudCk6IElXb3JkW11cblx0ZG9TZWdtZW50KHRleHQsIG9wdGlvbnM6IElPcHRpb25zRG9TZWdtZW50ID0ge30pXG5cdHtcblx0XHR0aGlzLmF1dG9Jbml0KHRoaXMub3B0aW9ucyk7XG5cblx0XHRyZXR1cm4gc3VwZXIuZG9TZWdtZW50KHRleHQsIG9wdGlvbnMpIGFzIGFueVxuXHR9XG5cbn1cblxuZXhwb3J0IGRlY2xhcmUgbmFtZXNwYWNlIFNlZ21lbnRcbntcblx0ZXhwb3J0IHtcblx0XHQvLyBAdHMtaWdub3JlXG5cdFx0SURJQ1QsXG5cdFx0Ly8gQHRzLWlnbm9yZVxuXHRcdElESUNUMixcblx0XHQvLyBAdHMtaWdub3JlXG5cdFx0SURJQ1RfQkxBQ0tMSVNULFxuXHRcdC8vIEB0cy1pZ25vcmVcblx0XHRJRElDVF9TVE9QV09SRCxcblx0XHQvLyBAdHMtaWdub3JlXG5cdFx0SURJQ1RfU1lOT05ZTSxcblx0XHQvLyBAdHMtaWdub3JlXG5cdFx0SU9wdGlvbnNEb1NlZ21lbnQsXG5cdFx0Ly8gQHRzLWlnbm9yZVxuXHRcdElPcHRpb25zU2VnbWVudCxcblx0XHQvLyBAdHMtaWdub3JlXG5cdFx0SVNQTElULFxuXHRcdC8vIEB0cy1pZ25vcmVcblx0XHRJU1BMSVRfRklMVEVSLFxuXHRcdC8vIEB0cy1pZ25vcmVcblx0XHRJV29yZCxcblx0fVxufVxuXG5leHBvcnQge1xuXHRJRElDVCxcblx0SURJQ1QyLFxuXHRJRElDVF9CTEFDS0xJU1QsXG5cdElESUNUX1NUT1BXT1JELFxuXHRJRElDVF9TWU5PTllNLFxuXHRJT3B0aW9uc0RvU2VnbWVudCxcblx0SU9wdGlvbnNTZWdtZW50LFxuXHRJU1BMSVQsXG5cdElTUExJVF9GSUxURVIsXG5cdElXb3JkLFxufVxuXG5leHBvcnQgZGVmYXVsdCBTZWdtZW50O1xuIl19 |
\ | No newline at end of file |