1 | ;
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.init = exports.DictTokenizer = exports.DEFAULT_MAX_CHUNK_COUNT_MIN = exports.DEFAULT_MAX_CHUNK_COUNT = void 0;
|
4 | const mod_1 = require("../mod");
|
5 | const index_1 = require("../util/index");
|
6 | const CHS_NAMES_1 = require("../mod/CHS_NAMES");
|
7 | const const_1 = require("../mod/const");
|
8 | exports.DEFAULT_MAX_CHUNK_COUNT = 40;
|
9 | exports.DEFAULT_MAX_CHUNK_COUNT_MIN = 30;
|
10 | /**
|
11 | * 字典识别模块
|
12 | *
|
13 | * @author 老雷<leizongmin@gmail.com>
|
14 | */
|
15 | class DictTokenizer extends mod_1.SubSModuleTokenizer {
|
16 | constructor() {
|
17 | super(...arguments);
|
18 | /**
|
19 | * 防止因無分段導致分析過久甚至超過處理負荷
|
20 | * 越高越精準但是處理時間會加倍成長甚至超過記憶體能處理的程度
|
21 | *
|
22 | * 數字越小越快
|
23 | *
|
24 | * FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
|
25 | *
|
26 | * @type {number}
|
27 | */
|
28 | this.MAX_CHUNK_COUNT = exports.DEFAULT_MAX_CHUNK_COUNT;
|
29 | /**
|
30 | *
|
31 | * 追加新模式使 MAX_CHUNK_COUNT 遞減來防止無分段長段落的總處理次數過高 由 DEFAULT_MAX_CHUNK_COUNT_MIN 來限制最小值
|
32 | */
|
33 | this.DEFAULT_MAX_CHUNK_COUNT_MIN = exports.DEFAULT_MAX_CHUNK_COUNT_MIN;
|
34 | }
|
35 | _cache() {
|
36 | super._cache();
|
37 | this._TABLE = this.segment.getDict('TABLE');
|
38 | this._TABLE2 = this.segment.getDict('TABLE2');
|
39 | this._POSTAG = this.segment.POSTAG;
|
40 | if (typeof this.segment.options.maxChunkCount == 'number' && this.segment.options.maxChunkCount > exports.DEFAULT_MAX_CHUNK_COUNT_MIN) {
|
41 | this.MAX_CHUNK_COUNT = this.segment.options.maxChunkCount;
|
42 | }
|
43 | if (typeof this.segment.options.minChunkCount == 'number' && this.segment.options.minChunkCount > exports.DEFAULT_MAX_CHUNK_COUNT_MIN) {
|
44 | this.DEFAULT_MAX_CHUNK_COUNT_MIN = this.segment.options.minChunkCount;
|
45 | }
|
46 | }
|
47 | /**
|
48 | * 对未识别的单词进行分词
|
49 | *
|
50 | * @param {array} words 单词数组
|
51 | * @return {array}
|
52 | */
|
53 | split(words) {
|
54 | //debug(words);
|
55 | const TABLE = this._TABLE;
|
56 | //const POSTAG = this._POSTAG;
|
57 | const self = this;
|
58 | let ret = [];
|
59 | for (let i = 0, word; word = words[i]; i++) {
|
60 | if (word.p > 0) {
|
61 | ret.push(word);
|
62 | continue;
|
63 | }
|
64 | // 仅对未识别的词进行匹配
|
65 | let wordinfo = this.matchWord(word.w, 0, words[i - 1]);
|
66 | if (wordinfo.length < 1) {
|
67 | ret.push(word);
|
68 | continue;
|
69 | }
|
70 | // 分离出已识别的单词
|
71 | let lastc = 0;
|
72 | wordinfo.forEach(function (bw, ui) {
|
73 | if (bw.c > lastc) {
|
74 | ret.push({
|
75 | w: word.w.substr(lastc, bw.c - lastc),
|
76 | });
|
77 | }
|
78 | let cw = self.createRawToken({
|
79 | w: bw.w,
|
80 | f: bw.f,
|
81 | }, TABLE[bw.w]);
|
82 | ret.push(cw);
|
83 | /*
|
84 | ret.push({
|
85 | w: bw.w,
|
86 | p: ww.p,
|
87 | f: bw.f,
|
88 | s: ww.s,
|
89 | });
|
90 | */
|
91 | lastc = bw.c + bw.w.length;
|
92 | });
|
93 | let lastword = wordinfo[wordinfo.length - 1];
|
94 | if (lastword.c + lastword.w.length < word.w.length) {
|
95 | let cw = self.createRawToken({
|
96 | w: word.w.substr(lastword.c + lastword.w.length),
|
97 | });
|
98 | ret.push(cw);
|
99 | }
|
100 | }
|
101 | words = undefined;
|
102 | return ret;
|
103 | }
|
104 | // =================================================================
|
105 | /**
|
106 | * 匹配单词,返回相关信息
|
107 | *
|
108 | * @param {string} text 文本
|
109 | * @param {int} cur 开始位置
|
110 | * @param {object} preword 上一个单词
|
111 | * @return {array} 返回格式 {w: '单词', c: 开始位置}
|
112 | */
|
113 | matchWord(text, cur, preword) {
|
114 | if (isNaN(cur))
|
115 | cur = 0;
|
116 | let ret = [];
|
117 | let s = false;
|
118 | const TABLE2 = this._TABLE2;
|
119 | // 匹配可能出现的单词
|
120 | while (cur < text.length) {
|
121 | for (let i in TABLE2) {
|
122 | let w = text.substr(cur, i);
|
123 | if (w in TABLE2[i]) {
|
124 | ret.push({
|
125 | w: w,
|
126 | c: cur,
|
127 | f: TABLE2[i][w].f,
|
128 | });
|
129 | }
|
130 | }
|
131 | cur++;
|
132 | }
|
133 | return this.filterWord(ret, preword, text);
|
134 | }
|
135 | /**
|
136 | * 选择最有可能匹配的单词
|
137 | *
|
138 | * @param {array} words 单词信息数组
|
139 | * @param {object} preword 上一个单词
|
140 | * @param {string} text 本节要分词的文本
|
141 | * @return {array}
|
142 | */
|
143 | filterWord(words, preword, text) {
|
144 | const TABLE = this._TABLE;
|
145 | const POSTAG = this._POSTAG;
|
146 | let ret = [];
|
147 | // 将单词按位置分组
|
148 | let wordpos = this.getPosInfo(words, text);
|
149 | //debug(wordpos);
|
150 | /**
|
151 | * 使用类似于MMSG的分词算法
|
152 | * 找出所有分词可能,主要根据一下几项来评价:
|
153 | * x、词数量最少;
|
154 | * a、词平均频率最大;
|
155 | * b、每个词长度标准差最小;
|
156 | * c、未识别词最少;
|
157 | * d、符合语法结构项:如两个连续的动词减分,数词后面跟量词加分;
|
158 | * 取以上几项综合排名最最好的
|
159 | */
|
160 | let chunks = this.getChunks(wordpos, 0, text);
|
161 | //debug(chunks);
|
162 | let assess = []; // 评价表
|
163 | //console.log(chunks);
|
164 | // 对各个分支就行评估
|
165 | for (let i = 0, chunk; chunk = chunks[i]; i++) {
|
166 | assess[i] = {
|
167 | x: chunk.length,
|
168 | a: 0,
|
169 | b: 0,
|
170 | c: 0,
|
171 | d: 0,
|
172 | index: i,
|
173 | };
|
174 | // 词平均长度
|
175 | let sp = text.length / chunk.length;
|
176 | // 句子经常包含的语法结构
|
177 | let has_D_V = false; // 是否包含动词
|
178 | // 遍历各个词
|
179 | let prew;
|
180 | if (preword) {
|
181 | /*
|
182 | prew = {
|
183 | w: preword.w,
|
184 | p: preword.p,
|
185 | f: preword.f,
|
186 | s: preword.s,
|
187 | }
|
188 | */
|
189 | prew = this.createRawToken(preword);
|
190 | }
|
191 | else {
|
192 | prew = null;
|
193 | }
|
194 | for (let j = 0, w; w = chunk[j]; j++) {
|
195 | if (w.w in TABLE) {
|
196 | w.p = TABLE[w.w].p;
|
197 | assess[i].a += w.f; // 总词频
|
198 | if (j === 0 && !preword && (w.p & POSTAG.D_V)) {
|
199 | /**
|
200 | * 將第一個字也計算進去是否包含動詞
|
201 | */
|
202 | has_D_V = true;
|
203 | }
|
204 | // ================ 检查语法结构 ===================
|
205 | if (prew) {
|
206 | // 如果上一个词是数词且当前词是量词(单位),则加分
|
207 | if ((prew.p & POSTAG.A_M)
|
208 | &&
|
209 | ((w.p & POSTAG.A_Q)
|
210 | || w.w in const_1.DATETIME)) {
|
211 | assess[i].d++;
|
212 | }
|
213 | // 如果当前词是动词
|
214 | if (w.p & POSTAG.D_V) {
|
215 | has_D_V = true;
|
216 | // 如果是连续的两个动词,则减分
|
217 | //if ((prew.p & POSTAG.D_V) > 0)
|
218 | //assess[i].d--;
|
219 | /*
|
220 | // 如果是 形容词 + 动词,则加分
|
221 | if ((prew.p & POSTAG.D_A))
|
222 | {
|
223 | assess[i].d++;
|
224 | }
|
225 | */
|
226 | // 如果是 副词 + 动词,则加分
|
227 | if (prew.p & POSTAG.D_D) {
|
228 | assess[i].d++;
|
229 | }
|
230 | }
|
231 | // 如果是地区名、机构名或形容词,后面跟地区、机构、代词、名词等,则加分
|
232 | if (((prew.p & POSTAG.A_NS)
|
233 | || (prew.p & POSTAG.A_NT)
|
234 | || (prew.p & POSTAG.D_A)) &&
|
235 | ((w.p & POSTAG.D_N)
|
236 | || (w.p & POSTAG.A_NR)
|
237 | || (w.p & POSTAG.A_NS)
|
238 | || (w.p & POSTAG.A_NZ)
|
239 | || (w.p & POSTAG.A_NT))) {
|
240 | assess[i].d++;
|
241 | }
|
242 | // 如果是 方位词 + 数量词,则加分
|
243 | if ((prew.p & POSTAG.D_F)
|
244 | &&
|
245 | ((w.p & POSTAG.A_M)
|
246 | || (w.p & POSTAG.D_MQ))) {
|
247 | //debug(prew, w);
|
248 | assess[i].d++;
|
249 | }
|
250 | // 如果是 姓 + 名词,则加分
|
251 | if ((prew.w in CHS_NAMES_1.FAMILY_NAME_1
|
252 | || prew.w in CHS_NAMES_1.FAMILY_NAME_2) &&
|
253 | ((w.p & POSTAG.D_N)
|
254 | || (w.p & POSTAG.A_NZ))) {
|
255 | //debug(prew, w);
|
256 | assess[i].d++;
|
257 | }
|
258 | /**
|
259 | * 地名/处所 + 方位
|
260 | */
|
261 | if (index_1.hexAndAny(prew.p, POSTAG.D_S, POSTAG.A_NS) && index_1.hexAndAny(w.p, POSTAG.D_F)) {
|
262 | assess[i].d += 0.5;
|
263 | }
|
264 | // 探测下一个词
|
265 | let nextw = chunk[j + 1];
|
266 | if (nextw) {
|
267 | if (nextw.w in TABLE) {
|
268 | nextw.p = TABLE[nextw.w].p;
|
269 | }
|
270 | let _temp_ok = true;
|
271 | /**
|
272 | * 如果当前是“的”+ 名词,则加分
|
273 | */
|
274 | if ((w.w === '的' || w.w === '之')
|
275 | && nextw.p && ((nextw.p & POSTAG.D_N)
|
276 | || (nextw.p & POSTAG.D_V)
|
277 | || (nextw.p & POSTAG.A_NR)
|
278 | || (nextw.p & POSTAG.A_NS)
|
279 | || (nextw.p & POSTAG.A_NZ)
|
280 | || (nextw.p & POSTAG.A_NT))) {
|
281 | assess[i].d += 1.5;
|
282 | _temp_ok = false;
|
283 | }
|
284 | /**
|
285 | * 如果是连词,前后两个词词性相同则加分
|
286 | */
|
287 | else if (prew.p && (w.p & POSTAG.D_C)) {
|
288 | let p = prew.p & nextw.p;
|
289 | if (prew.p === nextw.p) {
|
290 | assess[i].d++;
|
291 | _temp_ok = false;
|
292 | }
|
293 | else if (p) {
|
294 | assess[i].d += 0.25;
|
295 | _temp_ok = false;
|
296 | if (p & POSTAG.D_N) {
|
297 | assess[i].d += 0.75;
|
298 | }
|
299 | }
|
300 | }
|
301 | /**
|
302 | * 在感動的重逢中有余在的話就太過閃耀
|
303 | */
|
304 | if (_temp_ok && (w.p & POSTAG.D_R) && (nextw.p & POSTAG.D_P)) {
|
305 | assess[i].d += 1;
|
306 | _temp_ok = false;
|
307 | }
|
308 | if (_temp_ok && nextw.p && (w.p & POSTAG.D_P)) {
|
309 | if (nextw.p & POSTAG.A_NR && (nextw.w.length > 1)) {
|
310 | assess[i].d++;
|
311 | if (prew.w === '的') {
|
312 | /**
|
313 | * 的 + 介詞 + 人名
|
314 | */
|
315 | assess[i].d += 1;
|
316 | _temp_ok = false;
|
317 | }
|
318 | }
|
319 | }
|
320 | if (_temp_ok && (w.p & POSTAG.D_P) && index_1.hexAndAny(prew.p, POSTAG.D_N) && index_1.hexAndAny(nextw.p, POSTAG.D_N, POSTAG.D_V)) {
|
321 | assess[i].d++;
|
322 | _temp_ok = false;
|
323 | }
|
324 | else if (_temp_ok && (w.p & POSTAG.D_P) && index_1.hexAndAny(prew.p, POSTAG.D_R) && index_1.hexAndAny(nextw.p, POSTAG.D_R)) {
|
325 | assess[i].d += 0.5;
|
326 | _temp_ok = false;
|
327 | }
|
328 | // @FIXME 暴力解決 三天后 的問題
|
329 | if (nextw.w === '后' && w.p & POSTAG.D_T && index_1.hexAndAny(prew.p, POSTAG.D_MQ, POSTAG.A_M)) {
|
330 | assess[i].d++;
|
331 | }
|
332 | // @FIXME 到湖中間后手終於能休息了
|
333 | else if ((nextw.w === '后'
|
334 | || nextw.w === '後')
|
335 | && index_1.hexAndAny(w.p, POSTAG.D_F)) {
|
336 | assess[i].d++;
|
337 | }
|
338 | if ((w.w === '后'
|
339 | || w.w === '後')
|
340 | && index_1.hexAndAny(prew.p, POSTAG.D_F)
|
341 | && index_1.hexAndAny(nextw.p, POSTAG.D_N)) {
|
342 | assess[i].d++;
|
343 | }
|
344 | }
|
345 | else {
|
346 | let _temp_ok = true;
|
347 | /**
|
348 | * 她把荷包蛋摆在像是印度烤饼的面包上
|
349 | */
|
350 | if (_temp_ok && (w.p & POSTAG.D_F) && index_1.hexAndAny(prew.p, POSTAG.D_N)) {
|
351 | assess[i].d += 1;
|
352 | _temp_ok = false;
|
353 | }
|
354 | }
|
355 | }
|
356 | // ===========================================
|
357 | }
|
358 | else {
|
359 | // 未识别的词数量
|
360 | assess[i].c++;
|
361 | }
|
362 | // 标准差
|
363 | assess[i].b += Math.pow(sp - w.w.length, 2);
|
364 | prew = chunk[j];
|
365 | }
|
366 | // 如果句子中包含了至少一个动词
|
367 | if (has_D_V === false)
|
368 | assess[i].d -= 0.5;
|
369 | assess[i].a = assess[i].a / chunk.length;
|
370 | assess[i].b = assess[i].b / chunk.length;
|
371 | }
|
372 | //console.dir(assess);
|
373 | // 计算排名
|
374 | let top = this.getTops(assess);
|
375 | let currchunk = chunks[top];
|
376 | if (false) {
|
377 | //console.log(assess);
|
378 | //console.log(Object.entries(chunks));
|
379 | console.dir(Object.entries(chunks)
|
380 | .map(([i, chunk]) => { return { i, asses: assess[i], chunk }; }), { depth: 5 });
|
381 | console.dir({ i: top, asses: assess[top], currchunk });
|
382 | //console.log(top);
|
383 | //console.log(currchunk);
|
384 | }
|
385 | // 剔除不能识别的词
|
386 | for (let i = 0, word; word = currchunk[i]; i++) {
|
387 | if (!(word.w in TABLE)) {
|
388 | currchunk.splice(i--, 1);
|
389 | }
|
390 | }
|
391 | ret = currchunk;
|
392 | // 試圖主動清除記憶體
|
393 | assess = undefined;
|
394 | chunks = undefined;
|
395 | currchunk = undefined;
|
396 | top = undefined;
|
397 | wordpos = undefined;
|
398 | //debug(ret);
|
399 | return ret;
|
400 | }
|
401 | /**
|
402 | * 评价排名
|
403 | *
|
404 | * @param {object} assess
|
405 | * @return {object}
|
406 | */
|
407 | getTops(assess) {
|
408 | //debug(assess);
|
409 | // 取各项最大值
|
410 | let top = {
|
411 | x: assess[0].x,
|
412 | a: assess[0].a,
|
413 | b: assess[0].b,
|
414 | c: assess[0].c,
|
415 | d: assess[0].d,
|
416 | };
|
417 | for (let i = 1, ass; ass = assess[i]; i++) {
|
418 | if (ass.a > top.a)
|
419 | top.a = ass.a; // 取最大平均词频
|
420 | if (ass.b < top.b)
|
421 | top.b = ass.b; // 取最小标准差
|
422 | if (ass.c > top.c)
|
423 | top.c = ass.c; // 取最大未识别词
|
424 | if (ass.d < top.d)
|
425 | top.d = ass.d; // 取最小语法分数
|
426 | if (ass.x > top.x)
|
427 | top.x = ass.x; // 取最大单词数量
|
428 | }
|
429 | //debug(top);
|
430 | // 评估排名
|
431 | let tops = [];
|
432 | for (let i = 0, ass; ass = assess[i]; i++) {
|
433 | tops[i] = 0;
|
434 | // 词数量,越小越好
|
435 | tops[i] += (top.x - ass.x) * 1.5;
|
436 | // 词总频率,越大越好
|
437 | if (ass.a >= top.a)
|
438 | tops[i] += 1;
|
439 | // 词标准差,越小越好
|
440 | if (ass.b <= top.b)
|
441 | tops[i] += 1;
|
442 | // 未识别词,越小越好
|
443 | tops[i] += (top.c - ass.c); //debug(tops[i]);
|
444 | // 符合语法结构程度,越大越好
|
445 | tops[i] += (ass.d < 0 ? top.d + ass.d : ass.d - top.d) * 1;
|
446 | ass.score = tops[i];
|
447 | //debug(tops[i]);debug('---');
|
448 | }
|
449 | //debug(tops.join(' '));
|
450 | //console.log(tops);
|
451 | //console.log(assess);
|
452 | //const old_method = true;
|
453 | const old_method = false;
|
454 | // 取分数最高的
|
455 | let curri = 0;
|
456 | let maxs = tops[0];
|
457 | for (let i in tops) {
|
458 | let s = tops[i];
|
459 | if (s > maxs) {
|
460 | curri = i;
|
461 | maxs = s;
|
462 | }
|
463 | else if (s === maxs) {
|
464 | /**
|
465 | * 如果分数相同,则根据词长度、未识别词个数和平均频率来选择
|
466 | *
|
467 | * 如果依然同分,則保持不變
|
468 | */
|
469 | let a = 0;
|
470 | let b = 0;
|
471 | if (assess[i].c < assess[curri].c) {
|
472 | a++;
|
473 | }
|
474 | else if (assess[i].c !== assess[curri].c) {
|
475 | b++;
|
476 | }
|
477 | if (assess[i].a > assess[curri].a) {
|
478 | a++;
|
479 | }
|
480 | else if (assess[i].a !== assess[curri].a) {
|
481 | b++;
|
482 | }
|
483 | if (assess[i].x < assess[curri].x) {
|
484 | a++;
|
485 | }
|
486 | else if (assess[i].x !== assess[curri].x) {
|
487 | b++;
|
488 | }
|
489 | if (a > b) {
|
490 | curri = i;
|
491 | maxs = s;
|
492 | }
|
493 | }
|
494 | //debug({ i, s, maxs, curri });
|
495 | }
|
496 | //debug('max: i=' + curri + ', s=' + tops[curri]);
|
497 | assess = undefined;
|
498 | top = undefined;
|
499 | return curri;
|
500 | }
|
501 | /**
|
502 | * 将单词按照位置排列
|
503 | *
|
504 | * @param {array} words
|
505 | * @param {string} text
|
506 | * @return {object}
|
507 | */
|
508 | getPosInfo(words, text) {
|
509 | let wordpos = {};
|
510 | // 将单词按位置分组
|
511 | for (let i = 0, word; word = words[i]; i++) {
|
512 | if (!wordpos[word.c]) {
|
513 | wordpos[word.c] = [];
|
514 | }
|
515 | wordpos[word.c].push(word);
|
516 | }
|
517 | // 按单字分割文本,填补空缺的位置
|
518 | for (let i = 0; i < text.length; i++) {
|
519 | if (!wordpos[i]) {
|
520 | wordpos[i] = [{ w: text.charAt(i), c: i, f: 0 }];
|
521 | }
|
522 | }
|
523 | return wordpos;
|
524 | }
|
525 | /**
|
526 | * 取所有分支
|
527 | *
|
528 | * @param {{[p: number]: Segment.IWord[]}} wordpos
|
529 | * @param {number} pos 当前位置
|
530 | * @param {string} text 本节要分词的文本
|
531 | * @param {number} total_count
|
532 | * @returns {Segment.IWord[][]}
|
533 | */
|
534 | getChunks(wordpos, pos, text, total_count = 0, MAX_CHUNK_COUNT) {
|
535 | /**
|
536 | *
|
537 | * 追加新模式使 MAX_CHUNK_COUNT 遞減來防止無分段長段落的總處理次數過高 由 DEFAULT_MAX_CHUNK_COUNT_MIN 來限制最小值
|
538 | */
|
539 | if (total_count === 0) {
|
540 | MAX_CHUNK_COUNT = this.MAX_CHUNK_COUNT;
|
541 | /**
|
542 | * 只有當目前文字長度大於 MAX_CHUNK_COUNT 時才遞減
|
543 | */
|
544 | if (text.length < MAX_CHUNK_COUNT) {
|
545 | MAX_CHUNK_COUNT += 1;
|
546 | }
|
547 | }
|
548 | else if (MAX_CHUNK_COUNT <= this.MAX_CHUNK_COUNT) {
|
549 | MAX_CHUNK_COUNT = Math.max(MAX_CHUNK_COUNT - 1, this.DEFAULT_MAX_CHUNK_COUNT_MIN, exports.DEFAULT_MAX_CHUNK_COUNT_MIN);
|
550 | }
|
551 | else {
|
552 | //MAX_CHUNK_COUNT = Math.max(MAX_CHUNK_COUNT, this.DEFAULT_MAX_CHUNK_COUNT_MIN, DEFAULT_MAX_CHUNK_COUNT_MIN)
|
553 | }
|
554 | /**
|
555 | * 忽略連字
|
556 | *
|
557 | * 例如: 啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
|
558 | */
|
559 | let m;
|
560 | if (m = text.match(/^((.+)\2{5,})/)) {
|
561 | let s1 = text.slice(0, m[1].length);
|
562 | let s2 = text.slice(m[1].length);
|
563 | let word = {
|
564 | w: s1,
|
565 | c: pos,
|
566 | f: 0,
|
567 | };
|
568 | let _ret = [];
|
569 | if (s2 !== '') {
|
570 | let chunks = this.getChunks(wordpos, pos + s1.length, s2, total_count, MAX_CHUNK_COUNT);
|
571 | for (let ws of chunks) {
|
572 | _ret.push([word].concat(ws));
|
573 | }
|
574 | }
|
575 | else {
|
576 | _ret.push([word]);
|
577 | }
|
578 | // console.dir(wordpos);
|
579 | //
|
580 | // console.dir(ret);
|
581 | //
|
582 | // console.dir([pos, text, total_count]);
|
583 | return _ret;
|
584 | }
|
585 | total_count++;
|
586 | let words = wordpos[pos] || [];
|
587 | //debug(total_count, MAX_CHUNK_COUNT);
|
588 | // debug({
|
589 | // total_count,
|
590 | // MAX_CHUNK_COUNT: this.MAX_CHUNK_COUNT,
|
591 | // text,
|
592 | // words,
|
593 | // });
|
594 | // debug('getChunks: ');
|
595 | // debug(words);
|
596 | //throw new Error();
|
597 | let ret = [];
|
598 | for (let word of words) {
|
599 | //debug(word);
|
600 | let nextcur = word.c + word.w.length;
|
601 | /**
|
602 | * @FIXME
|
603 | */
|
604 | if (!wordpos[nextcur]) {
|
605 | ret.push([word]);
|
606 | }
|
607 | else if (total_count > MAX_CHUNK_COUNT) {
|
608 | // do something
|
609 | // console.log(444, words.slice(i));
|
610 | // console.log(333, word);
|
611 | let w1 = [word];
|
612 | let j = nextcur;
|
613 | while (j in wordpos) {
|
614 | let w2 = wordpos[j][0];
|
615 | if (w2) {
|
616 | w1.push(w2);
|
617 | j += w2.w.length;
|
618 | }
|
619 | else {
|
620 | break;
|
621 | }
|
622 | }
|
623 | ret.push(w1);
|
624 | }
|
625 | else {
|
626 | let t = text.slice(word.w.length);
|
627 | let chunks = this.getChunks(wordpos, nextcur, t, total_count, MAX_CHUNK_COUNT);
|
628 | for (let ws of chunks) {
|
629 | ret.push([word].concat(ws));
|
630 | }
|
631 | chunks = null;
|
632 | }
|
633 | }
|
634 | words = undefined;
|
635 | wordpos = undefined;
|
636 | m = undefined;
|
637 | return ret;
|
638 | }
|
639 | }
|
640 | exports.DictTokenizer = DictTokenizer;
|
641 | exports.init = DictTokenizer.init.bind(DictTokenizer);
|
642 | exports.default = DictTokenizer;
|
643 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRGljdFRva2VuaXplci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIkRpY3RUb2tlbml6ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWSxDQUFDOzs7QUFFYixnQ0FBOEU7QUFJOUUseUNBQWlEO0FBQ2pELGdEQUFzSDtBQUd0SCx3Q0FBd0M7QUFHM0IsUUFBQSx1QkFBdUIsR0FBRyxFQUFFLENBQUM7QUFDN0IsUUFBQSwyQkFBMkIsR0FBRyxFQUFFLENBQUM7QUFFOUM7Ozs7R0FJRztBQUNILE1BQWEsYUFBYyxTQUFRLHlCQUFtQjtJQUF0RDs7UUFHQzs7Ozs7Ozs7O1dBU0c7UUFDSCxvQkFBZSxHQUFHLCtCQUF1QixDQUFDO1FBQzFDOzs7V0FHRztRQUNILGdDQUEyQixHQUFHLG1DQUEyQixDQUFDO0lBczBCM0QsQ0FBQztJQWowQkEsTUFBTTtRQUVMLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNmLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDNUMsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUM5QyxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDO1FBRW5DLElBQUksT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxhQUFhLElBQUksUUFBUSxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLGFBQWEsR0FBRyxtQ0FBMkIsRUFDN0g7WUFDQyxJQUFJLENBQUMsZUFBZSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQztTQUMxRDtRQUVELElBQUksT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxhQUFhLElBQUksUUFBUSxJQUFJLElBQUksQ0FBQyxPQUFP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LENBQUM7U0FDZCxDQUFDO1FBRUYsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsR0FBZSxFQUFFLEdBQUcsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQ3JEO1lBQ0MsSUFBSSxHQUFHLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDO2dCQUFFLEdBQUcsQ0FBQyxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFFLFVBQVU7WUFDN0MsSUFBSSxHQUFHLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDO2dCQUFFLEdBQUcsQ0FBQyxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFFLFNBQVM7WUFDNUMsSUFBSSxHQUFHLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDO2dCQUFFLEdBQUcsQ0FBQyxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFFLFVBQVU7WUFDN0MsSUFBSSxHQUFHLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDO2dCQUFFLEdBQUcsQ0FBQyxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFFLFVBQVU7WUFDN0MsSUFBSSxHQUFHLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDO2dCQUFFLEdBQUcsQ0FBQyxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFFLFVBQVU7U0FDN0M7UUFDRCxhQUFhO1FBRWIsT0FBTztRQUNQLElBQUksSUFBSSxHQUFhLEVBQUUsQ0FBQztRQUN4QixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxHQUFlLEVBQUUsR0FBRyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFDckQ7WUFDQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ1osV0FBVztZQUNYLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQyxH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d0JBQ0MsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQzt3QkFFWixDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUM7cUJBQ2pCO3lCQUVEO3dCQUNDLE1BQU07cUJBQ047aUJBQ0Q7Z0JBRUQsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQzthQUNiO2lCQUVEO2dCQUNDLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQztnQkFFbEMsSUFBSSxNQUFNLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxXQUFXLEVBQUUsZUFBZSxDQUFFLENBQUM7Z0JBQ2hGLEtBQUssSUFBSSxFQUFFLElBQUksTUFBTSxFQUNyQjtvQkFDQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7aUJBQzVCO2dCQUVELE1BQU0sR0FBRyxJQUFJLENBQUM7YUFDZDtTQUNEO1FBRUQsS0FBSyxHQUFHLFNBQVMsQ0FBQztRQUNsQixPQUFPLEdBQUcsU0FBUyxDQUFDO1FBQ3BCLENBQUMsR0FBRyxTQUFTLENBQUM7UUFFZCxPQUFPLEdBQUcsQ0FBQztJQUNaLENBQUM7Q0FDRDtBQXgxQkQsc0NBdzFCQztBQWtEWSxRQUFBLElBQUksR0FBRyxhQUFhLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQXVDLENBQUM7QUFFakcsa0JBQWUsYUFBYSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgeyBTdWJTTW9kdWxlLCBTdWJTTW9kdWxlVG9rZW5pemVyLCBJU3ViVG9rZW5pemVyQ3JlYXRlIH0gZnJvbSAnLi4vbW9kJztcbi8vIEB0cy1pZ25vcmVcbmltcG9ydCB7IFVTdHJpbmcgfSBmcm9tICd1bmktc3RyaW5nJztcbmltcG9ydCB7IElUYWJsZURpY3RSb3cgfSBmcm9tICcuLi90YWJsZS9kaWN0JztcbmltcG9ydCB7IGhleEFuZEFueSwgdG9IZXggfSBmcm9tICcuLi91dGlsL2luZGV4JztcbmltcG9ydCBDSFNfTkFNRVMsIHsgRkFNSUxZX05BTUVfMSwgRkFNSUxZX05BTUVfMiwgU0lOR0xFX05BTUUsIERPVUJMRV9OQU1FXzEsIERPVUJMRV9OQU1FXzIgfSBmcm9tICcuLi9tb2QvQ0hTX05BTUVTJztcbmltcG9ydCBTZWdtZW50LCB7IElESUNULCBJV29yZCwgSURJQ1QyIH0gZnJvbSAnLi4vU2VnbWVudCc7XG5pbXBvcnQgeyBkZWJ1ZyB9IGZyb20gJy4uL3V0aWwnO1xuaW1wb3J0IHsgREFURVRJTUUgfSBmcm9tICcuLi9tb2QvY29uc3QnO1xuaW1wb3J0IElQT1NUQUcgZnJvbSAnLi4vUE9TVEFHJztcblxuZXhwb3J0IGNvbnN0IERFRkFVTFRfTUFYX0NIVU5LX0NPVU5UID0gNDA7XG5leHBvcnQgY29uc3QgREVGQVVMVF9NQVhfQ0hVTktfQ09VTlRfTUlOID0gMzA7XG5cbi8qKlxuICog5a2X5YW46K+G5Yir5qih5Z2XXG4gKlxuICogQGF1dGhvciDogIHpm7c8bGVpem9uZ21pbkBnbWFpbC5jb20+XG4gKi9cbmV4cG9ydCBjbGFzcyBEaWN0VG9rZW5pemVyIGV4dGVuZHMgU3ViU01vZHVsZVRva2VuaXplclxue1xuXG5cdC8qKlxuXHQgKiDpmLLmraLlm6DnhKHliIbmrrXlsI7oh7TliIbmnpDpgY7kuYXnlJroh7PotoXpgY7omZXnkIbosqDojbdcblx0ICog6LaK6auY6LaK57K+5rqW5L2G5piv6JmV55CG5pmC6ZaT5pyD5Yqg5YCN5oiQ6ZW355Sa6Iez6LaF6YGO6KiY5oa26auU6IO96JmV55CG55qE56iL5bqmXG5cdCAqXG5cdCAqIOaVuOWtl+i2iuWwj+i2iuW/q1xuXHQgKlxuXHQgKiBGQVRBTCBFUlJPUjogQ0FMTF9BTkRfUkVUUllfTEFTVCBBbGxvY2F0aW9uIGZhaWxlZCAtIEphdmFTY3JpcHQgaGVhcCBvdXQgb2YgbWVtb3J5XG5cdCAqXG5cdCAqIEB0eXBlIHtudW1iZXJ9XG5cdCAqL1xuXHRNQVhfQ0hVTktfQ09VTlQgPSBERUZBVUxUX01BWF9DSFVOS19DT1VOVDtcblx0LyoqXG5cdCAqXG5cdCAqIOi/veWKoOaWsOaooeW8j+S9vyBNQVhfQ0hVTktfQ09VTlQg6YGe5rib5L6G6Ziy5q2i54Sh5YiG5q616ZW35q616JC955qE57i96JmV55CG5qyh5pW46YGO6auYIOeUsSBERUZBVUxUX01BWF9DSFVOS19DT1VOVF9NSU4g5L6G6ZmQ5Yi25pyA5bCP5YC8XG5cdCAqL1xuXHRERUZBVUxUX01BWF9DSFVOS19DT1VOVF9NSU4gPSBERUZBVUxUX01BWF9DSFVOS19DT1VOVF9NSU47XG5cblx0cHJvdGVjdGVkIF9UQUJMRTogSURJQ1Q8SVdvcmQ+O1xuXHRwcm90ZWN0ZWQgX1RBQkxFMjogSURJQ1QyPElXb3JkPjtcblxuXHRfY2FjaGUoKVxuXHR7XG5cdFx0c3VwZXIuX2NhY2hlKCk7XG5cdFx0dGhpcy5fVEFCTEUgPSB0aGlzLnNlZ21lbnQuZ2V0RGljdCgnVEFCTEUnKTtcblx0XHR0aGlzLl9UQUJMRTIgPSB0aGlzLnNlZ21lbnQuZ2V0RGljdCgnVEFCTEUyJyk7XG5cdFx0dGhpcy5fUE9TVEFHID0gdGhpcy5zZWdtZW50LlBPU1RBRztcblxuXHRcdGlmICh0eXBlb2YgdGhpcy5zZWdtZW50Lm9wdGlvbnMubWF4Q2h1bmtDb3VudCA9PSAnbnVtYmVyJyAmJiB0aGlzLnNlZ21lbnQub3B0aW9ucy5tYXhDaHVua0NvdW50ID4gREVGQVVMVF9NQVhfQ0hVTktfQ09VTlRfTUlOKVxuXHRcdHtcblx0XHRcdHRoaXMuTUFYX0NIVU5LX0NPVU5UID0gdGhpcy5zZWdtZW50Lm9wdGlvbnMubWF4Q2h1bmtDb3VudDtcblx0XHR9XG5cblx0XHRpZiAodHlwZW9mIHRoaXMuc2VnbWVudC5vcHRpb25zLm1pbkNodW5rQ291bnQgPT0gJ251bWJlcicgJiYgdGhpcy5zZWdtZW50Lm9wdGlvbnMubWluQ2h1bmtDb3VudCA+IERFRkFVTFRfTUFYX0NIVU5LX0NPVU5UX01JTilcblx0XHR7XG5cdFx0XHR0aGlzLkRFRkFVTFRfTUFYX0NIVU5LX0NPVU5UX01JTiA9IHRoaXMuc2VnbWVudC5vcHRpb25zLm1pbkNodW5rQ291bnQ7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIOWvueacquivhuWIq+eahOWNleivjei/m+ihjOWIhuivjVxuXHQgKlxuXHQgKiBAcGFyYW0ge2FycmF5fSB3b3JkcyDljZXor43mlbDnu4Rcblx0ICogQHJldHVybiB7YXJyYXl9XG5cdCAqL1xuXHRzcGxpdCh3b3JkczogSVdvcmRbXSk6IElXb3JkW11cblx0e1xuXHRcdC8vZGVidWcod29yZHMpO1xuXHRcdGNvbnN0IFRBQkxFID0gdGhpcy5fVEFCTEU7XG5cdFx0Ly9jb25zdCBQT1NUQUcgPSB0aGlzLl9QT1NUQUc7XG5cblx0XHRjb25zdCBzZWxmID0gdGhpcztcblxuXHRcdGxldCByZXQ6IElXb3JkW10gPSBbXTtcblx0XHRmb3IgKGxldCBpID0gMCwgd29yZDsgd29yZCA9IHdvcmRzW2ldOyBpKyspXG5cdFx0e1xuXHRcdFx0aWYgKHdvcmQucCA+IDApXG5cdFx0XHR7XG5cdFx0XHRcdHJldC5wdXNoKHdvcmQpO1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblxuXHRcdFx0Ly8g5LuF5a+55pyq6K+G5Yir55qE6K+N6L+b6KGM5Yy56YWNXG5cdFx0XHRsZXQgd29yZGluZm8gPSB0aGlzLm1hdGNoV29yZCh3b3JkLncsIDAsIHdvcmRzW2kgLSAxXSk7XG5cdFx0XHRpZiAod29yZGluZm8ubGVuZ3RoIDwgMSlcblx0XHRcdHtcblx0XHRcdFx0cmV0LnB1c2god29yZCk7XG5cdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyDliIbnprvlh7rlt7Lor4bliKvnmoTljZXor41cblx0XHRcdGxldCBsYXN0YyA9IDA7XG5cblx0XHRcdHdvcmRpbmZvLmZvckVhY2goZnVuY3Rpb24gKGJ3LCB1aSlcblx0XHRcdHtcblx0XHRcdFx0aWYgKGJ3LmMgPiBsYXN0Yylcblx0XHRcdFx0e1xuXHRcdFx0XHRcdHJldC5wdXNoKHtcblx0XHRcdFx0XHRcdHc6IHdvcmQudy5zdWJzdHIobGFzdGMsIGJ3LmMgLSBsYXN0YyksXG5cdFx0XHRcdFx0fSk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRsZXQgY3cgPSBzZWxmLmNyZWF0ZVJhd1Rva2VuKHtcblx0XHRcdFx0XHR3OiBidy53LFxuXHRcdFx0XHRcdGY6IGJ3LmYsXG5cdFx0XHRcdH0sIFRBQkxFW2J3LnddKTtcblxuXHRcdFx0XHRyZXQucHVzaChjdyk7XG5cblx0XHRcdFx0Lypcblx0XHRcdFx0cmV0LnB1c2goe1xuXHRcdFx0XHRcdHc6IGJ3LncsXG5cdFx0XHRcdFx0cDogd3cucCxcblx0XHRcdFx0XHRmOiBidy5mLFxuXHRcdFx0XHRcdHM6IHd3LnMsXG5cdFx0XHRcdH0pO1xuXHRcdFx0XHQqL1xuXHRcdFx0XHRsYXN0YyA9IGJ3LmMgKyBidy53Lmxlbmd0aDtcblx0XHRcdH0pO1xuXG5cdFx0XHRsZXQgbGFzdHdvcmQgPSB3b3JkaW5mb1t3b3JkaW5mby5sZW5ndGggLSAxXTtcblx0XHRcdGlmIChsYXN0d29yZC5jICsgbGFzdHdvcmQudy5sZW5ndGggPCB3b3JkLncubGVuZ3RoKVxuXHRcdFx0e1xuXHRcdFx0XHRsZXQgY3cgPSBzZWxmLmNyZWF0ZVJhd1Rva2VuKHtcblx0XHRcdFx0XHR3OiB3b3JkLncuc3Vic3RyKGxhc3R3b3JkLmMgKyBsYXN0d29yZC53Lmxlbmd0aCksXG5cdFx0XHRcdH0pO1xuXG5cdFx0XHRcdHJldC5wdXNoKGN3KTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHR3b3JkcyA9IHVuZGVmaW5lZDtcblxuXHRcdHJldHVybiByZXQ7XG5cdH1cblxuXHQvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5cdC8qKlxuXHQgKiDljLnphY3ljZXor43vvIzov5Tlm57nm7jlhbPkv6Hmga9cblx0ICpcblx0ICogQHBhcmFtIHtzdHJpbmd9IHRleHQg5paH5pysXG5cdCAqIEBwYXJhbSB7aW50fSBjdXIg5byA5aeL5L2N572uXG5cdCAqIEBwYXJhbSB7b2JqZWN0fSBwcmV3b3JkIOS4iuS4gOS4quWNleivjVxuXHQgKiBAcmV0dXJuIHthcnJheX0gIOi/lOWbnuagvOW8jyAgIHt3OiAn5Y2V6K+NJywgYzog5byA5aeL5L2N572ufVxuXHQgKi9cblx0cHJvdGVjdGVkIG1hdGNoV29yZCh0ZXh0OiBzdHJpbmcsIGN1cjogbnVtYmVyLCBwcmV3b3JkOiBJV29yZClcblx0e1xuXHRcdGlmIChpc05hTihjdXIpKSBjdXIgPSAwO1xuXHRcdGxldCByZXQ6IElXb3JkW10gPSBbXTtcblx0XHRsZXQgcyA9IGZhbHNlO1xuXG5cdFx0Y29uc3QgVEFCTEUyID0gdGhpcy5fVEFCTEUyO1xuXG5cdFx0Ly8g5Yy56YWN5Y+v6IO95Ye6546w55qE5Y2V6K+NXG5cdFx0d2hpbGUgKGN1ciA8IHRleHQubGVuZ3RoKVxuXHRcdHtcblx0XHRcdGZvciAobGV0IGkgaW4gVEFCTEUyKVxuXHRcdFx0e1xuXHRcdFx0XHRsZXQgdyA9IHRleHQuc3Vic3RyKGN1ciwgaSBhcyBhbnkgYXMgbnVtYmVyKTtcblx0XHRcdFx0aWYgKHcgaW4gVEFCTEUyW2ldKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0cmV0LnB1c2goe1xuXHRcdFx0XHRcdFx0dzogdyxcblx0XHRcdFx0XHRcdGM6IGN1cixcblx0XHRcdFx0XHRcdGY6IFRBQkxFMltpXVt3XS5mLFxuXHRcdFx0XHRcdH0pO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRjdXIrKztcblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcy5maWx0ZXJXb3JkKHJldCwgcHJld29yZCwgdGV4dCk7XG5cdH1cblxuXHQvKipcblx0ICog6YCJ5oup5pyA5pyJ5Y+v6IO95Yy56YWN55qE5Y2V6K+NXG5cdCAqXG5cdCAqIEBwYXJhbSB7YXJyYXl9IHdvcmRzIOWNleivjeS/oeaBr+aVsOe7hFxuXHQgKiBAcGFyYW0ge29iamVjdH0gcHJld29yZCDkuIrkuIDkuKrljZXor41cblx0ICogQHBhcmFtIHtzdHJpbmd9IHRleHQg5pys6IqC6KaB5YiG6K+N55qE5paH5pysXG5cdCAqIEByZXR1cm4ge2FycmF5fVxuXHQgKi9cblx0cHJvdGVjdGVkIGZpbHRlcldvcmQod29yZHM6IElXb3JkW10sIHByZXdvcmQ6IElXb3JkLCB0ZXh0OiBzdHJpbmcpXG5cdHtcblx0XHRjb25zdCBUQUJMRSA9IHRoaXMuX1RBQkxFO1xuXHRcdGNvbnN0IFBPU1RBRyA9IHRoaXMuX1BPU1RBRztcblx0XHRsZXQgcmV0OiBJV29yZFtdID0gW107XG5cblx0XHQvLyDlsIbljZXor43mjInkvY3nva7liIbnu4Rcblx0XHRsZXQgd29yZHBvcyA9IHRoaXMuZ2V0UG9zSW5mbyh3b3JkcywgdGV4dCk7XG5cdFx0Ly9kZWJ1Zyh3b3JkcG9zKTtcblxuXHRcdC8qKlxuXHRcdCAqIOS9v+eUqOexu+S8vOS6jk1NU0fnmoTliIbor43nrpfms5Vcblx0XHQgKiDmib7lh7rmiYDmnInliIbor43lj6/og73vvIzkuLvopoHmoLnmja7kuIDkuIvlh6DpobnmnaXor4Tku7fvvJpcblx0XHQgKiB444CB6K+N5pWw6YeP5pyA5bCR77ybXG5cdFx0ICogYeOAgeivjeW5s+Wdh+mikeeOh+acgOWkp++8m1xuXHRcdCAqIGLjgIHmr4/kuKror43plb/luqbmoIflh4blt67mnIDlsI/vvJtcblx0XHQgKiBj44CB5pyq6K+G5Yir6K+N5pyA5bCR77ybXG5cdFx0ICogZOOAgeespuWQiOivreazlee7k+aehOmhue+8muWmguS4pOS4qui/nue7reeahOWKqOivjeWHj+WIhu+8jOaVsOivjeWQjumdoui3n+mHj+ivjeWKoOWIhu+8m1xuXHRcdCAqIOWPluS7peS4iuWHoOmhuee7vOWQiOaOkuWQjeacgOacgOWlveeahFxuXHRcdCAqL1xuXHRcdGxldCBjaHVua3MgPSB0aGlzLmdldENodW5rcyh3b3JkcG9zLCAwLCB0ZXh0KTtcblx0XHQvL2RlYnVnKGNodW5rcyk7XG5cdFx0bGV0IGFzc2VzczogQXJyYXk8SUFzc2Vzc1Jvdz4gPSBbXTsgIC8vIOivhOS7t+ihqFxuXG5cdFx0Ly9jb25zb2xlLmxvZyhjaHVua3MpO1xuXG5cdFx0Ly8g5a+55ZCE5Liq5YiG5pSv5bCx6KGM6K+E5LywXG5cdFx0Zm9yIChsZXQgaSA9IDAsIGNodW5rOiBJV29yZFtdOyBjaHVuayA9IGNodW5rc1tpXTsgaSsrKVxuXHRcdHtcblx0XHRcdGFzc2Vzc1tpXSA9IHtcblx0XHRcdFx0eDogY2h1bmsubGVuZ3RoLFxuXHRcdFx0XHRhOiAwLFxuXHRcdFx0XHRiOiAwLFxuXHRcdFx0XHRjOiAwLFxuXHRcdFx0XHRkOiAwLFxuXG5cdFx0XHRcdGluZGV4OiBpLFxuXHRcdFx0fTtcblx0XHRcdC8vIOivjeW5s+Wdh+mVv+W6plxuXHRcdFx0bGV0IHNwID0gdGV4dC5sZW5ndGggLyBjaHVuay5sZW5ndGg7XG5cdFx0XHQvLyDlj6XlrZDnu4/luLjljIXlkKvnmoTor63ms5Xnu5PmnoRcblx0XHRcdGxldCBoYXNfRF9WID0gZmFsc2U7ICAvLyDmmK/lkKbljIXlkKvliqjor41cblxuXHRcdFx0Ly8g6YGN5Y6G5ZCE5Liq6K+NXG5cdFx0XHRsZXQgcHJldzogSVdvcmQ7XG5cblx0XHRcdGlmIChwcmV3b3JkKVxuXHRcdFx0e1xuXHRcdFx0XHQvKlxuXHRcdFx0XHRwcmV3ID0ge1xuXHRcdFx0XHRcdHc6IHByZXdvcmQudyxcblx0XHRcdFx0XHRwOiBwcmV3b3JkLnAsXG5cdFx0XHRcdFx0ZjogcHJld29yZC5mLFxuXHRcdFx0XHRcdHM6IHByZXdvcmQucyxcblx0XHRcdFx0fVxuXHRcdFx0XHQqL1xuXG5cdFx0XHRcdHByZXcgPSB0aGlzLmNyZWF0ZVJhd1Rva2VuKHByZXdvcmQpO1xuXG5cdFx0XHR9XG5cdFx0XHRlbHNlXG5cdFx0XHR7XG5cdFx0XHRcdHByZXcgPSBudWxsO1xuXHRcdFx0fVxuXHRcdFx0Zm9yIChsZXQgaiA9IDAsIHc6IElXb3JkOyB3ID0gY2h1bmtbal07IGorKylcblx0XHRcdHtcblx0XHRcdFx0aWYgKHcudyBpbiBUQUJMRSlcblx0XHRcdFx0e1xuXHRcdFx0XHRcdHcucCA9IFRBQkxFW3cud10ucDtcblx0XHRcdFx0XHRhc3Nlc3NbaV0uYSArPSB3LmY7ICAgLy8g5oC76K+N6aKRXG5cblx0XHRcdFx0XHRpZiAoaiA9PT0gMCAmJiAhcHJld29yZCAmJiAody5wICYgUE9TVEFHLkRfVikpXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0LyoqXG5cdFx0XHRcdFx0XHQgKiDlsIfnrKzkuIDlgIvlrZfkuZ/oqIjnrpfpgLLljrvmmK/lkKbljIXlkKvli5XoqZ5cblx0XHRcdFx0XHRcdCAqL1xuXHRcdFx0XHRcdFx0aGFzX0RfViA9IHRydWU7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gPT09PT09PT09PT09PT09PSDmo4Dmn6Xor63ms5Xnu5PmnoQgPT09PT09PT09PT09PT09PT09PVxuXHRcdFx0XHRcdGlmIChwcmV3KVxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdC8vIOWmguaenOS4iuS4gOS4quivjeaYr+aVsOivjeS4lOW9k+WJjeivjeaYr+mHj+ivje+8iOWNleS9je+8ie+8jOWImeWKoOWIhlxuXHRcdFx0XHRcdFx0aWYgKFxuXHRcdFx0XHRcdFx0XHQocHJldy5wICYgUE9TVEFHLkFfTSlcblx0XHRcdFx0XHRcdFx0JiZcblx0XHRcdFx0XHRcdFx0KFxuXHRcdFx0XHRcdFx0XHRcdCh3LnAgJiBQT1NUQUcuQV9RKVxuXHRcdFx0XHRcdFx0XHRcdHx8IHcudyBpbiBEQVRFVElNRVxuXHRcdFx0XHRcdFx0XHQpXG5cdFx0XHRcdFx0XHQpXG5cdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdGFzc2Vzc1tpXS5kKys7XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdC8vIOWmguaenOW9k+WJjeivjeaYr+WKqOivjVxuXHRcdFx0XHRcdFx0aWYgKHcucCAmIFBPU1RBRy5EX1YpXG5cdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdGhhc19EX1YgPSB0cnVlO1xuXHRcdFx0XHRcdFx0XHQvLyDlpoLmnpzmmK/ov57nu63nmoTkuKTkuKrliqjor43vvIzliJnlh4/liIZcblx0XHRcdFx0XHRcdFx0Ly9pZiAoKHByZXcucCAmIFBPU1RBRy5EX1YpID4gMClcblx0XHRcdFx0XHRcdFx0Ly9hc3Nlc3NbaV0uZC0tO1xuXG5cdFx0XHRcdFx0XHRcdC8qXG5cdFx0XHRcdFx0XHRcdC8vIOWmguaenOaYryDlvaLlrrnor40gKyDliqjor43vvIzliJnliqDliIZcblx0XHRcdFx0XHRcdFx0aWYgKChwcmV3LnAgJiBQT1NUQUcuRF9BKSlcblx0XHRcdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0XHRcdGFzc2Vzc1tpXS5kKys7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0Ki9cblxuXHRcdFx0XHRcdFx0XHQvLyDlpoLmnpzmmK8g5Ymv6K+NICsg5Yqo6K+N77yM5YiZ5Yqg5YiGXG5cdFx0XHRcdFx0XHRcdGlmIChwcmV3LnAgJiBQT1NUQUcuRF9EKVxuXHRcdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdFx0YXNzZXNzW2ldLmQrKztcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0Ly8g5aaC5p6c5piv5Zyw5Yy65ZCN44CB5py65p6E5ZCN5oiW5b2i5a656K+N77yM5ZCO6Z2i6Lef5Zyw5Yy644CB5py65p6E44CB5Luj6K+N44CB5ZCN6K+N562J77yM5YiZ5Yqg5YiGXG5cdFx0XHRcdFx0XHRpZiAoKFxuXHRcdFx0XHRcdFx0XHRcdChwcmV3LnAgJiBQT1NUQUcuQV9OUylcblx0XHRcdFx0XHRcdFx0XHR8fCAocHJldy5wICYgUE9TVEFHLkFfTlQpXG5cdFx0XHRcdFx0XHRcdFx0fHwgKHByZXcucCAmIFBPU1RBRy5EX0EpXG5cdFx0XHRcdFx0XHRcdCkgJiZcblx0XHRcdFx0XHRcdFx0KFxuXHRcdFx0XHRcdFx0XHRcdCh3LnAgJiBQT1NUQUcuRF9OKVxuXHRcdFx0XHRcdFx0XHRcdHx8ICh3LnAgJiBQT1NUQUcuQV9OUilcblx0XHRcdFx0XHRcdFx0XHR8fCAody5wICYgUE9TVEFHLkFfTlMpXG5cdFx0XHRcdFx0XHRcdFx0fHwgKHcucCAmIFBPU1RBRy5BX05aKVxuXHRcdFx0XHRcdFx0XHRcdHx8ICh3LnAgJiBQT1NUQUcuQV9OVClcblx0XHRcdFx0XHRcdFx0KSlcblx0XHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdFx0YXNzZXNzW2ldLmQrKztcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdC8vIOWmguaenOaYryDmlrnkvY3or40gKyDmlbDph4/or43vvIzliJnliqDliIZcblx0XHRcdFx0XHRcdGlmIChcblx0XHRcdFx0XHRcdFx0KHByZXcucCAmIFBPU1RBRy5EX0YpXG5cdFx0XHRcdFx0XHRcdCYmXG5cdFx0XHRcdFx0XHRcdChcblx0XHRcdFx0XHRcdFx0XHQody5wICYgUE9TVEFHLkFfTSlcblx0XHRcdFx0XHRcdFx0XHR8fCAody5wICYgUE9TVEFHLkRfTVEpXG5cdFx0XHRcdFx0XHRcdCkpXG5cdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdC8vZGVidWcocHJldywgdyk7XG5cdFx0XHRcdFx0XHRcdGFzc2Vzc1tpXS5kKys7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHQvLyDlpoLmnpzmmK8g5aeTICsg5ZCN6K+N77yM5YiZ5Yqg5YiGXG5cdFx0XHRcdFx0XHRpZiAoXG5cdFx0XHRcdFx0XHRcdChcblx0XHRcdFx0XHRcdFx0XHRwcmV3LncgaW4gRkFNSUxZX05BTUVfMVxuXHRcdFx0XHRcdFx0XHRcdHx8IHByZXcudyBpbiBGQU1JTFlfTkFNRV8yXG5cdFx0XHRcdFx0XHRcdCkgJiZcblx0XHRcdFx0XHRcdFx0KFxuXHRcdFx0XHRcdFx0XHRcdCh3LnAgJiBQT1NUQUcuRF9OKVxuXHRcdFx0XHRcdFx0XHRcdHx8ICh3LnAgJiBQT1NUQUcuQV9OWilcblx0XHRcdFx0XHRcdFx0KSlcblx0XHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdFx0Ly9kZWJ1ZyhwcmV3LCB3KTtcblx0XHRcdFx0XHRcdFx0YXNzZXNzW2ldLmQrKztcblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0LyoqXG5cdFx0XHRcdFx0XHQgKiDlnLDlkI0v5aSE5omAICsg5pa55L2NXG5cdFx0XHRcdFx0XHQgKi9cblx0XHRcdFx0XHRcdGlmIChoZXhBbmRBbnkocHJldy5wXG5cdFx0XHRcdFx0XHRcdCwgUE9TVEFHLkRfU1xuXHRcdFx0XHRcdFx0XHQsIFBPU1RBRy5BX05TLFxuXHRcdFx0XHRcdFx0KSAmJiBoZXhBbmRBbnkody5wXG5cdFx0XHRcdFx0XHRcdCwgUE9TVEFHLkRfRixcblx0XHRcdFx0XHRcdCkpXG5cdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdGFzc2Vzc1tpXS5kICs9IDAuNTtcblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0Ly8g5o6i5rWL5LiL5LiA5Liq6K+NXG5cdFx0XHRcdFx0XHRsZXQgbmV4dHcgPSBjaHVua1tqICsgMV07XG5cdFx0XHRcdFx0XHRpZiAobmV4dHcpXG5cdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdGlmIChuZXh0dy53IGluIFRBQkxFKVxuXHRcdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdFx0bmV4dHcucCA9IFRBQkxFW25leHR3LnddLnA7XG5cdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0XHRsZXQgX3RlbXBfb2s6IGJvb2xlYW4gPSB0cnVlO1xuXG5cdFx0XHRcdFx0XHRcdC8qKlxuXHRcdFx0XHRcdFx0XHQgKiDlpoLmnpzlvZPliY3mmK/igJznmoTigJ0rIOWQjeivje+8jOWImeWKoOWIhlxuXHRcdFx0XHRcdFx0XHQgKi9cblx0XHRcdFx0XHRcdFx0aWYgKFxuXHRcdFx0XHRcdFx0XHRcdCh3LncgPT09ICfnmoQnIHx8IHcudyA9PT0gJ+S5iycpXG5cdFx0XHRcdFx0XHRcdFx0JiYgbmV4dHcucCAmJiAoXG5cdFx0XHRcdFx0XHRcdFx0XHQobmV4dHcucCAmIFBPU1RBRy5EX04pXG5cdFx0XHRcdFx0XHRcdFx0XHR8fCAobmV4dHcucCAmIFBPU1RBRy5EX1YpXG5cdFx0XHRcdFx0XHRcdFx0XHR8fCAobmV4dHcucCAmIFBPU1RBRy5BX05SKVxuXHRcdFx0XHRcdFx0XHRcdFx0fHwgKG5leHR3LnAgJiBQT1NUQUcuQV9OUylcblx0XHRcdFx0XHRcdFx0XHRcdHx8IChuZXh0dy5wICYgUE9TVEFHLkFfTlopXG5cdFx0XHRcdFx0XHRcdFx0XHR8fCAobmV4dHcucCAmIFBPU1RBRy5BX05UKVxuXHRcdFx0XHRcdFx0XHRcdCkpXG5cdFx0XHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdFx0XHRhc3Nlc3NbaV0uZCArPSAxLjU7XG5cdFx0XHRcdFx0XHRcdFx0X3RlbXBfb2sgPSBmYWxzZTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHQvKipcblx0XHRcdFx0XHRcdFx0ICog5aaC5p6c5piv6L+e6K+N77yM5YmN5ZCO5Lik5Liq6K+N6K+N5oCn55u45ZCM5YiZ5Yqg5YiGXG5cdFx0XHRcdFx0XHRcdCAqL1xuXHRcdFx0XHRcdFx0XHRlbHNlIGlmIChwcmV3LnAgJiYgKHcucCAmIFBPU1RBRy5EX0MpKVxuXHRcdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdFx0bGV0IHAgPSBwcmV3LnAgJiBuZXh0dy5wO1xuXG5cdFx0XHRcdFx0XHRcdFx0aWYgKHByZXcucCA9PT0gbmV4dHcucClcblx0XHRcdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdFx0XHRhc3Nlc3NbaV0uZCsrO1xuXHRcdFx0XHRcdFx0XHRcdFx0X3RlbXBfb2sgPSBmYWxzZTtcblx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0ZWxzZSBpZiAocClcblx0XHRcdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdFx0XHRhc3Nlc3NbaV0uZCArPSAwLjI1O1xuXHRcdFx0XHRcdFx0XHRcdFx0X3RlbXBfb2sgPSBmYWxzZTtcblxuXHRcdFx0XHRcdFx0XHRcdFx0aWYgKHAgJiBQT1NUQUcuRF9OKVxuXHRcdFx0XHRcdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRhc3Nlc3NbaV0uZCArPSAwLjc1O1xuXHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdC8qKlxuXHRcdFx0XHRcdFx0XHQgKiDlnKjmhJ/li5XnmoTph43pgKLkuK3mnInkvZnlnKjnmoToqbHlsLHlpKrpgY7ploPogIBcblx0XHRcdFx0XHRcdFx0ICovXG5cdFx0XHRcdFx0XHRcdGlmIChfdGVtcF9vayAmJiAody5wICYgUE9TVEFHLkRfUikgJiYgKG5leHR3LnAgJiBQT1NUQUcuRF9QKSlcblx0XHRcdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0XHRcdGFzc2Vzc1tpXS5kICs9IDE7XG5cdFx0XHRcdFx0XHRcdFx0X3RlbXBfb2sgPSBmYWxzZTtcblx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdGlmIChfdGVtcF9vayAmJiBuZXh0dy5wICYmICh3LnAgJiBQT1NUQUcuRF9QKSlcblx0XHRcdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0XHRcdGlmIChuZXh0dy5wICYgUE9TVEFHLkFfTlIgJiYgKFxuXHRcdFx0XHRcdFx0XHRcdFx0bmV4dHcudy5sZW5ndGggPiAxXG5cdFx0XHRcdFx0XHRcdFx0KSlcblx0XHRcdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdFx0XHRhc3Nlc3NbaV0uZCsrO1xuXG5cdFx0XHRcdFx0XHRcdFx0XHRpZiAocHJldy53ID09PSAn55qEJylcblx0XHRcdFx0XHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0LyoqXG5cdFx0XHRcdFx0XHRcdFx0XHRcdCAqIOeahCArIOS7i+ipniArIOS6uuWQjVxuXHRcdFx0XHRcdFx0XHRcdFx0XHQgKi9cblx0XHRcdFx0XHRcdFx0XHRcdFx0YXNzZXNzW2ldLmQgKz0gMTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0X3RlbXBfb2sgPSBmYWxzZTtcblx0XHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0XHRpZiAoX3RlbXBfb2sgJiYgKHcucCAmIFBPU1RBRy5EX1ApICYmIGhleEFuZEFueShwcmV3LnAsXG5cdFx0XHRcdFx0XHRcdFx0UE9TVEFHLkRfTixcblx0XHRcdFx0XHRcdFx0KSAmJiBoZXhBbmRBbnkobmV4dHcucCxcblx0XHRcdFx0XHRcdFx0XHRQT1NUQUcuRF9OLFxuXHRcdFx0XHRcdFx0XHRcdFBPU1RBRy5EX1YsXG5cdFx0XHRcdFx0XHRcdCkpXG5cdFx0XHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdFx0XHRhc3Nlc3NbaV0uZCsrO1xuXHRcdFx0XHRcdFx0XHRcdF90ZW1wX29rID0gZmFsc2U7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0ZWxzZSBpZiAoX3RlbXBfb2sgJiYgKHcucCAmIFBPU1RBRy5EX1ApICYmIGhleEFuZEFueShwcmV3LnAsXG5cdFx0XHRcdFx0XHRcdFx0UE9TVEFHLkRfUixcblx0XHRcdFx0XHRcdFx0KSAmJiBoZXhBbmRBbnkobmV4dHcucCxcblx0XHRcdFx0XHRcdFx0XHRQT1NUQUcuRF9SLFxuXHRcdFx0XHRcdFx0XHQpKVxuXHRcdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdFx0YXNzZXNzW2ldLmQgKz0gMC41O1xuXHRcdFx0XHRcdFx0XHRcdF90ZW1wX29rID0gZmFsc2U7XG5cdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0XHQvLyBARklYTUUg5pq05Yqb6Kej5rG6IOS4ieWkqeWQjiDnmoTllY/poYxcblx0XHRcdFx0XHRcdFx0aWYgKG5leHR3LncgPT09ICflkI4nICYmIHcucCAmIFBPU1RBRy5EX1QgJiYgaGV4QW5kQW55KHByZXcucCxcblx0XHRcdFx0XHRcdFx0XHRQT1NUQUcuRF9NUSxcblx0XHRcdFx0XHRcdFx0XHRQT1NUQUcuQV9NLFxuXHRcdFx0XHRcdFx0XHQpKVxuXHRcdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdFx0YXNzZXNzW2ldLmQrKztcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHQvLyBARklYTUUg5Yiw5rmW5Lit6ZaT5ZCO5omL57WC5pa86IO95LyR5oGv5LqGXG5cdFx0XHRcdFx0XHRcdGVsc2UgaWYgKFxuXHRcdFx0XHRcdFx0XHRcdChcblx0XHRcdFx0XHRcdFx0XHRcdG5leHR3LncgPT09ICflkI4nXG5cdFx0XHRcdFx0XHRcdFx0XHR8fCBuZXh0dy53ID09PSAn5b6MJ1xuXHRcdFx0XHRcdFx0XHRcdClcblx0XHRcdFx0XHRcdFx0XHQmJiBoZXhBbmRBbnkody5wLFxuXHRcdFx0XHRcdFx0XHRcdFBPU1RBRy5EX0YsXG5cdFx0XHRcdFx0XHRcdFx0KVxuXHRcdFx0XHRcdFx0XHQpXG5cdFx0XHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdFx0XHRhc3Nlc3NbaV0uZCsrO1xuXHRcdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdFx0aWYgKFxuXHRcdFx0XHRcdFx0XHRcdChcblx0XHRcdFx0XHRcdFx0XHRcdHcudyA9PT0gJ+WQjidcblx0XHRcdFx0XHRcdFx0XHRcdHx8IHcudyA9PT0gJ+W+jCdcblx0XHRcdFx0XHRcdFx0XHQpXG5cdFx0XHRcdFx0XHRcdFx0JiYgaGV4QW5kQW55KHByZXcucCxcblx0XHRcdFx0XHRcdFx0XHRQT1NUQUcuRF9GLFxuXHRcdFx0XHRcdFx0XHRcdClcblx0XHRcdFx0XHRcdFx0XHQmJiBoZXhBbmRBbnkobmV4dHcucCxcblx0XHRcdFx0XHRcdFx0XHRQT1NUQUcuRF9OLFxuXHRcdFx0XHRcdFx0XHRcdClcblx0XHRcdFx0XHRcdFx0KVxuXHRcdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdFx0YXNzZXNzW2ldLmQrKztcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0ZWxzZVxuXHRcdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0XHRsZXQgX3RlbXBfb2s6IGJvb2xlYW4gPSB0cnVlO1xuXG5cdFx0XHRcdFx0XHRcdC8qKlxuXHRcdFx0XHRcdFx0XHQgKiDlpbnmiorojbfljIXom4vmkYblnKjlg4/mmK/ljbDluqbng6TppbznmoTpnaLljIXkuIpcblx0XHRcdFx0XHRcdFx0ICovXG5cdFx0XHRcdFx0XHRcdGlmIChfdGVtcF9vayAmJiAody5wICYgUE9TVEFHLkRfRikgJiYgaGV4QW5kQW55KHByZXcucCxcblx0XHRcdFx0XHRcdFx0XHRQT1NUQUcuRF9OLFxuXHRcdFx0XHRcdFx0XHQpKVxuXHRcdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdFx0YXNzZXNzW2ldLmQgKz0gMTtcblx0XHRcdFx0XHRcdFx0XHRfdGVtcF9vayA9IGZhbHNlO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblx0XHRcdFx0fVxuXHRcdFx0XHRlbHNlXG5cdFx0XHRcdHtcblx0XHRcdFx0XHQvLyDmnKror4bliKvnmoTor43mlbDph49cblx0XHRcdFx0XHRhc3Nlc3NbaV0uYysrO1xuXHRcdFx0XHR9XG5cdFx0XHRcdC8vIOagh+WHhuW3rlxuXHRcdFx0XHRhc3Nlc3NbaV0uYiArPSBNYXRoLnBvdyhzcCAtIHcudy5sZW5ndGgsIDIpO1xuXHRcdFx0XHRwcmV3ID0gY2h1bmtbal07XG5cdFx0XHR9XG5cblx0XHRcdC8vIOWmguaenOWPpeWtkOS4reWMheWQq+S6huiHs+WwkeS4gOS4quWKqOivjVxuXHRcdFx0aWYgKGhhc19EX1YgPT09IGZhbHNlKSBhc3Nlc3NbaV0uZCAtPSAwLjU7XG5cblx0XHRcdGFzc2Vzc1tpXS5hID0gYXNzZXNzW2ldLmEgLyBjaHVuay5sZW5ndGg7XG5cdFx0XHRhc3Nlc3NbaV0uYiA9IGFzc2Vzc1tpXS5iIC8gY2h1bmsubGVuZ3RoO1xuXHRcdH1cblxuXHRcdC8vY29uc29sZS5kaXIoYXNzZXNzKTtcblxuXHRcdC8vIOiuoeeul+aOkuWQjVxuXHRcdGxldCB0b3AgPSB0aGlzLmdldFRvcHMoYXNzZXNzKTtcblx0XHRsZXQgY3VycmNodW5rID0gY2h1bmtzW3RvcF07XG5cblx0XHRpZiAoZmFsc2UpXG5cdFx0e1xuXHRcdFx0Ly9jb25zb2xlLmxvZyhhc3Nlc3MpO1xuXHRcdFx0Ly9jb25zb2xlLmxvZyhPYmplY3QuZW50cmllcyhjaHVua3MpKTtcblx0XHRcdGNvbnNvbGUuZGlyKE9iamVjdC5lbnRyaWVzKGNodW5rcylcblx0XHRcdFx0Lm1hcCgoW2ksIGNodW5rXSkgPT4geyByZXR1cm4geyBpLCBhc3NlczogYXNzZXNzW2kgYXMgdW5rbm93biBhcyBudW1iZXJdLCBjaHVuayB9IH0pLCB7IGRlcHRoOiA1IH0pO1xuXHRcdFx0Y29uc29sZS5kaXIoeyBpOiB0b3AsIGFzc2VzOiBhc3Nlc3NbdG9wXSwgY3VycmNodW5rIH0pO1xuXHRcdFx0Ly9jb25zb2xlLmxvZyh0b3ApO1xuXHRcdFx0Ly9jb25zb2xlLmxvZyhjdXJyY2h1bmspO1xuXHRcdH1cblxuXHRcdC8vIOWJlOmZpOS4jeiDveivhuWIq+eahOivjVxuXHRcdGZvciAobGV0IGkgPSAwLCB3b3JkOiBJV29yZDsgd29yZCA9IGN1cnJjaHVua1tpXTsgaSsrKVxuXHRcdHtcblx0XHRcdGlmICghKHdvcmQudyBpbiBUQUJMRSkpXG5cdFx0XHR7XG5cdFx0XHRcdGN1cnJjaHVuay5zcGxpY2UoaS0tLCAxKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0ID0gY3VycmNodW5rO1xuXG5cdFx0Ly8g6Kmm5ZyW5Li75YuV5riF6Zmk6KiY5oa26auUXG5cdFx0YXNzZXNzID0gdW5kZWZpbmVkO1xuXHRcdGNodW5rcyA9IHVuZGVmaW5lZDtcblx0XHRjdXJyY2h1bmsgPSB1bmRlZmluZWQ7XG5cdFx0dG9wID0gdW5kZWZpbmVkO1xuXHRcdHdvcmRwb3MgPSB1bmRlZmluZWQ7XG5cblx0XHQvL2RlYnVnKHJldCk7XG5cdFx0cmV0dXJuIHJldDtcblx0fVxuXG5cdC8qKlxuXHQgKiDor4Tku7fmjpLlkI1cblx0ICpcblx0ICogQHBhcmFtIHtvYmplY3R9IGFzc2Vzc1xuXHQgKiBAcmV0dXJuIHtvYmplY3R9XG5cdCAqL1xuXHRnZXRUb3BzKGFzc2VzczogQXJyYXk8SUFzc2Vzc1Jvdz4pXG5cdHtcblx0XHQvL2RlYnVnKGFzc2Vzcyk7XG5cdFx0Ly8g5Y+W5ZCE6aG55pyA5aSn5YC8XG5cdFx0bGV0IHRvcDogSUFzc2Vzc1JvdyA9IHtcblx0XHRcdHg6IGFzc2Vzc1swXS54LFxuXHRcdFx0YTogYXNzZXNzWzBdLmEsXG5cdFx0XHRiOiBhc3Nlc3NbMF0uYixcblx0XHRcdGM6IGFzc2Vzc1swXS5jLFxuXHRcdFx0ZDogYXNzZXNzWzBdLmQsXG5cdFx0fTtcblxuXHRcdGZvciAobGV0IGkgPSAxLCBhc3M6IElBc3Nlc3NSb3c7IGFzcyA9IGFzc2Vzc1tpXTsgaSsrKVxuXHRcdHtcblx0XHRcdGlmIChhc3MuYSA+IHRvcC5hKSB0b3AuYSA9IGFzcy5hOyAgLy8g5Y+W5pyA5aSn5bmz5Z2H6K+N6aKRXG5cdFx0XHRpZiAoYXNzLmIgPCB0b3AuYikgdG9wLmIgPSBhc3MuYjsgIC8vIOWPluacgOWwj+agh+WHhuW3rlxuXHRcdFx0aWYgKGFzcy5jID4gdG9wLmMpIHRvcC5jID0gYXNzLmM7ICAvLyDlj5bmnIDlpKfmnKror4bliKvor41cblx0XHRcdGlmIChhc3MuZCA8IHRvcC5kKSB0b3AuZCA9IGFzcy5kOyAgLy8g5Y+W5pyA5bCP6K+t5rOV5YiG5pWwXG5cdFx0XHRpZiAoYXNzLnggPiB0b3AueCkgdG9wLnggPSBhc3MueDsgIC8vIOWPluacgOWkp+WNleivjeaVsOmHj1xuXHRcdH1cblx0XHQvL2RlYnVnKHRvcCk7XG5cblx0XHQvLyDor4TkvLDmjpLlkI1cblx0XHRsZXQgdG9wczogbnVtYmVyW10gPSBbXTtcblx0XHRmb3IgKGxldCBpID0gMCwgYXNzOiBJQXNzZXNzUm93OyBhc3MgPSBhc3Nlc3NbaV07IGkrKylcblx0XHR7XG5cdFx0XHR0b3BzW2ldID0gMDtcblx0XHRcdC8vIOivjeaVsOmHj++8jOi2iuWwj+i2iuWlvVxuXHRcdFx0dG9wc1tpXSArPSAodG9wLnggLSBhc3MueCkgKiAxLjU7XG5cdFx0XHQvLyDor43mgLvpopHnjofvvIzotorlpKfotorlpb1cblx0XHRcdGlmIChhc3MuYSA+PSB0b3AuYSkgdG9wc1tpXSArPSAxO1xuXHRcdFx0Ly8g6K+N5qCH5YeG5beu77yM6LaK5bCP6LaK5aW9XG5cdFx0XHRpZiAoYXNzLmIgPD0gdG9wLmIpIHRvcHNbaV0gKz0gMTtcblx0XHRcdC8vIOacquivhuWIq+ivje+8jOi2iuWwj+i2iuWlvVxuXHRcdFx0dG9wc1tpXSArPSAodG9wLmMgLSBhc3MuYyk7Ly9kZWJ1Zyh0b3BzW2ldKTtcblx0XHRcdC8vIOespuWQiOivreazlee7k+aehOeoi+W6pu+8jOi2iuWkp+i2iuWlvVxuXHRcdFx0dG9wc1tpXSArPSAoYXNzLmQgPCAwID8gdG9wLmQgKyBhc3MuZCA6IGFzcy5kIC0gdG9wLmQpICogMTtcblxuXHRcdFx0YXNzLnNjb3JlID0gdG9wc1tpXTtcblxuXHRcdFx0Ly9kZWJ1Zyh0b3BzW2ldKTtkZWJ1ZygnLS0tJyk7XG5cdFx0fVxuXHRcdC8vZGVidWcodG9wcy5qb2luKCcgICcpKTtcblxuXHRcdC8vY29uc29sZS5sb2codG9wcyk7XG5cdFx0Ly9jb25zb2xlLmxvZyhhc3Nlc3MpO1xuXG5cdFx0Ly9jb25zdCBvbGRfbWV0aG9kID0gdHJ1ZTtcblx0XHRjb25zdCBvbGRfbWV0aG9kID0gZmFsc2U7XG5cblx0XHQvLyDlj5bliIbmlbDmnIDpq5jnmoRcblx0XHRsZXQgY3VycmkgPSAwO1xuXHRcdGxldCBtYXhzID0gdG9wc1swXTtcblx0XHRmb3IgKGxldCBpIGluIHRvcHMpXG5cdFx0e1xuXHRcdFx0bGV0IHMgPSB0b3BzW2ldO1xuXHRcdFx0aWYgKHMgPiBtYXhzKVxuXHRcdFx0e1xuXHRcdFx0XHRjdXJyaSA9IGkgYXMgYW55IGFzIG51bWJlcjtcblx0XHRcdFx0bWF4cyA9IHM7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIGlmIChzID09PSBtYXhzKVxuXHRcdFx0e1xuXHRcdFx0XHQvKipcblx0XHRcdFx0ICog5aaC5p6c5YiG5pWw55u45ZCM77yM5YiZ5qC55o2u6K+N6ZW/5bqm44CB5pyq6K+G5Yir6K+N5Liq5pWw5ZKM5bmz5Z2H6aKR546H5p2l6YCJ5oupXG5cdFx0XHRcdCAqXG5cdFx0XHRcdCAqIOWmguaenOS+neeEtuWQjOWIhu+8jOWJh+S/neaMgeS4jeiuilxuXHRcdFx0XHQgKi9cblx0XHRcdFx0bGV0IGEgPSAwO1xuXHRcdFx0XHRsZXQgYiA9IDA7XG5cdFx0XHRcdGlmIChhc3Nlc3NbaV0uYyA8IGFzc2Vzc1tjdXJyaV0uYylcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGErKztcblx0XHRcdFx0fVxuXHRcdFx0XHRlbHNlIGlmIChhc3Nlc3NbaV0uYyAhPT0gYXNzZXNzW2N1cnJpXS5jKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0YisrO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmIChhc3Nlc3NbaV0uYSA+IGFzc2Vzc1tjdXJyaV0uYSlcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGErKztcblx0XHRcdFx0fVxuXHRcdFx0XHRlbHNlIGlmIChhc3Nlc3NbaV0uYSAhPT0gYXNzZXNzW2N1cnJpXS5hKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0YisrO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmIChhc3Nlc3NbaV0ueCA8IGFzc2Vzc1tjdXJyaV0ueClcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGErKztcblx0XHRcdFx0fVxuXHRcdFx0XHRlbHNlIGlmIChhc3Nlc3NbaV0ueCAhPT0gYXNzZXNzW2N1cnJpXS54KVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0YisrO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmIChhID4gYilcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGN1cnJpID0gaSBhcyBhbnkgYXMgbnVtYmVyO1xuXHRcdFx0XHRcdG1heHMgPSBzO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHQvL2RlYnVnKHsgaSwgcywgbWF4cywgY3VycmkgfSk7XG5cdFx0fVxuXHRcdC8vZGVidWcoJ21heDogaT0nICsgY3VycmkgKyAnLCBzPScgKyB0b3BzW2N1cnJpXSk7XG5cblx0XHRhc3Nlc3MgPSB1bmRlZmluZWQ7XG5cdFx0dG9wID0gdW5kZWZpbmVkO1xuXG5cdFx0cmV0dXJuIGN1cnJpO1xuXHR9XG5cblx0LyoqXG5cdCAqIOWwhuWNleivjeaMieeFp+S9jee9ruaOkuWIl1xuXHQgKlxuXHQgKiBAcGFyYW0ge2FycmF5fSB3b3Jkc1xuXHQgKiBAcGFyYW0ge3N0cmluZ30gdGV4dFxuXHQgKiBAcmV0dXJuIHtvYmplY3R9XG5cdCAqL1xuXHRnZXRQb3NJbmZvKHdvcmRzOiBJV29yZFtdLCB0ZXh0OiBzdHJpbmcpOiB7XG5cdFx0W2luZGV4OiBudW1iZXJdOiBJV29yZFtdO1xuXHR9XG5cdHtcblx0XHRsZXQgd29yZHBvcyA9IHt9O1xuXHRcdC8vIOWwhuWNleivjeaMieS9jee9ruWIhue7hFxuXHRcdGZvciAobGV0IGkgPSAwLCB3b3JkOyB3b3JkID0gd29yZHNbaV07IGkrKylcblx0XHR7XG5cdFx0XHRpZiAoIXdvcmRwb3Nbd29yZC5jXSlcblx0XHRcdHtcblx0XHRcdFx0d29yZHBvc1t3b3JkLmNdID0gW107XG5cdFx0XHR9XG5cdFx0XHR3b3JkcG9zW3dvcmQuY10ucHVzaCh3b3JkKTtcblx0XHR9XG5cdFx0Ly8g5oyJ5Y2V5a2X5YiG5Ymy5paH5pys77yM5aGr6KGl56m657y655qE5L2N572uXG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCB0ZXh0Lmxlbmd0aDsgaSsrKVxuXHRcdHtcblx0XHRcdGlmICghd29yZHBvc1tpXSlcblx0XHRcdHtcblx0XHRcdFx0d29yZHBvc1tpXSA9IFt7IHc6IHRleHQuY2hhckF0KGkpLCBjOiBpLCBmOiAwIH1dO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiB3b3JkcG9zO1xuXHR9XG5cblx0LyoqXG5cdCAqIOWPluaJgOacieWIhuaUr1xuXHQgKlxuXHQgKiBAcGFyYW0ge3tbcDogbnVtYmVyXTogU2VnbWVudC5JV29yZFtdfX0gd29yZHBvc1xuXHQgKiBAcGFyYW0ge251bWJlcn0gcG9zIOW9k+WJjeS9jee9rlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gdGV4dCDmnKzoioLopoHliIbor43nmoTmlofmnKxcblx0ICogQHBhcmFtIHtudW1iZXJ9IHRvdGFsX2NvdW50XG5cdCAqIEByZXR1cm5zIHtTZWdtZW50LklXb3JkW11bXX1cblx0ICovXG5cdGdldENodW5rcyh3b3JkcG9zOiB7XG5cdFx0W2luZGV4OiBudW1iZXJdOiBJV29yZFtdO1xuXHR9LCBwb3M6IG51bWJlciwgdGV4dD86IHN0cmluZywgdG90YWxfY291bnQgPSAwLCBNQVhfQ0hVTktfQ09VTlQ/OiBudW1iZXIpOiBJV29yZFtdW11cblx0e1xuXG5cdFx0LyoqXG5cdFx0ICpcblx0XHQgKiDov73liqDmlrDmqKHlvI/kvb8gTUFYX0NIVU5LX0NPVU5UIOmBnua4m+S+humYsuatoueEoeWIhuautemVt+auteiQveeahOe4veiZleeQhuasoeaVuOmBjumrmCDnlLEgREVGQVVMVF9NQVhfQ0hVTktfQ09VTlRfTUlOIOS+humZkOWItuacgOWwj+WAvFxuXHRcdCAqL1xuXHRcdGlmICh0b3RhbF9jb3VudCA9PT0gMClcblx0XHR7XG5cdFx0XHRNQVhfQ0hVTktfQ09VTlQgPSB0aGlzLk1BWF9DSFVOS19DT1VOVDtcblxuXHRcdFx0LyoqXG5cdFx0XHQgKiDlj6rmnInnlbbnm67liY3mloflrZfplbfluqblpKfmlrwgTUFYX0NIVU5LX0NPVU5UIOaZguaJjemBnua4m1xuXHRcdFx0ICovXG5cdFx0XHRpZiAodGV4dC5sZW5ndGggPCBNQVhfQ0hVTktfQ09VTlQpXG5cdFx0XHR7XG5cdFx0XHRcdE1BWF9DSFVOS19DT1VOVCArPSAxO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRlbHNlIGlmIChNQVhfQ0hVTktfQ09VTlQgPD0gdGhpcy5NQVhfQ0hVTktfQ09VTlQpXG5cdFx0e1xuXHRcdFx0TUFYX0NIVU5LX0NPVU5UID0gTWF0aC5tYXgoTUFYX0NIVU5LX0NPVU5UIC0gMSwgdGhpcy5ERUZBVUxUX01BWF9DSFVOS19DT1VOVF9NSU4sIERFRkFVTFRfTUFYX0NIVU5LX0NPVU5UX01JTilcblx0XHR9XG5cdFx0ZWxzZVxuXHRcdHtcblx0XHRcdC8vTUFYX0NIVU5LX0NPVU5UID0gTWF0aC5tYXgoTUFYX0NIVU5LX0NPVU5ULCB0aGlzLkRFRkFVTFRfTUFYX0NIVU5LX0NPVU5UX01JTiwgREVGQVVMVF9NQVhfQ0hVTktfQ09VTlRfTUlOKVxuXHRcdH1cblxuXHRcdC8qKlxuXHRcdCAqIOW/veeVpemAo+Wtl1xuXHRcdCAqXG5cdFx0ICog5L6L5aaCOiDllYrllYrllYrllYrllYrllYrllYrllYrllYrllYrllYrllYrllYrllYrllYrllYrllYrllYrllYrllYrllYrllYrllYrllYrllYrllYrllYrllYrllYrllYrllYrllYrllYrllYrllYrllYrllYrllYrllYrllYpcblx0XHQgKi9cblx0XHRsZXQgbTogUmVnRXhwTWF0Y2hBcnJheTtcblx0XHRpZiAobSA9IHRleHQubWF0Y2goL14oKC4rKVxcMns1LH0pLykpXG5cdFx0e1xuXHRcdFx0bGV0IHMxID0gdGV4dC5zbGljZSgwLCBtWzFdLmxlbmd0aCk7XG5cdFx0XHRsZXQgczIgPSB0ZXh0LnNsaWNlKG1bMV0ubGVuZ3RoKTtcblxuXHRcdFx0bGV0IHdvcmQgPSB7XG5cdFx0XHRcdHc6IHMxLFxuXHRcdFx0XHRjOiBwb3MsXG5cdFx0XHRcdGY6IDAsXG5cdFx0XHR9IGFzIElXb3JkO1xuXG5cdFx0XHRsZXQgX3JldDogSVdvcmRbXVtdID0gW107XG5cblx0XHRcdGlmIChzMiAhPT0gJycpXG5cdFx0XHR7XG5cdFx0XHRcdGxldCBjaHVua3MgPSB0aGlzLmdldENodW5rcyh3b3JkcG9zLCBwb3MgKyBzMS5sZW5ndGgsIHMyLCB0b3RhbF9jb3VudCwgTUFYX0NIVU5LX0NPVU5UKTtcblxuXHRcdFx0XHRmb3IgKGxldCB3cyBvZiBjaHVua3MpXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRfcmV0LnB1c2goW3dvcmRdLmNvbmNhdCh3cykpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRlbHNlXG5cdFx0XHR7XG5cdFx0XHRcdF9yZXQucHVzaChbd29yZF0pO1xuXHRcdFx0fVxuXG4vL1x0XHRcdGNvbnNvbGUuZGlyKHdvcmRwb3MpO1xuLy9cbi8vXHRcdFx0Y29uc29sZS5kaXIocmV0KTtcbi8vXG4vL1x0XHRcdGNvbnNvbGUuZGlyKFtwb3MsIHRleHQsIHRvdGFsX2NvdW50XSk7XG5cblx0XHRcdHJldHVybiBfcmV0O1xuXHRcdH1cblxuXHRcdHRvdGFsX2NvdW50Kys7XG5cblx0XHRsZXQgd29yZHMgPSB3b3JkcG9zW3Bvc10gfHwgW107XG5cblx0XHQvL2RlYnVnKHRvdGFsX2NvdW50LCBNQVhfQ0hVTktfQ09VTlQpO1xuXG4vL1x0XHRkZWJ1Zyh7XG4vL1x0XHRcdHRvdGFsX2NvdW50LFxuLy9cdFx0XHRNQVhfQ0hVTktfQ09VTlQ6IHRoaXMuTUFYX0NIVU5LX0NPVU5ULFxuLy9cdFx0XHR0ZXh0LFxuLy9cdFx0XHR3b3Jkcyxcbi8vXHRcdH0pO1xuXG5cdFx0Ly8gZGVidWcoJ2dldENodW5rczogJyk7XG5cdFx0Ly8gZGVidWcod29yZHMpO1xuXHRcdC8vdGhyb3cgbmV3IEVycm9yKCk7XG5cblx0XHRsZXQgcmV0OiBJV29yZFtdW10gPSBbXTtcblx0XHRmb3IgKGxldCB3b3JkIG9mIHdvcmRzKVxuXHRcdHtcblx0XHRcdC8vZGVidWcod29yZCk7XG5cdFx0XHRsZXQgbmV4dGN1ciA9IHdvcmQuYyArIHdvcmQudy5sZW5ndGg7XG5cdFx0XHQvKipcblx0XHRcdCAqIEBGSVhNRVxuXHRcdFx0ICovXG5cdFx0XHRpZiAoIXdvcmRwb3NbbmV4dGN1cl0pXG5cdFx0XHR7XG5cdFx0XHRcdHJldC5wdXNoKFt3b3JkXSk7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIGlmICh0b3RhbF9jb3VudCA+IE1BWF9DSFVOS19DT1VOVClcblx0XHRcdHtcblx0XHRcdFx0Ly8gZG8gc29tZXRoaW5nXG5cbi8vXHRcdFx0XHRjb25zb2xlLmxvZyg0NDQsIHdvcmRzLnNsaWNlKGkpKTtcbi8vXHRcdFx0XHRjb25zb2xlLmxvZygzMzMsIHdvcmQpO1xuXG5cdFx0XHRcdGxldCB3MTogSVdvcmRbXSA9IFt3b3JkXTtcblxuXHRcdFx0XHRsZXQgaiA9IG5leHRjdXI7XG5cdFx0XHRcdHdoaWxlIChqIGluIHdvcmRwb3MpXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRsZXQgdzIgPSB3b3JkcG9zW2pdWzBdO1xuXG5cdFx0XHRcdFx0aWYgKHcyKVxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdHcxLnB1c2godzIpO1xuXG5cdFx0XHRcdFx0XHRqICs9IHcyLncubGVuZ3RoO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRlbHNlXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0cmV0LnB1c2godzEpO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZVxuXHRcdFx0e1xuXHRcdFx0XHRsZXQgdCA9IHRleHQuc2xpY2Uod29yZC53Lmxlbmd0aCk7XG5cblx0XHRcdFx0bGV0IGNodW5rcyA9IHRoaXMuZ2V0Q2h1bmtzKHdvcmRwb3MsIG5leHRjdXIsIHQsIHRvdGFsX2NvdW50LCBNQVhfQ0hVTktfQ09VTlQgKTtcblx0XHRcdFx0Zm9yIChsZXQgd3Mgb2YgY2h1bmtzKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0cmV0LnB1c2goW3dvcmRdLmNvbmNhdCh3cykpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Y2h1bmtzID0gbnVsbDtcblx0XHRcdH1cblx0XHR9XG5cblx0XHR3b3JkcyA9IHVuZGVmaW5lZDtcblx0XHR3b3JkcG9zID0gdW5kZWZpbmVkO1xuXHRcdG0gPSB1bmRlZmluZWQ7XG5cblx0XHRyZXR1cm4gcmV0O1xuXHR9XG59XG5cbmV4cG9ydCBuYW1lc3BhY2UgRGljdFRva2VuaXplclxue1xuXHQvKipcblx0ICog5L2/55So57G75Ly85LqOTU1TR+eahOWIhuivjeeul+azlVxuXHQgKiDmib7lh7rmiYDmnInliIbor43lj6/og73vvIzkuLvopoHmoLnmja7kuIDkuIvlh6DpobnmnaXor4Tku7fvvJpcblx0ICpcblx0ICogeOOAgeivjeaVsOmHj+acgOWwke+8m1xuXHQgKiBh44CB6K+N5bmz5Z2H6aKR546H5pyA5aSn77ybXG5cdCAqIGLjgIHmr4/kuKror43plb/luqbmoIflh4blt67mnIDlsI/vvJtcblx0ICogY+OAgeacquivhuWIq+ivjeacgOWwke+8m1xuXHQgKiBk44CB56ym5ZCI6K+t5rOV57uT5p6E6aG577ya5aaC5Lik5Liq6L+e57ut55qE5Yqo6K+N5YeP5YiG77yM5pWw6K+N5ZCO6Z2i6Lef6YeP6K+N5Yqg5YiG77ybXG5cdCAqXG5cdCAqIOWPluS7peS4iuWHoOmhuee7vOWQiOaOkuWQjeacgOacgOWlveeahFxuXHQgKi9cblx0ZXhwb3J0IHR5cGUgSUFzc2Vzc1JvdyA9IHtcblx0XHQvKipcblx0XHQgKiDor43mlbDph4/vvIzotorlsI/otorlpb1cblx0XHQgKi9cblx0XHR4OiBudW1iZXIsXG5cdFx0LyoqXG5cdFx0ICog6K+N5oC76aKR546H77yM6LaK5aSn6LaK5aW9XG5cdFx0ICovXG5cdFx0YTogbnVtYmVyLFxuXHRcdC8qKlxuXHRcdCAqIOivjeagh+WHhuW3ru+8jOi2iuWwj+i2iuWlvVxuXHRcdCAqIOavj+S4quivjemVv+W6puagh+WHhuW3ruacgOWwj1xuXHRcdCAqL1xuXHRcdGI6IG51bWJlcixcblx0XHQvKipcblx0XHQgKiDmnKror4bliKvor43vvIzotorlsI/otorlpb1cblx0XHQgKi9cblx0XHRjOiBudW1iZXIsXG5cdFx0LyoqXG5cdFx0ICog56ym5ZCI6K+t5rOV57uT5p6E56iL5bqm77yM6LaK5aSn6LaK5aW9XG5cdFx0ICog56ym5ZCI6K+t5rOV57uT5p6E6aG577ya5aaC5Lik5Liq6L+e57ut55qE5Yqo6K+N5YeP5YiG77yM5pWw6K+N5ZCO6Z2i6Lef6YeP6K+N5Yqg5YiGXG5cdFx0ICovXG5cdFx0ZDogbnVtYmVyLFxuXG5cdFx0LyoqXG5cdFx0ICog57WQ566X6KmV5YiGKOiHquWLleioiOeulylcblx0XHQgKi9cblx0XHRzY29yZT86IG51bWJlcixcblx0XHRyZWFkb25seSBpbmRleD86IG51bWJlcixcblx0fTtcbn1cblxuZXhwb3J0IGltcG9ydCBJQXNzZXNzUm93ID0gRGljdFRva2VuaXplci5JQXNzZXNzUm93O1xuXG5leHBvcnQgY29uc3QgaW5pdCA9IERpY3RUb2tlbml6ZXIuaW5pdC5iaW5kKERpY3RUb2tlbml6ZXIpIGFzIElTdWJUb2tlbml6ZXJDcmVhdGU8RGljdFRva2VuaXplcj47XG5cbmV4cG9ydCBkZWZhdWx0IERpY3RUb2tlbml6ZXI7XG4iXX0= |
\ | No newline at end of file |