UNPKG

37.2 kBJavaScriptView Raw
1/**
2 * 分词器接口
3 *
4 * @author 老雷<leizongmin@gmail.com>
5 */
6'use strict';
7Object.defineProperty(exports, "__esModule", { value: true });
8const path = require("path");
9const get_1 = require("./fs/get");
10const blacklist_1 = require("./table/blacklist");
11const dict_1 = require("./table/dict");
12const loader_1 = require("./loader");
13const stopword_1 = require("./table/stopword");
14const synonym_1 = require("./table/synonym");
15const segment_dict_1 = require("segment-dict");
16const project_config_1 = require("../project.config");
17const core_1 = require("./segment/core");
18const defaults_1 = require("./segment/defaults");
19const index_1 = require("./defaults/index");
20const useModules2_1 = require("./segment/methods/useModules2");
21/**
22 * 创建分词器接口
23 */
24class 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}
297exports.Segment = Segment;
298Segment.defaultOptionsDoSegment = defaults_1.defaultOptionsDoSegment;
299exports.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