imba-source 0.14.1 → 0.14.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4048 @@
1
+ /******/ (function(modules) { // webpackBootstrap
2
+ /******/ // The module cache
3
+ /******/ var installedModules = {};
4
+ /******/
5
+ /******/ // The require function
6
+ /******/ function __webpack_require__(moduleId) {
7
+ /******/
8
+ /******/ // Check if module is in cache
9
+ /******/ if(installedModules[moduleId])
10
+ /******/ return installedModules[moduleId].exports;
11
+ /******/
12
+ /******/ // Create a new module (and put it into the cache)
13
+ /******/ var module = installedModules[moduleId] = {
14
+ /******/ exports: {},
15
+ /******/ id: moduleId,
16
+ /******/ loaded: false
17
+ /******/ };
18
+ /******/
19
+ /******/ // Execute the module function
20
+ /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
21
+ /******/
22
+ /******/ // Flag the module as loaded
23
+ /******/ module.loaded = true;
24
+ /******/
25
+ /******/ // Return the exports of the module
26
+ /******/ return module.exports;
27
+ /******/ }
28
+ /******/
29
+ /******/
30
+ /******/ // expose the modules object (__webpack_modules__)
31
+ /******/ __webpack_require__.m = modules;
32
+ /******/
33
+ /******/ // expose the module cache
34
+ /******/ __webpack_require__.c = installedModules;
35
+ /******/
36
+ /******/ // __webpack_public_path__
37
+ /******/ __webpack_require__.p = "";
38
+ /******/
39
+ /******/ // Load entry module and return exports
40
+ /******/ return __webpack_require__(0);
41
+ /******/ })
42
+ /************************************************************************/
43
+ /******/ ([
44
+ /* 0 */
45
+ /***/ function(module, exports, __webpack_require__) {
46
+
47
+ (function(){
48
+
49
+ if (typeof Imba === 'undefined') {
50
+ __webpack_require__(1);
51
+ __webpack_require__(2);
52
+ __webpack_require__(3);
53
+ __webpack_require__(4);
54
+ __webpack_require__(5);
55
+ __webpack_require__(6);
56
+ __webpack_require__(7);
57
+
58
+ if (false) {
59
+ require('./dom.server');
60
+ };
61
+
62
+ if (true) {
63
+ __webpack_require__(8);
64
+ __webpack_require__(9);
65
+ __webpack_require__(10);
66
+ };
67
+
68
+ return __webpack_require__(11);
69
+ } else {
70
+ return console.warn(("Imba v" + (Imba.VERSION) + " is already loaded"));
71
+ };
72
+
73
+ })()
74
+
75
+ /***/ },
76
+ /* 1 */
77
+ /***/ function(module, exports, __webpack_require__) {
78
+
79
+ /* WEBPACK VAR INJECTION */(function(global) {(function(){
80
+ if (typeof window !== 'undefined') {
81
+ // should not go there
82
+ global = window;
83
+ };
84
+
85
+ var isClient = (typeof window == 'object' && this == window);
86
+ /*
87
+ Imba is the namespace for all runtime related utilities
88
+ @namespace
89
+ */
90
+
91
+ Imba = {
92
+ VERSION: '0.14.3',
93
+ CLIENT: isClient,
94
+ SERVER: !(isClient),
95
+ DEBUG: false
96
+ };
97
+
98
+ var reg = /-./g;
99
+
100
+ /*
101
+ True if running in client environment.
102
+ @return {bool}
103
+ */
104
+
105
+ Imba.isClient = function (){
106
+ return (true) == true;
107
+ };
108
+
109
+ /*
110
+ True if running in server environment.
111
+ @return {bool}
112
+ */
113
+
114
+ Imba.isServer = function (){
115
+ return (false) == true;
116
+ };
117
+
118
+ Imba.subclass = function (obj,sup){
119
+ ;
120
+ for (var k in sup){
121
+ if (sup.hasOwnProperty(k)) { obj[k] = sup[k] };
122
+ };
123
+
124
+ obj.prototype = Object.create(sup.prototype);
125
+ obj.__super__ = obj.prototype.__super__ = sup.prototype;
126
+ obj.prototype.initialize = obj.prototype.constructor = obj;
127
+ return obj;
128
+ };
129
+
130
+ /*
131
+ Lightweight method for making an object iterable in imbas for/in loops.
132
+ If the compiler cannot say for certain that a target in a for loop is an
133
+ array, it will cache the iterable version before looping.
134
+
135
+ ```imba
136
+ # this is the whole method
137
+ def Imba.iterable o
138
+ return o ? (o:toArray ? o.toArray : o) : []
139
+
140
+ class CustomIterable
141
+ def toArray
142
+ [1,2,3]
143
+
144
+ # will return [2,4,6]
145
+ for x in CustomIterable.new
146
+ x * 2
147
+
148
+ ```
149
+ */
150
+
151
+ Imba.iterable = function (o){
152
+ return o ? ((o.toArray ? (o.toArray()) : (o))) : ([]);
153
+ };
154
+
155
+ /*
156
+ Coerces a value into a promise. If value is array it will
157
+ call `Promise.all(value)`, or if it is not a promise it will
158
+ wrap the value in `Promise.resolve(value)`. Used for experimental
159
+ await syntax.
160
+ @return {Promise}
161
+ */
162
+
163
+ Imba.await = function (value){
164
+ if (value instanceof Array) {
165
+ return Promise.all(value);
166
+ } else if (value && value.then) {
167
+ return value;
168
+ } else {
169
+ return Promise.resolve(value);
170
+ };
171
+ };
172
+
173
+ Imba.toCamelCase = function (str){
174
+ return str.replace(reg,function(m) { return m.charAt(1).toUpperCase(); });
175
+ };
176
+
177
+ Imba.toCamelCase = function (str){
178
+ return str.replace(reg,function(m) { return m.charAt(1).toUpperCase(); });
179
+ };
180
+
181
+ Imba.indexOf = function (a,b){
182
+ return (b && b.indexOf) ? (b.indexOf(a)) : ([].indexOf.call(a,b));
183
+ };
184
+
185
+ Imba.prop = function (scope,name,opts){
186
+ if (scope.defineProperty) {
187
+ return scope.defineProperty(name,opts);
188
+ };
189
+ return;
190
+ };
191
+
192
+ return Imba.attr = function (scope,name,opts){
193
+ if (scope.defineAttribute) {
194
+ return scope.defineAttribute(name,opts);
195
+ };
196
+
197
+ var getName = Imba.toCamelCase(name);
198
+ var setName = Imba.toCamelCase('set-' + name);
199
+
200
+ scope.prototype[getName] = function() {
201
+ return this.getAttribute(name);
202
+ };
203
+
204
+ scope.prototype[setName] = function(value) {
205
+ this.setAttribute(name,value);
206
+ return this;
207
+ };
208
+
209
+ return;
210
+ };
211
+
212
+ })()
213
+ /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
214
+
215
+ /***/ },
216
+ /* 2 */
217
+ /***/ function(module, exports) {
218
+
219
+ (function(){
220
+
221
+
222
+ function emit__(event,args,node){
223
+ // var node = cbs[event]
224
+ var prev,cb,ret;
225
+
226
+ while ((prev = node) && (node = node.next)){
227
+ if (cb = node.listener) {
228
+ if (node.path && cb[node.path]) {
229
+ ret = args ? (cb[node.path].apply(cb,args)) : (cb[node.path]());
230
+ } else {
231
+ // check if it is a method?
232
+ ret = args ? (cb.apply(node,args)) : (cb.call(node));
233
+ };
234
+ };
235
+
236
+ if (node.times && --node.times <= 0) {
237
+ prev.next = node.next;
238
+ node.listener = null;
239
+ };
240
+ };
241
+ return;
242
+ };
243
+
244
+ // method for registering a listener on object
245
+ Imba.listen = function (obj,event,listener,path){
246
+ var $1;
247
+ var cbs,list,tail;
248
+ cbs = obj.__listeners__ || (obj.__listeners__ = {});
249
+ list = cbs[($1 = event)] || (cbs[$1] = {});
250
+ tail = list.tail || (list.tail = (list.next = {}));
251
+ tail.listener = listener;
252
+ tail.path = path;
253
+ list.tail = tail.next = {};
254
+ return tail;
255
+ };
256
+
257
+ Imba.once = function (obj,event,listener){
258
+ var tail = Imba.listen(obj,event,listener);
259
+ tail.times = 1;
260
+ return tail;
261
+ };
262
+
263
+ Imba.unlisten = function (obj,event,cb,meth){
264
+ var node,prev;
265
+ var meta = obj.__listeners__;
266
+ if (!(meta)) { return };
267
+
268
+ if (node = meta[event]) {
269
+ while ((prev = node) && (node = node.next)){
270
+ if (node == cb || node.listener == cb) {
271
+ prev.next = node.next;
272
+ // check for correct path as well?
273
+ node.listener = null;
274
+ break;
275
+ };
276
+ };
277
+ };
278
+ return;
279
+ };
280
+
281
+ Imba.emit = function (obj,event,params){
282
+ var cb;
283
+ if (cb = obj.__listeners__) {
284
+ if (cb[event]) { emit__(event,params,cb[event]) };
285
+ if (cb.all) { emit__(event,[event,params],cb.all) }; // and event != 'all'
286
+ };
287
+ return;
288
+ };
289
+
290
+ return Imba.observeProperty = function (observer,key,trigger,target,prev){
291
+ if (prev && typeof prev == 'object') {
292
+ Imba.unlisten(prev,'all',observer,trigger);
293
+ };
294
+ if (target && typeof target == 'object') {
295
+ Imba.listen(target,'all',observer,trigger);
296
+ };
297
+ return this;
298
+ };
299
+
300
+ })()
301
+
302
+ /***/ },
303
+ /* 3 */
304
+ /***/ function(module, exports) {
305
+
306
+ /* WEBPACK VAR INJECTION */(function(global) {(function(){
307
+ function idx$(a,b){
308
+ return (b && b.indexOf) ? b.indexOf(a) : [].indexOf.call(a,b);
309
+ };
310
+
311
+
312
+ var raf; // very simple raf polyfill
313
+ raf || (raf = global.requestAnimationFrame);
314
+ raf || (raf = global.webkitRequestAnimationFrame);
315
+ raf || (raf = global.mozRequestAnimationFrame);
316
+ raf || (raf = function(blk) { return setTimeout(blk,1000 / 60); });
317
+
318
+ Imba.tick = function (d){
319
+ if (this._scheduled) { raf(Imba.ticker()) };
320
+ Imba.Scheduler.willRun();
321
+ this.emit(this,'tick',[d]);
322
+ Imba.Scheduler.didRun();
323
+ return;
324
+ };
325
+
326
+ Imba.ticker = function (){
327
+ var self = this;
328
+ return self._ticker || (self._ticker = function(e) { return self.tick(e); });
329
+ };
330
+
331
+ /*
332
+
333
+ Global alternative to requestAnimationFrame. Schedule a target
334
+ to tick every frame. You can specify which method to call on the
335
+ target (defaults to tick).
336
+
337
+ */
338
+
339
+ Imba.schedule = function (target,method){
340
+ if(method === undefined) method = 'tick';
341
+ this.listen(this,'tick',target,method);
342
+ // start scheduling now if this was the first one
343
+ if (!this._scheduled) {
344
+ this._scheduled = true;
345
+ raf(Imba.ticker());
346
+ };
347
+ return this;
348
+ };
349
+
350
+ /*
351
+
352
+ Unschedule a previously scheduled target
353
+
354
+ */
355
+
356
+ Imba.unschedule = function (target,method){
357
+ this.unlisten(this,'tick',target,method);
358
+ var cbs = this.__listeners__ || (this.__listeners__ = {});
359
+ if (!cbs.tick || !cbs.tick.next || !cbs.tick.next.listener) {
360
+ this._scheduled = false;
361
+ };
362
+ return this;
363
+ };
364
+
365
+ /*
366
+
367
+ Light wrapper around native setTimeout that expects the block / function
368
+ as last argument (instead of first). It also triggers an event to Imba
369
+ after the timeout to let schedulers update (to rerender etc) afterwards.
370
+
371
+ */
372
+
373
+ Imba.setTimeout = function (delay,block){
374
+ return setTimeout(function() {
375
+ block();
376
+ return Imba.Scheduler.markDirty();
377
+ // Imba.emit(Imba,'timeout',[block])
378
+ },delay);
379
+ };
380
+
381
+ /*
382
+
383
+ Light wrapper around native setInterval that expects the block / function
384
+ as last argument (instead of first). It also triggers an event to Imba
385
+ after every interval to let schedulers update (to rerender etc) afterwards.
386
+
387
+ */
388
+
389
+ Imba.setInterval = function (interval,block){
390
+ return setInterval(function() {
391
+ block();
392
+ return Imba.Scheduler.markDirty();
393
+ // Imba.emit(Imba,'interval',[block])
394
+ },interval);
395
+ };
396
+
397
+ /*
398
+ Clear interval with specified id
399
+ */
400
+
401
+ Imba.clearInterval = function (interval){
402
+ return clearInterval(interval);
403
+ };
404
+
405
+ /*
406
+ Clear timeout with specified id
407
+ */
408
+
409
+ Imba.clearTimeout = function (timeout){
410
+ return clearTimeout(timeout);
411
+ };
412
+
413
+ // should add an Imba.run / setImmediate that
414
+ // pushes listener onto the tick-queue with times - once
415
+
416
+
417
+ /*
418
+
419
+ Instances of Imba.Scheduler manages when to call `tick()` on their target,
420
+ at a specified framerate or when certain events occur. Root-nodes in your
421
+ applications will usually have a scheduler to make sure they rerender when
422
+ something changes. It is also possible to make inner components use their
423
+ own schedulers to control when they render.
424
+
425
+ @iname scheduler
426
+
427
+ */
428
+
429
+ Imba.Scheduler = function Scheduler(target){
430
+ var self = this;
431
+ self._target = target;
432
+ self._marked = false;
433
+ self._active = false;
434
+ self._marker = function() { return self.mark(); };
435
+ self._ticker = function(e) { return self.tick(e); };
436
+
437
+ self._events = true;
438
+ self._fps = 1;
439
+
440
+ self._dt = 0;
441
+ self._timestamp = 0;
442
+ self._ticks = 0;
443
+ self._flushes = 0;
444
+ };
445
+
446
+ Imba.Scheduler.markDirty = function (){
447
+ this._dirty = true;
448
+ return this;
449
+ };
450
+
451
+ Imba.Scheduler.isDirty = function (){
452
+ return !(!this._dirty);
453
+ };
454
+
455
+ Imba.Scheduler.willRun = function (){
456
+ return this._active = true;
457
+ };
458
+
459
+ Imba.Scheduler.didRun = function (){
460
+ this._active = false;
461
+ return this._dirty = false;
462
+ };
463
+
464
+ Imba.Scheduler.isActive = function (){
465
+ return !(!this._active);
466
+ };
467
+
468
+ /*
469
+ Create a new Imba.Scheduler for specified target
470
+ @return {Imba.Scheduler}
471
+ */
472
+
473
+ /*
474
+ Check whether the current scheduler is active or not
475
+ @return {bool}
476
+ */
477
+
478
+ Imba.Scheduler.prototype.active = function (){
479
+ return this._active;
480
+ };
481
+
482
+ /*
483
+ Delta time between the two last ticks
484
+ @return {Number}
485
+ */
486
+
487
+ Imba.Scheduler.prototype.dt = function (){
488
+ return this._dt;
489
+ };
490
+
491
+ /*
492
+ Configure the scheduler
493
+ @return {self}
494
+ */
495
+
496
+ Imba.Scheduler.prototype.configure = function (pars){
497
+ if(!pars||pars.constructor !== Object) pars = {};
498
+ var fps = pars.fps !== undefined ? pars.fps : 1;
499
+ var events = pars.events !== undefined ? pars.events : true;
500
+ if (events != null) { this._events = events };
501
+ if (fps != null) { this._fps = fps };
502
+ return this;
503
+ };
504
+
505
+ /*
506
+ Mark the scheduler as dirty. This will make sure that
507
+ the scheduler calls `target.tick` on the next frame
508
+ @return {self}
509
+ */
510
+
511
+ Imba.Scheduler.prototype.mark = function (){
512
+ this._marked = true;
513
+ return this;
514
+ };
515
+
516
+ /*
517
+ Instantly trigger target.tick and mark scheduler as clean (not dirty/marked).
518
+ This is called implicitly from tick, but can also be called manually if you
519
+ really want to force a tick without waiting for the next frame.
520
+ @return {self}
521
+ */
522
+
523
+ Imba.Scheduler.prototype.flush = function (){
524
+ this._marked = false;
525
+ this._flushes++;
526
+ this._target.tick();
527
+ return this;
528
+ };
529
+
530
+ /*
531
+ @fixme this expects raf to run at 60 fps
532
+
533
+ Called automatically on every frame while the scheduler is active.
534
+ It will only call `target.tick` if the scheduler is marked dirty,
535
+ or when according to @fps setting.
536
+
537
+ If you have set up a scheduler with an fps of 1, tick will still be
538
+ called every frame, but `target.tick` will only be called once every
539
+ second, and it will *make sure* each `target.tick` happens in separate
540
+ seconds according to Date. So if you have a node that renders a clock
541
+ based on Date.now (or something similar), you can schedule it with 1fps,
542
+ never needing to worry about two ticks happening within the same second.
543
+ The same goes for 4fps, 10fps etc.
544
+
545
+ @protected
546
+ @return {self}
547
+ */
548
+
549
+ Imba.Scheduler.prototype.tick = function (delta){
550
+ this._ticks++;
551
+ this._dt = delta;
552
+
553
+ var fps = this._fps;
554
+
555
+ if (fps == 60) {
556
+ this._marked = true;
557
+ } else if (fps == 30) {
558
+ if (this._ticks % 2) { this._marked = true };
559
+ } else if (fps) {
560
+ // if it is less round - we trigger based
561
+ // on date, for consistent rendering.
562
+ // ie, if you want to render every second
563
+ // it is important that no two renders
564
+ // happen during the same second (according to Date)
565
+ var period = ((60 / fps) / 60) * 1000;
566
+ var beat = Math.floor(Date.now() / period);
567
+
568
+ if (this._beat != beat) {
569
+ this._beat = beat;
570
+ this._marked = true;
571
+ };
572
+ };
573
+
574
+ if (this._marked || (this._events && Imba.Scheduler.isDirty())) this.flush();
575
+ // reschedule if @active
576
+ return this;
577
+ };
578
+
579
+ /*
580
+ Start the scheduler if it is not already active.
581
+ **While active**, the scheduler will override `target.commit`
582
+ to do nothing. By default Imba.tag#commit calls render, so
583
+ that rendering is cascaded through to children when rendering
584
+ a node. When a scheduler is active (for a node), Imba disables
585
+ this automatic rendering.
586
+ */
587
+
588
+ Imba.Scheduler.prototype.activate = function (){
589
+ if (!this._active) {
590
+ this._active = true;
591
+ // override target#commit while this is active
592
+ this._commit = this._target.commit;
593
+ this._target.commit = function() { return this; };
594
+ Imba.schedule(this);
595
+ if (this._events) { Imba.listen(Imba,'event',this,'onevent') };
596
+ this._target && this._target.flag && this._target.flag('scheduled_');
597
+ this.tick(0); // start ticking
598
+ };
599
+ return this;
600
+ };
601
+
602
+ /*
603
+ Stop the scheduler if it is active.
604
+ */
605
+
606
+ Imba.Scheduler.prototype.deactivate = function (){
607
+ if (this._active) {
608
+ this._active = false;
609
+ this._target.commit = this._commit;
610
+ Imba.unschedule(this);
611
+ Imba.unlisten(Imba,'event',this);
612
+ this._target && this._target.unflag && this._target.unflag('scheduled_');
613
+ };
614
+ return this;
615
+ };
616
+
617
+ Imba.Scheduler.prototype.track = function (){
618
+ return this._marker;
619
+ };
620
+
621
+ Imba.Scheduler.prototype.onevent = function (event){
622
+ var $1;
623
+ if (this._marked) { return this };
624
+
625
+ if (this._events instanceof Function) {
626
+ if (this._events(event)) this.mark();
627
+ } else if (this._events instanceof Array) {
628
+ if (idx$(($1 = event) && $1.type && $1.type(),this._events) >= 0) this.mark();
629
+ } else if (this._events) {
630
+ if (event._responder) this.mark();
631
+ };
632
+ return this;
633
+ };
634
+ return Imba.Scheduler;
635
+
636
+ })()
637
+ /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
638
+
639
+ /***/ },
640
+ /* 4 */
641
+ /***/ function(module, exports) {
642
+
643
+ (function(){
644
+ function idx$(a,b){
645
+ return (b && b.indexOf) ? b.indexOf(a) : [].indexOf.call(a,b);
646
+ };
647
+
648
+ Imba.static = function (items,nr){
649
+ items.static = nr;
650
+ return items;
651
+ };
652
+
653
+ /*
654
+ This is the baseclass that all tags in imba inherit from.
655
+ @iname node
656
+ */
657
+
658
+ Imba.Tag = function Tag(dom){
659
+ this.setDom(dom);
660
+ };
661
+
662
+ Imba.Tag.createNode = function (){
663
+ throw "Not implemented";
664
+ };
665
+
666
+ Imba.Tag.build = function (){
667
+ return new this(this.createNode());
668
+ };
669
+
670
+ Imba.Tag.prototype.object = function(v){ return this._object; }
671
+ Imba.Tag.prototype.setObject = function(v){ this._object = v; return this; };
672
+
673
+ Imba.Tag.prototype.dom = function (){
674
+ return this._dom;
675
+ };
676
+
677
+ Imba.Tag.prototype.setDom = function (dom){
678
+ dom._tag = this;
679
+ this._dom = dom;
680
+ return this;
681
+ };
682
+
683
+ /*
684
+ Setting references for tags like
685
+ `<div@header>` will compile to `tag('div').setRef('header',this).end()`
686
+ By default it adds the reference as a className to the tag.
687
+ @return {self}
688
+ */
689
+
690
+ Imba.Tag.prototype.setRef = function (ref,ctx){
691
+ this.flag(this._ref = ref);
692
+ return this;
693
+ };
694
+
695
+ /*
696
+ Method that is called by the compiled tag-chains, for
697
+ binding events on tags to methods etc.
698
+ `<a :tap=fn>` compiles to `tag('a').setHandler('tap',fn,this).end()`
699
+ where this refers to the context in which the tag is created.
700
+ @return {self}
701
+ */
702
+
703
+ Imba.Tag.prototype.setHandler = function (event,handler,ctx){
704
+ var key = 'on' + event;
705
+
706
+ if (handler instanceof Function) {
707
+ this[key] = handler;
708
+ } else if (handler instanceof Array) {
709
+ var fn = handler.shift();
710
+ this[key] = function(e) { return ctx[fn].apply(ctx,handler.concat(e)); };
711
+ } else {
712
+ this[key] = function(e) { return ctx[handler](e); };
713
+ };
714
+ return this;
715
+ };
716
+
717
+ Imba.Tag.prototype.setId = function (id){
718
+ this.dom().id = id;
719
+ return this;
720
+ };
721
+
722
+ Imba.Tag.prototype.id = function (){
723
+ return this.dom().id;
724
+ };
725
+
726
+ /*
727
+ Adds a new attribute or changes the value of an existing attribute
728
+ on the specified tag. If the value is null or false, the attribute
729
+ will be removed.
730
+ @return {self}
731
+ */
732
+
733
+ Imba.Tag.prototype.setAttribute = function (name,value){
734
+ // should this not return self?
735
+ var old = this.dom().getAttribute(name);
736
+
737
+ if (old == value) {
738
+ return value;
739
+ } else if (value != null && value !== false) {
740
+ return this.dom().setAttribute(name,value);
741
+ } else {
742
+ return this.dom().removeAttribute(name);
743
+ };
744
+ };
745
+
746
+ /*
747
+ removes an attribute from the specified tag
748
+ */
749
+
750
+ Imba.Tag.prototype.removeAttribute = function (name){
751
+ return this.dom().removeAttribute(name);
752
+ };
753
+
754
+ /*
755
+ returns the value of an attribute on the tag.
756
+ If the given attribute does not exist, the value returned
757
+ will either be null or "" (the empty string)
758
+ */
759
+
760
+ Imba.Tag.prototype.getAttribute = function (name){
761
+ return this.dom().getAttribute(name);
762
+ };
763
+
764
+ /*
765
+ Override this to provide special wrapping etc.
766
+ @return {self}
767
+ */
768
+
769
+ Imba.Tag.prototype.setContent = function (content,type){
770
+ this.setChildren(content,type);
771
+ return this;
772
+ };
773
+
774
+ /*
775
+ Set the children of node. type param is optional,
776
+ and should only be used by Imba when compiling tag trees.
777
+ @return {self}
778
+ */
779
+
780
+ Imba.Tag.prototype.setChildren = function (nodes,type){
781
+ throw "Not implemented";
782
+ };
783
+
784
+ /*
785
+ Get text of node. Uses textContent behind the scenes (not innerText)
786
+ [https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent]()
787
+ @return {string} inner text of node
788
+ */
789
+
790
+ Imba.Tag.prototype.text = function (v){
791
+ return this._dom.textContent;
792
+ };
793
+
794
+ /*
795
+ Set text of node. Uses textContent behind the scenes (not innerText)
796
+ [https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent]()
797
+ */
798
+
799
+ Imba.Tag.prototype.setText = function (txt){
800
+ this._empty = false;
801
+ this._dom.textContent = txt == null ? (txt = "") : (txt);
802
+ return this;
803
+ };
804
+
805
+
806
+ /*
807
+ Method for getting and setting data-attributes. When called with zero
808
+ arguments it will return the actual dataset for the tag.
809
+
810
+ var node = <div data-name='hello'>
811
+ # get the whole dataset
812
+ node.dataset # {name: 'hello'}
813
+ # get a single value
814
+ node.dataset('name') # 'hello'
815
+ # set a single value
816
+ node.dataset('name','newname') # self
817
+
818
+
819
+ */
820
+
821
+ Imba.Tag.prototype.dataset = function (key,val){
822
+ throw "Not implemented";
823
+ };
824
+
825
+ /*
826
+ Empty placeholder. Override to implement custom render behaviour.
827
+ Works much like the familiar render-method in React.
828
+ @return {self}
829
+ */
830
+
831
+ Imba.Tag.prototype.render = function (){
832
+ return this;
833
+ };
834
+
835
+ /*
836
+ Called implicitly through Imba.Tag#end, upon creating a tag. All
837
+ properties will have been set before build is called, including
838
+ setContent.
839
+ @return {self}
840
+ */
841
+
842
+ Imba.Tag.prototype.build = function (){
843
+ this.render();
844
+ return this;
845
+ };
846
+
847
+ /*
848
+ Called implicitly through Imba.Tag#end, for tags that are part of
849
+ a tag tree (that are rendered several times).
850
+ @return {self}
851
+ */
852
+
853
+ Imba.Tag.prototype.commit = function (){
854
+ this.render();
855
+ return this;
856
+ };
857
+
858
+ /*
859
+
860
+ Called by the tag-scheduler (if this tag is scheduled)
861
+ By default it will call this.render. Do not override unless
862
+ you really understand it.
863
+
864
+ */
865
+
866
+ Imba.Tag.prototype.tick = function (){
867
+ this.render();
868
+ return this;
869
+ };
870
+
871
+ /*
872
+
873
+ A very important method that you will practically never manually.
874
+ The tag syntax of Imba compiles to a chain of setters, which always
875
+ ends with .end. `<a.large>` compiles to `tag('a').flag('large').end()`
876
+
877
+ You are highly adviced to not override its behaviour. The first time
878
+ end is called it will mark the tag as built and call Imba.Tag#build,
879
+ and call Imba.Tag#commit on subsequent calls.
880
+ @return {self}
881
+ */
882
+
883
+ Imba.Tag.prototype.end = function (){
884
+ if (this._built) {
885
+ this.commit();
886
+ } else {
887
+ this._built = true;
888
+ this.build();
889
+ };
890
+ return this;
891
+ };
892
+
893
+ /*
894
+ This is called instead of Imba.Tag#end for `<self>` tag chains.
895
+ Defaults to noop
896
+ @return {self}
897
+ */
898
+
899
+ Imba.Tag.prototype.synced = function (){
900
+ return this;
901
+ };
902
+
903
+ // called when the node is awakened in the dom - either automatically
904
+ // upon attachment to the dom-tree, or the first time imba needs the
905
+ // tag for a domnode that has been rendered on the server
906
+ Imba.Tag.prototype.awaken = function (){
907
+ return this;
908
+ };
909
+
910
+ /*
911
+ List of flags for this node.
912
+ */
913
+
914
+ Imba.Tag.prototype.flags = function (){
915
+ return this._dom.classList;
916
+ };
917
+
918
+ /*
919
+ Add speficied flag to current node.
920
+ If a second argument is supplied, it will be coerced into a Boolean,
921
+ and used to indicate whether we should remove the flag instead.
922
+ @return {self}
923
+ */
924
+
925
+ Imba.Tag.prototype.flag = function (name,toggler){
926
+ // it is most natural to treat a second undefined argument as a no-switch
927
+ // so we need to check the arguments-length
928
+ if (arguments.length == 2 && !(toggler)) {
929
+ this._dom.classList.remove(name);
930
+ } else {
931
+ this._dom.classList.add(name);
932
+ };
933
+ return this;
934
+ };
935
+
936
+ /*
937
+ Remove specified flag from node
938
+ @return {self}
939
+ */
940
+
941
+ Imba.Tag.prototype.unflag = function (name){
942
+ this._dom.classList.remove(name);
943
+ return this;
944
+ };
945
+
946
+ /*
947
+ Toggle specified flag on node
948
+ @return {self}
949
+ */
950
+
951
+ Imba.Tag.prototype.toggleFlag = function (name){
952
+ this._dom.classList.toggle(name);
953
+ return this;
954
+ };
955
+
956
+ /*
957
+ Check whether current node has specified flag
958
+ @return {bool}
959
+ */
960
+
961
+ Imba.Tag.prototype.hasFlag = function (name){
962
+ return this._dom.classList.contains(name);
963
+ };
964
+
965
+ /*
966
+ Get the scheduler for this node. A new scheduler will be created
967
+ if it does not already exist.
968
+
969
+ @return {Imba.Scheduler}
970
+ */
971
+
972
+ Imba.Tag.prototype.scheduler = function (){
973
+ return this._scheduler == null ? (this._scheduler = new Imba.Scheduler(this)) : (this._scheduler);
974
+ };
975
+
976
+ /*
977
+
978
+ Shorthand to start scheduling a node. The method will basically
979
+ proxy the arguments through to scheduler.configure, and then
980
+ activate the scheduler.
981
+
982
+ @return {self}
983
+ */
984
+
985
+ Imba.Tag.prototype.schedule = function (options){
986
+ if(options === undefined) options = {};
987
+ this.scheduler().configure(options).activate();
988
+ return this;
989
+ };
990
+
991
+ /*
992
+ Shorthand for deactivating scheduler (if tag has one).
993
+ @deprecated
994
+ */
995
+
996
+ Imba.Tag.prototype.unschedule = function (){
997
+ if (this._scheduler) { this.scheduler().deactivate() };
998
+ return this;
999
+ };
1000
+
1001
+
1002
+ /*
1003
+ Get the parent of current node
1004
+ @return {Imba.Tag}
1005
+ */
1006
+
1007
+ Imba.Tag.prototype.parent = function (){
1008
+ return tag$wrap(this.dom().parentNode);
1009
+ };
1010
+
1011
+ /*
1012
+ Shorthand for console.log on elements
1013
+ @return {self}
1014
+ */
1015
+
1016
+ Imba.Tag.prototype.log = function (){
1017
+ var $0 = arguments, i = $0.length;
1018
+ var args = new Array(i>0 ? i : 0);
1019
+ while(i>0) args[i-1] = $0[--i];
1020
+ args.unshift(console);
1021
+ Function.prototype.call.apply(console.log,args);
1022
+ return this;
1023
+ };
1024
+
1025
+ Imba.Tag.prototype.css = function (key,val){
1026
+ if (key instanceof Object) {
1027
+ for (var i = 0, keys = Object.keys(key), l = keys.length; i < l; i++){
1028
+ this.css(keys[i],key[keys[i]]);
1029
+ };
1030
+ } else if (val == null) {
1031
+ this.dom().style.removeProperty(key);
1032
+ } else if (val == undefined) {
1033
+ return this.dom().style[key];
1034
+ } else {
1035
+ if ((typeof val=='number'||val instanceof Number) && key.match(/width|height|left|right|top|bottom/)) {
1036
+ val = val + "px";
1037
+ };
1038
+ this.dom().style[key] = val;
1039
+ };
1040
+ return this;
1041
+ };
1042
+
1043
+ Imba.Tag.prototype.setTransform = function (value){
1044
+ this.css('transform',value);
1045
+ return this;
1046
+ };
1047
+
1048
+ Imba.Tag.prototype.transform = function (){
1049
+ return this.css('transform');
1050
+ };
1051
+
1052
+
1053
+ Imba.Tag.prototype.initialize = Imba.Tag;
1054
+
1055
+ HTML_TAGS = "a abbr address area article aside audio b base bdi bdo big blockquote body br button canvas caption cite code col colgroup data datalist dd del details dfn div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 head header hr html i iframe img input ins kbd keygen label legend li link main map mark menu menuitem meta meter nav noscript object ol optgroup option output p param pre progress q rp rt ruby s samp script section select small source span strong style sub summary sup table tbody td textarea tfoot th thead time title tr track u ul var video wbr".split(" ");
1056
+ HTML_TAGS_UNSAFE = "article aside header section".split(" ");
1057
+ SVG_TAGS = "circle defs ellipse g line linearGradient mask path pattern polygon polyline radialGradient rect stop svg text tspan".split(" ");
1058
+
1059
+
1060
+ function extender(obj,sup){
1061
+ for (var i = 0, keys = Object.keys(sup), l = keys.length; i < l; i++){
1062
+ obj[($1 = keys[i])] == null ? (obj[$1] = sup[keys[i]]) : (obj[$1]);
1063
+ };
1064
+
1065
+ obj.prototype = Object.create(sup.prototype);
1066
+ obj.__super__ = obj.prototype.__super__ = sup.prototype;
1067
+ obj.prototype.initialize = obj.prototype.constructor = obj;
1068
+ if (sup.inherit) { sup.inherit(obj) };
1069
+ return obj;
1070
+ };
1071
+
1072
+ function Tag(){
1073
+ return function(dom) {
1074
+ this.setDom(dom);
1075
+ return this;
1076
+ };
1077
+ };
1078
+
1079
+ function TagSpawner(type){
1080
+ return function() { return type.build(); };
1081
+ };
1082
+
1083
+ Imba.Tags = function Tags(){
1084
+ this;
1085
+ };
1086
+
1087
+ Imba.Tags.prototype.__clone = function (ns){
1088
+ var clone = Object.create(this);
1089
+ clone._parent = this;
1090
+ return clone;
1091
+ };
1092
+
1093
+ Imba.Tags.prototype.defineNamespace = function (name){
1094
+ var clone = Object.create(this);
1095
+ clone._parent = this;
1096
+ clone._ns = name;
1097
+ this[name.toUpperCase()] = clone;
1098
+ return clone;
1099
+ };
1100
+
1101
+ Imba.Tags.prototype.baseType = function (name){
1102
+ return idx$(name,HTML_TAGS) >= 0 ? ('htmlelement') : ('div');
1103
+ };
1104
+
1105
+ Imba.Tags.prototype.defineTag = function (name,supr,body){
1106
+ if(body==undefined && typeof supr == 'function') body = supr,supr = '';
1107
+ if(supr==undefined) supr = '';
1108
+ supr || (supr = this.baseType(name));
1109
+ var supertype = this[supr];
1110
+ var tagtype = Tag();
1111
+ var norm = name.replace(/\-/g,'_');
1112
+
1113
+
1114
+ tagtype._name = name;
1115
+ extender(tagtype,supertype);
1116
+
1117
+ if (name[0] == '#') {
1118
+ this[name] = tagtype;
1119
+ Imba.SINGLETONS[name.slice(1)] = tagtype;
1120
+ } else {
1121
+ this[name] = tagtype;
1122
+ this['$' + norm] = TagSpawner(tagtype);
1123
+ };
1124
+
1125
+ if (body) {
1126
+ if (body.length == 2) {
1127
+ // create clone
1128
+ if (!tagtype.hasOwnProperty('TAGS')) {
1129
+ tagtype.TAGS = (supertype.TAGS || this).__clone();
1130
+ };
1131
+ };
1132
+
1133
+ body.call(tagtype,tagtype,tagtype.TAGS || this);
1134
+ };
1135
+
1136
+ return tagtype;
1137
+ };
1138
+
1139
+ Imba.Tags.prototype.defineSingleton = function (name,supr,body){
1140
+ return this.defineTag(name,supr,body);
1141
+ };
1142
+
1143
+ Imba.Tags.prototype.extendTag = function (name,supr,body){
1144
+ if(body==undefined && typeof supr == 'function') body = supr,supr = '';
1145
+ if(supr==undefined) supr = '';
1146
+ var klass = ((typeof name=='string'||name instanceof String) ? (this[name]) : (name));
1147
+ // allow for private tags here as well?
1148
+ if (body) { body && body.call(klass,klass,klass.prototype) };
1149
+ return klass;
1150
+ };
1151
+
1152
+
1153
+ Imba.TAGS = new Imba.Tags();
1154
+ Imba.TAGS.element = Imba.Tag;
1155
+
1156
+ var svg = Imba.TAGS.defineNamespace('svg');
1157
+
1158
+ svg.baseType = function (name){
1159
+ return 'svgelement';
1160
+ };
1161
+
1162
+
1163
+ Imba.SINGLETONS = {};
1164
+
1165
+
1166
+ Imba.defineTag = function (name,supr,body){
1167
+ if(body==undefined && typeof supr == 'function') body = supr,supr = '';
1168
+ if(supr==undefined) supr = '';
1169
+ return Imba.TAGS.defineTag(name,supr,body);
1170
+ };
1171
+
1172
+ Imba.defineSingletonTag = function (id,supr,body){
1173
+ if(body==undefined && typeof supr == 'function') body = supr,supr = 'div';
1174
+ if(supr==undefined) supr = 'div';
1175
+ return Imba.TAGS.defineTag(this.name(),supr,body);
1176
+ };
1177
+
1178
+ Imba.extendTag = function (name,body){
1179
+ return Imba.TAGS.extendTag(name,body);
1180
+ };
1181
+
1182
+ Imba.tag = function (name){
1183
+ var typ = Imba.TAGS[name];
1184
+ if (!(typ)) { throw new Error(("tag " + name + " is not defined")) };
1185
+ return new typ(typ.createNode());
1186
+ };
1187
+
1188
+ Imba.tagWithId = function (name,id){
1189
+ var typ = Imba.TAGS[name];
1190
+ if (!(typ)) { throw new Error(("tag " + name + " is not defined")) };
1191
+ var dom = typ.createNode();
1192
+ dom.id = id;
1193
+ return new typ(dom);
1194
+ };
1195
+
1196
+ // TODO: Can we move these out and into dom.imba in a clean way?
1197
+ // These methods depends on Imba.document.getElementById
1198
+
1199
+ Imba.getTagSingleton = function (id){
1200
+ var klass;
1201
+ var dom,node;
1202
+
1203
+ if (klass = Imba.SINGLETONS[id]) {
1204
+ if (klass && klass.Instance) { return klass.Instance };
1205
+
1206
+ // no instance - check for element
1207
+ if (dom = Imba.document().getElementById(id)) {
1208
+ // we have a live instance - when finding it through a selector we should awake it, no?
1209
+ // console.log('creating the singleton from existing node in dom?',id,type)
1210
+ node = klass.Instance = new klass(dom);
1211
+ node.awaken(dom); // should only awaken
1212
+ return node;
1213
+ };
1214
+
1215
+ dom = klass.createNode();
1216
+ dom.id = id;
1217
+ node = klass.Instance = new klass(dom);
1218
+ node.end().awaken(dom);
1219
+ return node;
1220
+ } else if (dom = Imba.document().getElementById(id)) {
1221
+ return Imba.getTagForDom(dom);
1222
+ };
1223
+ };
1224
+
1225
+ var svgSupport = typeof SVGElement !== 'undefined';
1226
+
1227
+ Imba.getTagForDom = function (dom){
1228
+ var m;
1229
+ if (!(dom)) { return null };
1230
+ if (dom._dom) { return dom }; // could use inheritance instead
1231
+ if (dom._tag) { return dom._tag };
1232
+ if (!dom.nodeName) { return null };
1233
+
1234
+ var ns = null;
1235
+ var id = dom.id;
1236
+ var type = dom.nodeName.toLowerCase();
1237
+ var tags = Imba.TAGS;
1238
+ var native$ = type;
1239
+ var cls = dom.className;
1240
+
1241
+ if (id && Imba.SINGLETONS[id]) {
1242
+ // FIXME control that it is the same singleton?
1243
+ // might collide -- not good?
1244
+ return Imba.getTagSingleton(id);
1245
+ };
1246
+ // look for id - singleton
1247
+
1248
+ // need better test here
1249
+ if (svgSupport && (dom instanceof SVGElement)) {
1250
+ ns = "svg";
1251
+ cls = dom.className.baseVal;
1252
+ tags = tags.SVG;
1253
+ };
1254
+
1255
+ var spawner;
1256
+
1257
+ if (cls) {
1258
+ // there can be several matches here - should choose the last
1259
+ // should fall back to less specific later? - otherwise things may fail
1260
+ // TODO rework this
1261
+ if (m = cls.match(/\b_([a-z\-]+)\b(?!\s*_[a-z\-]+)/)) {
1262
+ type = m[1]; // .replace(/-/g,'_')
1263
+ };
1264
+
1265
+ if (m = cls.match(/\b([A-Z\-]+)_\b/)) {
1266
+ ns = m[1];
1267
+ };
1268
+ };
1269
+
1270
+
1271
+ spawner = tags[type] || tags[native$];
1272
+ return spawner ? (new spawner(dom).awaken(dom)) : (null);
1273
+ };
1274
+
1275
+ tag$ = Imba.TAGS;
1276
+ t$ = Imba.tag;
1277
+ tc$ = Imba.tagWithFlags;
1278
+ ti$ = Imba.tagWithId;
1279
+ tic$ = Imba.tagWithIdAndFlags;
1280
+ id$ = Imba.getTagSingleton;
1281
+ return tag$wrap = Imba.getTagForDom;
1282
+
1283
+
1284
+ })()
1285
+
1286
+ /***/ },
1287
+ /* 5 */
1288
+ /***/ function(module, exports) {
1289
+
1290
+ (function(){
1291
+ function iter$(a){ return a ? (a.toArray ? a.toArray() : a) : []; };
1292
+
1293
+ Imba.document = function (){
1294
+ return window.document;
1295
+ };
1296
+
1297
+ /*
1298
+ Returns the body element wrapped in an Imba.Tag
1299
+ */
1300
+
1301
+ Imba.root = function (){
1302
+ return tag$wrap(Imba.document().body);
1303
+ };
1304
+
1305
+ tag$.defineTag('htmlelement', 'element', function(tag){
1306
+
1307
+ /*
1308
+ Called when a tag type is being subclassed.
1309
+ */
1310
+
1311
+ tag.inherit = function (child){
1312
+ child.prototype._empty = true;
1313
+ child._protoDom = null;
1314
+
1315
+ if (this._nodeType) {
1316
+ child._nodeType = this._nodeType;
1317
+
1318
+ var className = "_" + child._name.replace(/_/g,'-');
1319
+ if (child._name[0] != '#') { return child._classes = this._classes.concat(className) };
1320
+ } else {
1321
+ child._nodeType = child._name;
1322
+ return child._classes = [];
1323
+ };
1324
+ };
1325
+
1326
+ tag.buildNode = function (){
1327
+ var dom = Imba.document().createElement(this._nodeType);
1328
+ var cls = this._classes.join(" ");
1329
+ if (cls) { dom.className = cls };
1330
+ return dom;
1331
+ };
1332
+
1333
+ tag.createNode = function (){
1334
+ var proto = (this._protoDom || (this._protoDom = this.buildNode()));
1335
+ return proto.cloneNode(false);
1336
+ };
1337
+
1338
+ tag.dom = function (){
1339
+ return this._protoDom || (this._protoDom = this.buildNode());
1340
+ };
1341
+
1342
+ tag.prototype.id = function(v){ return this.getAttribute('id'); }
1343
+ tag.prototype.setId = function(v){ this.setAttribute('id',v); return this; };
1344
+ tag.prototype.tabindex = function(v){ return this.getAttribute('tabindex'); }
1345
+ tag.prototype.setTabindex = function(v){ this.setAttribute('tabindex',v); return this; };
1346
+ tag.prototype.title = function(v){ return this.getAttribute('title'); }
1347
+ tag.prototype.setTitle = function(v){ this.setAttribute('title',v); return this; };
1348
+ tag.prototype.role = function(v){ return this.getAttribute('role'); }
1349
+ tag.prototype.setRole = function(v){ this.setAttribute('role',v); return this; };
1350
+
1351
+ tag.prototype.width = function (){
1352
+ return this._dom.offsetWidth;
1353
+ };
1354
+
1355
+ tag.prototype.height = function (){
1356
+ return this._dom.offsetHeight;
1357
+ };
1358
+
1359
+ tag.prototype.setChildren = function (nodes,type){
1360
+ this._empty ? (this.append(nodes)) : (this.empty().append(nodes));
1361
+ this._children = null;
1362
+ return this;
1363
+ };
1364
+
1365
+ /*
1366
+ Set inner html of node
1367
+ */
1368
+
1369
+ tag.prototype.setHtml = function (html){
1370
+ this._dom.innerHTML = html;
1371
+ return this;
1372
+ };
1373
+
1374
+ /*
1375
+ Get inner html of node
1376
+ */
1377
+
1378
+ tag.prototype.html = function (){
1379
+ return this._dom.innerHTML;
1380
+ };
1381
+
1382
+ /*
1383
+ Remove all content inside node
1384
+ */
1385
+
1386
+ tag.prototype.empty = function (){
1387
+ while (this._dom.firstChild){
1388
+ this._dom.removeChild(this._dom.firstChild);
1389
+ };
1390
+ this._children = null;
1391
+ this._empty = true;
1392
+ return this;
1393
+ };
1394
+
1395
+ /*
1396
+ Remove specified child from current node.
1397
+ */
1398
+
1399
+ tag.prototype.remove = function (child){
1400
+ var par = this.dom();
1401
+ var el = child && child.dom();
1402
+ if (el && el.parentNode == par) { par.removeChild(el) };
1403
+ return this;
1404
+ };
1405
+
1406
+ tag.prototype.emit = function (name,pars){
1407
+ if(!pars||pars.constructor !== Object) pars = {};
1408
+ var data = pars.data !== undefined ? pars.data : null;
1409
+ var bubble = pars.bubble !== undefined ? pars.bubble : true;
1410
+ Imba.Events.trigger(name,this,{data: data,bubble: bubble});
1411
+ return this;
1412
+ };
1413
+
1414
+ tag.prototype.dataset = function (key,val){
1415
+ if (key instanceof Object) {
1416
+ for (var i = 0, keys = Object.keys(key), l = keys.length; i < l; i++){
1417
+ this.dataset(keys[i],key[keys[i]]);
1418
+ };
1419
+ return this;
1420
+ };
1421
+
1422
+ if (arguments.length == 2) {
1423
+ this.setAttribute(("data-" + key),val);
1424
+ return this;
1425
+ };
1426
+
1427
+ if (key) {
1428
+ return this.getAttribute(("data-" + key));
1429
+ };
1430
+
1431
+ var dataset = this.dom().dataset;
1432
+
1433
+ if (!(dataset)) {
1434
+ dataset = {};
1435
+ for (var i = 0, ary = iter$(this.dom().attributes), len = ary.length, atr; i < len; i++) {
1436
+ atr = ary[i];
1437
+ if (atr.name.substr(0,5) == 'data-') {
1438
+ dataset[Imba.toCamelCase(atr.name.slice(5))] = atr.value;
1439
+ };
1440
+ };
1441
+ };
1442
+
1443
+ return dataset;
1444
+ };
1445
+
1446
+ /*
1447
+ Get descendants of current node, optionally matching selector
1448
+ @return {Imba.Selector}
1449
+ */
1450
+
1451
+ tag.prototype.find = function (sel){
1452
+ return new Imba.Selector(sel,this);
1453
+ };
1454
+
1455
+ /*
1456
+ Get the first matching child of node
1457
+
1458
+ @return {Imba.Tag}
1459
+ */
1460
+
1461
+ tag.prototype.first = function (sel){
1462
+ return sel ? (this.find(sel).first()) : (tag$wrap(this.dom().firstElementChild));
1463
+ };
1464
+
1465
+ /*
1466
+ Get the last matching child of node
1467
+
1468
+ node.last # returns the last child of node
1469
+ node.last %span # returns the last span inside node
1470
+ node.last do |el| el.text == 'Hi' # return last node with text Hi
1471
+
1472
+ @return {Imba.Tag}
1473
+ */
1474
+
1475
+ tag.prototype.last = function (sel){
1476
+ return sel ? (this.find(sel).last()) : (tag$wrap(this.dom().lastElementChild));
1477
+ };
1478
+
1479
+ /*
1480
+ Get the child at index
1481
+ */
1482
+
1483
+ tag.prototype.child = function (i){
1484
+ return tag$wrap(this.dom().children[i || 0]);
1485
+ };
1486
+
1487
+ tag.prototype.children = function (sel){
1488
+ var nodes = new Imba.Selector(null,this,this._dom.children);
1489
+ return sel ? (nodes.filter(sel)) : (nodes);
1490
+ };
1491
+
1492
+ tag.prototype.orphanize = function (){
1493
+ var par;
1494
+ if (par = this.dom().parentNode) { par.removeChild(this._dom) };
1495
+ return this;
1496
+ };
1497
+
1498
+ tag.prototype.matches = function (sel){
1499
+ var fn;
1500
+ if (sel instanceof Function) {
1501
+ return sel(this);
1502
+ };
1503
+
1504
+ if (sel.query) { sel = sel.query() };
1505
+ if (fn = (this._dom.matches || this._dom.matchesSelector || this._dom.webkitMatchesSelector || this._dom.msMatchesSelector || this._dom.mozMatchesSelector)) {
1506
+ return fn.call(this._dom,sel);
1507
+ };
1508
+ };
1509
+
1510
+ /*
1511
+ Get the first element matching supplied selector / filter
1512
+ traversing upwards, but including the node itself.
1513
+ @return {Imba.Tag}
1514
+ */
1515
+
1516
+ tag.prototype.closest = function (sel){
1517
+ if (!(sel)) { return this.parent() }; // should return self?!
1518
+ var node = this;
1519
+ if (sel.query) { sel = sel.query() };
1520
+
1521
+ while (node){
1522
+ if (node.matches(sel)) { return node };
1523
+ node = node.parent();
1524
+ };
1525
+ return null;
1526
+ };
1527
+
1528
+ /*
1529
+ Get the closest ancestor of node that matches
1530
+ specified selector / matcher.
1531
+
1532
+ @return {Imba.Tag}
1533
+ */
1534
+
1535
+ tag.prototype.up = function (sel){
1536
+ if (!(sel)) { return this.parent() };
1537
+ return this.parent() && this.parent().closest(sel);
1538
+ };
1539
+
1540
+ tag.prototype.path = function (sel){
1541
+ var node = this;
1542
+ var nodes = [];
1543
+ if (sel && sel.query) { sel = sel.query() };
1544
+
1545
+ while (node){
1546
+ if (!(sel) || node.matches(sel)) { nodes.push(node) };
1547
+ node = node.parent();
1548
+ };
1549
+ return nodes;
1550
+ };
1551
+
1552
+ tag.prototype.parents = function (sel){
1553
+ var par = this.parent();
1554
+ return par ? (par.path(sel)) : ([]);
1555
+ };
1556
+
1557
+
1558
+
1559
+ tag.prototype.siblings = function (sel){
1560
+ var par, self = this;
1561
+ if (!(par = this.parent())) { return [] }; // FIXME
1562
+ var ary = this.dom().parentNode.children;
1563
+ var nodes = new Imba.Selector(null,this,ary);
1564
+ return nodes.filter(function(n) { return n != self && (!(sel) || n.matches(sel)); });
1565
+ };
1566
+
1567
+ /*
1568
+ Get the immediately following sibling of node.
1569
+ */
1570
+
1571
+ tag.prototype.next = function (sel){
1572
+ if (sel) {
1573
+ var el = this;
1574
+ while (el = el.next()){
1575
+ if (el.matches(sel)) { return el };
1576
+ };
1577
+ return null;
1578
+ };
1579
+ return tag$wrap(this.dom().nextElementSibling);
1580
+ };
1581
+
1582
+ /*
1583
+ Get the immediately preceeding sibling of node.
1584
+ */
1585
+
1586
+ tag.prototype.prev = function (sel){
1587
+ if (sel) {
1588
+ var el = this;
1589
+ while (el = el.prev()){
1590
+ if (el.matches(sel)) { return el };
1591
+ };
1592
+ return null;
1593
+ };
1594
+ return tag$wrap(this.dom().previousElementSibling);
1595
+ };
1596
+
1597
+ tag.prototype.contains = function (node){
1598
+ return this.dom().contains(node && node._dom || node);
1599
+ };
1600
+
1601
+ tag.prototype.index = function (){
1602
+ var i = 0;
1603
+ var el = this.dom();
1604
+ while (el.previousSibling){
1605
+ el = el.previousSibling;
1606
+ i++;
1607
+ };
1608
+ return i;
1609
+ };
1610
+
1611
+
1612
+ /*
1613
+
1614
+ @deprecated
1615
+ */
1616
+
1617
+ tag.prototype.insert = function (node,pars){
1618
+ if(!pars||pars.constructor !== Object) pars = {};
1619
+ var before = pars.before !== undefined ? pars.before : null;
1620
+ var after = pars.after !== undefined ? pars.after : null;
1621
+ if (after) { before = after.next() };
1622
+ if (node instanceof Array) {
1623
+ node = (tag$.$fragment().setContent(node,0).end());
1624
+ };
1625
+ if (before) {
1626
+ this.dom().insertBefore(node.dom(),before.dom());
1627
+ } else {
1628
+ this.append(node);
1629
+ };
1630
+ return this;
1631
+ };
1632
+
1633
+ /*
1634
+ Focus on current node
1635
+ @return {self}
1636
+ */
1637
+
1638
+ tag.prototype.focus = function (){
1639
+ this.dom().focus();
1640
+ return this;
1641
+ };
1642
+
1643
+ /*
1644
+ Remove focus from current node
1645
+ @return {self}
1646
+ */
1647
+
1648
+ tag.prototype.blur = function (){
1649
+ this.dom().blur();
1650
+ return this;
1651
+ };
1652
+
1653
+ tag.prototype.template = function (){
1654
+ return null;
1655
+ };
1656
+
1657
+ /*
1658
+ @todo Should support multiple arguments like append
1659
+
1660
+ The .prepend method inserts the specified content as the first
1661
+ child of the target node. If the content is already a child of
1662
+ node it will be moved to the start.
1663
+
1664
+ node.prepend <div.top> # prepend node
1665
+ node.prepend "some text" # prepend text
1666
+ node.prepend [<ul>,<ul>] # prepend array
1667
+
1668
+ */
1669
+
1670
+ tag.prototype.prepend = function (item){
1671
+ var first = this._dom.childNodes[0];
1672
+ first ? (this.insertBefore(item,first)) : (this.appendChild(item));
1673
+ return this;
1674
+ };
1675
+
1676
+ /*
1677
+ The .append method inserts the specified content as the last child
1678
+ of the target node. If the content is already a child of node it
1679
+ will be moved to the end.
1680
+
1681
+ # example
1682
+ var root = <div.root>
1683
+ var item = <div.item> "This is an item"
1684
+ root.append item # appends item to the end of root
1685
+
1686
+ root.prepend "some text" # append text
1687
+ root.prepend [<ul>,<ul>] # append array
1688
+ */
1689
+
1690
+ tag.prototype.append = function (item){
1691
+ // possible to append blank
1692
+ // possible to simplify on server?
1693
+ if (!(item)) { return this };
1694
+
1695
+ if (item instanceof Array) {
1696
+ for (var i = 0, ary = iter$(item), len = ary.length, member; i < len; i++) {
1697
+ member = ary[i];
1698
+ member && this.append(member);
1699
+ };
1700
+ } else if ((typeof item=='string'||item instanceof String) || (typeof item=='number'||item instanceof Number)) {
1701
+ var node = Imba.document().createTextNode(item);
1702
+ this._dom.appendChild(node);
1703
+ if (this._empty) { this._empty = false };
1704
+ } else {
1705
+ this._dom.appendChild(item._dom || item);
1706
+ if (this._empty) { this._empty = false };
1707
+ };
1708
+
1709
+ return this;
1710
+ };
1711
+
1712
+ /*
1713
+ Insert a node into the current node (self), before another.
1714
+ The relative node must be a child of current node.
1715
+ */
1716
+
1717
+ tag.prototype.insertBefore = function (node,rel){
1718
+ if ((typeof node=='string'||node instanceof String)) { node = Imba.document().createTextNode(node) };
1719
+ if (node && rel) { this.dom().insertBefore((node._dom || node),(rel._dom || rel)) };
1720
+ return this;
1721
+ };
1722
+
1723
+ /*
1724
+ Append a single item (node or string) to the current node.
1725
+ If supplied item is a string it will automatically. This is used
1726
+ by Imba internally, but will practically never be used explicitly.
1727
+ */
1728
+
1729
+ tag.prototype.appendChild = function (node){
1730
+ if ((typeof node=='string'||node instanceof String)) { node = Imba.document().createTextNode(node) };
1731
+ if (node) { this.dom().appendChild(node._dom || node) };
1732
+ return this;
1733
+ };
1734
+
1735
+ /*
1736
+ Remove a single child from the current node.
1737
+ Used by Imba internally.
1738
+ */
1739
+
1740
+ tag.prototype.removeChild = function (node){
1741
+ if (node) { this.dom().removeChild(node._dom || node) };
1742
+ return this;
1743
+ };
1744
+
1745
+ tag.prototype.toString = function (){
1746
+ return this._dom.toString(); // really?
1747
+ };
1748
+
1749
+ /*
1750
+ @deprecated
1751
+ */
1752
+
1753
+ tag.prototype.classes = function (){
1754
+ console.log('Imba.Tag#classes is deprecated');
1755
+ return this._dom.classList;
1756
+ };
1757
+ });
1758
+
1759
+ return tag$.defineTag('svgelement', 'htmlelement');
1760
+
1761
+ })()
1762
+
1763
+ /***/ },
1764
+ /* 6 */
1765
+ /***/ function(module, exports) {
1766
+
1767
+ (function(){
1768
+
1769
+ // predefine all supported html tags
1770
+ tag$.defineTag('fragment', 'htmlelement', function(tag){
1771
+
1772
+ tag.createNode = function (){
1773
+ return Imba.document().createDocumentFragment();
1774
+ };
1775
+ });
1776
+
1777
+ tag$.defineTag('a', function(tag){
1778
+ tag.prototype.href = function(v){ return this.getAttribute('href'); }
1779
+ tag.prototype.setHref = function(v){ this.setAttribute('href',v); return this; };
1780
+ });
1781
+
1782
+ tag$.defineTag('abbr');
1783
+ tag$.defineTag('address');
1784
+ tag$.defineTag('area');
1785
+ tag$.defineTag('article');
1786
+ tag$.defineTag('aside');
1787
+ tag$.defineTag('audio');
1788
+ tag$.defineTag('b');
1789
+ tag$.defineTag('base');
1790
+ tag$.defineTag('bdi');
1791
+ tag$.defineTag('bdo');
1792
+ tag$.defineTag('big');
1793
+ tag$.defineTag('blockquote');
1794
+ tag$.defineTag('body');
1795
+ tag$.defineTag('br');
1796
+
1797
+ tag$.defineTag('button', function(tag){
1798
+ tag.prototype.autofocus = function(v){ return this.getAttribute('autofocus'); }
1799
+ tag.prototype.setAutofocus = function(v){ this.setAttribute('autofocus',v); return this; };
1800
+ tag.prototype.type = function(v){ return this.getAttribute('type'); }
1801
+ tag.prototype.setType = function(v){ this.setAttribute('type',v); return this; };
1802
+ tag.prototype.disabled = function(v){ return this.getAttribute('disabled'); }
1803
+ tag.prototype.setDisabled = function(v){ this.setAttribute('disabled',v); return this; };
1804
+ });
1805
+
1806
+ tag$.defineTag('canvas', function(tag){
1807
+ tag.prototype.setWidth = function (val){
1808
+ if (this.width() != val) { this.dom().width = val };
1809
+ return this;
1810
+ };
1811
+
1812
+ tag.prototype.setHeight = function (val){
1813
+ if (this.height() != val) { this.dom().height = val };
1814
+ return this;
1815
+ };
1816
+
1817
+ tag.prototype.width = function (){
1818
+ return this.dom().width;
1819
+ };
1820
+
1821
+ tag.prototype.height = function (){
1822
+ return this.dom().height;
1823
+ };
1824
+
1825
+ tag.prototype.context = function (type){
1826
+ if(type === undefined) type = '2d';
1827
+ return this.dom().getContext(type);
1828
+ };
1829
+ });
1830
+
1831
+ tag$.defineTag('caption');
1832
+ tag$.defineTag('cite');
1833
+ tag$.defineTag('code');
1834
+ tag$.defineTag('col');
1835
+ tag$.defineTag('colgroup');
1836
+ tag$.defineTag('data');
1837
+ tag$.defineTag('datalist');
1838
+ tag$.defineTag('dd');
1839
+ tag$.defineTag('del');
1840
+ tag$.defineTag('details');
1841
+ tag$.defineTag('dfn');
1842
+ tag$.defineTag('div');
1843
+ tag$.defineTag('dl');
1844
+ tag$.defineTag('dt');
1845
+ tag$.defineTag('em');
1846
+ tag$.defineTag('embed');
1847
+ tag$.defineTag('fieldset');
1848
+ tag$.defineTag('figcaption');
1849
+ tag$.defineTag('figure');
1850
+ tag$.defineTag('footer');
1851
+
1852
+ tag$.defineTag('form', function(tag){
1853
+ tag.prototype.method = function(v){ return this.getAttribute('method'); }
1854
+ tag.prototype.setMethod = function(v){ this.setAttribute('method',v); return this; };
1855
+ tag.prototype.action = function(v){ return this.getAttribute('action'); }
1856
+ tag.prototype.setAction = function(v){ this.setAttribute('action',v); return this; };
1857
+ });
1858
+
1859
+ tag$.defineTag('h1');
1860
+ tag$.defineTag('h2');
1861
+ tag$.defineTag('h3');
1862
+ tag$.defineTag('h4');
1863
+ tag$.defineTag('h5');
1864
+ tag$.defineTag('h6');
1865
+ tag$.defineTag('head');
1866
+ tag$.defineTag('header');
1867
+ tag$.defineTag('hr');
1868
+ tag$.defineTag('html');
1869
+ tag$.defineTag('i');
1870
+
1871
+ tag$.defineTag('iframe', function(tag){
1872
+ tag.prototype.src = function(v){ return this.getAttribute('src'); }
1873
+ tag.prototype.setSrc = function(v){ this.setAttribute('src',v); return this; };
1874
+ });
1875
+
1876
+ tag$.defineTag('img', function(tag){
1877
+ tag.prototype.src = function(v){ return this.getAttribute('src'); }
1878
+ tag.prototype.setSrc = function(v){ this.setAttribute('src',v); return this; };
1879
+ });
1880
+
1881
+ tag$.defineTag('input', function(tag){
1882
+ // can use attr instead
1883
+ tag.prototype.name = function(v){ return this.getAttribute('name'); }
1884
+ tag.prototype.setName = function(v){ this.setAttribute('name',v); return this; };
1885
+ tag.prototype.type = function(v){ return this.getAttribute('type'); }
1886
+ tag.prototype.setType = function(v){ this.setAttribute('type',v); return this; };
1887
+ tag.prototype.required = function(v){ return this.getAttribute('required'); }
1888
+ tag.prototype.setRequired = function(v){ this.setAttribute('required',v); return this; };
1889
+ tag.prototype.disabled = function(v){ return this.getAttribute('disabled'); }
1890
+ tag.prototype.setDisabled = function(v){ this.setAttribute('disabled',v); return this; };
1891
+ tag.prototype.autofocus = function(v){ return this.getAttribute('autofocus'); }
1892
+ tag.prototype.setAutofocus = function(v){ this.setAttribute('autofocus',v); return this; };
1893
+
1894
+ tag.prototype.value = function (){
1895
+ return this.dom().value;
1896
+ };
1897
+
1898
+ tag.prototype.setValue = function (v){
1899
+ if (v != this.dom().value) { this.dom().value = v };
1900
+ return this;
1901
+ };
1902
+
1903
+ tag.prototype.setPlaceholder = function (v){
1904
+ if (v != this.dom().placeholder) { this.dom().placeholder = v };
1905
+ return this;
1906
+ };
1907
+
1908
+ tag.prototype.placeholder = function (){
1909
+ return this.dom().placeholder;
1910
+ };
1911
+
1912
+ tag.prototype.checked = function (){
1913
+ return this.dom().checked;
1914
+ };
1915
+
1916
+ tag.prototype.setChecked = function (bool){
1917
+ if (bool != this.dom().checked) { this.dom().checked = bool };
1918
+ return this;
1919
+ };
1920
+ });
1921
+
1922
+ tag$.defineTag('ins');
1923
+ tag$.defineTag('kbd');
1924
+ tag$.defineTag('keygen');
1925
+ tag$.defineTag('label');
1926
+ tag$.defineTag('legend');
1927
+ tag$.defineTag('li');
1928
+
1929
+ tag$.defineTag('link', function(tag){
1930
+ tag.prototype.rel = function(v){ return this.getAttribute('rel'); }
1931
+ tag.prototype.setRel = function(v){ this.setAttribute('rel',v); return this; };
1932
+ tag.prototype.type = function(v){ return this.getAttribute('type'); }
1933
+ tag.prototype.setType = function(v){ this.setAttribute('type',v); return this; };
1934
+ tag.prototype.href = function(v){ return this.getAttribute('href'); }
1935
+ tag.prototype.setHref = function(v){ this.setAttribute('href',v); return this; };
1936
+ tag.prototype.media = function(v){ return this.getAttribute('media'); }
1937
+ tag.prototype.setMedia = function(v){ this.setAttribute('media',v); return this; };
1938
+ });
1939
+
1940
+ tag$.defineTag('main');
1941
+ tag$.defineTag('map');
1942
+ tag$.defineTag('mark');
1943
+ tag$.defineTag('menu');
1944
+ tag$.defineTag('menuitem');
1945
+
1946
+ tag$.defineTag('meta', function(tag){
1947
+ tag.prototype.name = function(v){ return this.getAttribute('name'); }
1948
+ tag.prototype.setName = function(v){ this.setAttribute('name',v); return this; };
1949
+ tag.prototype.content = function(v){ return this.getAttribute('content'); }
1950
+ tag.prototype.setContent = function(v){ this.setAttribute('content',v); return this; };
1951
+ tag.prototype.charset = function(v){ return this.getAttribute('charset'); }
1952
+ tag.prototype.setCharset = function(v){ this.setAttribute('charset',v); return this; };
1953
+ });
1954
+
1955
+ tag$.defineTag('meter');
1956
+ tag$.defineTag('nav');
1957
+ tag$.defineTag('noscript');
1958
+ tag$.defineTag('object');
1959
+ tag$.defineTag('ol');
1960
+ tag$.defineTag('optgroup');
1961
+
1962
+ tag$.defineTag('option', function(tag){
1963
+ tag.prototype.value = function(v){ return this.getAttribute('value'); }
1964
+ tag.prototype.setValue = function(v){ this.setAttribute('value',v); return this; };
1965
+ });
1966
+
1967
+ tag$.defineTag('output');
1968
+ tag$.defineTag('p');
1969
+ tag$.defineTag('param');
1970
+ tag$.defineTag('pre');
1971
+ tag$.defineTag('progress');
1972
+ tag$.defineTag('q');
1973
+ tag$.defineTag('rp');
1974
+ tag$.defineTag('rt');
1975
+ tag$.defineTag('ruby');
1976
+ tag$.defineTag('s');
1977
+ tag$.defineTag('samp');
1978
+
1979
+ tag$.defineTag('script', function(tag){
1980
+ tag.prototype.src = function(v){ return this.getAttribute('src'); }
1981
+ tag.prototype.setSrc = function(v){ this.setAttribute('src',v); return this; };
1982
+ tag.prototype.type = function(v){ return this.getAttribute('type'); }
1983
+ tag.prototype.setType = function(v){ this.setAttribute('type',v); return this; };
1984
+ tag.prototype.async = function(v){ return this.getAttribute('async'); }
1985
+ tag.prototype.setAsync = function(v){ this.setAttribute('async',v); return this; };
1986
+ tag.prototype.defer = function(v){ return this.getAttribute('defer'); }
1987
+ tag.prototype.setDefer = function(v){ this.setAttribute('defer',v); return this; };
1988
+ });
1989
+
1990
+ tag$.defineTag('section');
1991
+
1992
+ tag$.defineTag('select', function(tag){
1993
+ tag.prototype.name = function(v){ return this.getAttribute('name'); }
1994
+ tag.prototype.setName = function(v){ this.setAttribute('name',v); return this; };
1995
+ tag.prototype.multiple = function(v){ return this.getAttribute('multiple'); }
1996
+ tag.prototype.setMultiple = function(v){ this.setAttribute('multiple',v); return this; };
1997
+ tag.prototype.required = function(v){ return this.getAttribute('required'); }
1998
+ tag.prototype.setRequired = function(v){ this.setAttribute('required',v); return this; };
1999
+ tag.prototype.disabled = function(v){ return this.getAttribute('disabled'); }
2000
+ tag.prototype.setDisabled = function(v){ this.setAttribute('disabled',v); return this; };
2001
+
2002
+ tag.prototype.value = function (){
2003
+ return this.dom().value;
2004
+ };
2005
+
2006
+ tag.prototype.setValue = function (v){
2007
+ if (v != this.dom().value) { this.dom().value = v };
2008
+ return this;
2009
+ };
2010
+ });
2011
+
2012
+
2013
+ tag$.defineTag('small');
2014
+ tag$.defineTag('source');
2015
+ tag$.defineTag('span');
2016
+ tag$.defineTag('strong');
2017
+ tag$.defineTag('style');
2018
+ tag$.defineTag('sub');
2019
+ tag$.defineTag('summary');
2020
+ tag$.defineTag('sup');
2021
+ tag$.defineTag('table');
2022
+ tag$.defineTag('tbody');
2023
+ tag$.defineTag('td');
2024
+
2025
+ tag$.defineTag('textarea', function(tag){
2026
+ tag.prototype.name = function(v){ return this.getAttribute('name'); }
2027
+ tag.prototype.setName = function(v){ this.setAttribute('name',v); return this; };
2028
+ tag.prototype.disabled = function(v){ return this.getAttribute('disabled'); }
2029
+ tag.prototype.setDisabled = function(v){ this.setAttribute('disabled',v); return this; };
2030
+ tag.prototype.required = function(v){ return this.getAttribute('required'); }
2031
+ tag.prototype.setRequired = function(v){ this.setAttribute('required',v); return this; };
2032
+ tag.prototype.rows = function(v){ return this.getAttribute('rows'); }
2033
+ tag.prototype.setRows = function(v){ this.setAttribute('rows',v); return this; };
2034
+ tag.prototype.cols = function(v){ return this.getAttribute('cols'); }
2035
+ tag.prototype.setCols = function(v){ this.setAttribute('cols',v); return this; };
2036
+ tag.prototype.autofocus = function(v){ return this.getAttribute('autofocus'); }
2037
+ tag.prototype.setAutofocus = function(v){ this.setAttribute('autofocus',v); return this; };
2038
+
2039
+ tag.prototype.value = function (){
2040
+ return this.dom().value;
2041
+ };
2042
+
2043
+ tag.prototype.setValue = function (v){
2044
+ if (v != this.dom().value) { this.dom().value = v };
2045
+ return this;
2046
+ };
2047
+
2048
+ tag.prototype.setPlaceholder = function (v){
2049
+ if (v != this.dom().placeholder) { this.dom().placeholder = v };
2050
+ return this;
2051
+ };
2052
+
2053
+ tag.prototype.placeholder = function (){
2054
+ return this.dom().placeholder;
2055
+ };
2056
+ });
2057
+
2058
+ tag$.defineTag('tfoot');
2059
+ tag$.defineTag('th');
2060
+ tag$.defineTag('thead');
2061
+ tag$.defineTag('time');
2062
+ tag$.defineTag('title');
2063
+ tag$.defineTag('tr');
2064
+ tag$.defineTag('track');
2065
+ tag$.defineTag('u');
2066
+ tag$.defineTag('ul');
2067
+ tag$.defineTag('video');
2068
+ return tag$.defineTag('wbr');
2069
+
2070
+ })()
2071
+
2072
+ /***/ },
2073
+ /* 7 */
2074
+ /***/ function(module, exports) {
2075
+
2076
+ (function(){
2077
+ function idx$(a,b){
2078
+ return (b && b.indexOf) ? b.indexOf(a) : [].indexOf.call(a,b);
2079
+ };
2080
+
2081
+
2082
+ tag$.SVG.defineTag('svgelement', function(tag){
2083
+
2084
+ tag.namespaceURI = function (){
2085
+ return "http://www.w3.org/2000/svg";
2086
+ };
2087
+
2088
+ var types = "circle defs ellipse g line linearGradient mask path pattern polygon polyline radialGradient rect stop svg text tspan".split(" ");
2089
+
2090
+ tag.buildNode = function (){
2091
+ var dom = Imba.document().createElementNS(this.namespaceURI(),this._nodeType);
2092
+ var cls = this._classes.join(" ");
2093
+ if (cls) { dom.className.baseVal = cls };
2094
+ return dom;
2095
+ };
2096
+
2097
+ tag.inherit = function (child){
2098
+ child._protoDom = null;
2099
+
2100
+ if (idx$(child._name,types) >= 0) {
2101
+ child._nodeType = child._name;
2102
+ return child._classes = [];
2103
+ } else {
2104
+ child._nodeType = this._nodeType;
2105
+ var className = "_" + child._name.replace(/_/g,'-');
2106
+ return child._classes = this._classes.concat(className);
2107
+ };
2108
+ };
2109
+
2110
+
2111
+ Imba.attr(tag,'x');
2112
+ Imba.attr(tag,'y');
2113
+
2114
+ Imba.attr(tag,'width');
2115
+ Imba.attr(tag,'height');
2116
+
2117
+ Imba.attr(tag,'stroke');
2118
+ Imba.attr(tag,'stroke-width');
2119
+ });
2120
+
2121
+ tag$.SVG.defineTag('svg', function(tag){
2122
+ Imba.attr(tag,'viewbox');
2123
+ });
2124
+
2125
+ tag$.SVG.defineTag('g');
2126
+
2127
+ tag$.SVG.defineTag('defs');
2128
+
2129
+ tag$.SVG.defineTag('symbol', function(tag){
2130
+ Imba.attr(tag,'preserveAspectRatio');
2131
+ Imba.attr(tag,'viewBox');
2132
+ });
2133
+
2134
+ tag$.SVG.defineTag('marker', function(tag){
2135
+ Imba.attr(tag,'markerUnits');
2136
+ Imba.attr(tag,'refX');
2137
+ Imba.attr(tag,'refY');
2138
+ Imba.attr(tag,'markerWidth');
2139
+ Imba.attr(tag,'markerHeight');
2140
+ Imba.attr(tag,'orient');
2141
+ });
2142
+
2143
+
2144
+ // Basic shapes
2145
+
2146
+ tag$.SVG.defineTag('rect', function(tag){
2147
+ Imba.attr(tag,'rx');
2148
+ Imba.attr(tag,'ry');
2149
+ });
2150
+
2151
+ tag$.SVG.defineTag('circle', function(tag){
2152
+ Imba.attr(tag,'cx');
2153
+ Imba.attr(tag,'cy');
2154
+ Imba.attr(tag,'r');
2155
+ });
2156
+
2157
+ tag$.SVG.defineTag('ellipse', function(tag){
2158
+ Imba.attr(tag,'cx');
2159
+ Imba.attr(tag,'cy');
2160
+ Imba.attr(tag,'rx');
2161
+ Imba.attr(tag,'ry');
2162
+ });
2163
+
2164
+ tag$.SVG.defineTag('path', function(tag){
2165
+ Imba.attr(tag,'d');
2166
+ Imba.attr(tag,'pathLength');
2167
+ });
2168
+
2169
+ tag$.SVG.defineTag('line', function(tag){
2170
+ Imba.attr(tag,'x1');
2171
+ Imba.attr(tag,'x2');
2172
+ Imba.attr(tag,'y1');
2173
+ Imba.attr(tag,'y2');
2174
+ });
2175
+
2176
+ tag$.SVG.defineTag('polyline', function(tag){
2177
+ Imba.attr(tag,'points');
2178
+ });
2179
+
2180
+ tag$.SVG.defineTag('polygon', function(tag){
2181
+ Imba.attr(tag,'points');
2182
+ });
2183
+
2184
+ tag$.SVG.defineTag('text', function(tag){
2185
+ Imba.attr(tag,'dx');
2186
+ Imba.attr(tag,'dy');
2187
+ Imba.attr(tag,'text-anchor');
2188
+ Imba.attr(tag,'rotate');
2189
+ Imba.attr(tag,'textLength');
2190
+ Imba.attr(tag,'lengthAdjust');
2191
+ });
2192
+
2193
+ return tag$.SVG.defineTag('tspan', function(tag){
2194
+ Imba.attr(tag,'dx');
2195
+ Imba.attr(tag,'dy');
2196
+ Imba.attr(tag,'rotate');
2197
+ Imba.attr(tag,'textLength');
2198
+ Imba.attr(tag,'lengthAdjust');
2199
+ });
2200
+
2201
+ })()
2202
+
2203
+ /***/ },
2204
+ /* 8 */
2205
+ /***/ function(module, exports, __webpack_require__) {
2206
+
2207
+ (function(){
2208
+ function iter$(a){ return a ? (a.toArray ? a.toArray() : a) : []; };
2209
+ // Extending Imba.Tag#css to work without prefixes by inspecting
2210
+ // the properties of a CSSStyleDeclaration and creating a map
2211
+
2212
+ // var prefixes = ['-webkit-','-ms-','-moz-','-o-','-blink-']
2213
+ // var props = ['transform','transition','animation']
2214
+
2215
+ if (true) {
2216
+ var styles = window.getComputedStyle(document.documentElement,'');
2217
+
2218
+ Imba.CSSKeyMap = {};
2219
+
2220
+ for (var i = 0, ary = iter$(styles), len = ary.length, prefixed; i < len; i++) {
2221
+ prefixed = ary[i];
2222
+ var unprefixed = prefixed.replace(/^-(webkit|ms|moz|o|blink)-/,'');
2223
+ var camelCase = unprefixed.replace(/-(\w)/g,function(m,a) { return a.toUpperCase(); });
2224
+
2225
+ // if there exists an unprefixed version -- always use this
2226
+ if (prefixed != unprefixed) {
2227
+ if (styles.hasOwnProperty(unprefixed)) { continue; };
2228
+ };
2229
+
2230
+ // register the prefixes
2231
+ Imba.CSSKeyMap[unprefixed] = Imba.CSSKeyMap[camelCase] = prefixed;
2232
+ };
2233
+
2234
+ tag$.extendTag('element', function(tag){
2235
+
2236
+ // override the original css method
2237
+ tag.prototype.css = function (key,val){
2238
+ if (key instanceof Object) {
2239
+ for (var i = 0, keys = Object.keys(key), l = keys.length; i < l; i++){
2240
+ this.css(keys[i],key[keys[i]]);
2241
+ };
2242
+ return this;
2243
+ };
2244
+
2245
+ key = Imba.CSSKeyMap[key] || key;
2246
+
2247
+ if (val == null) {
2248
+ this.dom().style.removeProperty(key);
2249
+ } else if (val == undefined) {
2250
+ return this.dom().style[key];
2251
+ } else {
2252
+ if ((typeof val=='number'||val instanceof Number) && key.match(/width|height|left|right|top|bottom/)) {
2253
+ val = val + "px";
2254
+ };
2255
+ this.dom().style[key] = val;
2256
+ };
2257
+ return this;
2258
+ };
2259
+ });
2260
+
2261
+ if (!document.documentElement.classList) {
2262
+ tag$.extendTag('element', function(tag){
2263
+
2264
+ tag.prototype.hasFlag = function (ref){
2265
+ return new RegExp('(^|\\s)' + ref + '(\\s|$)').test(this._dom.className);
2266
+ };
2267
+
2268
+ tag.prototype.addFlag = function (ref){
2269
+ if (this.hasFlag(ref)) { return this };
2270
+ this._dom.className += (this._dom.className ? (' ') : ('')) + ref;
2271
+ return this;
2272
+ };
2273
+
2274
+ tag.prototype.unflag = function (ref){
2275
+ if (!this.hasFlag(ref)) { return this };
2276
+ var regex = new RegExp('(^|\\s)*' + ref + '(\\s|$)*','g');
2277
+ this._dom.className = this._dom.className.replace(regex,'');
2278
+ return this;
2279
+ };
2280
+
2281
+ tag.prototype.toggleFlag = function (ref){
2282
+ return this.hasFlag(ref) ? (this.unflag(ref)) : (this.flag(ref));
2283
+ };
2284
+
2285
+ tag.prototype.flag = function (ref,bool){
2286
+ if (arguments.length == 2 && !(!(bool)) === false) {
2287
+ return this.unflag(ref);
2288
+ };
2289
+ return this.addFlag(ref);
2290
+ };
2291
+ });
2292
+ return true;
2293
+ };
2294
+ };
2295
+
2296
+ })()
2297
+
2298
+ /***/ },
2299
+ /* 9 */
2300
+ /***/ function(module, exports) {
2301
+
2302
+ (function(){
2303
+ function iter$(a){ return a ? (a.toArray ? a.toArray() : a) : []; };
2304
+ var doc = document;
2305
+ var win = window;
2306
+
2307
+ var hasTouchEvents = window && window.ontouchstart !== undefined;
2308
+
2309
+ Imba.Pointer = function Pointer(){
2310
+ this.setButton(-1);
2311
+ this.setEvent({x: 0,y: 0,type: 'uninitialized'});
2312
+ return this;
2313
+ };
2314
+
2315
+ Imba.Pointer.prototype.phase = function(v){ return this._phase; }
2316
+ Imba.Pointer.prototype.setPhase = function(v){ this._phase = v; return this; };
2317
+ Imba.Pointer.prototype.prevEvent = function(v){ return this._prevEvent; }
2318
+ Imba.Pointer.prototype.setPrevEvent = function(v){ this._prevEvent = v; return this; };
2319
+ Imba.Pointer.prototype.button = function(v){ return this._button; }
2320
+ Imba.Pointer.prototype.setButton = function(v){ this._button = v; return this; };
2321
+ Imba.Pointer.prototype.event = function(v){ return this._event; }
2322
+ Imba.Pointer.prototype.setEvent = function(v){ this._event = v; return this; };
2323
+ Imba.Pointer.prototype.dirty = function(v){ return this._dirty; }
2324
+ Imba.Pointer.prototype.setDirty = function(v){ this._dirty = v; return this; };
2325
+ Imba.Pointer.prototype.events = function(v){ return this._events; }
2326
+ Imba.Pointer.prototype.setEvents = function(v){ this._events = v; return this; };
2327
+ Imba.Pointer.prototype.touch = function(v){ return this._touch; }
2328
+ Imba.Pointer.prototype.setTouch = function(v){ this._touch = v; return this; };
2329
+
2330
+ Imba.Pointer.prototype.update = function (e){
2331
+ this.setEvent(e);
2332
+ this.setDirty(true);
2333
+ return this;
2334
+ };
2335
+
2336
+ // this is just for regular mouse now
2337
+ Imba.Pointer.prototype.process = function (){
2338
+ var e1 = this.event();
2339
+
2340
+ if (this.dirty()) {
2341
+ this.setPrevEvent(e1);
2342
+ this.setDirty(false);
2343
+
2344
+ // button should only change on mousedown etc
2345
+ if (e1.type == 'mousedown') {
2346
+ this.setButton(e1.button);
2347
+
2348
+ // do not create touch for right click
2349
+ if (this.button() == 2 || (this.touch() && this.button() != 0)) {
2350
+ return;
2351
+ };
2352
+
2353
+ // cancel the previous touch
2354
+ if (this.touch()) { this.touch().cancel() };
2355
+ this.setTouch(new Imba.Touch(e1,this));
2356
+ this.touch().mousedown(e1,e1);
2357
+ } else if (e1.type == 'mousemove') {
2358
+ if (this.touch()) { this.touch().mousemove(e1,e1) };
2359
+ } else if (e1.type == 'mouseup') {
2360
+ this.setButton(-1);
2361
+
2362
+ if (this.touch() && this.touch().button() == e1.button) {
2363
+ this.touch().mouseup(e1,e1);
2364
+ this.setTouch(null);
2365
+ };
2366
+ // trigger pointerup
2367
+ };
2368
+ } else {
2369
+ if (this.touch()) { this.touch().idle() };
2370
+ };
2371
+ return this;
2372
+ };
2373
+
2374
+ Imba.Pointer.prototype.cleanup = function (){
2375
+ return Imba.POINTERS;
2376
+ };
2377
+
2378
+ Imba.Pointer.prototype.x = function (){
2379
+ return this.event().x;
2380
+ };
2381
+ Imba.Pointer.prototype.y = function (){
2382
+ return this.event().y;
2383
+ };
2384
+
2385
+ // deprecated -- should remove
2386
+ Imba.Pointer.update = function (){
2387
+ // console.log('update touch')
2388
+ for (var i = 0, ary = iter$(Imba.POINTERS), len = ary.length; i < len; i++) {
2389
+ ary[i].process();
2390
+ };
2391
+ // need to be able to prevent the default behaviour of touch, no?
2392
+ win.requestAnimationFrame(Imba.Pointer.update);
2393
+ return this;
2394
+ };
2395
+
2396
+ var lastNativeTouchTimeStamp = 0;
2397
+ var lastNativeTouchTimeout = 50;
2398
+
2399
+ // Imba.Touch
2400
+ // Began A finger touched the screen.
2401
+ // Moved A finger moved on the screen.
2402
+ // Stationary A finger is touching the screen but hasn't moved.
2403
+ // Ended A finger was lifted from the screen. This is the final phase of a touch.
2404
+ // Canceled The system cancelled tracking for the touch.
2405
+
2406
+ /*
2407
+ Consolidates mouse and touch events. Touch objects persist across a touch,
2408
+ from touchstart until end/cancel. When a touch starts, it will traverse
2409
+ down from the innermost target, until it finds a node that responds to
2410
+ ontouchstart. Unless the touch is explicitly redirected, the touch will
2411
+ call ontouchmove and ontouchend / ontouchcancel on the responder when appropriate.
2412
+
2413
+ tag draggable
2414
+ # called when a touch starts
2415
+ def ontouchstart touch
2416
+ flag 'dragging'
2417
+ self
2418
+
2419
+ # called when touch moves - same touch object
2420
+ def ontouchmove touch
2421
+ # move the node with touch
2422
+ css top: touch.dy, left: touch.dx
2423
+
2424
+ # called when touch ends
2425
+ def ontouchend touch
2426
+ unflag 'dragging'
2427
+
2428
+ @iname touch
2429
+ */
2430
+
2431
+ Imba.Touch = function Touch(event,pointer){
2432
+ // @native = false
2433
+ this.setEvent(event);
2434
+ this.setData({});
2435
+ this.setActive(true);
2436
+ this._button = event && event.button || 0;
2437
+ this._suppress = false; // deprecated
2438
+ this._captured = false;
2439
+ this.setBubble(false);
2440
+ pointer = pointer;
2441
+ this.setUpdates(0);
2442
+ return this;
2443
+ };
2444
+
2445
+ var touches = [];
2446
+ var count = 0;
2447
+ var identifiers = {};
2448
+
2449
+ Imba.Touch.count = function (){
2450
+ return count;
2451
+ };
2452
+
2453
+ Imba.Touch.lookup = function (item){
2454
+ return item && (item.__touch__ || identifiers[item.identifier]);
2455
+ };
2456
+
2457
+ Imba.Touch.release = function (item,touch){
2458
+ var v_, $1;
2459
+ (((v_ = identifiers[item.identifier]),delete identifiers[item.identifier], v_));
2460
+ ((($1 = item.__touch__),delete item.__touch__, $1));
2461
+ return;
2462
+ };
2463
+
2464
+ Imba.Touch.ontouchstart = function (e){
2465
+ for (var i = 0, ary = iter$(e.changedTouches), len = ary.length, t; i < len; i++) {
2466
+ t = ary[i];
2467
+ if (this.lookup(t)) { continue; };
2468
+ var touch = identifiers[t.identifier] = new this(e); // (e)
2469
+ t.__touch__ = touch;
2470
+ touches.push(touch);
2471
+ count++;
2472
+ touch.touchstart(e,t);
2473
+ };
2474
+ return this;
2475
+ };
2476
+
2477
+ Imba.Touch.ontouchmove = function (e){
2478
+ var touch;
2479
+ for (var i = 0, ary = iter$(e.changedTouches), len = ary.length, t; i < len; i++) {
2480
+ t = ary[i];
2481
+ if (touch = this.lookup(t)) {
2482
+ touch.touchmove(e,t);
2483
+ };
2484
+ };
2485
+
2486
+ return this;
2487
+ };
2488
+
2489
+ Imba.Touch.ontouchend = function (e){
2490
+ var touch;
2491
+ for (var i = 0, ary = iter$(e.changedTouches), len = ary.length, t; i < len; i++) {
2492
+ t = ary[i];
2493
+ if (touch = this.lookup(t)) {
2494
+ touch.touchend(e,t);
2495
+ this.release(t,touch);
2496
+ count--;
2497
+ };
2498
+ };
2499
+
2500
+ // e.preventDefault
2501
+ // not always supported!
2502
+ // touches = touches.filter(||)
2503
+ return this;
2504
+ };
2505
+
2506
+ Imba.Touch.ontouchcancel = function (e){
2507
+ var touch;
2508
+ for (var i = 0, ary = iter$(e.changedTouches), len = ary.length, t; i < len; i++) {
2509
+ t = ary[i];
2510
+ if (touch = this.lookup(t)) {
2511
+ touch.touchcancel(e,t);
2512
+ this.release(t,touch);
2513
+ count--;
2514
+ };
2515
+ };
2516
+ return this;
2517
+ };
2518
+
2519
+ Imba.Touch.onmousedown = function (e){
2520
+ return this;
2521
+ };
2522
+
2523
+ Imba.Touch.onmousemove = function (e){
2524
+ return this;
2525
+ };
2526
+
2527
+ Imba.Touch.onmouseup = function (e){
2528
+ return this;
2529
+ };
2530
+
2531
+
2532
+ Imba.Touch.prototype.phase = function(v){ return this._phase; }
2533
+ Imba.Touch.prototype.setPhase = function(v){ this._phase = v; return this; };
2534
+ Imba.Touch.prototype.active = function(v){ return this._active; }
2535
+ Imba.Touch.prototype.setActive = function(v){ this._active = v; return this; };
2536
+ Imba.Touch.prototype.event = function(v){ return this._event; }
2537
+ Imba.Touch.prototype.setEvent = function(v){ this._event = v; return this; };
2538
+ Imba.Touch.prototype.pointer = function(v){ return this._pointer; }
2539
+ Imba.Touch.prototype.setPointer = function(v){ this._pointer = v; return this; };
2540
+ Imba.Touch.prototype.target = function(v){ return this._target; }
2541
+ Imba.Touch.prototype.setTarget = function(v){ this._target = v; return this; };
2542
+ Imba.Touch.prototype.handler = function(v){ return this._handler; }
2543
+ Imba.Touch.prototype.setHandler = function(v){ this._handler = v; return this; };
2544
+ Imba.Touch.prototype.updates = function(v){ return this._updates; }
2545
+ Imba.Touch.prototype.setUpdates = function(v){ this._updates = v; return this; };
2546
+ Imba.Touch.prototype.suppress = function(v){ return this._suppress; }
2547
+ Imba.Touch.prototype.setSuppress = function(v){ this._suppress = v; return this; };
2548
+ Imba.Touch.prototype.data = function(v){ return this._data; }
2549
+ Imba.Touch.prototype.setData = function(v){ this._data = v; return this; };
2550
+ Imba.Touch.prototype.__bubble = {chainable: true,name: 'bubble'};
2551
+ Imba.Touch.prototype.bubble = function(v){ return v !== undefined ? (this.setBubble(v),this) : this._bubble; }
2552
+ Imba.Touch.prototype.setBubble = function(v){ this._bubble = v; return this; };
2553
+
2554
+ Imba.Touch.prototype.gestures = function(v){ return this._gestures; }
2555
+ Imba.Touch.prototype.setGestures = function(v){ this._gestures = v; return this; };
2556
+
2557
+ /*
2558
+
2559
+
2560
+ @internal
2561
+ @constructor
2562
+ */
2563
+
2564
+ Imba.Touch.prototype.capture = function (){
2565
+ this._captured = true;
2566
+ this._event && this._event.preventDefault();
2567
+ return this;
2568
+ };
2569
+
2570
+ Imba.Touch.prototype.isCaptured = function (){
2571
+ return !(!this._captured);
2572
+ };
2573
+
2574
+ /*
2575
+ Extend the touch with a plugin / gesture.
2576
+ All events (touchstart,move etc) for the touch
2577
+ will be triggered on the plugins in the order they
2578
+ are added.
2579
+ */
2580
+
2581
+ Imba.Touch.prototype.extend = function (plugin){
2582
+ // console.log "added gesture!!!"
2583
+ this._gestures || (this._gestures = []);
2584
+ this._gestures.push(plugin);
2585
+ return this;
2586
+ };
2587
+
2588
+ /*
2589
+ Redirect touch to specified target. ontouchstart will always be
2590
+ called on the new target.
2591
+ @return {Number}
2592
+ */
2593
+
2594
+ Imba.Touch.prototype.redirect = function (target){
2595
+ this._redirect = target;
2596
+ return this;
2597
+ };
2598
+
2599
+ /*
2600
+ Suppress the default behaviour. Will call preventDefault for
2601
+ all native events that are part of the touch.
2602
+ */
2603
+
2604
+ Imba.Touch.prototype.suppress = function (){
2605
+ // collision with the suppress property
2606
+ this._active = false;
2607
+ return this;
2608
+ };
2609
+
2610
+ Imba.Touch.prototype.setSuppress = function (value){
2611
+ console.warn('Imba.Touch#suppress= is deprecated');
2612
+ this._supress = value;
2613
+ return this;
2614
+ };
2615
+
2616
+ Imba.Touch.prototype.touchstart = function (e,t){
2617
+ this._event = e;
2618
+ this._touch = t;
2619
+ this._button = 0;
2620
+ this._x = t.clientX;
2621
+ this._y = t.clientY;
2622
+ this.began();
2623
+ if (e && this.isCaptured()) { e.preventDefault() };
2624
+ return this;
2625
+ };
2626
+
2627
+ Imba.Touch.prototype.touchmove = function (e,t){
2628
+ this._event = e;
2629
+ this._x = t.clientX;
2630
+ this._y = t.clientY;
2631
+ this.update();
2632
+ if (e && this.isCaptured()) { e.preventDefault() };
2633
+ return this;
2634
+ };
2635
+
2636
+ Imba.Touch.prototype.touchend = function (e,t){
2637
+ this._event = e;
2638
+ this._x = t.clientX;
2639
+ this._y = t.clientY;
2640
+ this.ended();
2641
+
2642
+ lastNativeTouchTimeStamp = e.timeStamp;
2643
+
2644
+ if (this._maxdr < 20) {
2645
+ var tap = new Imba.Event(e);
2646
+ tap.setType('tap');
2647
+ tap.process();
2648
+ if (tap._responder) { e.preventDefault() };
2649
+ };
2650
+
2651
+ if (e && this.isCaptured()) {
2652
+ e.preventDefault();
2653
+ };
2654
+
2655
+ return this;
2656
+ };
2657
+
2658
+ Imba.Touch.prototype.touchcancel = function (e,t){
2659
+ return this.cancel();
2660
+ };
2661
+
2662
+ Imba.Touch.prototype.mousedown = function (e,t){
2663
+ var self = this;
2664
+ self._event = e;
2665
+ self._button = e.button;
2666
+ self._x = t.clientX;
2667
+ self._y = t.clientY;
2668
+ self.began();
2669
+
2670
+ self._mousemove = function(e) { return self.mousemove(e,e); };
2671
+ doc.addEventListener('mousemove',self._mousemove,true);
2672
+ return self;
2673
+ };
2674
+
2675
+ Imba.Touch.prototype.mousemove = function (e,t){
2676
+ this._x = t.clientX;
2677
+ this._y = t.clientY;
2678
+ this._event = e;
2679
+ if (this.isCaptured()) { e.preventDefault() };
2680
+ this.update();
2681
+ this.move();
2682
+ return this;
2683
+ };
2684
+
2685
+ Imba.Touch.prototype.mouseup = function (e,t){
2686
+ this._x = t.clientX;
2687
+ this._y = t.clientY;
2688
+ this.ended();
2689
+ doc.removeEventListener('mousemove',this._mousemove,true);
2690
+ this._mousemove = null;
2691
+ return this;
2692
+ };
2693
+
2694
+ Imba.Touch.prototype.idle = function (){
2695
+ return this.update();
2696
+ };
2697
+
2698
+ Imba.Touch.prototype.began = function (){
2699
+ this._maxdr = this._dr = 0;
2700
+ this._x0 = this._x;
2701
+ this._y0 = this._y;
2702
+
2703
+ var dom = this.event().target;
2704
+ var node = null;
2705
+
2706
+ this._sourceTarget = dom && tag$wrap(dom);
2707
+
2708
+ while (dom){
2709
+ node = tag$wrap(dom);
2710
+ if (node && node.ontouchstart) {
2711
+ this._bubble = false;
2712
+ this.setTarget(node);
2713
+ this.target().ontouchstart(this);
2714
+ if (!this._bubble) { break; };
2715
+ };
2716
+ dom = dom.parentNode;
2717
+ };
2718
+
2719
+ this._updates++;
2720
+ return this;
2721
+ };
2722
+
2723
+ Imba.Touch.prototype.update = function (){
2724
+ var target_;
2725
+ if (!this._active) { return this };
2726
+
2727
+ var dr = Math.sqrt(this.dx() * this.dx() + this.dy() * this.dy());
2728
+ if (dr > this._dr) { this._maxdr = dr };
2729
+ this._dr = dr;
2730
+
2731
+ // catching a touch-redirect?!?
2732
+ if (this._redirect) {
2733
+ if (this._target && this._target.ontouchcancel) {
2734
+ this._target.ontouchcancel(this);
2735
+ };
2736
+ this.setTarget(this._redirect);
2737
+ this._redirect = null;
2738
+ if (this.target().ontouchstart) { this.target().ontouchstart(this) };
2739
+ };
2740
+
2741
+
2742
+ this._updates++;
2743
+ if (this._gestures) {
2744
+ for (var i = 0, ary = iter$(this._gestures), len = ary.length; i < len; i++) {
2745
+ ary[i].ontouchupdate(this);
2746
+ };
2747
+ };
2748
+
2749
+ (target_ = this.target()) && target_.ontouchupdate && target_.ontouchupdate(this);
2750
+ return this;
2751
+ };
2752
+
2753
+ Imba.Touch.prototype.move = function (){
2754
+ var target_;
2755
+ if (!this._active) { return this };
2756
+
2757
+ if (this._gestures) {
2758
+ for (var i = 0, ary = iter$(this._gestures), len = ary.length, g; i < len; i++) {
2759
+ g = ary[i];
2760
+ if (g.ontouchmove) { g.ontouchmove(this,this._event) };
2761
+ };
2762
+ };
2763
+
2764
+ (target_ = this.target()) && target_.ontouchmove && target_.ontouchmove(this,this._event);
2765
+ return this;
2766
+ };
2767
+
2768
+ Imba.Touch.prototype.ended = function (){
2769
+ var target_;
2770
+ if (!this._active) { return this };
2771
+
2772
+ this._updates++;
2773
+
2774
+ if (this._gestures) {
2775
+ for (var i = 0, ary = iter$(this._gestures), len = ary.length; i < len; i++) {
2776
+ ary[i].ontouchend(this);
2777
+ };
2778
+ };
2779
+
2780
+ (target_ = this.target()) && target_.ontouchend && target_.ontouchend(this);
2781
+
2782
+ return this;
2783
+ };
2784
+
2785
+ Imba.Touch.prototype.cancel = function (){
2786
+ if (!this._cancelled) {
2787
+ this._cancelled = true;
2788
+ this.cancelled();
2789
+ if (this._mousemove) { doc.removeEventListener('mousemove',this._mousemove,true) };
2790
+ };
2791
+ return this;
2792
+ };
2793
+
2794
+ Imba.Touch.prototype.cancelled = function (){
2795
+ var target_;
2796
+ if (!this._active) { return this };
2797
+
2798
+ this._cancelled = true;
2799
+ this._updates++;
2800
+
2801
+ if (this._gestures) {
2802
+ for (var i = 0, ary = iter$(this._gestures), len = ary.length, g; i < len; i++) {
2803
+ g = ary[i];
2804
+ if (g.ontouchcancel) { g.ontouchcancel(this) };
2805
+ };
2806
+ };
2807
+
2808
+ (target_ = this.target()) && target_.ontouchcancel && target_.ontouchcancel(this);
2809
+ return this;
2810
+ };
2811
+
2812
+ /*
2813
+ The absolute distance the touch has moved from starting position
2814
+ @return {Number}
2815
+ */
2816
+
2817
+ Imba.Touch.prototype.dr = function (){
2818
+ return this._dr;
2819
+ };
2820
+
2821
+ /*
2822
+ The distance the touch has moved horizontally
2823
+ @return {Number}
2824
+ */
2825
+
2826
+ Imba.Touch.prototype.dx = function (){
2827
+ return this._x - this._x0;
2828
+ };
2829
+
2830
+ /*
2831
+ The distance the touch has moved vertically
2832
+ @return {Number}
2833
+ */
2834
+
2835
+ Imba.Touch.prototype.dy = function (){
2836
+ return this._y - this._y0;
2837
+ };
2838
+
2839
+ /*
2840
+ Initial horizontal position of touch
2841
+ @return {Number}
2842
+ */
2843
+
2844
+ Imba.Touch.prototype.x0 = function (){
2845
+ return this._x0;
2846
+ };
2847
+
2848
+ /*
2849
+ Initial vertical position of touch
2850
+ @return {Number}
2851
+ */
2852
+
2853
+ Imba.Touch.prototype.y0 = function (){
2854
+ return this._y0;
2855
+ };
2856
+
2857
+ /*
2858
+ Horizontal position of touch
2859
+ @return {Number}
2860
+ */
2861
+
2862
+ Imba.Touch.prototype.x = function (){
2863
+ return this._x;
2864
+ };
2865
+
2866
+ /*
2867
+ Vertical position of touch
2868
+ @return {Number}
2869
+ */
2870
+
2871
+ Imba.Touch.prototype.y = function (){
2872
+ return this._y;
2873
+ };
2874
+
2875
+ /*
2876
+ Horizontal position of touch relative to target
2877
+ @return {Number}
2878
+ */
2879
+
2880
+ Imba.Touch.prototype.tx = function (){
2881
+ this._targetBox || (this._targetBox = this._target.dom().getBoundingClientRect());
2882
+ return this._x - this._targetBox.left;
2883
+ };
2884
+
2885
+ /*
2886
+ Vertical position of touch relative to target
2887
+ @return {Number}
2888
+ */
2889
+
2890
+ Imba.Touch.prototype.ty = function (){
2891
+ this._targetBox || (this._targetBox = this._target.dom().getBoundingClientRect());
2892
+ return this._y - this._targetBox.top;
2893
+ };
2894
+
2895
+ /*
2896
+ Button pressed in this touch. Native touches defaults to left-click (0)
2897
+ @return {Number}
2898
+ */
2899
+
2900
+ Imba.Touch.prototype.button = function (){
2901
+ return this._button;
2902
+ }; // @pointer ? @pointer.button : 0
2903
+
2904
+ Imba.Touch.prototype.sourceTarget = function (){
2905
+ return this._sourceTarget;
2906
+ };
2907
+
2908
+
2909
+ Imba.TouchGesture = function TouchGesture(){ };
2910
+
2911
+ Imba.TouchGesture.prototype.__active = {'default': false,name: 'active'};
2912
+ Imba.TouchGesture.prototype.active = function(v){ return this._active; }
2913
+ Imba.TouchGesture.prototype.setActive = function(v){ this._active = v; return this; }
2914
+ Imba.TouchGesture.prototype._active = false;
2915
+
2916
+ Imba.TouchGesture.prototype.ontouchstart = function (e){
2917
+ return this;
2918
+ };
2919
+
2920
+ Imba.TouchGesture.prototype.ontouchupdate = function (e){
2921
+ return this;
2922
+ };
2923
+
2924
+ Imba.TouchGesture.prototype.ontouchend = function (e){
2925
+ return this;
2926
+ };
2927
+
2928
+
2929
+ // A Touch-event is created on mousedown (always)
2930
+ // and while it exists, mousemove and mouseup will
2931
+ // be delegated to this active event.
2932
+ Imba.POINTER = new Imba.Pointer();
2933
+ Imba.POINTERS = [Imba.POINTER];
2934
+
2935
+
2936
+ // regular event stuff
2937
+ Imba.KEYMAP = {
2938
+ "8": 'backspace',
2939
+ "9": 'tab',
2940
+ "13": 'enter',
2941
+ "16": 'shift',
2942
+ "17": 'ctrl',
2943
+ "18": 'alt',
2944
+ "19": 'break',
2945
+ "20": 'caps',
2946
+ "27": 'esc',
2947
+ "32": 'space',
2948
+ "35": 'end',
2949
+ "36": 'home',
2950
+ "37": 'larr',
2951
+ "38": 'uarr',
2952
+ "39": 'rarr',
2953
+ "40": 'darr',
2954
+ "45": 'insert',
2955
+ "46": 'delete',
2956
+ "107": 'plus',
2957
+ "106": 'mult',
2958
+ "91": 'meta'
2959
+ };
2960
+
2961
+ Imba.CHARMAP = {
2962
+ "%": 'modulo',
2963
+ "*": 'multiply',
2964
+ "+": 'add',
2965
+ "-": 'sub',
2966
+ "/": 'divide',
2967
+ ".": 'dot'
2968
+ };
2969
+
2970
+ /*
2971
+ Imba handles all events in the dom through a single manager,
2972
+ listening at the root of your document. If Imba finds a tag
2973
+ that listens to a certain event, the event will be wrapped
2974
+ in an `Imba.Event`, which normalizes some of the quirks and
2975
+ browser differences.
2976
+
2977
+ @iname event
2978
+ */
2979
+
2980
+ Imba.Event = function Event(e){
2981
+ this.setEvent(e);
2982
+ this.setBubble(true);
2983
+ };
2984
+
2985
+ /* reference to the native event */
2986
+
2987
+ Imba.Event.prototype.event = function(v){ return this._event; }
2988
+ Imba.Event.prototype.setEvent = function(v){ this._event = v; return this; };
2989
+
2990
+ /* reference to the native event */
2991
+
2992
+ Imba.Event.prototype.prefix = function(v){ return this._prefix; }
2993
+ Imba.Event.prototype.setPrefix = function(v){ this._prefix = v; return this; };
2994
+
2995
+ Imba.Event.prototype.data = function(v){ return this._data; }
2996
+ Imba.Event.prototype.setData = function(v){ this._data = v; return this; };
2997
+
2998
+ /*
2999
+ should remove this alltogether?
3000
+ @deprecated
3001
+ */
3002
+
3003
+ Imba.Event.prototype.source = function(v){ return this._source; }
3004
+ Imba.Event.prototype.setSource = function(v){ this._source = v; return this; };
3005
+
3006
+ /* A {Boolean} indicating whether the event bubbles up or not */
3007
+
3008
+ Imba.Event.prototype.__bubble = {type: Boolean,chainable: true,name: 'bubble'};
3009
+ Imba.Event.prototype.bubble = function(v){ return v !== undefined ? (this.setBubble(v),this) : this._bubble; }
3010
+ Imba.Event.prototype.setBubble = function(v){ this._bubble = v; return this; };
3011
+
3012
+ Imba.Event.wrap = function (e){
3013
+ return new this(e);
3014
+ };
3015
+
3016
+ Imba.Event.prototype.setType = function (type){
3017
+ this._type = type;
3018
+ return this;
3019
+ };
3020
+
3021
+ /*
3022
+ @return {String} The name of the event (case-insensitive)
3023
+ */
3024
+
3025
+ Imba.Event.prototype.type = function (){
3026
+ return this._type || this.event().type;
3027
+ };
3028
+
3029
+ Imba.Event.prototype.name = function (){
3030
+ return this._name || (this._name = this.type().toLowerCase().replace(/\:/g,''));
3031
+ };
3032
+
3033
+ // mimc getset
3034
+ Imba.Event.prototype.bubble = function (v){
3035
+ if (v != undefined) {
3036
+ this.setBubble(v);
3037
+ return this;
3038
+ };
3039
+ return this._bubble;
3040
+ };
3041
+
3042
+ /*
3043
+ Prevents further propagation of the current event.
3044
+ @return {self}
3045
+ */
3046
+
3047
+ Imba.Event.prototype.halt = function (){
3048
+ this.setBubble(false);
3049
+ return this;
3050
+ };
3051
+
3052
+ /*
3053
+ Cancel the event (if cancelable). In the case of native events it
3054
+ will call `preventDefault` on the wrapped event object.
3055
+ @return {self}
3056
+ */
3057
+
3058
+ Imba.Event.prototype.cancel = function (){
3059
+ if (this.event().preventDefault) { this.event().preventDefault() };
3060
+ this._cancel = true;
3061
+ return this;
3062
+ };
3063
+
3064
+ Imba.Event.prototype.silence = function (){
3065
+ this._silenced = true;
3066
+ return this;
3067
+ };
3068
+
3069
+ Imba.Event.prototype.isSilenced = function (){
3070
+ return !(!this._silenced);
3071
+ };
3072
+
3073
+ /*
3074
+ Indicates whether or not event.cancel has been called.
3075
+
3076
+ @return {Boolean}
3077
+ */
3078
+
3079
+ Imba.Event.prototype.isPrevented = function (){
3080
+ return this.event() && this.event().defaultPrevented || this._cancel;
3081
+ };
3082
+
3083
+ /*
3084
+ A reference to the initial target of the event.
3085
+ */
3086
+
3087
+ Imba.Event.prototype.target = function (){
3088
+ return tag$wrap(this.event()._target || this.event().target);
3089
+ };
3090
+
3091
+ /*
3092
+ A reference to the object responding to the event.
3093
+ */
3094
+
3095
+ Imba.Event.prototype.responder = function (){
3096
+ return this._responder;
3097
+ };
3098
+
3099
+ /*
3100
+ Redirect the event to new target
3101
+ */
3102
+
3103
+ Imba.Event.prototype.redirect = function (node){
3104
+ this._redirect = node;
3105
+ return this;
3106
+ };
3107
+
3108
+ /*
3109
+ Get the normalized character for KeyboardEvent/TextEvent
3110
+ @return {String}
3111
+ */
3112
+
3113
+ Imba.Event.prototype.keychar = function (){
3114
+ if (this.event() instanceof KeyboardEvent) {
3115
+ var ki = this.event().keyIdentifier;
3116
+ var sym = Imba.KEYMAP[this.event().keyCode];
3117
+
3118
+ if (!(sym) && ki.substr(0,2) == "U+") {
3119
+ sym = String.fromCharCode(parseInt(ki.substr(2),16));
3120
+ };
3121
+ return sym;
3122
+ } else if (this.event() instanceof (window.TextEvent || window.InputEvent)) {
3123
+ return this.event().data;
3124
+ };
3125
+
3126
+ return null;
3127
+ };
3128
+
3129
+ /*
3130
+ @deprecated
3131
+ */
3132
+
3133
+ Imba.Event.prototype.keycombo = function (){
3134
+ var sym;
3135
+ if (!(sym = this.keychar())) { return };
3136
+ sym = Imba.CHARMAP[sym] || sym;
3137
+ var combo = [],e = this.event();
3138
+ if (e.ctrlKey) { combo.push('ctrl') };
3139
+ if (e.shiftKey) { combo.push('shift') };
3140
+ if (e.altKey) { combo.push('alt') };
3141
+ if (e.metaKey) { combo.push('cmd') };
3142
+ combo.push(sym);
3143
+ return combo.join("_").toLowerCase();
3144
+ };
3145
+
3146
+
3147
+ Imba.Event.prototype.process = function (){
3148
+ var node;
3149
+ var meth = ("on" + (this._prefix || '') + this.name());
3150
+ var args = null;
3151
+ var domtarget = this.event()._target || this.event().target;
3152
+ // var node = <{domtarget:_responder or domtarget}>
3153
+ // need to clean up and document this behaviour
3154
+
3155
+ var domnode = domtarget._responder || domtarget;
3156
+ // @todo need to stop infinite redirect-rules here
3157
+
3158
+ var $1;while (domnode){
3159
+ this._redirect = null;
3160
+ if (node = tag$wrap(domnode)) { // not only tag
3161
+
3162
+ if ((typeof node[($1 = meth)]=='string'||node[$1] instanceof String)) {
3163
+ // should remember the receiver of the event
3164
+ meth = node[meth];
3165
+ continue; // should not continue?
3166
+ };
3167
+
3168
+ if (node[meth] instanceof Array) {
3169
+ args = node[meth].concat(node);
3170
+ meth = args.shift();
3171
+ continue; // should not continue?
3172
+ };
3173
+
3174
+ if (node[meth] instanceof Function) {
3175
+ this._responder || (this._responder = node);
3176
+ // should autostop bubble here?
3177
+ args ? (node[meth].apply(node,args)) : (node[meth](this,this.data()));
3178
+ };
3179
+ };
3180
+
3181
+ // add node.nextEventResponder as a separate method here?
3182
+ if (!(this.bubble() && (domnode = (this._redirect || (node ? (node.parent()) : (domnode.parentNode)))))) {
3183
+ break;
3184
+ };
3185
+ };
3186
+
3187
+ this.processed();
3188
+ return this;
3189
+ };
3190
+
3191
+
3192
+ Imba.Event.prototype.processed = function (){
3193
+ if (!this._silenced) { Imba.emit(Imba,'event',[this]) };
3194
+ return this;
3195
+ };
3196
+
3197
+ /*
3198
+ Return the x/left coordinate of the mouse / pointer for this event
3199
+ @return {Number} x coordinate of mouse / pointer for event
3200
+ */
3201
+
3202
+ Imba.Event.prototype.x = function (){
3203
+ return this.event().x;
3204
+ };
3205
+
3206
+ /*
3207
+ Return the y/top coordinate of the mouse / pointer for this event
3208
+ @return {Number} y coordinate of mouse / pointer for event
3209
+ */
3210
+
3211
+ Imba.Event.prototype.y = function (){
3212
+ return this.event().y;
3213
+ };
3214
+
3215
+ /*
3216
+ Returns a Number representing a system and implementation
3217
+ dependent numeric code identifying the unmodified value of the
3218
+ pressed key; this is usually the same as keyCode.
3219
+
3220
+ For mouse-events, the returned value indicates which button was
3221
+ pressed on the mouse to trigger the event.
3222
+
3223
+ @return {Number}
3224
+ */
3225
+
3226
+ Imba.Event.prototype.which = function (){
3227
+ return this.event().which;
3228
+ };
3229
+
3230
+
3231
+ /*
3232
+
3233
+ Manager for listening to and delegating events in Imba. A single instance
3234
+ is always created by Imba (as `Imba.Events`), which handles and delegates all
3235
+ events at the very root of the document. Imba does not capture all events
3236
+ by default, so if you want to make sure exotic or custom DOMEvents are delegated
3237
+ in Imba you will need to register them in `Imba.Events.register(myCustomEventName)`
3238
+
3239
+ @iname manager
3240
+
3241
+ */
3242
+
3243
+ Imba.EventManager = function EventManager(node,pars){
3244
+ var self = this;
3245
+ if(!pars||pars.constructor !== Object) pars = {};
3246
+ var events = pars.events !== undefined ? pars.events : [];
3247
+ self.setRoot(node);
3248
+ self.setCount(0);
3249
+ self.setListeners([]);
3250
+ self.setDelegators({});
3251
+ self.setDelegator(function(e) {
3252
+ // console.log "delegating event?! {e}"
3253
+ self.delegate(e);
3254
+ return true;
3255
+ });
3256
+
3257
+ for (var i = 0, ary = iter$(events), len = ary.length; i < len; i++) {
3258
+ self.register(ary[i]);
3259
+ };
3260
+
3261
+ return self;
3262
+ };
3263
+
3264
+ Imba.EventManager.prototype.root = function(v){ return this._root; }
3265
+ Imba.EventManager.prototype.setRoot = function(v){ this._root = v; return this; };
3266
+ Imba.EventManager.prototype.count = function(v){ return this._count; }
3267
+ Imba.EventManager.prototype.setCount = function(v){ this._count = v; return this; };
3268
+ Imba.EventManager.prototype.__enabled = {'default': false,watch: 'enabledDidSet',name: 'enabled'};
3269
+ Imba.EventManager.prototype.enabled = function(v){ return this._enabled; }
3270
+ Imba.EventManager.prototype.setEnabled = function(v){
3271
+ var a = this.enabled();
3272
+ if(v != a) { this._enabled = v; }
3273
+ if(v != a) { this.enabledDidSet && this.enabledDidSet(v,a,this.__enabled) }
3274
+ return this;
3275
+ }
3276
+ Imba.EventManager.prototype._enabled = false;
3277
+ Imba.EventManager.prototype.listeners = function(v){ return this._listeners; }
3278
+ Imba.EventManager.prototype.setListeners = function(v){ this._listeners = v; return this; };
3279
+ Imba.EventManager.prototype.delegators = function(v){ return this._delegators; }
3280
+ Imba.EventManager.prototype.setDelegators = function(v){ this._delegators = v; return this; };
3281
+ Imba.EventManager.prototype.delegator = function(v){ return this._delegator; }
3282
+ Imba.EventManager.prototype.setDelegator = function(v){ this._delegator = v; return this; };
3283
+
3284
+ Imba.EventManager.prototype.enabledDidSet = function (bool){
3285
+ bool ? (this.onenable()) : (this.ondisable());
3286
+ return this;
3287
+ };
3288
+
3289
+ /*
3290
+
3291
+ Tell the current EventManager to intercept and handle event of a certain name.
3292
+ By default, Imba.Events will register interceptors for: *keydown*, *keyup*,
3293
+ *keypress*, *textInput*, *input*, *change*, *submit*, *focusin*, *focusout*,
3294
+ *blur*, *contextmenu*, *dblclick*, *mousewheel*, *wheel*
3295
+
3296
+ */
3297
+
3298
+ Imba.EventManager.prototype.register = function (name,handler){
3299
+ if(handler === undefined) handler = true;
3300
+ if (name instanceof Array) {
3301
+ for (var i = 0, ary = iter$(name), len = ary.length; i < len; i++) {
3302
+ this.register(ary[i],handler);
3303
+ };
3304
+ return this;
3305
+ };
3306
+
3307
+ if (this.delegators()[name]) { return this };
3308
+ // console.log("register for event {name}")
3309
+ var fn = this.delegators()[name] = handler instanceof Function ? (handler) : (this.delegator());
3310
+ if (this.enabled()) { return this.root().addEventListener(name,fn,true) };
3311
+ };
3312
+
3313
+ Imba.EventManager.prototype.listen = function (name,handler,capture){
3314
+ if(capture === undefined) capture = true;
3315
+ this.listeners().push([name,handler,capture]);
3316
+ if (this.enabled()) { this.root().addEventListener(name,handler,capture) };
3317
+ return this;
3318
+ };
3319
+
3320
+ Imba.EventManager.prototype.delegate = function (e){
3321
+ this.setCount(this.count() + 1);
3322
+ var event = Imba.Event.wrap(e);
3323
+ event.process();
3324
+ return this;
3325
+ };
3326
+
3327
+ Imba.EventManager.prototype.create = function (type,target,pars){
3328
+ if(!pars||pars.constructor !== Object) pars = {};
3329
+ var data = pars.data !== undefined ? pars.data : null;
3330
+ var source = pars.source !== undefined ? pars.source : null;
3331
+ var event = Imba.Event.wrap({type: type,target: target});
3332
+ if (data) { (event.setData(data),data) };
3333
+ if (source) { (event.setSource(source),source) };
3334
+ return event;
3335
+ };
3336
+
3337
+ // use create instead?
3338
+ Imba.EventManager.prototype.trigger = function (){
3339
+ return this.create.apply(this,arguments).process();
3340
+ };
3341
+
3342
+ Imba.EventManager.prototype.onenable = function (){
3343
+ for (var o = this.delegators(), i = 0, keys = Object.keys(o), l = keys.length; i < l; i++){
3344
+ this.root().addEventListener(keys[i],o[keys[i]],true);
3345
+ };
3346
+
3347
+ for (var i = 0, ary = iter$(this.listeners()), len = ary.length, item; i < len; i++) {
3348
+ item = ary[i];
3349
+ this.root().addEventListener(item[0],item[1],item[2]);
3350
+ };
3351
+ return this;
3352
+ };
3353
+
3354
+ Imba.EventManager.prototype.ondisable = function (){
3355
+ for (var o = this.delegators(), i = 0, keys = Object.keys(o), l = keys.length; i < l; i++){
3356
+ this.root().removeEventListener(keys[i],o[keys[i]],true);
3357
+ };
3358
+
3359
+ for (var i = 0, ary = iter$(this.listeners()), len = ary.length, item; i < len; i++) {
3360
+ item = ary[i];
3361
+ this.root().removeEventListener(item[0],item[1],item[2]);
3362
+ };
3363
+ return this;
3364
+ };
3365
+
3366
+
3367
+ ED = Imba.Events = new Imba.EventManager(document,{events: [
3368
+ 'keydown','keyup','keypress','textInput','input','change','submit',
3369
+ 'focusin','focusout','blur','contextmenu','dblclick',
3370
+ 'mousewheel','wheel','scroll'
3371
+ ]});
3372
+
3373
+ // should set these up inside the Imba.Events object itself
3374
+ // so that we can have different EventManager for different roots
3375
+
3376
+ if (hasTouchEvents) {
3377
+ Imba.Events.listen('touchstart',function(e) {
3378
+ var Events_, v_;
3379
+ (((Events_ = Imba.Events).setCount(v_ = Events_.count() + 1),v_)) - 1;
3380
+ return Imba.Touch.ontouchstart(e);
3381
+ });
3382
+
3383
+ Imba.Events.listen('touchmove',function(e) {
3384
+ var Events_, v_;
3385
+ (((Events_ = Imba.Events).setCount(v_ = Events_.count() + 1),v_)) - 1;
3386
+ return Imba.Touch.ontouchmove(e);
3387
+ });
3388
+
3389
+ Imba.Events.listen('touchend',function(e) {
3390
+ var Events_, v_;
3391
+ (((Events_ = Imba.Events).setCount(v_ = Events_.count() + 1),v_)) - 1;
3392
+ return Imba.Touch.ontouchend(e);
3393
+ });
3394
+
3395
+ Imba.Events.listen('touchcancel',function(e) {
3396
+ var Events_, v_;
3397
+ (((Events_ = Imba.Events).setCount(v_ = Events_.count() + 1),v_)) - 1;
3398
+ return Imba.Touch.ontouchcancel(e);
3399
+ });
3400
+ };
3401
+
3402
+ Imba.Events.register('click',function(e) {
3403
+ // Only for main mousebutton, no?
3404
+ if ((e.timeStamp - lastNativeTouchTimeStamp) > lastNativeTouchTimeout) {
3405
+ var tap = new Imba.Event(e);
3406
+ tap.setType('tap');
3407
+ tap.process();
3408
+ if (tap._responder) {
3409
+ return e.preventDefault();
3410
+ };
3411
+ };
3412
+ // delegate the real click event
3413
+ return Imba.Events.delegate(e);
3414
+ });
3415
+
3416
+ Imba.Events.listen('mousedown',function(e) {
3417
+ if ((e.timeStamp - lastNativeTouchTimeStamp) > lastNativeTouchTimeout) {
3418
+ if (Imba.POINTER) { return Imba.POINTER.update(e).process() };
3419
+ };
3420
+ });
3421
+
3422
+ // Imba.Events.listen(:mousemove) do |e|
3423
+ // # console.log 'mousemove',e:timeStamp
3424
+ // if (e:timeStamp - lastNativeTouchTimeStamp) > lastNativeTouchTimeout
3425
+ // Imba.POINTER.update(e).process if Imba.POINTER # .process if touch # should not happen? We process through
3426
+
3427
+ Imba.Events.listen('mouseup',function(e) {
3428
+ // console.log 'mouseup',e:timeStamp
3429
+ if ((e.timeStamp - lastNativeTouchTimeStamp) > lastNativeTouchTimeout) {
3430
+ if (Imba.POINTER) { return Imba.POINTER.update(e).process() };
3431
+ };
3432
+ });
3433
+
3434
+
3435
+ Imba.Events.register(['mousedown','mouseup']);
3436
+ return (Imba.Events.setEnabled(true),true);
3437
+
3438
+ })()
3439
+
3440
+ /***/ },
3441
+ /* 10 */
3442
+ /***/ function(module, exports) {
3443
+
3444
+ (function(){
3445
+ function iter$(a){ return a ? (a.toArray ? a.toArray() : a) : []; };
3446
+ var ImbaTag = Imba.TAGS.element;
3447
+
3448
+ function removeNested(root,node,caret){
3449
+ // if node/nodes isa String
3450
+ // we need to use the caret to remove elements
3451
+ // for now we will simply not support this
3452
+ if (node instanceof ImbaTag) {
3453
+ root.removeChild(node);
3454
+ } else if (node instanceof Array) {
3455
+ for (var i = 0, ary = iter$(node), len = ary.length; i < len; i++) {
3456
+ removeNested(root,ary[i],caret);
3457
+ };
3458
+ } else {
3459
+ // what if this is not null?!?!?
3460
+ // take a chance and remove a text-elementng
3461
+ var next = caret ? (caret.nextSibling) : (root._dom.firstChild);
3462
+ if ((next instanceof Text) && next.textContent == node) {
3463
+ root.removeChild(next);
3464
+ } else {
3465
+ throw 'cannot remove string';
3466
+ };
3467
+ };
3468
+
3469
+ return caret;
3470
+ };
3471
+
3472
+ function appendNested(root,node){
3473
+ if (node instanceof ImbaTag) {
3474
+ root.appendChild(node);
3475
+ } else if (node instanceof Array) {
3476
+ for (var i = 0, ary = iter$(node), len = ary.length; i < len; i++) {
3477
+ appendNested(root,ary[i]);
3478
+ };
3479
+ } else if (node != null && node !== false) {
3480
+ root.appendChild(Imba.document().createTextNode(node));
3481
+ };
3482
+
3483
+ return;
3484
+ };
3485
+
3486
+
3487
+ // insert nodes before a certain node
3488
+ // does not need to return any tail, as before
3489
+ // will still be correct there
3490
+ // before must be an actual domnode
3491
+ function insertNestedBefore(root,node,before){
3492
+ if (node instanceof ImbaTag) {
3493
+ root.insertBefore(node,before);
3494
+ } else if (node instanceof Array) {
3495
+ for (var i = 0, ary = iter$(node), len = ary.length; i < len; i++) {
3496
+ insertNestedBefore(root,ary[i],before);
3497
+ };
3498
+ } else if (node != null && node !== false) {
3499
+ root.insertBefore(Imba.document().createTextNode(node),before);
3500
+ };
3501
+
3502
+ return before;
3503
+ };
3504
+
3505
+ // after must be an actual domnode
3506
+ function insertNestedAfter(root,node,after){
3507
+ var before = after ? (after.nextSibling) : (root._dom.firstChild);
3508
+
3509
+ if (before) {
3510
+ insertNestedBefore(root,node,before);
3511
+ return before.previousSibling;
3512
+ } else {
3513
+ appendNested(root,node);
3514
+ return root._dom.lastChild;
3515
+ };
3516
+ };
3517
+
3518
+ function reconcileCollectionChanges(root,new$,old,caret){
3519
+
3520
+ var newLen = new$.length;
3521
+ var lastNew = new$[newLen - 1];
3522
+
3523
+ // This re-order algorithm is based on the following principle:
3524
+ //
3525
+ // We build a "chain" which shows which items are already sorted.
3526
+ // If we're going from [1, 2, 3] -> [2, 1, 3], the tree looks like:
3527
+ //
3528
+ // 3 -> 0 (idx)
3529
+ // 2 -> -1 (idx)
3530
+ // 1 -> -1 (idx)
3531
+ //
3532
+ // This tells us that we have two chains of ordered items:
3533
+ //
3534
+ // (1, 3) and (2)
3535
+ //
3536
+ // The optimal re-ordering then becomes two keep the longest chain intact,
3537
+ // and move all the other items.
3538
+
3539
+ var newPosition = [];
3540
+
3541
+ // The tree/graph itself
3542
+ var prevChain = [];
3543
+ // The length of the chain
3544
+ var lengthChain = [];
3545
+
3546
+ // Keep track of the longest chain
3547
+ var maxChainLength = 0;
3548
+ var maxChainEnd = 0;
3549
+
3550
+ for (var idx = 0, ary = iter$(old), len = ary.length, node; idx < len; idx++) {
3551
+ node = ary[idx];
3552
+ var newPos = new$.indexOf(node);
3553
+ newPosition.push(newPos);
3554
+
3555
+ if (newPos == -1) {
3556
+ root.removeChild(node);
3557
+ prevChain.push(-1);
3558
+ lengthChain.push(-1);
3559
+ continue;
3560
+ };
3561
+
3562
+ var prevIdx = newPosition.length - 2;
3563
+
3564
+ // Build the chain:
3565
+ while (prevIdx >= 0){
3566
+ if (newPosition[prevIdx] == -1) {
3567
+ prevIdx--;
3568
+ } else if (newPos > newPosition[prevIdx]) {
3569
+ // Yay, we're bigger than the previous!
3570
+ break;
3571
+ } else {
3572
+ // Nope, let's walk back the chain
3573
+ prevIdx = prevChain[prevIdx];
3574
+ };
3575
+ };
3576
+
3577
+ prevChain.push(prevIdx);
3578
+
3579
+ var currLength = (prevIdx == -1) ? (0) : (lengthChain[prevIdx] + 1);
3580
+
3581
+ if (currLength > maxChainLength) {
3582
+ maxChainLength = currLength;
3583
+ maxChainEnd = idx;
3584
+ };
3585
+
3586
+ lengthChain.push(currLength);
3587
+ };
3588
+
3589
+ var stickyNodes = [];
3590
+
3591
+ // Now we can walk the longest chain backwards and mark them as "sticky",
3592
+ // which implies that they should not be moved
3593
+ var cursor = newPosition.length - 1;
3594
+ while (cursor >= 0){
3595
+ if (cursor == maxChainEnd && newPosition[cursor] != -1) {
3596
+ stickyNodes[newPosition[cursor]] = true;
3597
+ maxChainEnd = prevChain[maxChainEnd];
3598
+ };
3599
+
3600
+ cursor -= 1;
3601
+ };
3602
+
3603
+ // And let's iterate forward, but only move non-sticky nodes
3604
+ for (var idx1 = 0, ary = iter$(new$), len = ary.length; idx1 < len; idx1++) {
3605
+ if (!stickyNodes[idx1]) {
3606
+ var after = new$[idx1 - 1];
3607
+ insertNestedAfter(root,ary[idx1],(after && after._dom) || caret);
3608
+ };
3609
+ };
3610
+
3611
+ // should trust that the last item in new list is the caret
3612
+ return lastNew && lastNew._dom || caret;
3613
+ };
3614
+
3615
+
3616
+ // expects a flat non-sparse array of nodes in both new and old, always
3617
+ function reconcileCollection(root,new$,old,caret){
3618
+ var k = new$.length;
3619
+ var i = k;
3620
+ var last = new$[k - 1];
3621
+
3622
+
3623
+ if (k == old.length && new$[0] === old[0]) {
3624
+ // running through to compare
3625
+ while (i--){
3626
+ if (new$[i] !== old[i]) { break; };
3627
+ };
3628
+ };
3629
+
3630
+ if (i == -1) {
3631
+ return last && last._dom || caret;
3632
+ } else {
3633
+ return reconcileCollectionChanges(root,new$,old,caret);
3634
+ };
3635
+ };
3636
+
3637
+ // the general reconciler that respects conditions etc
3638
+ // caret is the current node we want to insert things after
3639
+ function reconcileNested(root,new$,old,caret){
3640
+
3641
+ // if new == null or new === false or new === true
3642
+ // if new === old
3643
+ // return caret
3644
+ // if old && new != old
3645
+ // removeNested(root,old,caret) if old
3646
+ //
3647
+ // return caret
3648
+
3649
+ // var skipnew = new == null or new === false or new === true
3650
+ var newIsNull = new$ == null || new$ === false;
3651
+ var oldIsNull = old == null || old === false;
3652
+
3653
+
3654
+ if (new$ === old) {
3655
+ // remember that the caret must be an actual dom element
3656
+ // we should instead move the actual caret? - trust
3657
+ if (newIsNull) {
3658
+ return caret;
3659
+ } else if (new$ && new$._dom) {
3660
+ return new$._dom;
3661
+ } else {
3662
+ return caret ? (caret.nextSibling) : (root._dom.firstChild);
3663
+ };
3664
+ } else if (new$ instanceof Array) {
3665
+ if (old instanceof Array) {
3666
+ if (new$.static || old.static) {
3667
+ // if the static is not nested - we could get a hint from compiler
3668
+ // and just skip it
3669
+ if (new$.static == old.static) {
3670
+ for (var i = 0, ary = iter$(new$), len = ary.length; i < len; i++) {
3671
+ // this is where we could do the triple equal directly
3672
+ caret = reconcileNested(root,ary[i],old[i],caret);
3673
+ };
3674
+ return caret;
3675
+ } else {
3676
+ removeNested(root,old,caret);
3677
+ };
3678
+
3679
+ // if they are not the same we continue through to the default
3680
+ } else {
3681
+ return reconcileCollection(root,new$,old,caret);
3682
+ };
3683
+ } else if (old instanceof ImbaTag) {
3684
+ root.removeChild(old);
3685
+ } else if (!(oldIsNull)) {
3686
+ // old was a string-like object?
3687
+ root.removeChild(caret ? (caret.nextSibling) : (root._dom.firstChild));
3688
+ };
3689
+
3690
+ return insertNestedAfter(root,new$,caret);
3691
+ // remove old
3692
+ } else if (new$ instanceof ImbaTag) {
3693
+ if (!(oldIsNull)) { removeNested(root,old,caret) };
3694
+ insertNestedAfter(root,new$,caret);
3695
+ return new$;
3696
+ } else if (newIsNull) {
3697
+ if (!(oldIsNull)) { removeNested(root,old,caret) };
3698
+ return caret;
3699
+ } else {
3700
+ // if old did not exist we need to add a new directly
3701
+ var nextNode;
3702
+ // if old was array or imbatag we need to remove it and then add
3703
+ if (old instanceof Array) {
3704
+ removeNested(root,old,caret);
3705
+ } else if (old instanceof ImbaTag) {
3706
+ root.removeChild(old);
3707
+ } else if (!(oldIsNull)) {
3708
+ // ...
3709
+ nextNode = caret ? (caret.nextSibling) : (root._dom.firstChild);
3710
+ if ((nextNode instanceof Text) && nextNode.textContent != new$) {
3711
+ nextNode.textContent = new$;
3712
+ return nextNode;
3713
+ };
3714
+ };
3715
+
3716
+ // now add the textnode
3717
+ return insertNestedAfter(root,new$,caret);
3718
+ };
3719
+ };
3720
+
3721
+
3722
+ return tag$.extendTag('htmlelement', function(tag){
3723
+
3724
+ tag.prototype.setChildren = function (new$,typ){
3725
+ var old = this._children;
3726
+ // var isArray = nodes isa Array
3727
+ if (new$ === old) {
3728
+ return this;
3729
+ };
3730
+
3731
+ if (!(old)) {
3732
+ this.empty();
3733
+ appendNested(this,new$);
3734
+ } else if (typ == 2) {
3735
+ return this;
3736
+ } else if (typ == 1) {
3737
+ // here we _know _that it is an array with the same shape
3738
+ // every time
3739
+ var caret = null;
3740
+ for (var i = 0, ary = iter$(new$), len = ary.length; i < len; i++) {
3741
+ // prev = old[i]
3742
+ caret = reconcileNested(this,ary[i],old[i],caret);
3743
+ };
3744
+ } else if (typ == 3) {
3745
+ // this is possibly fully dynamic. It often is
3746
+ // but the old or new could be static while the other is not
3747
+ // this is not handled now
3748
+ // what if it was previously a static array? edgecase - but must work
3749
+ if (new$ instanceof ImbaTag) {
3750
+ this.empty();
3751
+ this.appendChild(new$);
3752
+ } else if (new$ instanceof Array) {
3753
+ if (old instanceof Array) {
3754
+ // is this not the same as setting staticChildren now but with the
3755
+ reconcileCollection(this,new$,old,null);
3756
+ } else {
3757
+ this.empty();
3758
+ appendNested(this,new$);
3759
+ };
3760
+ } else {
3761
+ this.setText(new$);
3762
+ return this;
3763
+ };
3764
+ } else if ((new$ instanceof Array) && (old instanceof Array)) {
3765
+ reconcileCollection(this,new$,old,null);
3766
+ } else {
3767
+ this.empty();
3768
+ appendNested(this,new$);
3769
+ };
3770
+
3771
+ this._children = new$;
3772
+ return this;
3773
+ };
3774
+
3775
+
3776
+ // only ever called with array as argument
3777
+ tag.prototype.setStaticChildren = function (new$){
3778
+ var old = this._children;
3779
+
3780
+ var caret = null;
3781
+ for (var i = 0, ary = iter$(new$), len = ary.length; i < len; i++) {
3782
+ // prev = old[i]
3783
+ caret = reconcileNested(this,ary[i],old[i],caret);
3784
+ };
3785
+
3786
+ this._children = new$;
3787
+ return this;
3788
+ };
3789
+
3790
+ tag.prototype.content = function (){
3791
+ return this._content || this.children().toArray();
3792
+ };
3793
+
3794
+ tag.prototype.setText = function (text){
3795
+ if (text != this._children) {
3796
+ this._children = text;
3797
+ this.dom().textContent = text == null || text === false ? ('') : (text);
3798
+ };
3799
+ return this;
3800
+ };
3801
+ });
3802
+
3803
+ })()
3804
+
3805
+ /***/ },
3806
+ /* 11 */
3807
+ /***/ function(module, exports) {
3808
+
3809
+ (function(){
3810
+ function iter$(a){ return a ? (a.toArray ? a.toArray() : a) : []; };
3811
+
3812
+ /*
3813
+ The special syntax for selectors in Imba creates Imba.Selector
3814
+ instances.
3815
+ */
3816
+
3817
+ Imba.Selector = function Selector(sel,scope,nodes){
3818
+
3819
+ this._query = sel instanceof Imba.Selector ? (sel.query()) : (sel);
3820
+ this._context = scope;
3821
+
3822
+ if (nodes) {
3823
+ for (var i = 0, ary = iter$(nodes), len = ary.length, res = []; i < len; i++) {
3824
+ res.push(tag$wrap(ary[i]));
3825
+ };
3826
+ this._nodes = res;
3827
+ };
3828
+
3829
+ this._lazy = !(nodes);
3830
+ return this;
3831
+ };
3832
+
3833
+ Imba.Selector.one = function (sel,scope){
3834
+ var el = (scope || Imba.document()).querySelector(sel);
3835
+ return el && tag$wrap(el) || null;
3836
+ };
3837
+
3838
+ Imba.Selector.all = function (sel,scope){
3839
+ return new Imba.Selector(sel,scope);
3840
+ };
3841
+
3842
+ Imba.Selector.prototype.query = function(v){ return this._query; }
3843
+ Imba.Selector.prototype.setQuery = function(v){ this._query = v; return this; };
3844
+
3845
+ Imba.Selector.prototype.reload = function (){
3846
+ this._nodes = null;
3847
+ return this;
3848
+ };
3849
+
3850
+ Imba.Selector.prototype.scope = function (){
3851
+ var ctx;
3852
+ if (this._scope) { return this._scope };
3853
+ if (!(ctx = this._context)) { return Imba.document() };
3854
+ return this._scope = ctx.toScope ? (ctx.toScope()) : (ctx);
3855
+ };
3856
+
3857
+ /*
3858
+ @returns {Imba.Tag} first node matching this selector
3859
+ */
3860
+
3861
+ Imba.Selector.prototype.first = function (){
3862
+ if (this._lazy) { return tag$wrap(this._first || (this._first = this.scope().querySelector(this.query()))) } else {
3863
+ return this.nodes()[0];
3864
+ };
3865
+ };
3866
+
3867
+ /*
3868
+ @returns {Imba.Tag} last node matching this selector
3869
+ */
3870
+
3871
+ Imba.Selector.prototype.last = function (){
3872
+ return this.nodes()[this._nodes.length - 1];
3873
+ };
3874
+
3875
+ /*
3876
+ @returns [Imba.Tag] all nodes matching this selector
3877
+ */
3878
+
3879
+ Imba.Selector.prototype.nodes = function (){
3880
+ if (this._nodes) { return this._nodes };
3881
+ var items = this.scope().querySelectorAll(this.query());
3882
+ for (var i = 0, ary = iter$(items), len = ary.length, res = []; i < len; i++) {
3883
+ res.push(tag$wrap(ary[i]));
3884
+ };
3885
+ this._nodes = res;
3886
+ this._lazy = false;
3887
+ return this._nodes;
3888
+ };
3889
+
3890
+ /*
3891
+ The number of nodes matching this selector
3892
+ */
3893
+
3894
+ Imba.Selector.prototype.count = function (){
3895
+ return this.nodes().length;
3896
+ };
3897
+
3898
+ Imba.Selector.prototype.len = function (){
3899
+ return this.nodes().length;
3900
+ };
3901
+
3902
+ /*
3903
+ @todo Add support for block or selector?
3904
+ */
3905
+
3906
+ Imba.Selector.prototype.some = function (){
3907
+ return this.count() >= 1;
3908
+ };
3909
+
3910
+ /*
3911
+ Get node at index
3912
+ */
3913
+
3914
+ Imba.Selector.prototype.at = function (idx){
3915
+ return this.nodes()[idx];
3916
+ };
3917
+
3918
+ /*
3919
+ Loop through nodes
3920
+ */
3921
+
3922
+ Imba.Selector.prototype.forEach = function (block){
3923
+ this.nodes().forEach(block);
3924
+ return this;
3925
+ };
3926
+
3927
+ /*
3928
+ Map nodes
3929
+ */
3930
+
3931
+ Imba.Selector.prototype.map = function (block){
3932
+ return this.nodes().map(block);
3933
+ };
3934
+
3935
+ /*
3936
+ Returns a plain array containing nodes. Implicitly called
3937
+ when iterating over a selector in Imba `(node for node in $(selector))`
3938
+ */
3939
+
3940
+ Imba.Selector.prototype.toArray = function (){
3941
+ return this.nodes();
3942
+ };
3943
+
3944
+ // Get the first element that matches the selector,
3945
+ // beginning at the current element and progressing up through the DOM tree
3946
+ Imba.Selector.prototype.closest = function (sel){
3947
+ // seems strange that we alter this selector?
3948
+ this._nodes = this.map(function(node) { return node.closest(sel); });
3949
+ return this;
3950
+ };
3951
+
3952
+ // Get the siblings of each element in the set of matched elements,
3953
+ // optionally filtered by a selector.
3954
+ // TODO remove duplicates?
3955
+ Imba.Selector.prototype.siblings = function (sel){
3956
+ this._nodes = this.map(function(node) { return node.siblings(sel); });
3957
+ return this;
3958
+ };
3959
+
3960
+ // Get the descendants of each element in the current set of matched
3961
+ // elements, filtered by a selector.
3962
+ Imba.Selector.prototype.find = function (sel){
3963
+ this._nodes = this.__query__(sel.query(),this.nodes());
3964
+ return this;
3965
+ };
3966
+
3967
+ Imba.Selector.prototype.reject = function (blk){
3968
+ return this.filter(blk,false);
3969
+ };
3970
+
3971
+ /*
3972
+ Filter the nodes in selector by a function or other selector
3973
+ */
3974
+
3975
+ Imba.Selector.prototype.filter = function (blk,bool){
3976
+ if(bool === undefined) bool = true;
3977
+ var fn = (blk instanceof Function) && blk || function(n) { return n.matches(blk); };
3978
+ var ary = this.nodes().filter(function(n) { return fn(n) == bool; });
3979
+ // if we want to return a new selector for this, we should do that for
3980
+ // others as well
3981
+ return new Imba.Selector("",this._scope,ary);
3982
+ };
3983
+
3984
+ Imba.Selector.prototype.__query__ = function (query,contexts){
3985
+ var nodes = [];
3986
+ var i = 0;
3987
+ var l = contexts.length;
3988
+
3989
+ while (i < l){
3990
+ nodes.push.apply(nodes,contexts[i++].querySelectorAll(query));
3991
+ };
3992
+ return nodes;
3993
+ };
3994
+
3995
+ Imba.Selector.prototype.__matches__ = function (){
3996
+ return true;
3997
+ };
3998
+
3999
+ /*
4000
+ Add specified flag to all nodes in selector
4001
+ */
4002
+
4003
+ Imba.Selector.prototype.flag = function (flag){
4004
+ return this.forEach(function(n) { return n.flag(flag); });
4005
+ };
4006
+
4007
+ /*
4008
+ Remove specified flag from all nodes in selector
4009
+ */
4010
+
4011
+ Imba.Selector.prototype.unflag = function (flag){
4012
+ return this.forEach(function(n) { return n.unflag(flag); });
4013
+ };
4014
+
4015
+
4016
+ // def Imba.querySelectorAll
4017
+ q$ = function(sel,scope) { return new Imba.Selector(sel,scope); };
4018
+
4019
+ // def Imba.Selector.one
4020
+ q$$ = function(sel,scope) {
4021
+ var el = (scope || Imba.document()).querySelector(sel);
4022
+ return el && tag$wrap(el) || null;
4023
+ };
4024
+
4025
+
4026
+ // extending tags with query-methods
4027
+ // must be a better way to reopen classes
4028
+ return tag$.extendTag('element', function(tag){
4029
+ tag.prototype.querySelectorAll = function (q){
4030
+ return this._dom.querySelectorAll(q);
4031
+ };
4032
+ tag.prototype.querySelector = function (q){
4033
+ return this._dom.querySelector(q);
4034
+ };
4035
+
4036
+ // should be moved to Imba.Tag instead?
4037
+ // or we should implement all of them here
4038
+ tag.prototype.find = function (sel){
4039
+ return new Imba.Selector(sel,this);
4040
+ };
4041
+ });
4042
+
4043
+
4044
+ })()
4045
+
4046
+ /***/ }
4047
+ /******/ ]);
4048
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay9ib290c3RyYXAgYmNmNDBhNWMzMzRhYzIxOTc1MzEiLCJ3ZWJwYWNrOi8vL3NyYy9pbWJhL2luZGV4LmltYmEiLCJ3ZWJwYWNrOi8vL3NyYy9pbWJhL2ltYmEuaW1iYSIsIndlYnBhY2s6Ly8vc3JjL2ltYmEvY29yZS5ldmVudHMuaW1iYSIsIndlYnBhY2s6Ly8vc3JjL2ltYmEvc2NoZWR1bGVyLmltYmEiLCJ3ZWJwYWNrOi8vL3NyYy9pbWJhL3RhZy5pbWJhIiwid2VicGFjazovLy9zcmMvaW1iYS9kb20uaW1iYSIsIndlYnBhY2s6Ly8vc3JjL2ltYmEvZG9tLmh0bWwuaW1iYSIsIndlYnBhY2s6Ly8vc3JjL2ltYmEvZG9tLnN2Zy5pbWJhIiwid2VicGFjazovLy9zcmMvaW1iYS9kb20uY2xpZW50LmltYmEiLCJ3ZWJwYWNrOi8vL3NyYy9pbWJhL2RvbS5ldmVudHMuaW1iYSIsIndlYnBhY2s6Ly8vc3JjL2ltYmEvZG9tLnN0YXRpYy5pbWJhIiwid2VicGFjazovLy9zcmMvaW1iYS9zZWxlY3Rvci5pbWJhIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSx1QkFBZTtBQUNmO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOzs7Ozs7Ozs7RUNyQ0EsV0FBVSxLQUFLO0dBQ2Q7R0FDQTtHQUNBO0dBQ0E7R0FDQTtHQUNBO0dBQ0E7O0dBRUEsSUFBRyxLQUFLO0lBQ1A7OztHQUVELElBQUcsSUFBSztJQUNQO0lBQ0E7SUFDQTs7O1VBRUQ7O1VBRUEsUUFBUSxrQkFBYSxLQUFLOzs7Ozs7Ozs7O0VDcEIzQixXQUFVLE9BQU87O0dBRWhCLE9BQU8sRUFBRTs7O01BRU4sU0FBUyxVQUFVLE9BQU8sWUFBWSxRQUFTLEdBQUc7Ozs7OztFQUt0RCxLQUFLOztXQUVJO2FBQ0M7Ozs7TUFJTixJQUFJOzs7Ozs7O0VBTUo7VUFDSCxNQUFLLENBQU87Ozs7Ozs7O0VBTVQ7VUFDSCxPQUFLLENBQU87OztFQUVUOztHQUNIO0lBQ1ksSUFBRyxJQUFJLGVBQWUsTUFBakMsSUFBSSxHQUFHLEVBQUU7OztHQUVWLElBQUksVUFBVSxFQUFFLE9BQU8sT0FBTyxJQUFJO0dBQ2xDLElBQUksVUFBVSxFQUFFLElBQUksVUFBVSxVQUFVLEVBQUUsSUFBSTtHQUM5QyxJQUFJLFVBQVUsV0FBVyxFQUFFLElBQUksVUFBVSxZQUFZLEVBQUU7VUFDaEQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztFQXNCSjtVQUNJLE1BQUssRUFBRSxXQUFVLEVBQUUsY0FBVTs7Ozs7Ozs7Ozs7RUFTakM7R0FDSCxJQUFHLGlCQUFVO1dBQ1osUUFBUSxJQUFJO1VBQ2IsSUFBSyxNQUFNLEdBQUksTUFBTTtXQUNwQjs7V0FFQSxRQUFRLFFBQVE7Ozs7RUFFZDtVQUNILElBQUksUUFBUSx5QkFBWSxFQUFFLE9BQU8sR0FBRzs7O0VBRWpDO1VBQ0gsSUFBSSxRQUFRLHlCQUFZLEVBQUUsT0FBTyxHQUFHOzs7RUFFakM7V0FDSyxFQUFFLEdBQUcsRUFBRSxZQUFXLEVBQUUsUUFBUSxVQUFRLFFBQVEsS0FBSyxFQUFFOzs7RUFFeEQ7R0FDSCxJQUFHLE1BQU07V0FDRCxNQUFNLGVBQWUsS0FBSzs7Ozs7U0FHL0I7R0FDSCxJQUFHLE1BQU07V0FDRCxNQUFNLGdCQUFnQixLQUFLOzs7T0FFL0IsUUFBUSxFQUFFLEtBQUssWUFBWTtPQUMzQixRQUFRLEVBQUUsS0FBSyxtQkFBbUIsRUFBRTs7R0FFeEMsTUFBTSxVQUFVLFNBQVM7Z0JBQ1osYUFBYTs7O0dBRTFCLE1BQU0sVUFBVSxTQUFTO1NBQ25CLGFBQWEsS0FBSzs7Ozs7Ozs7Ozs7Ozs7Ozs7RUN0R3pCOztPQUVLLEtBQU0sR0FBSTs7V0FFUCxLQUFLLEVBQUUsTUFBTSxJQUFLLEtBQUssRUFBRSxLQUFLO0lBQ3BDLElBQUcsR0FBRyxFQUFFLEtBQUs7S0FDWixJQUFHLEtBQUssS0FBSyxHQUFJLEdBQUcsS0FBSztNQUN4QixJQUFJLEVBQUUsUUFBTyxHQUFHLEtBQUssTUFBTSxNQUFNLEdBQUcsVUFBUSxHQUFHLEtBQUs7OztNQUdwRCxJQUFJLEVBQUUsUUFBTyxHQUFHLE1BQU0sS0FBTSxVQUFRLEdBQUcsS0FBSzs7OztJQUU5QyxJQUFHLEtBQUssTUFBTSxLQUFLLEtBQUssTUFBTSxHQUFHO0tBQ2hDLEtBQUssS0FBSyxFQUFFLEtBQUs7S0FDakIsS0FBSyxTQUFTOzs7Ozs7O0VBSWI7O09BQ0MsSUFBSyxLQUFNO0dBQ2YsSUFBSSxFQUFFLElBQUksa0JBQUosSUFBSTtHQUNWLEtBQUssRUFBRSxVQUFJLFlBQUo7R0FDUCxLQUFLLEVBQUUsS0FBSyxLQUFLLElBQUksS0FBSyxLQUFLLEdBQUcsS0FBSyxLQUFLO0dBQzVDLEtBQUssU0FBUyxFQUFFO0dBQ2hCLEtBQUssS0FBSyxFQUFFO0dBQ1osS0FBSyxLQUFLLEVBQUUsS0FBSyxLQUFLO1VBQ2Y7OztFQUVKO09BQ0MsS0FBSyxFQUFFLEtBQUssT0FBTyxJQUFJLE1BQU07R0FDakMsS0FBSyxNQUFNLEVBQUU7VUFDTjs7O0VBRUo7T0FDQyxLQUFNO09BQ04sS0FBSyxFQUFFLElBQUk7R0FDUixNQUFPOztHQUVkLElBQUcsS0FBSyxFQUFFLEtBQUs7WUFDUCxLQUFLLEVBQUUsTUFBTSxJQUFLLEtBQUssRUFBRSxLQUFLO0tBQ3BDLElBQUcsS0FBSyxHQUFHLEdBQUcsR0FBRyxLQUFLLFNBQVMsR0FBRztNQUNqQyxLQUFLLEtBQUssRUFBRSxLQUFLOztNQUVqQixLQUFLLFNBQVM7Ozs7Ozs7O0VBSWQ7O0dBQ0gsSUFBTyxHQUFHLEVBQUUsSUFBSTtJQUNnQixJQUFHLEdBQUcsVUFBckMsT0FBTyxNQUFNLE9BQU8sR0FBRztJQUNhLElBQUcsR0FBRyxPQUExQyxPQUFPLE9BQU8sTUFBTSxRQUFRLEdBQUc7Ozs7O1NBRzdCO0dBQ0gsSUFBRyxLQUFLLFVBQVcsS0FBSztJQUN2QixLQUFLLFNBQVMsV0FBVyxTQUFTOztHQUNuQyxJQUFHLE9BQU8sVUFBVyxPQUFPO0lBQzNCLEtBQUssT0FBTyxhQUFhLFNBQVM7Ozs7Ozs7Ozs7Ozs7Ozs7O01DMURoQztFQUNKLGNBQVEsT0FBTztFQUNmLGNBQVEsT0FBTztFQUNmLGNBQVEsT0FBTztFQUNmLHFDQUFpQixXQUFXLElBQUksS0FBSyxFQUFFOztFQUVuQztHQUNjLFNBQUcsY0FBcEIsSUFBSSxLQUFLO0dBQ1QsS0FBSyxVQUFVO1FBQ2Ysa0JBQWtCO0dBQ2xCLEtBQUssVUFBVTs7OztFQUdaOztlQUNILHFEQUFtQixLQUFLOzs7Ozs7Ozs7OztFQVNyQjs7UUFDSCxtQkFBbUIsT0FBTzs7R0FFMUIsVUFBTztTQUNOLFdBQVc7SUFDWCxJQUFJLEtBQUs7Ozs7Ozs7Ozs7O0VBUVA7UUFDSCxxQkFBcUIsT0FBTztPQUN4QixJQUFJLE9BQU87R0FDZixLQUFJLElBQUksS0FBSyxJQUFJLElBQUksS0FBSyxLQUFLLElBQUksSUFBSSxLQUFLLEtBQUs7U0FDaEQsV0FBVzs7Ozs7Ozs7Ozs7OztFQVVUO1VBQ0g7SUFDQztXQUNBLEtBQUssVUFBVTs7S0FGSDs7Ozs7Ozs7Ozs7RUFZVjtVQUNIO0lBQ0M7V0FDQSxLQUFLLFVBQVU7O0tBRkY7Ozs7Ozs7RUFRWDtVQUNILGNBQWM7Ozs7Ozs7RUFLWDtVQUNILGFBQWE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7RUFpQlIsS0FBSyxZQXVCVixTQXZCVTs7UUF3QlQsUUFBUSxFQUFFO1FBQ1YsUUFBUTtRQUNSLFFBQVE7UUFDUixRQUFRLHNCQUFLO1FBQ2IsUUFBUSw0QkFBUyxLQUFLOztRQUV0QixRQUFRO1FBQ1IsS0FBSyxFQUFFOztRQUVQLElBQUksRUFBRTtRQUNOLFdBQVcsRUFBRTtRQUNiLE9BQU8sRUFBRTtRQUNULFNBQVMsRUFBRTs7O0VBbENaLEtBRlU7UUFHVCxPQUFPOzs7O0VBR1IsS0FOVTtrQkFPUDs7O0VBRUgsS0FUVTtlQVVULFFBQVE7OztFQUVULEtBWlU7UUFhVCxRQUFRO2VBQ1IsT0FBTzs7O0VBRVIsS0FoQlU7a0JBaUJQOzs7Ozs7Ozs7Ozs7O0VBeUJILEtBMUNVO2VBMkNUOzs7Ozs7OztFQU1ELEtBakRVO2VBa0RUOzs7Ozs7OztFQU1ELEtBeERVOztpREF3RFM7O0dBQ0QsSUFBRyxPQUFPLGdCQUEzQixRQUFRLEVBQUU7R0FDQyxJQUFHLElBQUksZ0JBQWxCLEtBQUssRUFBRTs7Ozs7Ozs7OztFQVFSLEtBbEVVO1FBbUVULFFBQVE7Ozs7Ozs7Ozs7O0VBU1QsS0E1RVU7UUE2RVQsUUFBUTtRQUNSO1FBQ0EsUUFBUTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7RUFxQlQsS0FwR1U7UUFxR1Q7UUFDQSxJQUFJLEVBQUU7O09BRUYsSUFBSSxPQUFFOztHQUVWLElBQUcsSUFBSSxHQUFHO1NBQ1QsUUFBUTtVQUNULElBQUssSUFBSSxHQUFHO0lBQ0csU0FBRyxPQUFPLEVBQUUsVUFBMUIsUUFBUTtVQUNULElBQUs7Ozs7OztRQU1BLE9BQU8sSUFBSSxHQUFHLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRTtRQUM3QixLQUFLLEVBQUUsS0FBSyxNQUFNLEtBQUssTUFBSSxFQUFFOztJQUVqQyxTQUFHLE1BQU0sR0FBRztVQUNYLE1BQU0sRUFBRTtVQUNSLFFBQVE7Ozs7R0FFSixTQUFHLFFBQVEsU0FBSSxRQUFRLEdBQUksS0FBSyxVQUFVLFlBQWhEOzs7Ozs7Ozs7Ozs7OztFQVlELEtBdklVO0dBd0lULFVBQU87U0FDTixRQUFROztTQUVSLFFBQVEsT0FBRSxRQUFRO1NBQ2xCLFFBQVEsT0FBTztJQUNmLEtBQUs7SUFDb0MsU0FBRyxXQUE1QyxLQUFLLE9BQU87U0FDWix3QkFBUyxlQUFULFFBQVM7U0FDVCxLQUFLOzs7Ozs7Ozs7RUFNUCxLQXRKVTtHQXVKVCxTQUFHO1NBQ0YsUUFBUTtTQUNSLFFBQVEsT0FBTyxPQUFFO0lBQ2pCLEtBQUs7SUFDTCxLQUFLLFNBQVM7U0FDZCx3QkFBUyxpQkFBVCxRQUFTOzs7OztFQUdYLEtBL0pVO2VBZ0tUOzs7RUFFRCxLQWxLVTs7R0FtS0csU0FBRzs7R0FFZixTQUFHLG1CQUFZO0lBQ1QsU0FBRyxRQUFRLFFBQWhCO1VBQ0QsU0FBSyxtQkFBWTtJQUNYLFNBQUcsbUJBQU8sVUFBUCxHQUFPLFlBQVEsZUFBdkI7VUFDRCxTQUFLO0lBQ0MsSUFBRyxNQUFNLFlBQWQ7Ozs7U0ExS0csS0FBSzs7Ozs7Ozs7Ozs7Ozs7RUNqR1A7R0FDSCxNQUFNLE9BQU8sRUFBRTtVQUNSOzs7Ozs7OztFQU1GLEtBQUssTUFhVixTQWJVO1FBY0osT0FBTTs7O0VBWlosS0FGVTs7OztFQUtWLEtBTFU7d0JBTUs7OztFQU5WLEtBQUs7RUFBTCxLQUFLOztFQVVWLEtBVlU7ZUFXVDs7O0VBS0QsS0FoQlU7R0FpQlQsSUFBSSxLQUFLO1FBQ1QsS0FBSyxFQUFFOzs7Ozs7Ozs7OztFQVNSLEtBM0JVO1FBNEJULFVBQUssS0FBSyxFQUFFOzs7Ozs7Ozs7Ozs7RUFVYixLQXRDVTtPQXVDTCxJQUFJLE9BQU8sRUFBRTs7R0FFakIsSUFBRyxtQkFBWTtTQUNULEtBQUssRUFBRTtVQUNiLElBQUssbUJBQVk7UUFDWixHQUFHLEVBQUUsUUFBUTtTQUNaLEtBQUssdUJBQVMsSUFBSSxJQUFJLE1BQU0sSUFBSSxRQUFRLE9BQU87O1NBRS9DLEtBQUssdUJBQVMsSUFBSSxTQUFTOzs7OztFQUdsQyxLQWxEVTtHQW1EVCxXQUFJLEdBQUcsRUFBRTs7OztFQUdWLEtBdERVO1VBdURULFdBQUk7Ozs7Ozs7Ozs7RUFRTCxLQS9EVTs7T0FpRUwsSUFBSSxFQUFFLFdBQUksYUFBYTs7R0FFM0IsSUFBRyxJQUFJLEdBQUc7V0FDVDtVQUNELElBQUssTUFBTSxRQUFRLEdBQUcsTUFBTTtXQUMzQixXQUFJLGFBQWEsS0FBSzs7V0FFdEIsV0FBSSxnQkFBZ0I7Ozs7Ozs7O0VBS3RCLEtBN0VVO1VBOEVULFdBQUksZ0JBQWdCOzs7Ozs7Ozs7RUFPckIsS0FyRlU7VUFzRlQsV0FBSSxhQUFhOzs7Ozs7OztFQU1sQixLQTVGVTtRQTZGVCxZQUFZLFFBQVM7Ozs7Ozs7Ozs7RUFRdEIsS0FyR1U7Ozs7Ozs7Ozs7RUE2R1YsS0E3R1U7ZUE4R1QsS0FBSzs7Ozs7Ozs7RUFNTixLQXBIVTtRQXFIVCxPQUFPO1FBQ1AsS0FBSyxZQUFZLEVBQUU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0VBa0JwQixLQXhJVTs7Ozs7Ozs7OztFQWdKVixLQWhKVTs7Ozs7Ozs7Ozs7RUF5SlYsS0F6SlU7R0EwSlQ7Ozs7Ozs7Ozs7RUFRRCxLQWxLVTtHQW1LVDs7Ozs7Ozs7Ozs7O0VBVUQsS0E3S1U7R0E4S1Q7Ozs7Ozs7Ozs7Ozs7Ozs7RUFjRCxLQTVMVTtHQTZMVCxTQUFHO0lBQ0Y7O1NBRUEsT0FBTztJQUNQOzs7Ozs7Ozs7OztFQVFGLEtBek1VOzs7Ozs7O0VBK01WLEtBL01VOzs7Ozs7OztFQXFOVixLQXJOVTtlQXNOVCxLQUFLOzs7Ozs7Ozs7O0VBUU4sS0E5TlU7OztHQWlPVCxjQUFhLE9BQU8sR0FBRyxFQUFFLEtBQUs7U0FDN0IsS0FBSyxVQUFVLE9BQU87O1NBRXRCLEtBQUssVUFBVSxJQUFJOzs7Ozs7Ozs7O0VBT3JCLEtBM09VO1FBNE9ULEtBQUssVUFBVSxPQUFPOzs7Ozs7Ozs7RUFPdkIsS0FuUFU7UUFvUFQsS0FBSyxVQUFVLE9BQU87Ozs7Ozs7OztFQU92QixLQTNQVTtlQTRQVCxLQUFLLFVBQVUsU0FBUzs7Ozs7Ozs7OztFQVF6QixLQXBRVTtlQXFRVCw0Q0FBYyxLQUFLLHlCQUFuQjs7Ozs7Ozs7Ozs7O0VBVUQsS0EvUVU7O0dBZ1JULGlCQUFVLFVBQVUsU0FBUzs7Ozs7Ozs7O0VBTzlCLEtBdlJVO0dBd1JZLFNBQUcsY0FBeEIsaUJBQVU7Ozs7Ozs7Ozs7RUFRWCxLQWhTVTttQkFpU0wsV0FBSTs7Ozs7Ozs7RUFNVCxLQXZTVTs7OztHQXdTVCxLQUFLLFFBQVE7R0FDYixTQUFTLFVBQVUsS0FBSyxNQUFNLFFBQVEsSUFBSzs7OztFQUc1QyxLQTVTVTtHQTZTVCxJQUFHLGVBQVE7SUFDRDtVQUFULElBQUksUUFBRTs7VUFDUCxJQUFLLElBQUk7SUFDUixXQUFJLE1BQU0sZUFBZTtVQUMxQixJQUFLLElBQUk7V0FDRCxXQUFJLE1BQU07O0lBRWpCLFlBQUcsc0NBQWUsR0FBSSxJQUFJO0tBQ3pCLElBQUksRUFBRSxJQUFJOztJQUNYLFdBQUksTUFBTSxLQUFLLEVBQUU7Ozs7O0VBR25CLEtBelRVO1FBMFRULGdCQUFnQjs7OztFQUdqQixLQTdUVTtlQThUVDs7OztFQUdGLEtBQUssSUFBSSxVQUFVLFdBQVcsRUFBRSxLQUFLOztFQUVyQyxVQUFVLHdrQkFBd2tCO0VBQ2xsQixpQkFBaUIsaUNBQWlDO0VBQ2xELFNBQVMseUhBQXlIOzs7RUFHbEk7R0FDQztJQUNDLFVBQUkscUJBQUosVUFBVSxpQkFBVjs7O0dBRUQsSUFBSSxVQUFVLEVBQUUsT0FBTyxPQUFPLElBQUk7R0FDbEMsSUFBSSxVQUFVLEVBQUUsSUFBSSxVQUFVLFVBQVUsRUFBRSxJQUFJO0dBQzlDLElBQUksVUFBVSxXQUFXLEVBQUUsSUFBSSxVQUFVLFlBQVksRUFBRTtHQUN0QyxJQUFHLElBQUksV0FBeEIsSUFBSSxRQUFRO1VBQ0w7OztFQUVSOztTQUVPLE9BQU87Ozs7O0VBR2Q7OEJBQ1csS0FBSzs7O0VBRVYsS0FBSyxPQUVWLFNBRlU7Ozs7RUFLVixLQUxVO09BTUwsTUFBTSxFQUFFLE9BQU87R0FDbkIsTUFBTSxRQUFRO1VBQ1A7OztFQUVSLEtBVlU7T0FXTCxNQUFNLEVBQUUsT0FBTztHQUNuQixNQUFNLFFBQVE7R0FDZCxNQUFNLElBQUksRUFBRTtRQUNQLEtBQUssZUFBYSxFQUFFO1VBQ2xCOzs7RUFFUixLQWpCVTtlQWtCVCxLQUFROzs7RUFFVCxLQXBCVTs7O0dBcUJULHFCQUFTLFNBQVM7T0FDZCxVQUFVLE9BQU87T0FDakIsUUFBUSxFQUFFO09BQ1YsS0FBSyxFQUFFLEtBQUs7OztHQUdoQixRQUFRLE1BQU0sRUFBRTtHQUNoQixTQUFTLFFBQVE7O0dBRWpCLElBQUcsS0FBSyxHQUFHO1NBQ0wsTUFBTSxFQUFFO0lBQ2IsS0FBSyxXQUFXLEtBQUssTUFBTSxJQUFJLEVBQUU7O1NBRTVCLE1BQU0sRUFBRTthQUNMLEVBQUMsTUFBTSxFQUFFLFdBQVc7OztHQUU3QixJQUFHO0lBQ0YsSUFBRyxLQUFLLE9BQU8sR0FBRzs7S0FFakIsS0FBTyxRQUFRO01BQ2QsUUFBUSxLQUFLLEdBQUcsVUFBVSxLQUFLLFNBQVM7Ozs7SUFFMUMsS0FBSyxLQUFLLFFBQVEsUUFBUyxRQUFRLEtBQUs7OztVQUVsQzs7O0VBRVIsS0EvQ1U7ZUFnRFQsVUFBVSxLQUFLLEtBQUs7OztFQUVyQixLQWxEVTs7O09BbURMLE1BQU0sV0FBRyxnREFBdUIsVUFBUTs7R0FFSSxJQUFHLFFBQW5ELEtBQUssR0FBSSxLQUFLLEtBQUssTUFBTSxNQUFNLE1BQU07VUFDOUI7Ozs7RUFHVCxLQUFLLEtBQUssTUFBRSxLQUFLO0VBQ2pCLEtBQUssYUFBZSxFQUFFLEtBQUs7O01BRXZCLElBQUksRUFBRSxLQUFLLEtBQUs7O0VBRXBCOzs7OztFQUlBLEtBQUssV0FBVzs7O0VBR1o7OztVQUNJLEtBQUssS0FBSyxVQUFVLEtBQUssS0FBSzs7O0VBRWxDOzs7VUFDSSxLQUFLLEtBQUssVUFBVSxZQUFLLEtBQUs7OztFQUVsQztVQUNJLEtBQUssS0FBSyxVQUFVLEtBQUs7OztFQUU3QjtPQUNDLElBQUksRUFBRSxLQUFLLEtBQUs7R0FDeUIsTUFBSSxrQkFBM0MsZ0JBQWdCO2NBQ2YsSUFBUSxJQUFJOzs7RUFFaEI7T0FDQyxJQUFJLEVBQUUsS0FBSyxLQUFLO0dBQ3lCLE1BQUksa0JBQTNDLGdCQUFnQjtPQUNsQixJQUFJLEVBQUUsSUFBSTtHQUNkLElBQUksR0FBRyxFQUFFO2NBQ0YsSUFBUTs7Ozs7O0VBS1o7O09BQ0MsSUFBSzs7R0FFVCxJQUFPLE1BQU0sRUFBRSxLQUFLLFdBQVc7SUFDUixJQUFHLE1BQU0sR0FBSSxNQUFNLG1CQUFsQyxNQUFNOzs7SUFHYixJQUFHLElBQUksRUFBRSxLQUFLLFdBQVMsZUFBZTs7O0tBR3JDLEtBQUssRUFBRSxNQUFNLFNBQVMsTUFBRSxNQUFVO0tBQ2xDLEtBQUssT0FBTztZQUNMOzs7SUFFUixJQUFJLEVBQUUsTUFBTTtJQUNaLElBQUksR0FBRyxFQUFFO0lBQ1QsS0FBSyxFQUFFLE1BQU0sU0FBUyxNQUFFLE1BQVU7SUFDbEMsS0FBSyxNQUFJLE9BQU87V0FDVDtVQUNSLElBQUssSUFBSSxFQUFFLEtBQUssV0FBUyxlQUFlO1dBQ2hDLEtBQUssYUFBYTs7OztNQUV2QixXQUFXLFNBQVMsV0FBVzs7RUFFL0I7O0dBQ1MsTUFBTztHQUNSLElBQUcsSUFBSSxlQUFYO0dBQ1MsSUFBRyxJQUFJLGVBQWhCLElBQUk7R0FDQyxLQUFPLElBQUk7O09BRW5CLEdBQUs7T0FDTCxHQUFLLEVBQUUsSUFBSTtPQUNYLEtBQUssRUFBRSxJQUFJLFNBQVM7T0FDcEIsS0FBSyxFQUFFLEtBQUs7T0FDWixRQUFPLEVBQUU7T0FDVCxJQUFLLEVBQUUsSUFBSTs7R0FFZixJQUFHLEdBQUcsR0FBSSxLQUFLLFdBQVc7OztXQUdsQixLQUFLLGdCQUFnQjs7Ozs7R0FJN0IsSUFBRyxXQUFXLElBQUksZUFBUTtJQUN6QixHQUFHO0lBQ0gsSUFBSSxFQUFFLElBQUksVUFBVTtJQUNwQixLQUFLLEVBQUUsS0FBSzs7O09BRVQ7O0dBRUosSUFBRzs7OztJQUlGLElBQU8sRUFBRSxFQUFFLElBQUk7S0FDZCxLQUFLLEVBQUUsRUFBRTs7O0lBRVYsSUFBRyxFQUFFLEVBQUUsSUFBSTtLQUNWLEdBQUcsRUFBRSxFQUFFOzs7OztHQUdULFFBQVEsRUFBRSxLQUFLLE1BQU0sR0FBRyxLQUFLO1VBQzdCLGVBQVUsUUFBWSxLQUFLLE9BQU87OztPQUU5QixFQUFFLEtBQUs7S0FDVCxFQUFFLEtBQUs7TUFDTixFQUFFLEtBQUs7TUFDUCxFQUFFLEtBQUs7T0FDTixFQUFFLEtBQUs7TUFDUixFQUFFLEtBQUs7a0JBQ0YsRUFBRSxLQUFLOzs7Ozs7Ozs7Ozs7RUNyZ0JaO1VBQ0gsT0FBTzs7Ozs7OztFQUtKO21CQUNDLEtBQUssV0FBUzs7O0VBRW5COzs7Ozs7R0FLQztJQUNDLE1BQU0sVUFBVSxPQUFPO0lBQ3ZCLE1BQU0sVUFBVTs7SUFFaEIsU0FBRztLQUNGLE1BQU0sVUFBVSxPQUFFOztTQUVkLFVBQVUsTUFBTSxFQUFFLE1BQU0sTUFBTTtLQUNVLElBQU8sTUFBTSxNQUFNLEdBQUcsaUJBQWxFLE1BQU0sU0FBUyxPQUFFLFNBQVMsT0FBTzs7S0FFakMsTUFBTSxVQUFVLEVBQUUsTUFBTTtZQUN4QixNQUFNLFNBQVM7Ozs7R0FFakI7UUFDSyxJQUFJLEVBQUUsS0FBSyxXQUFTLG1CQUFjO1FBQ2xDLElBQUksT0FBRSxTQUFTO0lBQ0MsSUFBRyxPQUF2QixJQUFJLFVBQVUsRUFBRTtXQUNoQjs7O0dBRUQ7UUFDSyxNQUFNLFFBQUcsK0JBQWM7V0FDM0IsTUFBTTs7O0dBRVA7Z0JBQ0MsK0JBQWM7Ozs7Ozs7Ozs7OztHQU9mO2dCQUNDLEtBQUs7OztHQUVOO2dCQUNDLEtBQUs7OztHQUVOO1NBQ0MsZUFBUyxPQUFPLFdBQVMsYUFBTSxPQUFPO1NBQ3RDLFVBQVU7Ozs7Ozs7O0dBTVg7U0FDQyxLQUFLLFVBQVUsRUFBRTs7Ozs7Ozs7R0FNbEI7Z0JBQ0MsS0FBSzs7Ozs7OztHQUtOO2dCQUN5QyxLQUFLO1VBQTdDLEtBQUssaUJBQVksS0FBSzs7U0FDdEIsVUFBVTtTQUNWLE9BQU87Ozs7Ozs7O0dBTVI7UUFDSyxJQUFJLEVBQUU7UUFDTixHQUFHLEVBQUUsTUFBTSxHQUFJLE1BQU07SUFDTCxJQUFHLEdBQUcsR0FBSSxHQUFHLFdBQVcsR0FBRyxPQUEvQyxJQUFJLFlBQVk7Ozs7R0FHakI7Ozs7SUFDQyxLQUFLLE9BQU8sUUFBUSxpQkFBa0IsYUFBYzs7OztHQUdyRDtJQUNDLElBQUcsZUFBUTtLQUNHO1dBQWIsUUFBUSxRQUFFOzs7OztJQUdYLGNBQWEsT0FBTyxHQUFHO1VBQ3RCLHdCQUFvQixLQUFNOzs7O0lBRzNCLElBQUc7aUJBQ0ssd0JBQW9COzs7UUFFeEIsUUFBUSxFQUFFLFdBQUk7O0lBRWxCLE1BQU87S0FDTixRQUFRO0tBQ1IsNEJBQWEsV0FBSTs7TUFDaEIsSUFBRyxJQUFJLEtBQUssT0FBTyxFQUFFLEdBQUc7T0FDdkIsUUFBUSxLQUFLLFlBQVksSUFBSSxLQUFLLE1BQU0sS0FBSyxFQUFFLElBQUk7Ozs7O1dBRS9DOzs7Ozs7OztHQU1SO2VBQ0MsS0FBSyxTQUFhOzs7Ozs7Ozs7R0FPbkI7V0FDQyxZQUFNLEtBQUssS0FBSyxxQkFBWSxXQUFJOzs7Ozs7Ozs7Ozs7O0dBV2pDO1dBQ0MsWUFBTSxLQUFLLEtBQUssb0JBQVcsV0FBSTs7Ozs7OztHQUtoQztvQkFDSyxXQUFJLFNBQVMsRUFBRSxHQUFHOzs7R0FFdkI7UUFDSyxNQUFNLE1BQUUsS0FBSyx3QkFBeUIsS0FBSztXQUMvQyxPQUFNLE1BQU0sT0FBTyxTQUFPOzs7R0FFM0I7O0lBQ3VCLElBQU8sSUFBSSxFQUFFLFdBQUksY0FBdkMsSUFBSSxpQkFBWTs7OztHQUdqQjs7SUFDQyxJQUFHLGVBQVE7WUFDSDs7O0lBRVEsSUFBRyxJQUFJLFNBQXZCLElBQUksRUFBRSxJQUFJO0lBQ1YsSUFBTyxHQUFHLFFBQUcsS0FBSyxRQUFRLFFBQUcsS0FBSyxnQkFBZ0IsUUFBRyxLQUFLLHNCQUFzQixRQUFHLEtBQUssa0JBQWtCLFFBQUcsS0FBSztZQUMxRyxHQUFHLFVBQUssS0FBSzs7Ozs7Ozs7OztHQU90QjtJQUNlLE1BQU8sZUFBZDtRQUNILEtBQUs7SUFDTyxJQUFHLElBQUksU0FBdkIsSUFBSSxFQUFFLElBQUk7O1dBRUo7S0FDTyxJQUFHLEtBQUssUUFBUSxlQUFyQjtLQUNQLEtBQUssRUFBRSxLQUFLOzs7Ozs7Ozs7Ozs7R0FTZDtJQUNlLE1BQU8sZUFBZDtXQUNQLGNBQU8sR0FBSSxjQUFPLFFBQVE7OztHQUUzQjtRQUNLLEtBQUs7UUFDTCxNQUFNO0lBQ00sSUFBRyxJQUFJLEdBQUksSUFBSSxTQUEvQixJQUFJLEVBQUUsSUFBSTs7V0FFSjtLQUNZLE1BQUksS0FBSSxHQUFHLEtBQUssUUFBUSxRQUF6QyxNQUFNLEtBQUs7S0FDWCxLQUFLLEVBQUUsS0FBSzs7V0FDTjs7O0dBRVI7UUFDSyxJQUFJLEVBQUU7V0FDVixPQUFNLElBQUksS0FBSzs7Ozs7R0FJaEI7O0lBQ1csTUFBVyxJQUFJLEVBQUU7UUFDdkIsSUFBSSxFQUFFLFdBQUksV0FBVztRQUNyQixNQUFNLE1BQUUsS0FBSyxtQkFBeUI7V0FDMUMsTUFBTSw0QkFBVyxFQUFFLFFBQVEsTUFBSyxLQUFJLEdBQUcsRUFBRSxRQUFROzs7Ozs7O0dBS2xEO0lBQ0MsSUFBRztTQUNFLEdBQUc7WUFDRCxHQUFHLEVBQUUsR0FBRztNQUNILElBQUcsR0FBRyxRQUFRLGVBQWpCOzs7O29CQUVMLFdBQUk7Ozs7Ozs7R0FLVDtJQUNDLElBQUc7U0FDRSxHQUFHO1lBQ0QsR0FBRyxFQUFFLEdBQUc7TUFDSCxJQUFHLEdBQUcsUUFBUSxlQUFqQjs7OztvQkFFTCxXQUFJOzs7R0FFVDtXQUNDLFdBQUksU0FBUyxLQUFLLEdBQUksS0FBSyxLQUFLLEdBQUc7OztHQUVwQztRQUNLLEVBQUUsRUFBRTtRQUNKLEdBQUcsRUFBRTtXQUNILEdBQUc7S0FDUixHQUFHLEVBQUUsR0FBRztLQUNSOztXQUNNOzs7Ozs7Ozs7R0FPUjs7OztJQUNxQixJQUFHLFNBQXZCLE9BQU8sRUFBRSxNQUFNO0lBQ2YsSUFBRyxnQkFBUztLQUNYLEtBQUssR0FBRyw0QkFBVzs7SUFDcEIsSUFBRztLQUNGLFdBQUksYUFBYSxLQUFLLE1BQUksT0FBTzs7VUFFakMsT0FBTzs7Ozs7Ozs7OztHQU9UO0lBQ0MsV0FBSTs7Ozs7Ozs7O0dBT0w7SUFDQyxXQUFJOzs7O0dBR0w7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBZUE7UUFDSyxNQUFNLE9BQUUsS0FBSyxXQUFXO0lBQzVCLGNBQVEsYUFBYSxLQUFNLGdCQUFTLFlBQVk7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQWdCakQ7OztJQUdhLE1BQU87O0lBRW5CLElBQUcsZ0JBQVM7S0FDYyw0QkFBYzs7TUFBdkMsT0FBTyxRQUFHLE9BQU87O1dBRWxCLFlBQUssd0NBQWdCLFdBQUc7U0FDbkIsS0FBSyxFQUFFLEtBQUssV0FBUyxlQUFlO1VBQ3hDLEtBQUssWUFBWTtLQUNMLFNBQUcsZUFBZixPQUFPOztVQUVQLEtBQUssWUFBWSxLQUFLLEtBQUssR0FBRztLQUNsQixTQUFHLGVBQWYsT0FBTzs7Ozs7Ozs7Ozs7R0FRVDtJQUMyQyxZQUFHLDJDQUE3QyxLQUFLLEVBQUUsS0FBSyxXQUFTLGVBQWU7SUFDdUIsSUFBRyxLQUFLLEdBQUksT0FBdkUsV0FBSSxjQUFlLEtBQUssS0FBSyxHQUFHLE9BQVEsSUFBSSxLQUFLLEdBQUc7Ozs7Ozs7Ozs7R0FRckQ7SUFDMkMsWUFBRywyQ0FBN0MsS0FBSyxFQUFFLEtBQUssV0FBUyxlQUFlO0lBQ0QsSUFBRyxRQUF0QyxXQUFJLFlBQVksS0FBSyxLQUFLLEdBQUc7Ozs7Ozs7OztHQU85QjtJQUNvQyxJQUFHLFFBQXRDLFdBQUksWUFBWSxLQUFLLEtBQUssR0FBRzs7OztHQUc5QjtnQkFDQyxLQUFLOzs7Ozs7O0dBS047SUFDQyxRQUFRO2dCQUNSLEtBQUs7Ozs7U0FFUDs7Ozs7Ozs7Ozs7RUN4V0E7O0dBRUM7V0FDQyxLQUFLLFdBQVM7Ozs7RUFFaEI7Ozs7O0VBR0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTs7RUFFQTs7Ozs7Ozs7O0VBS0E7R0FDQztJQUNpQixJQUFPLGFBQU0sR0FBRyxPQUFoQyxXQUFJLE1BQU0sRUFBRTs7OztHQUdiO0lBQ2tCLElBQU8sY0FBTyxHQUFHLE9BQWxDLFdBQUksT0FBTyxFQUFFOzs7O0dBR2Q7V0FDQyxXQUFJOzs7R0FFTDtXQUNDLFdBQUk7OztHQUVMOztXQUNDLFdBQUksV0FBVzs7OztFQUVqQjtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBOztFQUVBOzs7Ozs7O0VBSUE7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTs7RUFFQTs7Ozs7RUFHQTs7Ozs7RUFHQTs7Ozs7Ozs7Ozs7OztHQVFDO1dBQ0MsV0FBSTs7O0dBRUw7SUFDZSxJQUFPLEVBQUUsR0FBRyxXQUFJLFNBQTlCLFdBQUksTUFBTSxFQUFFOzs7O0dBR2I7SUFDcUIsSUFBTyxFQUFFLEdBQUcsV0FBSSxlQUFwQyxXQUFJLFlBQVksRUFBRTs7OztHQUduQjtXQUNDLFdBQUk7OztHQUVMO1dBQ0MsV0FBSTs7O0dBRUw7SUFDb0IsSUFBTyxLQUFLLEdBQUcsV0FBSSxXQUF0QyxXQUFJLFFBQVEsRUFBRTs7Ozs7RUFHaEI7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBOztFQUVBOzs7Ozs7Ozs7OztFQU1BO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7O0VBRUE7Ozs7Ozs7OztFQUtBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTs7RUFFQTs7Ozs7RUFHQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBOztFQUVBOzs7Ozs7Ozs7OztFQU1BOztFQUVBOzs7Ozs7Ozs7O0dBTUM7V0FDQyxXQUFJOzs7R0FFTDtJQUNlLElBQU8sRUFBRSxHQUFHLFdBQUksU0FBOUIsV0FBSSxNQUFNLEVBQUU7Ozs7OztFQUlkO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7O0VBRUE7Ozs7Ozs7Ozs7Ozs7O0dBUUM7V0FDQyxXQUFJOzs7R0FFTDtJQUNlLElBQU8sRUFBRSxHQUFHLFdBQUksU0FBOUIsV0FBSSxNQUFNLEVBQUU7Ozs7R0FHYjtJQUNxQixJQUFPLEVBQUUsR0FBRyxXQUFJLGVBQXBDLFdBQUksWUFBWSxFQUFFOzs7O0dBR25CO1dBQ0MsV0FBSTs7OztFQUVOO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO1NBQ0E7Ozs7Ozs7Ozs7Ozs7O0VDdk9BOztHQUVDOzs7O09BR0ksTUFBTSx5SEFBeUg7O0dBRW5JO1FBQ0ssSUFBSSxFQUFFLEtBQUssV0FBUyxnQkFBZ0IseUJBQWE7UUFDakQsSUFBSSxPQUFFLFNBQVM7SUFDUyxJQUFHLE9BQS9CLElBQUksVUFBVSxRQUFRLEVBQUU7V0FDeEI7OztHQUVEO0lBQ0MsTUFBTSxVQUFVOztJQUVoQixTQUFHLE1BQU0sTUFBUztLQUNqQixNQUFNLFVBQVUsRUFBRSxNQUFNO1lBQ3hCLE1BQU0sU0FBUzs7S0FFZixNQUFNLFVBQVUsT0FBRTtTQUNkLFVBQVUsTUFBTSxFQUFFLE1BQU0sTUFBTTtZQUNsQyxNQUFNLFNBQVMsT0FBRSxTQUFTLE9BQU87Ozs7Ozs7Ozs7Ozs7OztFQVlwQzs7OztFQUdBOztFQUVBOztFQUVBOzs7OztFQUlBOzs7Ozs7Ozs7Ozs7RUFXQTs7Ozs7RUFJQTs7Ozs7O0VBS0E7Ozs7Ozs7RUFNQTs7Ozs7RUFJQTs7Ozs7OztFQU1BOzs7O0VBR0E7Ozs7RUFHQTs7Ozs7Ozs7O1NBUUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7RUMxRkEsSUFBRyxJQUFLO09BQ0gsT0FBTyxFQUFFLE9BQU8saUJBQWlCLFNBQVM7O0dBRTlDLEtBQUssVUFBVTs7R0FFZiw0QkFBZ0I7O1FBQ1gsV0FBVyxFQUFFLFNBQVM7UUFDdEIsVUFBVSxFQUFFLFdBQVcsd0NBQTJCLEVBQUU7OztJQUd4RCxJQUFHLFNBQVMsR0FBRztLQUNMLElBQUcsT0FBTyxlQUFlOzs7O0lBR25DLEtBQUssVUFBVSxZQUFZLEVBQUUsS0FBSyxVQUFVLFdBQVcsRUFBRTs7O0dBRW5EOzs7SUFHTjtLQUNDLElBQUcsZUFBUTtNQUNEO1lBQVQsSUFBSSxRQUFFOzs7OztLQUdQLElBQUksRUFBRSxLQUFLLFVBQVUsS0FBSyxHQUFHOztLQUU3QixJQUFHLElBQUk7TUFDTixXQUFJLE1BQU0sZUFBZTtZQUMxQixJQUFLLElBQUk7YUFDRCxXQUFJLE1BQU07O01BRWpCLFlBQUcsc0NBQWUsR0FBSSxJQUFJO09BQ3pCLElBQUksRUFBRSxJQUFJOztNQUNYLFdBQUksTUFBTSxLQUFLLEVBQUU7Ozs7OztHQUdwQixLQUFPLFNBQVMsZ0JBQWdCO0lBQ3hCOztLQUVOO2lCQUNRLGlCQUFxQixFQUFFLElBQUksYUFBYSxVQUFLLEtBQUs7OztLQUUxRDtNQUNhLFNBQUcsUUFBUTtXQUN2QixLQUFLLFVBQVUsU0FBSSxLQUFLLDBCQUFzQixFQUFFOzs7O0tBR2pEO01BQ2EsVUFBTyxRQUFRO1VBQ3ZCLE1BQU0sTUFBRSxrQkFBc0IsRUFBRSxJQUFJO1dBQ3hDLEtBQUssVUFBVSxPQUFFLEtBQUssVUFBVSxRQUFROzs7O0tBR3pDO2tCQUNDLFFBQVEsYUFBTyxPQUFPLGNBQU8sS0FBSzs7O0tBRW5DO01BQ0MsY0FBYSxPQUFPLEdBQUcsRUFBRSxPQUFNLE9BQUs7bUJBQzVCLE9BQU87O2tCQUNSLFFBQVE7Ozs7Ozs7Ozs7Ozs7OztNQ2pFZixJQUFJLEVBQUU7TUFDTixJQUFJLEVBQUU7O01BRU4sZUFBZSxFQUFFLE9BQU8sR0FBRyxPQUFPLGFBQWE7O0VBRTdDLEtBQUssVUFZVixTQVpVO1FBYVQsV0FBVTtRQUNWLGFBQVksS0FBTTs7OztFQWRkLEtBQUs7RUFBTCxLQUFLO0VBQUwsS0FBSztFQUFMLEtBQUs7RUFBTCxLQUFLO0VBQUwsS0FBSztFQUFMLEtBQUs7RUFBTCxLQUFLO0VBQUwsS0FBSztFQUFMLEtBQUs7RUFBTCxLQUFLO0VBQUwsS0FBSztFQUFMLEtBQUs7RUFBTCxLQUFLOztFQWlCVixLQWpCVTtRQWtCVCxTQUFRO1FBQ1I7Ozs7O0VBSUQsS0F2QlU7T0F3QkwsR0FBRyxFQUFFOztHQUVULElBQUc7U0FDRixhQUFZO1NBQ1o7OztJQUdBLElBQUcsR0FBRyxLQUFLO1VBQ1YsVUFBUyxHQUFHOzs7S0FHWixJQUFHLGNBQU8sR0FBRyxFQUFFLElBQUksYUFBTSxHQUFJLGNBQU8sR0FBRzs7Ozs7S0FJMUIsSUFBRyxnQkFBaEIsYUFBTTtVQUNOLGFBQVEsS0FBSyxNQUFVO0tBQ3ZCLGFBQU0sVUFBVSxHQUFHO1dBRXBCLElBQUssR0FBRyxLQUFLO0tBQ1csSUFBRyxnQkFBMUIsYUFBTSxVQUFVLEdBQUc7V0FFcEIsSUFBSyxHQUFHLEtBQUs7VUFDWixXQUFVOztLQUVWLElBQUcsYUFBTSxHQUFJLGFBQU0sU0FBTyxHQUFHLEdBQUc7TUFDL0IsYUFBTSxRQUFRLEdBQUc7V0FDakI7Ozs7O0lBR1MsSUFBRyxnQkFBZCxhQUFNOzs7OztFQUdSLEtBekRVO1VBMERULEtBQUs7OztFQUVOLEtBNURVO1VBNERELGFBQU07O0VBQ2YsS0E3RFU7VUE2REQsYUFBTTs7OztFQUdmLEtBaEVVOztHQWtFVCw0QkFBYSxLQUFLO0lBQ2pCLE9BQUk7OztHQUVMLElBQUksc0JBQXNCLEtBQUssUUFBUTs7OztNQUdyQyx5QkFBeUIsRUFBRTtNQUMzQix1QkFBdUIsRUFBRTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztFQWlDdkIsS0FBSyxRQW1GVixTQW5GVTs7UUFxRkosU0FBUTtRQUNiO1FBQ0E7UUFDQSxRQUFRLEVBQUUsTUFBTSxHQUFJLE1BQU0sT0FBTyxHQUFHO1FBQ3BDLFVBQVU7UUFDVixVQUFVO1FBQ1Y7R0FDQSxRQUFRLEVBQUU7UUFDVixXQUFVOzs7O01BM0ZQLFFBQVE7TUFDUixNQUFNLEVBQUU7TUFDUixZQUFZOztFQUVoQixLQU5VO1VBT1Q7OztFQUVELEtBVFU7VUFVRixLQUFLLElBQUssS0FBSyxVQUFVLEdBQUcsWUFBWSxLQUFLOzs7RUFFckQsS0FaVTs7V0FhRixZQUFZLEtBQUssb0JBQWpCLFlBQVksS0FBSztXQUNqQixLQUFLLGtCQUFMLEtBQUs7Ozs7RUFHYixLQWpCVTtHQWtCVCw0QkFBUyxFQUFFOztJQUNELFNBQUcsT0FBTztRQUNmLE1BQU0sRUFBRSxZQUFZLEVBQUUsWUFBWSxXQUFXO0lBQ2pELEVBQUUsVUFBVSxFQUFFO0lBQ2QsUUFBUSxLQUFLO0lBQ2I7SUFDQSxNQUFNLFdBQVcsRUFBRTs7Ozs7RUFHckIsS0EzQlU7O0dBNEJULDRCQUFTLEVBQUU7O0lBQ1YsSUFBTyxNQUFNLE9BQUUsT0FBTztLQUNyQixNQUFNLFVBQVUsRUFBRTs7Ozs7OztFQUlyQixLQWxDVTs7R0FtQ1QsNEJBQVMsRUFBRTs7SUFDVixJQUFPLE1BQU0sT0FBRSxPQUFPO0tBQ3JCLE1BQU0sU0FBUyxFQUFFO1VBQ2pCLFFBQVEsRUFBRTtLQUNWOzs7Ozs7Ozs7O0VBT0gsS0E5Q1U7O0dBK0NULDRCQUFTLEVBQUU7O0lBQ1YsSUFBTyxNQUFNLE9BQUUsT0FBTztLQUNyQixNQUFNLFlBQVksRUFBRTtVQUNwQixRQUFRLEVBQUU7S0FDVjs7Ozs7O0VBR0gsS0F0RFU7Ozs7RUF5RFYsS0F6RFU7Ozs7RUE0RFYsS0E1RFU7Ozs7O0VBQUwsS0FBSztFQUFMLEtBQUs7RUFBTCxLQUFLO0VBQUwsS0FBSztFQUFMLEtBQUs7RUFBTCxLQUFLO0VBQUwsS0FBSztFQUFMLEtBQUs7RUFBTCxLQUFLO0VBQUwsS0FBSztFQUFMLEtBQUs7RUFBTCxLQUFLO0VBQUwsS0FBSztFQUFMLEtBQUs7RUFBTCxLQUFLO0VBQUwsS0FBSztFQUFMLEtBQUs7RUFBTCxLQUFLO0VBQUwsS0FBSztFQUFMLEtBQUs7RUFBTCxLQUFLOztFQUFMLEtBQUs7RUFBTCxLQUFLOzs7Ozs7Ozs7RUFnR1YsS0FoR1U7UUFpR1QsVUFBVTtRQUNWLE9BQU8sUUFBSSxPQUFPOzs7O0VBR25CLEtBckdVO2tCQXNHUDs7Ozs7Ozs7OztFQVFILEtBOUdVOztRQWdIVDtRQUNBLFVBQVUsS0FBSzs7Ozs7Ozs7OztFQVFoQixLQXpIVTtRQTBIVCxVQUFVLEVBQUU7Ozs7Ozs7OztFQU9iLEtBaklVOztRQW1JVCxRQUFROzs7O0VBR1QsS0F0SVU7R0F1SVQsUUFBUTtRQUNSLFNBQVMsRUFBRTs7OztFQUdaLEtBM0lVO1FBNElULE9BQU8sRUFBRTtRQUNULE9BQU8sRUFBRTtRQUNULFFBQVEsRUFBRTtRQUNWLEdBQUcsRUFBRSxFQUFFO1FBQ1AsR0FBRyxFQUFFLEVBQUU7R0FDUDtHQUNpQixJQUFHLEVBQUUsR0FBSSxxQkFBMUIsRUFBRTs7OztFQUdILEtBckpVO1FBc0pULE9BQU8sRUFBRTtRQUNULEdBQUcsRUFBRSxFQUFFO1FBQ1AsR0FBRyxFQUFFLEVBQUU7R0FDUDtHQUNpQixJQUFHLEVBQUUsR0FBSSxxQkFBMUIsRUFBRTs7OztFQUdILEtBN0pVO1FBOEpULE9BQU8sRUFBRTtRQUNULEdBQUcsRUFBRSxFQUFFO1FBQ1AsR0FBRyxFQUFFLEVBQUU7R0FDUDs7R0FFQSx5QkFBeUIsRUFBRSxFQUFFOztHQUU3QixTQUFHLE9BQU8sRUFBRTtRQUNQLElBQUksTUFBRSxLQUFLLE1BQVU7SUFDekIsSUFBSTtJQUNKLElBQUk7SUFDYSxJQUFHLElBQUksY0FBeEIsRUFBRTs7O0dBRUgsSUFBRyxFQUFFLEdBQUk7SUFDUixFQUFFOzs7Ozs7RUFJSixLQWhMVTtVQWlMVDs7O0VBRUQsS0FuTFU7O1FBb0xULE9BQU8sRUFBRTtRQUNULFFBQVEsRUFBRSxFQUFFO1FBQ1osR0FBRyxFQUFFLEVBQUU7UUFDUCxHQUFHLEVBQUUsRUFBRTtHQUNQOztRQUVBLFdBQVcsNEJBQU8sVUFBVSxFQUFFO0dBQzlCLElBQUksa0NBQTZCOzs7O0VBR2xDLEtBOUxVO1FBK0xULEdBQUcsRUFBRSxFQUFFO1FBQ1AsR0FBRyxFQUFFLEVBQUU7UUFDUCxPQUFPLEVBQUU7R0FDUSxJQUFHLHFCQUFwQixFQUFFO0dBQ0Y7R0FDQTs7OztFQUdELEtBdk1VO1FBd01ULEdBQUcsRUFBRSxFQUFFO1FBQ1AsR0FBRyxFQUFFLEVBQUU7R0FDUDtHQUNBLElBQUkscUNBQWdDO1FBQ3BDLFdBQVc7Ozs7RUFHWixLQS9NVTtVQWdOVDs7O0VBRUQsS0FsTlU7UUFtTlQsT0FBTyxPQUFFLElBQUksRUFBRTtRQUNmLElBQUksT0FBRTtRQUNOLElBQUksT0FBRTs7T0FFRixJQUFJLEVBQUUsYUFBTTtPQUNaLEtBQUs7O1FBRVQsY0FBYyxFQUFFLElBQUksWUFBUTs7VUFFdEI7SUFDTCxLQUFLLFdBQU07SUFDWCxJQUFHLEtBQUssR0FBRyxLQUFLO1VBQ2YsUUFBUTtVQUNSLFVBQVM7S0FDVCxjQUFPO0tBQ0QsVUFBTzs7SUFDZCxJQUFJLEVBQUUsSUFBSTs7O1FBRVg7Ozs7RUFHRCxLQXhPVTs7R0F5T0csVUFBTzs7T0FFZixHQUFHLEVBQUUsS0FBSyxLQUFLLFVBQUUsRUFBQyxVQUFHLEVBQUUsVUFBRSxFQUFDO0dBQ2xCLElBQUcsR0FBRyxPQUFFLFlBQXBCLE9BQU8sRUFBRTtRQUNULElBQUksRUFBRTs7O0dBR04sU0FBRztJQUNGLFNBQUcsUUFBUSxRQUFJLFFBQVE7VUFDdEIsUUFBUTs7U0FDVCxlQUFTO1NBQ1QsVUFBVTtJQUNnQixJQUFHLGNBQU8sZ0JBQXBDLGNBQU87Ozs7UUFHUjtHQUNBLFNBQUc7SUFDb0IsaUNBQVM7S0FBL0IsT0FBRTs7OztHQUVILHFDQUFRLG1CQUFSLFFBQVE7Ozs7RUFHVCxLQS9QVTs7R0FnUUcsVUFBTzs7R0FFbkIsU0FBRztJQUNGLGlDQUFTOztLQUNtQixJQUFHLEVBQUUsZUFBaEMsRUFBRSxzQkFBaUI7Ozs7R0FFckIscUNBQVEsaUJBQVIsUUFBUSxzQkFBaUI7Ozs7RUFHMUIsS0F6UVU7O0dBMFFHLFVBQU87O1FBRW5COztHQUVBLFNBQUc7SUFDaUIsaUNBQVM7S0FBNUIsT0FBRTs7OztHQUVILHFDQUFRLGdCQUFSLFFBQVE7Ozs7O0VBSVQsS0FyUlU7R0FzUlQsVUFBTztTQUNOLFdBQVc7SUFDWDtJQUNvRCxTQUFHLGNBQXZELElBQUkscUNBQWdDOzs7OztFQUd0QyxLQTVSVTs7R0E2UkcsVUFBTzs7UUFFbkIsV0FBVztRQUNYOztHQUVBLFNBQUc7SUFDRixpQ0FBUzs7S0FDYyxJQUFHLEVBQUUsaUJBQTNCLEVBQUU7Ozs7R0FFSixxQ0FBUSxtQkFBUixRQUFROzs7Ozs7Ozs7RUFPVCxLQTdTVTtlQTZTQTs7Ozs7Ozs7RUFNVixLQW5UVTtlQW1UQSxHQUFHLE9BQUU7Ozs7Ozs7O0VBTWYsS0F6VFU7ZUF5VEEsR0FBRyxPQUFFOzs7Ozs7OztFQU1mLEtBL1RVO2VBK1RBOzs7Ozs7OztFQU1WLEtBclVVO2VBcVVBOzs7Ozs7OztFQU1WLEtBM1VVO2VBMlVEOzs7Ozs7OztFQU1ULEtBalZVO2VBaVZEOzs7Ozs7OztFQU1ULEtBdlZVO1FBd1ZULHNDQUFlLFFBQVEsTUFBSTtlQUMzQixHQUFHLE9BQUUsV0FBVzs7Ozs7Ozs7RUFNakIsS0EvVlU7UUFnV1Qsc0NBQWUsUUFBUSxNQUFJO2VBQzNCLEdBQUcsT0FBRSxXQUFXOzs7Ozs7OztFQU1qQixLQXZXVTtlQXVXSTs7O0VBRWQsS0F6V1U7ZUEwV1Q7Ozs7RUFHSSxLQUFLLGVBQVgsU0FBVzs7RUFBTCxLQUFLO0VBQUwsS0FBSztFQUFMLEtBQUs7RUFBTCxLQUFLOztFQUlWLEtBSlU7Ozs7RUFPVixLQVBVOzs7O0VBVVYsS0FWVTs7Ozs7Ozs7RUFpQlgsS0FBSyxRQUFRLE1BQUUsS0FBSztFQUNwQixLQUFLLFNBQVMsR0FBRyxLQUFLOzs7O0VBSXRCLEtBQUssT0FBTzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0VBd0JaLEtBQUssUUFBUTs7Ozs7Ozs7Ozs7Ozs7Ozs7OztFQWtCUCxLQUFLLFFBc0JWLFNBdEJVO1FBdUJULFNBQVE7UUFDUjs7Ozs7RUF4QkksS0FBSztFQUFMLEtBQUs7Ozs7RUFBTCxLQUFLO0VBQUwsS0FBSzs7RUFBTCxLQUFLO0VBQUwsS0FBSzs7Ozs7OztFQUFMLEtBQUs7RUFBTCxLQUFLOzs7O0VBQUwsS0FBSyxrQ0FpQlE7RUFqQmIsS0FBSztFQUFMLEtBQUs7O0VBbUJWLEtBbkJVO21CQW9CQTs7O0VBTVYsS0ExQlU7UUEyQlQsTUFBTSxFQUFFOzs7Ozs7OztFQU1ULEtBakNVO2VBa0NULE1BQU0sR0FBRyxhQUFNOzs7RUFFaEIsS0FwQ1U7ZUFxQ1QsdUJBQVUsWUFBSyxjQUFZOzs7O0VBRzVCLEtBeENVO0dBeUNULElBQUcsRUFBRTtTQUNDLFVBQVM7OztlQUVSOzs7Ozs7OztFQU1SLEtBbERVO1FBbURUOzs7Ozs7Ozs7O0VBUUQsS0EzRFU7R0E0RFksSUFBRyxhQUFNLGtCQUE5QixhQUFNO1FBQ04sUUFBUTs7OztFQUdULEtBaEVVO1FBaUVULFVBQVU7Ozs7RUFHWCxLQXBFVTtrQkFxRVA7Ozs7Ozs7OztFQU9ILEtBNUVVO1VBNkVULGFBQU0sR0FBSSxhQUFNLGlCQUFpQixRQUFHOzs7Ozs7O0VBS3JDLEtBbEZVO21CQW1GTCxhQUFNLFFBQVEsR0FBRyxhQUFNOzs7Ozs7O0VBSzVCLEtBeEZVO2VBeUZUOzs7Ozs7O0VBS0QsS0E5RlU7UUErRlQsVUFBVSxFQUFFOzs7Ozs7Ozs7RUFPYixLQXRHVTtHQXVHVCxJQUFHLHdCQUFVO1FBQ1IsR0FBRyxFQUFFLGFBQU07UUFDWCxJQUFJLEVBQUUsS0FBSyxPQUFPLGFBQU07O0lBRTVCLE1BQUksS0FBSSxHQUFJLEdBQUcsT0FBTyxFQUFFLEdBQUc7S0FDMUIsSUFBSSxFQUFFLE9BQU8sYUFBYSxTQUFTLEdBQUcsT0FBTyxHQUFJOztXQUMzQztVQUVSLElBQUsseUJBQVcsT0FBTyxVQUFVLEdBQUcsT0FBTztXQUNuQyxhQUFNOzs7Ozs7Ozs7O0VBT2YsS0F2SFU7O0dBd0hGLE1BQVcsSUFBSSxFQUFFO0dBQ3hCLElBQUksRUFBRSxLQUFLLFFBQVEsS0FBSyxHQUFHO09BQ3ZCLE1BQU0sS0FBTSxFQUFFLEVBQUU7R0FDRixJQUFHLEVBQUUsV0FBdkIsTUFBTTtHQUNhLElBQUcsRUFBRSxZQUF4QixNQUFNO0dBQ1csSUFBRyxFQUFFLFVBQXRCLE1BQU07R0FDVyxJQUFHLEVBQUUsV0FBdEIsTUFBTTtHQUNOLE1BQU0sS0FBSztVQUNYLE1BQU0sVUFBVTs7OztFQUdqQixLQW5JVTs7T0FvSUwsS0FBSyxnQkFBTSxRQUFRLFNBQU87T0FDMUIsS0FBSztPQUNMLFVBQVUsRUFBRSxhQUFNLFFBQVEsR0FBRyxhQUFNOzs7O09BSW5DLFFBQVEsRUFBRSxVQUFVLFdBQVcsR0FBRzs7O2lCQUdoQztTQUNMLFVBQVU7SUFDVixJQUFPLEtBQUssV0FBTTs7S0FFakIsWUFBRyxXQUFLLGtCQUFMOztNQUVGLEtBQUssRUFBRSxLQUFLOzs7O0tBR2IsSUFBRyxLQUFLLGlCQUFVO01BQ2pCLEtBQUssRUFBRSxLQUFLLE1BQU0sT0FBTztNQUN6QixLQUFLLEVBQUUsS0FBSzs7OztLQUdiLElBQUcsS0FBSyxpQkFBVTtXQUNqQixpQ0FBZTs7TUFFZixRQUFPLEtBQUssTUFBTSxNQUFNLEtBQUssVUFBUSxLQUFLLFdBQVc7Ozs7O0lBR3ZELE1BQU8sY0FBTyxJQUFJLFFBQVEsUUFBRyxVQUFVLElBQUksUUFBTyxLQUFLLGFBQVMsUUFBUTs7Ozs7R0FHekU7Ozs7O0VBSUQsS0F4S1U7R0F5S3NCLFVBQU8sYUFBdEMsS0FBSyxLQUFLOzs7Ozs7Ozs7RUFPWCxLQWhMVTtVQWdMRCxhQUFNOzs7Ozs7OztFQU1mLEtBdExVO1VBc0xELGFBQU07Ozs7Ozs7Ozs7Ozs7O0VBWWYsS0FsTVU7VUFrTUcsYUFBTTs7Ozs7Ozs7Ozs7Ozs7OztFQWNkLEtBQUssZUFhVixTQWJVOzs7O1FBY1QsUUFBTztRQUNQLFNBQVE7UUFDUjtRQUNBO1FBQ0E7O1NBRUMsU0FBUzs7OztHQUdWLDRCQUFhO1NBQ1osU0FBUzs7Ozs7O0VBeEJOLEtBQUs7RUFBTCxLQUFLO0VBQUwsS0FBSztFQUFMLEtBQUs7RUFBTCxLQUFLO0VBQUwsS0FBSztFQUFMLEtBQUs7Ozs7OztFQUFMLEtBQUs7RUFBTCxLQUFLO0VBQUwsS0FBSztFQUFMLEtBQUs7RUFBTCxLQUFLO0VBQUwsS0FBSztFQUFMLEtBQUs7O0VBU1YsS0FUVTtHQVVULFFBQU8sb0JBQVc7Ozs7Ozs7Ozs7Ozs7RUEwQm5CLEtBcENVOztHQXFDVCxJQUFHLGdCQUFTO0lBQ1MsNEJBQVM7VUFBN0IsU0FBUyxPQUFFOzs7OztHQUdBLElBQUcsa0JBQVc7O09BRXRCLEdBQUcsRUFBRSxrQkFBVyxNQUFNLEVBQUUsbUJBQVksWUFBVyxZQUFVO0dBQzFCLElBQUcseUJBQXRDLFlBQUssaUJBQWlCLEtBQUs7OztFQUU1QixLQTlDVTs7R0ErQ1QsaUJBQVUsTUFBTSxLQUFLLFFBQVE7R0FDZSxJQUFHLGtCQUEvQyxZQUFLLGlCQUFpQixLQUFLLFFBQVE7Ozs7RUFHcEMsS0FuRFU7UUFvRFQsd0JBQVM7T0FDTCxNQUFNLEVBQUUsS0FBSyxNQUFNLEtBQUs7R0FDNUIsTUFBTTs7OztFQUdQLEtBekRVOzs7O09BMERMLE1BQU0sRUFBRSxLQUFLLE1BQU0sWUFBVyxhQUFjO0dBQzlCLElBQUcsU0FBckIsTUFBTSxRQUFPO0dBQ1MsSUFBRyxXQUF6QixNQUFNLFVBQVM7VUFDZjs7OztFQUdELEtBaEVVO2VBaUVULDZCQUFtQjs7O0VBRXBCLEtBbkVVO0dBb0VULGFBQXdCO0lBQ3ZCLFlBQUssaUJBQWlCLFFBQUs7OztHQUU1Qiw0QkFBWTs7SUFDWCxZQUFLLGlCQUFpQixLQUFLLEdBQUcsS0FBSyxHQUFHLEtBQUs7Ozs7O0VBRzdDLEtBM0VVO0dBNEVULGFBQXdCO0lBQ3ZCLFlBQUssb0JBQW9CLFFBQUs7OztHQUUvQiw0QkFBWTs7SUFDWCxZQUFLLG9CQUFvQixLQUFLLEdBQUcsS0FBSyxHQUFHLEtBQUs7Ozs7OztFQUlqRCxHQUFHLEVBQUUsS0FBSyxPQUFPLE1BQUUsS0FBSyxhQUFpQjs7Ozs7Ozs7O0VBU3pDLElBQUc7R0FDRixLQUFLLE9BQU87O2lCQUNYLEtBQUssUUFBTztXQUNaLEtBQUssTUFBTSxhQUFhOzs7R0FFekIsS0FBSyxPQUFPOztpQkFDWCxLQUFLLFFBQU87V0FDWixLQUFLLE1BQU0sWUFBWTs7O0dBRXhCLEtBQUssT0FBTzs7aUJBQ1gsS0FBSyxRQUFPO1dBQ1osS0FBSyxNQUFNLFdBQVc7OztHQUV2QixLQUFLLE9BQU87O2lCQUNYLEtBQUssUUFBTztXQUNaLEtBQUssTUFBTSxjQUFjOzs7O0VBRTNCLEtBQUssT0FBTzs7R0FFWCxLQUFJLEVBQUUsVUFBVSxFQUFFLDBCQUEwQixFQUFFO1FBQ3pDLElBQUksTUFBRSxLQUFLLE1BQVU7SUFDekIsSUFBSTtJQUNKLElBQUk7SUFDSixJQUFHLElBQUk7WUFDQyxFQUFFOzs7O1VBRVgsS0FBSyxPQUFPLFNBQVM7OztFQUV0QixLQUFLLE9BQU87R0FDWCxLQUFJLEVBQUUsVUFBVSxFQUFFLDBCQUEwQixFQUFFO0lBQ2QsSUFBRyxLQUFLLGtCQUF2QyxLQUFLLFFBQVEsT0FBTyxHQUFHOzs7Ozs7Ozs7RUFPekIsS0FBSyxPQUFPOztHQUVYLEtBQUksRUFBRSxVQUFVLEVBQUUsMEJBQTBCLEVBQUU7SUFDZCxJQUFHLEtBQUssa0JBQXZDLEtBQUssUUFBUSxPQUFPLEdBQUc7Ozs7O0VBR3pCLEtBQUssT0FBTztVQUNaLEtBQUssT0FBTzs7Ozs7Ozs7OztNQ3IzQlIsUUFBUSxFQUFFLEtBQUssS0FBSzs7RUFFeEI7Ozs7R0FJQyxJQUFHLGdCQUFTO0lBQ1gsS0FBSyxZQUFZO1VBQ2xCLElBQUssZ0JBQVM7SUFDbUIsNEJBQWM7S0FBOUMsYUFBYSxLQUFLLE9BQU87Ozs7O1FBSXJCLEtBQUssRUFBRSxTQUFRLE1BQU0sZ0JBQWMsS0FBSyxLQUFLO0lBQ2pELEtBQUcsZ0JBQVMsTUFBSyxHQUFJLEtBQUssWUFBWSxHQUFHO0tBQ3hDLEtBQUssWUFBWTs7Ozs7O1VBSVo7OztFQUVSO0dBQ0MsSUFBRyxnQkFBUztJQUNYLEtBQUssWUFBWTtVQUVsQixJQUFLLGdCQUFTO0lBQ2EsNEJBQWM7S0FBeEMsYUFBYSxLQUFLOztVQUVuQixJQUFLLEtBQUssUUFBUSxHQUFJLEtBQUs7SUFDMUIsS0FBSyxZQUFZLEtBQUssV0FBUyxlQUFlOzs7Ozs7Ozs7OztFQVNoRDtHQUNDLElBQUcsZ0JBQVM7SUFDWCxLQUFLLGFBQWEsS0FBSztVQUN4QixJQUFLLGdCQUFTO0lBQzBCLDRCQUFjO0tBQXJELG1CQUFtQixLQUFLLE9BQU87O1VBQ2hDLElBQUssS0FBSyxRQUFRLEdBQUksS0FBSztJQUMxQixLQUFLLGFBQWEsS0FBSyxXQUFTLGVBQWUsTUFBTTs7O1VBRS9DOzs7O0VBR1I7T0FDSyxPQUFPLEVBQUUsU0FBUSxNQUFNLGdCQUFjLEtBQUssS0FBSzs7R0FFbkQsSUFBRztJQUNGLG1CQUFtQixLQUFLLEtBQUs7V0FDdEIsT0FBTzs7SUFFZCxhQUFhLEtBQUs7V0FDWCxLQUFLLEtBQUs7Ozs7RUFFbkI7O09BRUssT0FBTyxFQUFFLEtBQUk7T0FDYixRQUFRLEVBQUUsS0FBSSxPQUFPLEVBQUU7Ozs7Ozs7Ozs7Ozs7Ozs7OztPQWtCdkIsWUFBWTs7O09BR1osVUFBVTs7T0FFVixZQUFZOzs7T0FHWixlQUFlLEVBQUU7T0FDakIsWUFBWSxFQUFFOztHQUVsQiw4QkFBaUI7O1FBQ1osT0FBTyxFQUFFLEtBQUksUUFBUTtJQUN6QixZQUFZLEtBQUs7O0lBRWpCLElBQUcsT0FBTyxJQUFJO0tBQ2IsS0FBSyxZQUFZO0tBQ2pCLFVBQVUsTUFBTTtLQUNoQixZQUFZLE1BQU07Ozs7UUFHZixRQUFRLEVBQUUsWUFBWSxPQUFPLEVBQUU7OztXQUc3QixRQUFRLEdBQUc7S0FDaEIsSUFBRyxZQUFZLFNBQVMsSUFBSTtNQUMzQjtZQUNELElBQUssT0FBTyxFQUFFLFlBQVk7Ozs7O01BS3pCLFFBQVEsRUFBRSxVQUFVOzs7O0lBRXRCLFVBQVUsS0FBSzs7UUFFWCxXQUFXLEdBQUcsUUFBUSxJQUFJLE1BQUssTUFBSSxZQUFZLFNBQVEsRUFBQzs7SUFFNUQsSUFBRyxXQUFXLEVBQUU7S0FDZixlQUFlLEVBQUU7S0FDakIsWUFBWSxFQUFFOzs7SUFFZixZQUFZLEtBQUs7OztPQUVkLFlBQVk7Ozs7T0FJWixPQUFPLEVBQUUsWUFBWSxPQUFPLEVBQUU7VUFDNUIsT0FBTyxHQUFHO0lBQ2YsSUFBRyxPQUFPLEdBQUcsWUFBWSxHQUFJLFlBQVksUUFBUSxJQUFJO0tBQ3BELFlBQVksWUFBWSxTQUFTO0tBQ2pDLFlBQVksRUFBRSxVQUFVOzs7SUFFekIsT0FBTyxHQUFHOzs7O0dBR1gsK0JBQWlCO0lBQ2hCLEtBQUksWUFBWTtTQUNYLE1BQU0sRUFBRSxLQUFJLEtBQUksRUFBRTtLQUN0QixrQkFBa0IsS0FBTSxXQUFPLE1BQU0sR0FBSSxNQUFNLE1BQU0sR0FBRzs7Ozs7VUFHbkQsUUFBUSxHQUFJLFFBQVEsS0FBSyxHQUFHOzs7OztFQUlwQztPQUNLLEVBQUUsRUFBRSxLQUFJO09BQ1IsRUFBRSxFQUFFO09BQ0osS0FBSyxFQUFFLEtBQUksRUFBRSxFQUFFOzs7R0FHbkIsSUFBRyxFQUFFLEdBQUcsSUFBSSxPQUFPLEdBQUksS0FBSSxHQUFHLElBQUksSUFBSTs7V0FFL0I7S0FDQyxJQUFHLEtBQUksR0FBRyxJQUFJLElBQUk7Ozs7R0FFMUIsSUFBRyxFQUFFLElBQUk7V0FDRCxLQUFLLEdBQUksS0FBSyxLQUFLLEdBQUc7O1dBRXRCLDJCQUEyQixLQUFLLEtBQUksSUFBSTs7Ozs7O0VBSWpEOzs7Ozs7Ozs7OztPQVdLLFVBQVUsRUFBRSxLQUFJLFFBQVEsR0FBRyxLQUFJO09BQy9CLFVBQVUsRUFBRSxJQUFJLFFBQVEsR0FBRyxJQUFJOzs7R0FHbkMsSUFBRyxLQUFJLElBQUk7OztJQUdWLElBQUc7WUFDSztXQUNSLElBQUssS0FBSSxHQUFJLEtBQUk7WUFDVCxLQUFJOztZQUVKLFNBQVEsTUFBTSxnQkFBYyxLQUFLLEtBQUs7O1VBRS9DLElBQUssZ0JBQVE7SUFDWixJQUFHLGVBQVE7S0FDVixJQUFHLEtBQUksT0FBTyxHQUFHLElBQUk7OztNQUdwQixJQUFHLEtBQUksT0FBTyxHQUFHLElBQUk7T0FDcEIsNEJBQWM7O1FBRWIsTUFBTSxFQUFFLGdCQUFnQixLQUFLLE9BQUssSUFBSSxHQUFHOztjQUNuQzs7T0FFUCxhQUFhLEtBQUssSUFBSTs7Ozs7YUFJaEIsb0JBQW9CLEtBQUssS0FBSSxJQUFJOztXQUUxQyxJQUFLLGVBQVE7S0FDWixLQUFLLFlBQVk7V0FDbEIsTUFBTTs7S0FFTCxLQUFLLFlBQVksU0FBUSxNQUFNLGdCQUFjLEtBQUssS0FBSzs7O1dBRWpELGtCQUFrQixLQUFLLEtBQUk7O1VBR25DLElBQUssZ0JBQVE7SUFDaUIsTUFBTyxjQUFwQyxhQUFhLEtBQUssSUFBSTtJQUN0QixrQkFBa0IsS0FBSyxLQUFJO1dBQ3BCO1VBRVIsSUFBSztJQUN5QixNQUFPLGNBQXBDLGFBQWEsS0FBSyxJQUFJO1dBQ2Y7OztRQUdIOztJQUVKLElBQUcsZUFBUTtLQUNWLGFBQWEsS0FBSyxJQUFJO1dBQ3ZCLElBQUssZUFBUTtLQUNaLEtBQUssWUFBWTtXQUNsQixNQUFNOztLQUVMLFNBQVMsRUFBRSxTQUFRLE1BQU0sZ0JBQWMsS0FBSyxLQUFLO0tBQ2pELEtBQUcsb0JBQWEsTUFBSyxHQUFJLFNBQVMsWUFBWSxHQUFHO01BQ2hELFNBQVMsWUFBWSxFQUFFO2FBQ2hCOzs7OztXQUdGLGtCQUFrQixLQUFLLEtBQUk7Ozs7O1NBRzdCOztHQUVOO1FBQ0ssSUFBSSxPQUFFOztJQUVWLElBQUcsS0FBSSxJQUFJOzs7O0lBR1gsTUFBSTtLQUNIO0tBQ0Esa0JBQWtCO1dBRW5CLElBQUssSUFBSSxHQUFHOztXQUdaLElBQUssSUFBSSxHQUFHOzs7U0FHUCxNQUFNO0tBQ1YsNEJBQWM7O01BRWIsTUFBTSxFQUFFLHFCQUFxQixPQUFLLElBQUksR0FBRzs7V0FFM0MsSUFBSyxJQUFJLEdBQUc7Ozs7O0tBS1gsSUFBRyxnQkFBUTtNQUNWO1dBQ0EsWUFBWTtZQUdiLElBQUssZ0JBQVE7TUFDWixJQUFHLGVBQVE7O09BRVYseUJBQXlCLEtBQUk7O09BRTdCO09BQ0Esa0JBQWtCOzs7V0FHbkIsUUFBTzs7O1dBR1QsS0FBSyxnQkFBUSxPQUFNLElBQUksZUFBUTtLQUM5Qix5QkFBeUIsS0FBSTs7S0FFN0I7S0FDQSxrQkFBa0I7OztTQUVuQixVQUFVLEVBQUU7Ozs7OztHQUtiO1FBQ0ssSUFBSSxPQUFFOztRQUVOLE1BQU07SUFDViw0QkFBYzs7S0FFYixNQUFNLEVBQUUscUJBQXFCLE9BQUssSUFBSSxHQUFHOzs7U0FFMUMsVUFBVSxFQUFFOzs7O0dBR2I7Z0JBQ0MsU0FBUyxHQUFHLGdCQUFTOzs7R0FFdEI7SUFDQyxJQUFHLEtBQUssUUFBRztVQUNWLFVBQVUsRUFBRTtLQUNaLFdBQUksWUFBWSxFQUFFLEtBQUssUUFBUSxHQUFHLEtBQUssb0JBQWlCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7OztFQ3ZUckQsS0FBSyxXQVdWLFNBWFU7O1FBYVQsT0FBTyxFQUFFLGVBQVEsS0FBSyxZQUFXLElBQUksWUFBUTtRQUM3QyxTQUFTLEVBQUU7O0dBRVgsSUFBRztJQUNrQiw0QkFBWTt1QkFBbEI7O1NBQWQ7OztRQUVELE1BQU0sSUFBRzs7OztFQWpCVixLQUZVO09BR0wsR0FBRyxHQUFHLE1BQU0sR0FBRyxLQUFLLFlBQVUsY0FBYztVQUNoRCxHQUFHLFlBQU8sSUFBSTs7O0VBRWYsS0FOVTtjQU9ULEtBQUssU0FBYSxJQUFJOzs7RUFQbEIsS0FBSztFQUFMLEtBQUs7O0VBc0JWLEtBdEJVO1FBdUJULE9BQU87Ozs7RUFHUixLQTFCVTs7R0EyQkssU0FBRyxzQkFBVjtHQUNjLE1BQVcsSUFBSSxPQUFFLG9CQUEvQixLQUFLO2VBQ1osT0FBTyxFQUFFLElBQUksV0FBVSxJQUFJLGNBQVU7Ozs7Ozs7RUFLdEMsS0FsQ1U7R0FtQ1QsU0FBRyw4QkFBZSx5QkFBVyxhQUFNLGNBQWM7V0FDNUMsYUFBTTs7Ozs7Ozs7RUFLWixLQXpDVTtVQTBDVCxrQkFBTSxPQUFPLE9BQU8sRUFBRTs7Ozs7OztFQUt2QixLQS9DVTtHQWdESyxTQUFHLHNCQUFWO09BQ0gsTUFBTSxFQUFFLGFBQU0saUJBQWlCO0dBQ2YsNEJBQVk7c0JBQWxCOztRQUFkO1FBQ0EsTUFBTTtlQUNOOzs7Ozs7O0VBS0QsS0F6RFU7VUF5REcsYUFBTTs7O0VBRW5CLEtBM0RVO1VBMkRDLGFBQU07Ozs7Ozs7RUFLakIsS0FoRVU7VUFpRVQsYUFBTSxHQUFHOzs7Ozs7O0VBS1YsS0F0RVU7VUF1RVQsYUFBTTs7Ozs7OztFQUtQLEtBNUVVO0dBNkVULGFBQU0sUUFBUTs7Ozs7Ozs7RUFNZixLQW5GVTtVQW9GVCxhQUFNLElBQUk7Ozs7Ozs7O0VBTVgsS0ExRlU7VUEyRlQ7Ozs7O0VBSUQsS0EvRlU7O1FBaUdULE9BQU8sT0FBRSw0QkFBYyxLQUFLLFFBQVE7Ozs7Ozs7RUFNckMsS0F2R1U7UUF3R1QsT0FBTyxPQUFFLDRCQUFjLEtBQUssU0FBUzs7Ozs7O0VBS3RDLEtBN0dVO1FBOEdULE9BQU8sT0FBRSxVQUFVLElBQUksUUFBTzs7OztFQUcvQixLQWpIVTtlQWtIVCxPQUFPOzs7Ozs7O0VBS1IsS0F2SFU7O09Bd0hMLEdBQUcsR0FBRSxlQUFRLFVBQVMsR0FBSSxJQUFJLHdCQUFRLEVBQUUsUUFBUTtPQUNoRCxJQUFJLEVBQUUsYUFBTSw0QkFBVyxHQUFHLEdBQUcsR0FBRzs7O2NBR3BDLEtBQUssaUJBQWlCLE9BQVE7OztFQUUvQixLQTlIVTtPQStITCxNQUFNO09BQ04sRUFBRSxFQUFFO09BQ0osRUFBRSxFQUFFLFNBQVM7O1VBRVgsRUFBRSxFQUFFO0lBQ1QsTUFBTSxXQUFOLE1BQVksU0FBUyxLQUFLLGlCQUFpQjs7VUFDckM7OztFQUVSLEtBdklVOzs7Ozs7OztFQTZJVixLQTdJVTtlQThJVCw2QkFBZSxFQUFFLEtBQUs7Ozs7Ozs7RUFLdkIsS0FuSlU7ZUFvSlQsNkJBQWUsRUFBRSxPQUFPOzs7OztLQUl2QixtQ0FBaUIsS0FBSyxTQUFhLElBQUs7OztNQUd2QztPQUNDLEdBQUcsR0FBRyxNQUFNLEdBQUcsS0FBSyxZQUFVLGNBQWM7VUFDaEQsR0FBRyxZQUFPLElBQUk7Ozs7OztTQUtSO0dBQ047Z0JBQTBCLEtBQUssaUJBQWlCOztHQUNoRDtnQkFBdUIsS0FBSyxjQUFjOzs7OztHQUkxQztlQUFnQixLQUFLLFNBQWEiLCJmaWxlIjoiLi9kaXN0L2ltYmEuZGV2LmpzIiwic291cmNlc0NvbnRlbnQiOlsiIFx0Ly8gVGhlIG1vZHVsZSBjYWNoZVxuIFx0dmFyIGluc3RhbGxlZE1vZHVsZXMgPSB7fTtcblxuIFx0Ly8gVGhlIHJlcXVpcmUgZnVuY3Rpb25cbiBcdGZ1bmN0aW9uIF9fd2VicGFja19yZXF1aXJlX18obW9kdWxlSWQpIHtcblxuIFx0XHQvLyBDaGVjayBpZiBtb2R1bGUgaXMgaW4gY2FjaGVcbiBcdFx0aWYoaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0pXG4gXHRcdFx0cmV0dXJuIGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdLmV4cG9ydHM7XG5cbiBcdFx0Ly8gQ3JlYXRlIGEgbmV3IG1vZHVsZSAoYW5kIHB1dCBpdCBpbnRvIHRoZSBjYWNoZSlcbiBcdFx0dmFyIG1vZHVsZSA9IGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdID0ge1xuIFx0XHRcdGV4cG9ydHM6IHt9LFxuIFx0XHRcdGlkOiBtb2R1bGVJZCxcbiBcdFx0XHRsb2FkZWQ6IGZhbHNlXG4gXHRcdH07XG5cbiBcdFx0Ly8gRXhlY3V0ZSB0aGUgbW9kdWxlIGZ1bmN0aW9uXG4gXHRcdG1vZHVsZXNbbW9kdWxlSWRdLmNhbGwobW9kdWxlLmV4cG9ydHMsIG1vZHVsZSwgbW9kdWxlLmV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pO1xuXG4gXHRcdC8vIEZsYWcgdGhlIG1vZHVsZSBhcyBsb2FkZWRcbiBcdFx0bW9kdWxlLmxvYWRlZCA9IHRydWU7XG5cbiBcdFx0Ly8gUmV0dXJuIHRoZSBleHBvcnRzIG9mIHRoZSBtb2R1bGVcbiBcdFx0cmV0dXJuIG1vZHVsZS5leHBvcnRzO1xuIFx0fVxuXG5cbiBcdC8vIGV4cG9zZSB0aGUgbW9kdWxlcyBvYmplY3QgKF9fd2VicGFja19tb2R1bGVzX18pXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm0gPSBtb2R1bGVzO1xuXG4gXHQvLyBleHBvc2UgdGhlIG1vZHVsZSBjYWNoZVxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5jID0gaW5zdGFsbGVkTW9kdWxlcztcblxuIFx0Ly8gX193ZWJwYWNrX3B1YmxpY19wYXRoX19cbiBcdF9fd2VicGFja19yZXF1aXJlX18ucCA9IFwiXCI7XG5cbiBcdC8vIExvYWQgZW50cnkgbW9kdWxlIGFuZCByZXR1cm4gZXhwb3J0c1xuIFx0cmV0dXJuIF9fd2VicGFja19yZXF1aXJlX18oMCk7XG5cblxuXG4vKiogV0VCUEFDSyBGT09URVIgKipcbiAqKiB3ZWJwYWNrL2Jvb3RzdHJhcCBiY2Y0MGE1YzMzNGFjMjE5NzUzMVxuICoqLyIsIlxuaWYgdHlwZW9mIEltYmEgPT09ICd1bmRlZmluZWQnXG5cdHJlcXVpcmUgJy4vaW1iYSdcblx0cmVxdWlyZSAnLi9jb3JlLmV2ZW50cydcblx0cmVxdWlyZSAnLi9zY2hlZHVsZXInXG5cdHJlcXVpcmUgJy4vdGFnJ1xuXHRyZXF1aXJlICcuL2RvbSdcblx0cmVxdWlyZSAnLi9kb20uaHRtbCdcblx0cmVxdWlyZSAnLi9kb20uc3ZnJ1xuXG5cdGlmIEltYmEuU0VSVkVSXG5cdFx0cmVxdWlyZSAnLi9kb20uc2VydmVyJ1xuXHRcblx0aWYgSW1iYS5DTElFTlRcblx0XHRyZXF1aXJlICcuL2RvbS5jbGllbnQnXG5cdFx0cmVxdWlyZSAnLi9kb20uZXZlbnRzJ1xuXHRcdHJlcXVpcmUgJy4vZG9tLnN0YXRpYydcblxuXHRyZXF1aXJlICcuL3NlbGVjdG9yJ1xuZWxzZVxuXHRjb25zb2xlLndhcm4gXCJJbWJhIHZ7SW1iYS5WRVJTSU9OfSBpcyBhbHJlYWR5IGxvYWRlZFwiXG5cblxuXG4vKiogV0VCUEFDSyBGT09URVIgKipcbiAqKiBzcmMvaW1iYS9pbmRleC5pbWJhXG4gKiovIiwiaWYgdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCdcblx0IyBzaG91bGQgbm90IGdvIHRoZXJlXG5cdGdsb2JhbCA9IHdpbmRvd1xuXG52YXIgaXNDbGllbnQgPSAodHlwZW9mIHdpbmRvdyA9PSAnb2JqZWN0JyBhbmQgdGhpcyA9PSB3aW5kb3cpXG4jIyNcbkltYmEgaXMgdGhlIG5hbWVzcGFjZSBmb3IgYWxsIHJ1bnRpbWUgcmVsYXRlZCB1dGlsaXRpZXNcbkBuYW1lc3BhY2VcbiMjI1xuSW1iYSA9IHtcblx0VkVSU0lPTjogJzAuMTQuMydcblx0Q0xJRU5UOiBpc0NsaWVudFxuXHRTRVJWRVI6ICFpc0NsaWVudFxuXHRERUJVRzogbm9cbn1cblxudmFyIHJlZyA9IC8tLi9nXG5cbiMjI1xuVHJ1ZSBpZiBydW5uaW5nIGluIGNsaWVudCBlbnZpcm9ubWVudC5cbkByZXR1cm4ge2Jvb2x9XG4jIyNcbmRlZiBJbWJhLmlzQ2xpZW50XG5cdEltYmEuQ0xJRU5UID09IHllc1xuXG4jIyNcblRydWUgaWYgcnVubmluZyBpbiBzZXJ2ZXIgZW52aXJvbm1lbnQuXG5AcmV0dXJuIHtib29sfVxuIyMjXG5kZWYgSW1iYS5pc1NlcnZlclxuXHRJbWJhLlNFUlZFUiA9PSB5ZXNcblxuZGVmIEltYmEuc3ViY2xhc3Mgb2JqLCBzdXBcblx0Zm9yIGssdiBvZiBzdXBcblx0XHRvYmpba10gPSB2IGlmIHN1cC5oYXNPd25Qcm9wZXJ0eShrKVxuXG5cdG9iajpwcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cDpwcm90b3R5cGUpXG5cdG9iajpfX3N1cGVyX18gPSBvYmo6cHJvdG90eXBlOl9fc3VwZXJfXyA9IHN1cDpwcm90b3R5cGVcblx0b2JqOnByb3RvdHlwZTppbml0aWFsaXplID0gb2JqOnByb3RvdHlwZTpjb25zdHJ1Y3RvciA9IG9ialxuXHRyZXR1cm4gb2JqXG5cbiMjI1xuTGlnaHR3ZWlnaHQgbWV0aG9kIGZvciBtYWtpbmcgYW4gb2JqZWN0IGl0ZXJhYmxlIGluIGltYmFzIGZvci9pbiBsb29wcy5cbklmIHRoZSBjb21waWxlciBjYW5ub3Qgc2F5IGZvciBjZXJ0YWluIHRoYXQgYSB0YXJnZXQgaW4gYSBmb3IgbG9vcCBpcyBhblxuYXJyYXksIGl0IHdpbGwgY2FjaGUgdGhlIGl0ZXJhYmxlIHZlcnNpb24gYmVmb3JlIGxvb3BpbmcuXG5cbmBgYGltYmFcbiMgdGhpcyBpcyB0aGUgd2hvbGUgbWV0aG9kXG5kZWYgSW1iYS5pdGVyYWJsZSBvXG5cdHJldHVybiBvID8gKG86dG9BcnJheSA/IG8udG9BcnJheSA6IG8pIDogW11cblxuY2xhc3MgQ3VzdG9tSXRlcmFibGVcblx0ZGVmIHRvQXJyYXlcblx0XHRbMSwyLDNdXG5cbiMgd2lsbCByZXR1cm4gWzIsNCw2XVxuZm9yIHggaW4gQ3VzdG9tSXRlcmFibGUubmV3XG5cdHggKiAyXG5cbmBgYFxuIyMjXG5kZWYgSW1iYS5pdGVyYWJsZSBvXG5cdHJldHVybiBvID8gKG86dG9BcnJheSA/IG8udG9BcnJheSA6IG8pIDogW11cblxuIyMjXG5Db2VyY2VzIGEgdmFsdWUgaW50byBhIHByb21pc2UuIElmIHZhbHVlIGlzIGFycmF5IGl0IHdpbGxcbmNhbGwgYFByb21pc2UuYWxsKHZhbHVlKWAsIG9yIGlmIGl0IGlzIG5vdCBhIHByb21pc2UgaXQgd2lsbFxud3JhcCB0aGUgdmFsdWUgaW4gYFByb21pc2UucmVzb2x2ZSh2YWx1ZSlgLiBVc2VkIGZvciBleHBlcmltZW50YWxcbmF3YWl0IHN5bnRheC5cbkByZXR1cm4ge1Byb21pc2V9XG4jIyNcbmRlZiBJbWJhLmF3YWl0IHZhbHVlXG5cdGlmIHZhbHVlIGlzYSBBcnJheVxuXHRcdFByb21pc2UuYWxsKHZhbHVlKVxuXHRlbGlmIHZhbHVlIGFuZCB2YWx1ZTp0aGVuXG5cdFx0dmFsdWVcblx0ZWxzZVxuXHRcdFByb21pc2UucmVzb2x2ZSh2YWx1ZSlcblxuZGVmIEltYmEudG9DYW1lbENhc2Ugc3RyXG5cdHN0ci5yZXBsYWNlKHJlZykgZG8gfG18IG0uY2hhckF0KDEpLnRvVXBwZXJDYXNlXG5cbmRlZiBJbWJhLnRvQ2FtZWxDYXNlIHN0clxuXHRzdHIucmVwbGFjZShyZWcpIGRvIHxtfCBtLmNoYXJBdCgxKS50b1VwcGVyQ2FzZVxuXG5kZWYgSW1iYS5pbmRleE9mIGEsYlxuXHRyZXR1cm4gKGIgJiYgYjppbmRleE9mKSA/IGIuaW5kZXhPZihhKSA6IFtdOmluZGV4T2YuY2FsbChhLGIpXG5cbmRlZiBJbWJhLnByb3Agc2NvcGUsIG5hbWUsIG9wdHNcblx0aWYgc2NvcGU6ZGVmaW5lUHJvcGVydHlcblx0XHRyZXR1cm4gc2NvcGUuZGVmaW5lUHJvcGVydHkobmFtZSxvcHRzKVxuXHRyZXR1cm5cblxuZGVmIEltYmEuYXR0ciBzY29wZSwgbmFtZSwgb3B0c1xuXHRpZiBzY29wZTpkZWZpbmVBdHRyaWJ1dGVcblx0XHRyZXR1cm4gc2NvcGUuZGVmaW5lQXR0cmlidXRlKG5hbWUsb3B0cylcblxuXHRsZXQgZ2V0TmFtZSA9IEltYmEudG9DYW1lbENhc2UobmFtZSlcblx0bGV0IHNldE5hbWUgPSBJbWJhLnRvQ2FtZWxDYXNlKCdzZXQtJyArIG5hbWUpXG5cblx0c2NvcGU6cHJvdG90eXBlW2dldE5hbWVdID0gZG9cblx0XHRyZXR1cm4gdGhpcy5nZXRBdHRyaWJ1dGUobmFtZSlcblxuXHRzY29wZTpwcm90b3R5cGVbc2V0TmFtZV0gPSBkbyB8dmFsdWV8XG5cdFx0dGhpcy5zZXRBdHRyaWJ1dGUobmFtZSx2YWx1ZSlcblx0XHRyZXR1cm4gdGhpc1xuXG5cdHJldHVyblxuXG5cblxuLyoqIFdFQlBBQ0sgRk9PVEVSICoqXG4gKiogc3JjL2ltYmEvaW1iYS5pbWJhXG4gKiovIiwiXG5cbmRlZiBlbWl0X18gZXZlbnQsIGFyZ3MsIG5vZGVcblx0IyB2YXIgbm9kZSA9IGNic1tldmVudF1cblx0dmFyIHByZXYsIGNiLCByZXRcblxuXHR3aGlsZSAocHJldiA9IG5vZGUpIGFuZCAobm9kZSA9IG5vZGU6bmV4dClcblx0XHRpZiBjYiA9IG5vZGU6bGlzdGVuZXJcblx0XHRcdGlmIG5vZGU6cGF0aCBhbmQgY2Jbbm9kZTpwYXRoXVxuXHRcdFx0XHRyZXQgPSBhcmdzID8gY2Jbbm9kZTpwYXRoXS5hcHBseShjYixhcmdzKSA6IGNiW25vZGU6cGF0aF0oKVxuXHRcdFx0ZWxzZVxuXHRcdFx0XHQjIGNoZWNrIGlmIGl0IGlzIGEgbWV0aG9kP1xuXHRcdFx0XHRyZXQgPSBhcmdzID8gY2IuYXBwbHkobm9kZSwgYXJncykgOiBjYi5jYWxsKG5vZGUpXG5cblx0XHRpZiBub2RlOnRpbWVzICYmIC0tbm9kZTp0aW1lcyA8PSAwXG5cdFx0XHRwcmV2Om5leHQgPSBub2RlOm5leHRcblx0XHRcdG5vZGU6bGlzdGVuZXIgPSBudWxsXG5cdHJldHVyblxuXG4jIG1ldGhvZCBmb3IgcmVnaXN0ZXJpbmcgYSBsaXN0ZW5lciBvbiBvYmplY3RcbmRlZiBJbWJhLmxpc3RlbiBvYmosIGV2ZW50LCBsaXN0ZW5lciwgcGF0aFxuXHR2YXIgY2JzLCBsaXN0LCB0YWlsXG5cdGNicyA9IG9iajpfX2xpc3RlbmVyc19fIHx8PSB7fVxuXHRsaXN0ID0gY2JzW2V2ZW50XSB8fD0ge31cblx0dGFpbCA9IGxpc3Q6dGFpbCB8fCAobGlzdDp0YWlsID0gKGxpc3Q6bmV4dCA9IHt9KSlcblx0dGFpbDpsaXN0ZW5lciA9IGxpc3RlbmVyXG5cdHRhaWw6cGF0aCA9IHBhdGhcblx0bGlzdDp0YWlsID0gdGFpbDpuZXh0ID0ge31cblx0cmV0dXJuIHRhaWxcblxuZGVmIEltYmEub25jZSBvYmosIGV2ZW50LCBsaXN0ZW5lclxuXHR2YXIgdGFpbCA9IEltYmEubGlzdGVuKG9iaixldmVudCxsaXN0ZW5lcilcblx0dGFpbDp0aW1lcyA9IDFcblx0cmV0dXJuIHRhaWxcblxuZGVmIEltYmEudW5saXN0ZW4gb2JqLCBldmVudCwgY2IsIG1ldGhcblx0dmFyIG5vZGUsIHByZXZcblx0dmFyIG1ldGEgPSBvYmo6X19saXN0ZW5lcnNfX1xuXHRyZXR1cm4gdW5sZXNzIG1ldGFcblxuXHRpZiBub2RlID0gbWV0YVtldmVudF1cblx0XHR3aGlsZSAocHJldiA9IG5vZGUpIGFuZCAobm9kZSA9IG5vZGU6bmV4dClcblx0XHRcdGlmIG5vZGUgPT0gY2IgfHwgbm9kZTpsaXN0ZW5lciA9PSBjYlxuXHRcdFx0XHRwcmV2Om5leHQgPSBub2RlOm5leHRcblx0XHRcdFx0IyBjaGVjayBmb3IgY29ycmVjdCBwYXRoIGFzIHdlbGw/XG5cdFx0XHRcdG5vZGU6bGlzdGVuZXIgPSBudWxsXG5cdFx0XHRcdGJyZWFrXG5cdHJldHVyblxuXG5kZWYgSW1iYS5lbWl0IG9iaiwgZXZlbnQsIHBhcmFtc1xuXHRpZiB2YXIgY2IgPSBvYmo6X19saXN0ZW5lcnNfX1xuXHRcdGVtaXRfXyhldmVudCxwYXJhbXMsY2JbZXZlbnRdKSBpZiBjYltldmVudF1cblx0XHRlbWl0X18oZXZlbnQsW2V2ZW50LHBhcmFtc10sY2I6YWxsKSBpZiBjYjphbGwgIyBhbmQgZXZlbnQgIT0gJ2FsbCdcblx0cmV0dXJuXG5cbmRlZiBJbWJhLm9ic2VydmVQcm9wZXJ0eSBvYnNlcnZlciwga2V5LCB0cmlnZ2VyLCB0YXJnZXQsIHByZXZcblx0aWYgcHJldiBhbmQgdHlwZW9mIHByZXYgPT0gJ29iamVjdCdcblx0XHRJbWJhLnVubGlzdGVuKHByZXYsJ2FsbCcsb2JzZXJ2ZXIsdHJpZ2dlcilcblx0aWYgdGFyZ2V0IGFuZCB0eXBlb2YgdGFyZ2V0ID09ICdvYmplY3QnXG5cdFx0SW1iYS5saXN0ZW4odGFyZ2V0LCdhbGwnLG9ic2VydmVyLHRyaWdnZXIpXG5cdHNlbGZcblxuXG4vKiogV0VCUEFDSyBGT09URVIgKipcbiAqKiBzcmMvaW1iYS9jb3JlLmV2ZW50cy5pbWJhXG4gKiovIiwiXG52YXIgcmFmICMgdmVyeSBzaW1wbGUgcmFmIHBvbHlmaWxsXG5yYWYgfHw9IGdsb2JhbDpyZXF1ZXN0QW5pbWF0aW9uRnJhbWVcbnJhZiB8fD0gZ2xvYmFsOndlYmtpdFJlcXVlc3RBbmltYXRpb25GcmFtZVxucmFmIHx8PSBnbG9iYWw6bW96UmVxdWVzdEFuaW1hdGlvbkZyYW1lXG5yYWYgfHw9IGRvIHxibGt8IHNldFRpbWVvdXQoYmxrLDEwMDAgLyA2MClcblxuZGVmIEltYmEudGljayBkXG5cdHJhZihJbWJhLnRpY2tlcikgaWYgQHNjaGVkdWxlZFxuXHRJbWJhLlNjaGVkdWxlci53aWxsUnVuXG5cdGVtaXQoc2VsZiwndGljaycsW2RdKVxuXHRJbWJhLlNjaGVkdWxlci5kaWRSdW5cblx0cmV0dXJuXG5cbmRlZiBJbWJhLnRpY2tlclxuXHRAdGlja2VyIHx8PSBkbyB8ZXwgdGljayhlKVxuXG4jIyNcblxuR2xvYmFsIGFsdGVybmF0aXZlIHRvIHJlcXVlc3RBbmltYXRpb25GcmFtZS4gU2NoZWR1bGUgYSB0YXJnZXRcbnRvIHRpY2sgZXZlcnkgZnJhbWUuIFlvdSBjYW4gc3BlY2lmeSB3aGljaCBtZXRob2QgdG8gY2FsbCBvbiB0aGVcbnRhcmdldCAoZGVmYXVsdHMgdG8gdGljaykuXG5cbiMjI1xuZGVmIEltYmEuc2NoZWR1bGUgdGFyZ2V0LCBtZXRob2QgPSAndGljaydcblx0bGlzdGVuKHNlbGYsJ3RpY2snLHRhcmdldCxtZXRob2QpXG5cdCMgc3RhcnQgc2NoZWR1bGluZyBub3cgaWYgdGhpcyB3YXMgdGhlIGZpcnN0IG9uZVxuXHR1bmxlc3MgQHNjaGVkdWxlZFxuXHRcdEBzY2hlZHVsZWQgPSB5ZXNcblx0XHRyYWYoSW1iYS50aWNrZXIpXG5cdHNlbGZcblxuIyMjXG5cblVuc2NoZWR1bGUgYSBwcmV2aW91c2x5IHNjaGVkdWxlZCB0YXJnZXRcblxuIyMjXG5kZWYgSW1iYS51bnNjaGVkdWxlIHRhcmdldCwgbWV0aG9kXG5cdHVubGlzdGVuKHNlbGYsJ3RpY2snLHRhcmdldCxtZXRob2QpXG5cdHZhciBjYnMgPSBzZWxmOl9fbGlzdGVuZXJzX18gfHw9IHt9XG5cdGlmICFjYnM6dGljayBvciAhY2JzOnRpY2s6bmV4dCBvciAhY2JzOnRpY2s6bmV4dDpsaXN0ZW5lclxuXHRcdEBzY2hlZHVsZWQgPSBub1xuXHRzZWxmXG5cbiMjI1xuXG5MaWdodCB3cmFwcGVyIGFyb3VuZCBuYXRpdmUgc2V0VGltZW91dCB0aGF0IGV4cGVjdHMgdGhlIGJsb2NrIC8gZnVuY3Rpb25cbmFzIGxhc3QgYXJndW1lbnQgKGluc3RlYWQgb2YgZmlyc3QpLiBJdCBhbHNvIHRyaWdnZXJzIGFuIGV2ZW50IHRvIEltYmFcbmFmdGVyIHRoZSB0aW1lb3V0IHRvIGxldCBzY2hlZHVsZXJzIHVwZGF0ZSAodG8gcmVyZW5kZXIgZXRjKSBhZnRlcndhcmRzLlxuXG4jIyNcbmRlZiBJbWJhLnNldFRpbWVvdXQgZGVsYXksICZibG9ja1xuXHRzZXRUaW1lb3V0KCYsZGVsYXkpIGRvXG5cdFx0YmxvY2soKVxuXHRcdEltYmEuU2NoZWR1bGVyLm1hcmtEaXJ0eVxuXHRcdCMgSW1iYS5lbWl0KEltYmEsJ3RpbWVvdXQnLFtibG9ja10pXG5cbiMjI1xuXG5MaWdodCB3cmFwcGVyIGFyb3VuZCBuYXRpdmUgc2V0SW50ZXJ2YWwgdGhhdCBleHBlY3RzIHRoZSBibG9jayAvIGZ1bmN0aW9uXG5hcyBsYXN0IGFyZ3VtZW50IChpbnN0ZWFkIG9mIGZpcnN0KS4gSXQgYWxzbyB0cmlnZ2VycyBhbiBldmVudCB0byBJbWJhXG5hZnRlciBldmVyeSBpbnRlcnZhbCB0byBsZXQgc2NoZWR1bGVycyB1cGRhdGUgKHRvIHJlcmVuZGVyIGV0YykgYWZ0ZXJ3YXJkcy5cblxuIyMjXG5kZWYgSW1iYS5zZXRJbnRlcnZhbCBpbnRlcnZhbCwgJmJsb2NrXG5cdHNldEludGVydmFsKCYsaW50ZXJ2YWwpIGRvXG5cdFx0YmxvY2soKVxuXHRcdEltYmEuU2NoZWR1bGVyLm1hcmtEaXJ0eVxuXHRcdCMgSW1iYS5lbWl0KEltYmEsJ2ludGVydmFsJyxbYmxvY2tdKVxuXG4jIyNcbkNsZWFyIGludGVydmFsIHdpdGggc3BlY2lmaWVkIGlkXG4jIyNcbmRlZiBJbWJhLmNsZWFySW50ZXJ2YWwgaW50ZXJ2YWxcblx0Y2xlYXJJbnRlcnZhbChpbnRlcnZhbClcblxuIyMjXG5DbGVhciB0aW1lb3V0IHdpdGggc3BlY2lmaWVkIGlkXG4jIyNcbmRlZiBJbWJhLmNsZWFyVGltZW91dCB0aW1lb3V0XG5cdGNsZWFyVGltZW91dCh0aW1lb3V0KVxuXG4jIHNob3VsZCBhZGQgYW4gSW1iYS5ydW4gLyBzZXRJbW1lZGlhdGUgdGhhdFxuIyBwdXNoZXMgbGlzdGVuZXIgb250byB0aGUgdGljay1xdWV1ZSB3aXRoIHRpbWVzIC0gb25jZVxuXG5cbiMjI1xuXG5JbnN0YW5jZXMgb2YgSW1iYS5TY2hlZHVsZXIgbWFuYWdlcyB3aGVuIHRvIGNhbGwgYHRpY2soKWAgb24gdGhlaXIgdGFyZ2V0LFxuYXQgYSBzcGVjaWZpZWQgZnJhbWVyYXRlIG9yIHdoZW4gY2VydGFpbiBldmVudHMgb2NjdXIuIFJvb3Qtbm9kZXMgaW4geW91clxuYXBwbGljYXRpb25zIHdpbGwgdXN1YWxseSBoYXZlIGEgc2NoZWR1bGVyIHRvIG1ha2Ugc3VyZSB0aGV5IHJlcmVuZGVyIHdoZW5cbnNvbWV0aGluZyBjaGFuZ2VzLiBJdCBpcyBhbHNvIHBvc3NpYmxlIHRvIG1ha2UgaW5uZXIgY29tcG9uZW50cyB1c2UgdGhlaXJcbm93biBzY2hlZHVsZXJzIHRvIGNvbnRyb2wgd2hlbiB0aGV5IHJlbmRlci5cblxuQGluYW1lIHNjaGVkdWxlclxuXG4jIyNcbmNsYXNzIEltYmEuU2NoZWR1bGVyXG5cblx0ZGVmIHNlbGYubWFya0RpcnR5XG5cdFx0QGRpcnR5ID0geWVzXG5cdFx0c2VsZlxuXG5cdGRlZiBzZWxmLmlzRGlydHlcblx0XHQhIUBkaXJ0eVxuXG5cdGRlZiBzZWxmLndpbGxSdW5cblx0XHRAYWN0aXZlID0geWVzXG5cblx0ZGVmIHNlbGYuZGlkUnVuXG5cdFx0QGFjdGl2ZSA9IG5vXG5cdFx0QGRpcnR5ID0gbm9cblxuXHRkZWYgc2VsZi5pc0FjdGl2ZVxuXHRcdCEhQGFjdGl2ZVxuXG5cdCMjI1xuXHRDcmVhdGUgYSBuZXcgSW1iYS5TY2hlZHVsZXIgZm9yIHNwZWNpZmllZCB0YXJnZXRcblx0QHJldHVybiB7SW1iYS5TY2hlZHVsZXJ9XG5cdCMjI1xuXHRkZWYgaW5pdGlhbGl6ZSB0YXJnZXRcblx0XHRAdGFyZ2V0ID0gdGFyZ2V0XG5cdFx0QG1hcmtlZCA9IG5vXG5cdFx0QGFjdGl2ZSA9IG5vXG5cdFx0QG1hcmtlciA9IGRvIG1hcmtcblx0XHRAdGlja2VyID0gZG8gfGV8IHRpY2soZSlcblx0XHRcblx0XHRAZXZlbnRzID0geWVzXG5cdFx0QGZwcyA9IDFcblxuXHRcdEBkdCA9IDBcblx0XHRAdGltZXN0YW1wID0gMFxuXHRcdEB0aWNrcyA9IDBcblx0XHRAZmx1c2hlcyA9IDBcblxuXHQjIyNcblx0Q2hlY2sgd2hldGhlciB0aGUgY3VycmVudCBzY2hlZHVsZXIgaXMgYWN0aXZlIG9yIG5vdFxuXHRAcmV0dXJuIHtib29sfVxuXHQjIyNcblx0ZGVmIGFjdGl2ZVxuXHRcdEBhY3RpdmVcblxuXHQjIyNcblx0RGVsdGEgdGltZSBiZXR3ZWVuIHRoZSB0d28gbGFzdCB0aWNrc1xuXHRAcmV0dXJuIHtOdW1iZXJ9XG5cdCMjI1xuXHRkZWYgZHRcblx0XHRAZHRcblxuXHQjIyNcblx0Q29uZmlndXJlIHRoZSBzY2hlZHVsZXJcblx0QHJldHVybiB7c2VsZn1cblx0IyMjXG5cdGRlZiBjb25maWd1cmUgZnBzOiAxLCBldmVudHM6IHllc1xuXHRcdEBldmVudHMgPSBldmVudHMgaWYgZXZlbnRzICE9IG51bGxcblx0XHRAZnBzID0gZnBzIGlmIGZwcyAhPSBudWxsXG5cdFx0c2VsZlxuXG5cdCMjI1xuXHRNYXJrIHRoZSBzY2hlZHVsZXIgYXMgZGlydHkuIFRoaXMgd2lsbCBtYWtlIHN1cmUgdGhhdFxuXHR0aGUgc2NoZWR1bGVyIGNhbGxzIGB0YXJnZXQudGlja2Agb24gdGhlIG5leHQgZnJhbWVcblx0QHJldHVybiB7c2VsZn1cblx0IyMjXG5cdGRlZiBtYXJrXG5cdFx0QG1hcmtlZCA9IHllc1xuXHRcdHNlbGZcblxuXHQjIyNcblx0SW5zdGFudGx5IHRyaWdnZXIgdGFyZ2V0LnRpY2sgYW5kIG1hcmsgc2NoZWR1bGVyIGFzIGNsZWFuIChub3QgZGlydHkvbWFya2VkKS5cblx0VGhpcyBpcyBjYWxsZWQgaW1wbGljaXRseSBmcm9tIHRpY2ssIGJ1dCBjYW4gYWxzbyBiZSBjYWxsZWQgbWFudWFsbHkgaWYgeW91XG5cdHJlYWxseSB3YW50IHRvIGZvcmNlIGEgdGljayB3aXRob3V0IHdhaXRpbmcgZm9yIHRoZSBuZXh0IGZyYW1lLlxuXHRAcmV0dXJuIHtzZWxmfVxuXHQjIyNcblx0ZGVmIGZsdXNoXG5cdFx0QG1hcmtlZCA9IG5vXG5cdFx0QGZsdXNoZXMrK1xuXHRcdEB0YXJnZXQudGlja1xuXHRcdHNlbGZcblxuXHQjIyNcblx0QGZpeG1lIHRoaXMgZXhwZWN0cyByYWYgdG8gcnVuIGF0IDYwIGZwcyBcblxuXHRDYWxsZWQgYXV0b21hdGljYWxseSBvbiBldmVyeSBmcmFtZSB3aGlsZSB0aGUgc2NoZWR1bGVyIGlzIGFjdGl2ZS5cblx0SXQgd2lsbCBvbmx5IGNhbGwgYHRhcmdldC50aWNrYCBpZiB0aGUgc2NoZWR1bGVyIGlzIG1hcmtlZCBkaXJ0eSxcblx0b3Igd2hlbiBhY2NvcmRpbmcgdG8gQGZwcyBzZXR0aW5nLlxuXG5cdElmIHlvdSBoYXZlIHNldCB1cCBhIHNjaGVkdWxlciB3aXRoIGFuIGZwcyBvZiAxLCB0aWNrIHdpbGwgc3RpbGwgYmVcblx0Y2FsbGVkIGV2ZXJ5IGZyYW1lLCBidXQgYHRhcmdldC50aWNrYCB3aWxsIG9ubHkgYmUgY2FsbGVkIG9uY2UgZXZlcnlcblx0c2Vjb25kLCBhbmQgaXQgd2lsbCAqbWFrZSBzdXJlKiBlYWNoIGB0YXJnZXQudGlja2AgaGFwcGVucyBpbiBzZXBhcmF0ZVxuXHRzZWNvbmRzIGFjY29yZGluZyB0byBEYXRlLiBTbyBpZiB5b3UgaGF2ZSBhIG5vZGUgdGhhdCByZW5kZXJzIGEgY2xvY2tcblx0YmFzZWQgb24gRGF0ZS5ub3cgKG9yIHNvbWV0aGluZyBzaW1pbGFyKSwgeW91IGNhbiBzY2hlZHVsZSBpdCB3aXRoIDFmcHMsXG5cdG5ldmVyIG5lZWRpbmcgdG8gd29ycnkgYWJvdXQgdHdvIHRpY2tzIGhhcHBlbmluZyB3aXRoaW4gdGhlIHNhbWUgc2Vjb25kLlxuXHRUaGUgc2FtZSBnb2VzIGZvciA0ZnBzLCAxMGZwcyBldGMuXG5cblx0QHByb3RlY3RlZFxuXHRAcmV0dXJuIHtzZWxmfVxuXHQjIyNcblx0ZGVmIHRpY2sgZGVsdGFcblx0XHRAdGlja3MrK1xuXHRcdEBkdCA9IGRlbHRhXG5cblx0XHRsZXQgZnBzID0gQGZwc1xuXHRcdFxuXHRcdGlmIGZwcyA9PSA2MFxuXHRcdFx0QG1hcmtlZCA9IHllc1xuXHRcdGVsaWYgZnBzID09IDMwXG5cdFx0XHRAbWFya2VkID0geWVzIGlmIEB0aWNrcyAlIDJcblx0XHRlbGlmIGZwc1xuXHRcdFx0IyBpZiBpdCBpcyBsZXNzIHJvdW5kIC0gd2UgdHJpZ2dlciBiYXNlZFxuXHRcdFx0IyBvbiBkYXRlLCBmb3IgY29uc2lzdGVudCByZW5kZXJpbmcuXG5cdFx0XHQjIGllLCBpZiB5b3Ugd2FudCB0byByZW5kZXIgZXZlcnkgc2Vjb25kXG5cdFx0XHQjIGl0IGlzIGltcG9ydGFudCB0aGF0IG5vIHR3byByZW5kZXJzXG5cdFx0XHQjIGhhcHBlbiBkdXJpbmcgdGhlIHNhbWUgc2Vjb25kIChhY2NvcmRpbmcgdG8gRGF0ZSlcblx0XHRcdGxldCBwZXJpb2QgPSAoKDYwIC8gZnBzKSAvIDYwKSAqIDEwMDBcblx0XHRcdGxldCBiZWF0ID0gTWF0aC5mbG9vcihEYXRlLm5vdyAvIHBlcmlvZClcblxuXHRcdFx0aWYgQGJlYXQgIT0gYmVhdFxuXHRcdFx0XHRAYmVhdCA9IGJlYXRcblx0XHRcdFx0QG1hcmtlZCA9IHllc1xuXG5cdFx0Zmx1c2ggaWYgQG1hcmtlZCBvciAoQGV2ZW50cyBhbmQgSW1iYS5TY2hlZHVsZXIuaXNEaXJ0eSlcblx0XHQjIHJlc2NoZWR1bGUgaWYgQGFjdGl2ZVxuXHRcdHNlbGZcblxuXHQjIyNcblx0U3RhcnQgdGhlIHNjaGVkdWxlciBpZiBpdCBpcyBub3QgYWxyZWFkeSBhY3RpdmUuXG5cdCoqV2hpbGUgYWN0aXZlKiosIHRoZSBzY2hlZHVsZXIgd2lsbCBvdmVycmlkZSBgdGFyZ2V0LmNvbW1pdGBcblx0dG8gZG8gbm90aGluZy4gQnkgZGVmYXVsdCBJbWJhLnRhZyNjb21taXQgY2FsbHMgcmVuZGVyLCBzb1xuXHR0aGF0IHJlbmRlcmluZyBpcyBjYXNjYWRlZCB0aHJvdWdoIHRvIGNoaWxkcmVuIHdoZW4gcmVuZGVyaW5nXG5cdGEgbm9kZS4gV2hlbiBhIHNjaGVkdWxlciBpcyBhY3RpdmUgKGZvciBhIG5vZGUpLCBJbWJhIGRpc2FibGVzXG5cdHRoaXMgYXV0b21hdGljIHJlbmRlcmluZy5cblx0IyMjXG5cdGRlZiBhY3RpdmF0ZVxuXHRcdHVubGVzcyBAYWN0aXZlXG5cdFx0XHRAYWN0aXZlID0geWVzXG5cdFx0XHQjIG92ZXJyaWRlIHRhcmdldCNjb21taXQgd2hpbGUgdGhpcyBpcyBhY3RpdmVcblx0XHRcdEBjb21taXQgPSBAdGFyZ2V0OmNvbW1pdFxuXHRcdFx0QHRhcmdldDpjb21taXQgPSBkbyB0aGlzXG5cdFx0XHRJbWJhLnNjaGVkdWxlKHNlbGYpXG5cdFx0XHRJbWJhLmxpc3RlbihJbWJhLCdldmVudCcsc2VsZiwnb25ldmVudCcpIGlmIEBldmVudHNcblx0XHRcdEB0YXJnZXQ/LmZsYWcoJ3NjaGVkdWxlZF8nKVxuXHRcdFx0dGljaygwKSAjIHN0YXJ0IHRpY2tpbmdcblx0XHRyZXR1cm4gc2VsZlxuXG5cdCMjI1xuXHRTdG9wIHRoZSBzY2hlZHVsZXIgaWYgaXQgaXMgYWN0aXZlLlxuXHQjIyNcblx0ZGVmIGRlYWN0aXZhdGVcblx0XHRpZiBAYWN0aXZlXG5cdFx0XHRAYWN0aXZlID0gbm9cblx0XHRcdEB0YXJnZXQ6Y29tbWl0ID0gQGNvbW1pdFxuXHRcdFx0SW1iYS51bnNjaGVkdWxlKHNlbGYpXG5cdFx0XHRJbWJhLnVubGlzdGVuKEltYmEsJ2V2ZW50JyxzZWxmKVxuXHRcdFx0QHRhcmdldD8udW5mbGFnKCdzY2hlZHVsZWRfJylcblx0XHRyZXR1cm4gc2VsZlxuXG5cdGRlZiB0cmFja1xuXHRcdEBtYXJrZXJcblxuXHRkZWYgb25ldmVudCBldmVudFxuXHRcdHJldHVybiBzZWxmIGlmIEBtYXJrZWRcblxuXHRcdGlmIEBldmVudHMgaXNhIEZ1bmN0aW9uXG5cdFx0XHRtYXJrIGlmIEBldmVudHMoZXZlbnQpXHRcblx0XHRlbGlmIEBldmVudHMgaXNhIEFycmF5XG5cdFx0XHRtYXJrIGlmIGV2ZW50Py50eXBlIGluIEBldmVudHNcblx0XHRlbGlmIEBldmVudHNcblx0XHRcdG1hcmsgaWYgZXZlbnQuQHJlc3BvbmRlclxuXHRcdHNlbGZcblxuXG5cbi8qKiBXRUJQQUNLIEZPT1RFUiAqKlxuICoqIHNyYy9pbWJhL3NjaGVkdWxlci5pbWJhXG4gKiovIiwiZGVmIEltYmEuc3RhdGljIGl0ZW1zLCBuclxuXHRpdGVtczpzdGF0aWMgPSBuclxuXHRyZXR1cm4gaXRlbXNcblxuIyMjXG5UaGlzIGlzIHRoZSBiYXNlY2xhc3MgdGhhdCBhbGwgdGFncyBpbiBpbWJhIGluaGVyaXQgZnJvbS5cbkBpbmFtZSBub2RlXG4jIyNcbmNsYXNzIEltYmEuVGFnXG5cblx0ZGVmIHNlbGYuY3JlYXRlTm9kZVxuXHRcdHRocm93IFwiTm90IGltcGxlbWVudGVkXCJcblxuXHRkZWYgc2VsZi5idWlsZFxuXHRcdHNlbGYubmV3KHNlbGYuY3JlYXRlTm9kZSlcblxuXHRwcm9wIG9iamVjdFxuXG5cdGRlZiBkb21cblx0XHRAZG9tXG5cblx0ZGVmIGluaXRpYWxpemUgZG9tXG5cdFx0c2VsZi5kb20gPSBkb21cblx0XHRcblx0ZGVmIHNldERvbSBkb21cblx0XHRkb20uQHRhZyA9IHNlbGZcblx0XHRAZG9tID0gZG9tXG5cdFx0c2VsZlxuXG5cdCMjI1xuXHRTZXR0aW5nIHJlZmVyZW5jZXMgZm9yIHRhZ3MgbGlrZVxuXHRgPGRpdkBoZWFkZXI+YCB3aWxsIGNvbXBpbGUgdG8gYHRhZygnZGl2Jykuc2V0UmVmKCdoZWFkZXInLHRoaXMpLmVuZCgpYFxuXHRCeSBkZWZhdWx0IGl0IGFkZHMgdGhlIHJlZmVyZW5jZSBhcyBhIGNsYXNzTmFtZSB0byB0aGUgdGFnLlxuXHRAcmV0dXJuIHtzZWxmfVxuXHQjIyNcblx0ZGVmIHNldFJlZiByZWYsIGN0eFxuXHRcdGZsYWcoQHJlZiA9IHJlZilcblx0XHRzZWxmXG5cblx0IyMjXG5cdE1ldGhvZCB0aGF0IGlzIGNhbGxlZCBieSB0aGUgY29tcGlsZWQgdGFnLWNoYWlucywgZm9yXG5cdGJpbmRpbmcgZXZlbnRzIG9uIHRhZ3MgdG8gbWV0aG9kcyBldGMuXG5cdGA8YSA6dGFwPWZuPmAgY29tcGlsZXMgdG8gYHRhZygnYScpLnNldEhhbmRsZXIoJ3RhcCcsZm4sdGhpcykuZW5kKClgXG5cdHdoZXJlIHRoaXMgcmVmZXJzIHRvIHRoZSBjb250ZXh0IGluIHdoaWNoIHRoZSB0YWcgaXMgY3JlYXRlZC5cblx0QHJldHVybiB7c2VsZn1cblx0IyMjXG5cdGRlZiBzZXRIYW5kbGVyIGV2ZW50LCBoYW5kbGVyLCBjdHhcblx0XHR2YXIga2V5ID0gJ29uJyArIGV2ZW50XG5cblx0XHRpZiBoYW5kbGVyIGlzYSBGdW5jdGlvblxuXHRcdFx0c2VsZltrZXldID0gaGFuZGxlclxuXHRcdGVsaWYgaGFuZGxlciBpc2EgQXJyYXlcblx0XHRcdHZhciBmbiA9IGhhbmRsZXIuc2hpZnRcblx0XHRcdHNlbGZba2V5XSA9IGRvIHxlfCBjdHhbZm5dLmFwcGx5KGN0eCxoYW5kbGVyLmNvbmNhdChlKSlcblx0XHRlbHNlXG5cdFx0XHRzZWxmW2tleV0gPSBkbyB8ZXwgY3R4W2hhbmRsZXJdKGUpXG5cdFx0c2VsZlxuXG5cdGRlZiBpZD0gaWRcblx0XHRkb206aWQgPSBpZFxuXHRcdHNlbGZcblxuXHRkZWYgaWRcblx0XHRkb206aWRcblxuXHQjIyNcblx0QWRkcyBhIG5ldyBhdHRyaWJ1dGUgb3IgY2hhbmdlcyB0aGUgdmFsdWUgb2YgYW4gZXhpc3RpbmcgYXR0cmlidXRlXG5cdG9uIHRoZSBzcGVjaWZpZWQgdGFnLiBJZiB0aGUgdmFsdWUgaXMgbnVsbCBvciBmYWxzZSwgdGhlIGF0dHJpYnV0ZVxuXHR3aWxsIGJlIHJlbW92ZWQuXG5cdEByZXR1cm4ge3NlbGZ9XG5cdCMjI1xuXHRkZWYgc2V0QXR0cmlidXRlIG5hbWUsIHZhbHVlXG5cdFx0IyBzaG91bGQgdGhpcyBub3QgcmV0dXJuIHNlbGY/XG5cdFx0dmFyIG9sZCA9IGRvbS5nZXRBdHRyaWJ1dGUobmFtZSlcblxuXHRcdGlmIG9sZCA9PSB2YWx1ZVxuXHRcdFx0dmFsdWVcblx0XHRlbGlmIHZhbHVlICE9IG51bGwgJiYgdmFsdWUgIT09IGZhbHNlXG5cdFx0XHRkb20uc2V0QXR0cmlidXRlKG5hbWUsdmFsdWUpXG5cdFx0ZWxzZVxuXHRcdFx0ZG9tLnJlbW92ZUF0dHJpYnV0ZShuYW1lKVxuXG5cdCMjI1xuXHRyZW1vdmVzIGFuIGF0dHJpYnV0ZSBmcm9tIHRoZSBzcGVjaWZpZWQgdGFnXG5cdCMjI1xuXHRkZWYgcmVtb3ZlQXR0cmlidXRlIG5hbWVcblx0XHRkb20ucmVtb3ZlQXR0cmlidXRlKG5hbWUpXG5cblx0IyMjXG5cdHJldHVybnMgdGhlIHZhbHVlIG9mIGFuIGF0dHJpYnV0ZSBvbiB0aGUgdGFnLlxuXHRJZiB0aGUgZ2l2ZW4gYXR0cmlidXRlIGRvZXMgbm90IGV4aXN0LCB0aGUgdmFsdWUgcmV0dXJuZWRcblx0d2lsbCBlaXRoZXIgYmUgbnVsbCBvciBcIlwiICh0aGUgZW1wdHkgc3RyaW5nKVxuXHQjIyNcblx0ZGVmIGdldEF0dHJpYnV0ZSBuYW1lXG5cdFx0ZG9tLmdldEF0dHJpYnV0ZShuYW1lKVxuXG5cdCMjI1xuXHRPdmVycmlkZSB0aGlzIHRvIHByb3ZpZGUgc3BlY2lhbCB3cmFwcGluZyBldGMuXG5cdEByZXR1cm4ge3NlbGZ9XG5cdCMjI1xuXHRkZWYgc2V0Q29udGVudCBjb250ZW50LCB0eXBlXG5cdFx0c2V0Q2hpbGRyZW4gY29udGVudCwgdHlwZVxuXHRcdHNlbGZcblxuXHQjIyNcblx0U2V0IHRoZSBjaGlsZHJlbiBvZiBub2RlLiB0eXBlIHBhcmFtIGlzIG9wdGlvbmFsLFxuXHRhbmQgc2hvdWxkIG9ubHkgYmUgdXNlZCBieSBJbWJhIHdoZW4gY29tcGlsaW5nIHRhZyB0cmVlcy4gXG5cdEByZXR1cm4ge3NlbGZ9XG5cdCMjI1xuXHRkZWYgc2V0Q2hpbGRyZW4gbm9kZXMsIHR5cGVcblx0XHR0aHJvdyBcIk5vdCBpbXBsZW1lbnRlZFwiXG5cblx0IyMjXG5cdEdldCB0ZXh0IG9mIG5vZGUuIFVzZXMgdGV4dENvbnRlbnQgYmVoaW5kIHRoZSBzY2VuZXMgKG5vdCBpbm5lclRleHQpXG5cdFtodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvTm9kZS90ZXh0Q29udGVudF0oKVxuXHRAcmV0dXJuIHtzdHJpbmd9IGlubmVyIHRleHQgb2Ygbm9kZVxuXHQjIyNcblx0ZGVmIHRleHQgdlxuXHRcdEBkb206dGV4dENvbnRlbnRcblxuXHQjIyNcblx0U2V0IHRleHQgb2Ygbm9kZS4gVXNlcyB0ZXh0Q29udGVudCBiZWhpbmQgdGhlIHNjZW5lcyAobm90IGlubmVyVGV4dClcblx0W2h0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9Ob2RlL3RleHRDb250ZW50XSgpXG5cdCMjI1xuXHRkZWYgdGV4dD0gdHh0XG5cdFx0QGVtcHR5ID0gbm9cblx0XHRAZG9tOnRleHRDb250ZW50ID0gdHh0ID89IFwiXCJcblx0XHRzZWxmXG5cblxuXHQjIyNcblx0TWV0aG9kIGZvciBnZXR0aW5nIGFuZCBzZXR0aW5nIGRhdGEtYXR0cmlidXRlcy4gV2hlbiBjYWxsZWQgd2l0aCB6ZXJvXG5cdGFyZ3VtZW50cyBpdCB3aWxsIHJldHVybiB0aGUgYWN0dWFsIGRhdGFzZXQgZm9yIHRoZSB0YWcuXG5cblx0XHR2YXIgbm9kZSA9IDxkaXYgZGF0YS1uYW1lPSdoZWxsbyc+XG5cdFx0IyBnZXQgdGhlIHdob2xlIGRhdGFzZXRcblx0XHRub2RlLmRhdGFzZXQgIyB7bmFtZTogJ2hlbGxvJ31cblx0XHQjIGdldCBhIHNpbmdsZSB2YWx1ZVxuXHRcdG5vZGUuZGF0YXNldCgnbmFtZScpICMgJ2hlbGxvJ1xuXHRcdCMgc2V0IGEgc2luZ2xlIHZhbHVlXG5cdFx0bm9kZS5kYXRhc2V0KCduYW1lJywnbmV3bmFtZScpICMgc2VsZlxuXG5cblx0IyMjXG5cdGRlZiBkYXRhc2V0IGtleSwgdmFsXG5cdFx0dGhyb3cgXCJOb3QgaW1wbGVtZW50ZWRcIlxuXG5cdCMjI1xuXHRFbXB0eSBwbGFjZWhvbGRlci4gT3ZlcnJpZGUgdG8gaW1wbGVtZW50IGN1c3RvbSByZW5kZXIgYmVoYXZpb3VyLlxuXHRXb3JrcyBtdWNoIGxpa2UgdGhlIGZhbWlsaWFyIHJlbmRlci1tZXRob2QgaW4gUmVhY3QuXG5cdEByZXR1cm4ge3NlbGZ9XG5cdCMjI1xuXHRkZWYgcmVuZGVyXG5cdFx0c2VsZlxuXG5cdCMjI1xuXHRDYWxsZWQgaW1wbGljaXRseSB0aHJvdWdoIEltYmEuVGFnI2VuZCwgdXBvbiBjcmVhdGluZyBhIHRhZy4gQWxsXG5cdHByb3BlcnRpZXMgd2lsbCBoYXZlIGJlZW4gc2V0IGJlZm9yZSBidWlsZCBpcyBjYWxsZWQsIGluY2x1ZGluZ1xuXHRzZXRDb250ZW50LlxuXHRAcmV0dXJuIHtzZWxmfVxuXHQjIyNcblx0ZGVmIGJ1aWxkXG5cdFx0cmVuZGVyXG5cdFx0c2VsZlxuXG5cdCMjI1xuXHRDYWxsZWQgaW1wbGljaXRseSB0aHJvdWdoIEltYmEuVGFnI2VuZCwgZm9yIHRhZ3MgdGhhdCBhcmUgcGFydCBvZlxuXHRhIHRhZyB0cmVlICh0aGF0IGFyZSByZW5kZXJlZCBzZXZlcmFsIHRpbWVzKS5cblx0QHJldHVybiB7c2VsZn1cblx0IyMjXG5cdGRlZiBjb21taXRcblx0XHRyZW5kZXJcblx0XHRzZWxmXG5cblx0IyMjXG5cblx0Q2FsbGVkIGJ5IHRoZSB0YWctc2NoZWR1bGVyIChpZiB0aGlzIHRhZyBpcyBzY2hlZHVsZWQpXG5cdEJ5IGRlZmF1bHQgaXQgd2lsbCBjYWxsIHRoaXMucmVuZGVyLiBEbyBub3Qgb3ZlcnJpZGUgdW5sZXNzXG5cdHlvdSByZWFsbHkgdW5kZXJzdGFuZCBpdC5cblxuXHQjIyNcblx0ZGVmIHRpY2tcblx0XHRyZW5kZXJcblx0XHRzZWxmXG5cblx0IyMjXG5cdFxuXHRBIHZlcnkgaW1wb3J0YW50IG1ldGhvZCB0aGF0IHlvdSB3aWxsIHByYWN0aWNhbGx5IG5ldmVyIG1hbnVhbGx5LlxuXHRUaGUgdGFnIHN5bnRheCBvZiBJbWJhIGNvbXBpbGVzIHRvIGEgY2hhaW4gb2Ygc2V0dGVycywgd2hpY2ggYWx3YXlzXG5cdGVuZHMgd2l0aCAuZW5kLiBgPGEubGFyZ2U+YCBjb21waWxlcyB0byBgdGFnKCdhJykuZmxhZygnbGFyZ2UnKS5lbmQoKWBcblx0XG5cdFlvdSBhcmUgaGlnaGx5IGFkdmljZWQgdG8gbm90IG92ZXJyaWRlIGl0cyBiZWhhdmlvdXIuIFRoZSBmaXJzdCB0aW1lXG5cdGVuZCBpcyBjYWxsZWQgaXQgd2lsbCBtYXJrIHRoZSB0YWcgYXMgYnVpbHQgYW5kIGNhbGwgSW1iYS5UYWcjYnVpbGQsXG5cdGFuZCBjYWxsIEltYmEuVGFnI2NvbW1pdCBvbiBzdWJzZXF1ZW50IGNhbGxzLlxuXHRAcmV0dXJuIHtzZWxmfVxuXHQjIyNcblx0ZGVmIGVuZFxuXHRcdGlmIEBidWlsdFxuXHRcdFx0Y29tbWl0XG5cdFx0ZWxzZVxuXHRcdFx0QGJ1aWx0ID0geWVzXG5cdFx0XHRidWlsZFxuXHRcdHNlbGZcblxuXHQjIyNcblx0VGhpcyBpcyBjYWxsZWQgaW5zdGVhZCBvZiBJbWJhLlRhZyNlbmQgZm9yIGA8c2VsZj5gIHRhZyBjaGFpbnMuXG5cdERlZmF1bHRzIHRvIG5vb3Bcblx0QHJldHVybiB7c2VsZn1cblx0IyMjXG5cdGRlZiBzeW5jZWRcblx0XHRzZWxmXG5cblx0IyBjYWxsZWQgd2hlbiB0aGUgbm9kZSBpcyBhd2FrZW5lZCBpbiB0aGUgZG9tIC0gZWl0aGVyIGF1dG9tYXRpY2FsbHlcblx0IyB1cG9uIGF0dGFjaG1lbnQgdG8gdGhlIGRvbS10cmVlLCBvciB0aGUgZmlyc3QgdGltZSBpbWJhIG5lZWRzIHRoZVxuXHQjIHRhZyBmb3IgYSBkb21ub2RlIHRoYXQgaGFzIGJlZW4gcmVuZGVyZWQgb24gdGhlIHNlcnZlclxuXHRkZWYgYXdha2VuXG5cdFx0c2VsZlxuXG5cdCMjI1xuXHRMaXN0IG9mIGZsYWdzIGZvciB0aGlzIG5vZGUuIFxuXHQjIyNcblx0ZGVmIGZsYWdzXG5cdFx0QGRvbTpjbGFzc0xpc3RcblxuXHQjIyNcblx0QWRkIHNwZWZpY2llZCBmbGFnIHRvIGN1cnJlbnQgbm9kZS5cblx0SWYgYSBzZWNvbmQgYXJndW1lbnQgaXMgc3VwcGxpZWQsIGl0IHdpbGwgYmUgY29lcmNlZCBpbnRvIGEgQm9vbGVhbixcblx0YW5kIHVzZWQgdG8gaW5kaWNhdGUgd2hldGhlciB3ZSBzaG91bGQgcmVtb3ZlIHRoZSBmbGFnIGluc3RlYWQuXG5cdEByZXR1cm4ge3NlbGZ9XG5cdCMjI1xuXHRkZWYgZmxhZyBuYW1lLCB0b2dnbGVyXG5cdFx0IyBpdCBpcyBtb3N0IG5hdHVyYWwgdG8gdHJlYXQgYSBzZWNvbmQgdW5kZWZpbmVkIGFyZ3VtZW50IGFzIGEgbm8tc3dpdGNoXG5cdFx0IyBzbyB3ZSBuZWVkIHRvIGNoZWNrIHRoZSBhcmd1bWVudHMtbGVuZ3RoXG5cdFx0aWYgYXJndW1lbnRzOmxlbmd0aCA9PSAyIGFuZCAhdG9nZ2xlclxuXHRcdFx0QGRvbTpjbGFzc0xpc3QucmVtb3ZlKG5hbWUpXG5cdFx0ZWxzZVxuXHRcdFx0QGRvbTpjbGFzc0xpc3QuYWRkKG5hbWUpXG5cdFx0cmV0dXJuIHNlbGZcblxuXHQjIyNcblx0UmVtb3ZlIHNwZWNpZmllZCBmbGFnIGZyb20gbm9kZVxuXHRAcmV0dXJuIHtzZWxmfVxuXHQjIyNcblx0ZGVmIHVuZmxhZyBuYW1lXG5cdFx0QGRvbTpjbGFzc0xpc3QucmVtb3ZlKG5hbWUpXG5cdFx0c2VsZlxuXG5cdCMjI1xuXHRUb2dnbGUgc3BlY2lmaWVkIGZsYWcgb24gbm9kZVxuXHRAcmV0dXJuIHtzZWxmfVxuXHQjIyNcblx0ZGVmIHRvZ2dsZUZsYWcgbmFtZVxuXHRcdEBkb206Y2xhc3NMaXN0LnRvZ2dsZShuYW1lKVxuXHRcdHNlbGZcblxuXHQjIyNcblx0Q2hlY2sgd2hldGhlciBjdXJyZW50IG5vZGUgaGFzIHNwZWNpZmllZCBmbGFnXG5cdEByZXR1cm4ge2Jvb2x9XG5cdCMjI1xuXHRkZWYgaGFzRmxhZyBuYW1lXG5cdFx0QGRvbTpjbGFzc0xpc3QuY29udGFpbnMobmFtZSlcblxuXHQjIyNcblx0R2V0IHRoZSBzY2hlZHVsZXIgZm9yIHRoaXMgbm9kZS4gQSBuZXcgc2NoZWR1bGVyIHdpbGwgYmUgY3JlYXRlZFxuXHRpZiBpdCBkb2VzIG5vdCBhbHJlYWR5IGV4aXN0LlxuXG5cdEByZXR1cm4ge0ltYmEuU2NoZWR1bGVyfVxuXHQjIyNcblx0ZGVmIHNjaGVkdWxlclxuXHRcdEBzY2hlZHVsZXIgPz0gSW1iYS5TY2hlZHVsZXIubmV3KHNlbGYpXG5cblx0IyMjXG5cblx0U2hvcnRoYW5kIHRvIHN0YXJ0IHNjaGVkdWxpbmcgYSBub2RlLiBUaGUgbWV0aG9kIHdpbGwgYmFzaWNhbGx5XG5cdHByb3h5IHRoZSBhcmd1bWVudHMgdGhyb3VnaCB0byBzY2hlZHVsZXIuY29uZmlndXJlLCBhbmQgdGhlblxuXHRhY3RpdmF0ZSB0aGUgc2NoZWR1bGVyLlxuXHRcblx0QHJldHVybiB7c2VsZn1cblx0IyMjXG5cdGRlZiBzY2hlZHVsZSBvcHRpb25zID0ge31cblx0XHRzY2hlZHVsZXIuY29uZmlndXJlKG9wdGlvbnMpLmFjdGl2YXRlXG5cdFx0c2VsZlxuXG5cdCMjI1xuXHRTaG9ydGhhbmQgZm9yIGRlYWN0aXZhdGluZyBzY2hlZHVsZXIgKGlmIHRhZyBoYXMgb25lKS5cblx0QGRlcHJlY2F0ZWRcblx0IyMjXG5cdGRlZiB1bnNjaGVkdWxlXG5cdFx0c2NoZWR1bGVyLmRlYWN0aXZhdGUgaWYgQHNjaGVkdWxlclxuXHRcdHNlbGZcblxuXG5cdCMjI1xuXHRHZXQgdGhlIHBhcmVudCBvZiBjdXJyZW50IG5vZGVcblx0QHJldHVybiB7SW1iYS5UYWd9IFxuXHQjIyNcblx0ZGVmIHBhcmVudFxuXHRcdHRhZyhkb206cGFyZW50Tm9kZSlcblxuXHQjIyNcblx0U2hvcnRoYW5kIGZvciBjb25zb2xlLmxvZyBvbiBlbGVtZW50c1xuXHRAcmV0dXJuIHtzZWxmfVxuXHQjIyNcblx0ZGVmIGxvZyAqYXJnc1xuXHRcdGFyZ3MudW5zaGlmdChjb25zb2xlKVxuXHRcdEZ1bmN0aW9uOnByb3RvdHlwZTpjYWxsLmFwcGx5KGNvbnNvbGU6bG9nLCBhcmdzKVxuXHRcdHNlbGZcblxuXHRkZWYgY3NzIGtleSwgdmFsXG5cdFx0aWYga2V5IGlzYSBPYmplY3Rcblx0XHRcdGNzcyhrLHYpIGZvciBvd24gayx2IG9mIGtleVxuXHRcdGVsaWYgdmFsID09IG51bGxcblx0XHRcdGRvbTpzdHlsZS5yZW1vdmVQcm9wZXJ0eShrZXkpXG5cdFx0ZWxpZiB2YWwgPT0gdW5kZWZpbmVkXG5cdFx0XHRyZXR1cm4gZG9tOnN0eWxlW2tleV1cblx0XHRlbHNlXG5cdFx0XHRpZiB2YWwgaXNhIE51bWJlciBhbmQga2V5Lm1hdGNoKC93aWR0aHxoZWlnaHR8bGVmdHxyaWdodHx0b3B8Ym90dG9tLylcblx0XHRcdFx0dmFsID0gdmFsICsgXCJweFwiXG5cdFx0XHRkb206c3R5bGVba2V5XSA9IHZhbFxuXHRcdHNlbGZcblxuXHRkZWYgdHJhbnNmb3JtPSB2YWx1ZVxuXHRcdGNzcyg6dHJhbnNmb3JtLCB2YWx1ZSlcblx0XHRzZWxmXG5cblx0ZGVmIHRyYW5zZm9ybVxuXHRcdGNzcyg6dHJhbnNmb3JtKVxuXG5cbkltYmEuVGFnOnByb3RvdHlwZTppbml0aWFsaXplID0gSW1iYS5UYWdcblxuSFRNTF9UQUdTID0gXCJhIGFiYnIgYWRkcmVzcyBhcmVhIGFydGljbGUgYXNpZGUgYXVkaW8gYiBiYXNlIGJkaSBiZG8gYmlnIGJsb2NrcXVvdGUgYm9keSBiciBidXR0b24gY2FudmFzIGNhcHRpb24gY2l0ZSBjb2RlIGNvbCBjb2xncm91cCBkYXRhIGRhdGFsaXN0IGRkIGRlbCBkZXRhaWxzIGRmbiBkaXYgZGwgZHQgZW0gZW1iZWQgZmllbGRzZXQgZmlnY2FwdGlvbiBmaWd1cmUgZm9vdGVyIGZvcm0gaDEgaDIgaDMgaDQgaDUgaDYgaGVhZCBoZWFkZXIgaHIgaHRtbCBpIGlmcmFtZSBpbWcgaW5wdXQgaW5zIGtiZCBrZXlnZW4gbGFiZWwgbGVnZW5kIGxpIGxpbmsgbWFpbiBtYXAgbWFyayBtZW51IG1lbnVpdGVtIG1ldGEgbWV0ZXIgbmF2IG5vc2NyaXB0IG9iamVjdCBvbCBvcHRncm91cCBvcHRpb24gb3V0cHV0IHAgcGFyYW0gcHJlIHByb2dyZXNzIHEgcnAgcnQgcnVieSBzIHNhbXAgc2NyaXB0IHNlY3Rpb24gc2VsZWN0IHNtYWxsIHNvdXJjZSBzcGFuIHN0cm9uZyBzdHlsZSBzdWIgc3VtbWFyeSBzdXAgdGFibGUgdGJvZHkgdGQgdGV4dGFyZWEgdGZvb3QgdGggdGhlYWQgdGltZSB0aXRsZSB0ciB0cmFjayB1IHVsIHZhciB2aWRlbyB3YnJcIi5zcGxpdChcIiBcIilcbkhUTUxfVEFHU19VTlNBRkUgPSBcImFydGljbGUgYXNpZGUgaGVhZGVyIHNlY3Rpb25cIi5zcGxpdChcIiBcIilcblNWR19UQUdTID0gXCJjaXJjbGUgZGVmcyBlbGxpcHNlIGcgbGluZSBsaW5lYXJHcmFkaWVudCBtYXNrIHBhdGggcGF0dGVybiBwb2x5Z29uIHBvbHlsaW5lIHJhZGlhbEdyYWRpZW50IHJlY3Qgc3RvcCBzdmcgdGV4dCB0c3BhblwiLnNwbGl0KFwiIFwiKVxuXG5cbmRlZiBleHRlbmRlciBvYmosIHN1cFxuXHRmb3Igb3duIGssdiBvZiBzdXBcblx0XHRvYmpba10gPz0gdlxuXG5cdG9iajpwcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cDpwcm90b3R5cGUpXG5cdG9iajpfX3N1cGVyX18gPSBvYmo6cHJvdG90eXBlOl9fc3VwZXJfXyA9IHN1cDpwcm90b3R5cGVcblx0b2JqOnByb3RvdHlwZTppbml0aWFsaXplID0gb2JqOnByb3RvdHlwZTpjb25zdHJ1Y3RvciA9IG9ialxuXHRzdXAuaW5oZXJpdChvYmopIGlmIHN1cDppbmhlcml0XG5cdHJldHVybiBvYmpcblxuZGVmIFRhZ1xuXHRyZXR1cm4gZG8gfGRvbXxcblx0XHR0aGlzLnNldERvbShkb20pXG5cdFx0cmV0dXJuIHRoaXNcblxuZGVmIFRhZ1NwYXduZXIgdHlwZVxuXHRyZXR1cm4gZG8gdHlwZS5idWlsZFxuXG5jbGFzcyBJbWJhLlRhZ3NcblxuXHRkZWYgaW5pdGlhbGl6ZVxuXHRcdHNlbGZcblxuXHRkZWYgX19jbG9uZSBuc1xuXHRcdHZhciBjbG9uZSA9IE9iamVjdC5jcmVhdGUoc2VsZilcblx0XHRjbG9uZS5AcGFyZW50ID0gc2VsZlxuXHRcdHJldHVybiBjbG9uZVxuXG5cdGRlZiBkZWZpbmVOYW1lc3BhY2UgbmFtZVxuXHRcdHZhciBjbG9uZSA9IE9iamVjdC5jcmVhdGUoc2VsZilcblx0XHRjbG9uZS5AcGFyZW50ID0gc2VsZlxuXHRcdGNsb25lLkBucyA9IG5hbWVcblx0XHRzZWxmW25hbWUudG9VcHBlckNhc2VdID0gY2xvbmVcblx0XHRyZXR1cm4gY2xvbmVcblxuXHRkZWYgYmFzZVR5cGUgbmFtZVxuXHRcdG5hbWUgaW4gSFRNTF9UQUdTID8gJ2h0bWxlbGVtZW50JyA6ICdkaXYnXG5cblx0ZGVmIGRlZmluZVRhZyBuYW1lLCBzdXByID0gJycsICZib2R5XG5cdFx0c3VwciB8fD0gYmFzZVR5cGUobmFtZSlcblx0XHRsZXQgc3VwZXJ0eXBlID0gc2VsZltzdXByXVxuXHRcdGxldCB0YWd0eXBlID0gVGFnKClcblx0XHRsZXQgbm9ybSA9IG5hbWUucmVwbGFjZSgvXFwtL2csJ18nKVxuXG5cblx0XHR0YWd0eXBlLkBuYW1lID0gbmFtZVxuXHRcdGV4dGVuZGVyKHRhZ3R5cGUsc3VwZXJ0eXBlKVxuXG5cdFx0aWYgbmFtZVswXSA9PSAnIydcblx0XHRcdHNlbGZbbmFtZV0gPSB0YWd0eXBlXG5cdFx0XHRJbWJhLlNJTkdMRVRPTlNbbmFtZS5zbGljZSgxKV0gPSB0YWd0eXBlXG5cdFx0ZWxzZVxuXHRcdFx0c2VsZltuYW1lXSA9IHRhZ3R5cGVcblx0XHRcdHNlbGZbJyQnK25vcm1dID0gVGFnU3Bhd25lcih0YWd0eXBlKVxuXG5cdFx0aWYgYm9keVxuXHRcdFx0aWYgYm9keTpsZW5ndGggPT0gMlxuXHRcdFx0XHQjIGNyZWF0ZSBjbG9uZVxuXHRcdFx0XHR1bmxlc3MgdGFndHlwZS5oYXNPd25Qcm9wZXJ0eSgnVEFHUycpXG5cdFx0XHRcdFx0dGFndHlwZS5UQUdTID0gKHN1cGVydHlwZS5UQUdTIG9yIHNlbGYpLl9fY2xvbmVcblxuXHRcdFx0Ym9keS5jYWxsKHRhZ3R5cGUsdGFndHlwZSwgdGFndHlwZS5UQUdTIG9yIHNlbGYpXG5cblx0XHRyZXR1cm4gdGFndHlwZVxuXG5cdGRlZiBkZWZpbmVTaW5nbGV0b24gbmFtZSwgc3VwciwgJmJvZHlcblx0XHRkZWZpbmVUYWcobmFtZSxzdXByLGJvZHkpXG5cblx0ZGVmIGV4dGVuZFRhZyBuYW1lLCBzdXByID0gJycsICZib2R5XG5cdFx0dmFyIGtsYXNzID0gKG5hbWUgaXNhIFN0cmluZyA/IHNlbGZbbmFtZV0gOiBuYW1lKVxuXHRcdCMgYWxsb3cgZm9yIHByaXZhdGUgdGFncyBoZXJlIGFzIHdlbGw/XG5cdFx0Ym9keSBhbmQgYm9keS5jYWxsKGtsYXNzLGtsYXNzLGtsYXNzOnByb3RvdHlwZSkgaWYgYm9keVxuXHRcdHJldHVybiBrbGFzc1xuXG5cbkltYmEuVEFHUyA9IEltYmEuVGFncy5uZXdcbkltYmEuVEFHU1s6ZWxlbWVudF0gPSBJbWJhLlRhZ1xuXG52YXIgc3ZnID0gSW1iYS5UQUdTLmRlZmluZU5hbWVzcGFjZSgnc3ZnJylcblxuZGVmIHN2Zy5iYXNlVHlwZSBuYW1lXG5cdCdzdmdlbGVtZW50J1xuXG5cbkltYmEuU0lOR0xFVE9OUyA9IHt9XG5cblxuZGVmIEltYmEuZGVmaW5lVGFnIG5hbWUsIHN1cHIgPSAnJywgJmJvZHlcblx0cmV0dXJuIEltYmEuVEFHUy5kZWZpbmVUYWcobmFtZSxzdXByLGJvZHkpXG5cbmRlZiBJbWJhLmRlZmluZVNpbmdsZXRvblRhZyBpZCwgc3VwciA9ICdkaXYnLCAmYm9keVxuXHRyZXR1cm4gSW1iYS5UQUdTLmRlZmluZVRhZyhuYW1lLHN1cHIsYm9keSlcblxuZGVmIEltYmEuZXh0ZW5kVGFnIG5hbWUsIGJvZHlcblx0cmV0dXJuIEltYmEuVEFHUy5leHRlbmRUYWcobmFtZSxib2R5KVxuXG5kZWYgSW1iYS50YWcgbmFtZVxuXHR2YXIgdHlwID0gSW1iYS5UQUdTW25hbWVdXG5cdHRocm93IEVycm9yLm5ldyhcInRhZyB7bmFtZX0gaXMgbm90IGRlZmluZWRcIikgaWYgIXR5cFxuXHRyZXR1cm4gdHlwLm5ldyh0eXAuY3JlYXRlTm9kZSlcblxuZGVmIEltYmEudGFnV2l0aElkIG5hbWUsIGlkXG5cdHZhciB0eXAgPSBJbWJhLlRBR1NbbmFtZV1cblx0dGhyb3cgRXJyb3IubmV3KFwidGFnIHtuYW1lfSBpcyBub3QgZGVmaW5lZFwiKSBpZiAhdHlwXG5cdHZhciBkb20gPSB0eXAuY3JlYXRlTm9kZVxuXHRkb206aWQgPSBpZFxuXHRyZXR1cm4gdHlwLm5ldyhkb20pXG5cbiMgVE9ETzogQ2FuIHdlIG1vdmUgdGhlc2Ugb3V0IGFuZCBpbnRvIGRvbS5pbWJhIGluIGEgY2xlYW4gd2F5P1xuIyBUaGVzZSBtZXRob2RzIGRlcGVuZHMgb24gSW1iYS5kb2N1bWVudC5nZXRFbGVtZW50QnlJZFxuXG5kZWYgSW1iYS5nZXRUYWdTaW5nbGV0b24gaWRcdFxuXHR2YXIgZG9tLCBub2RlXG5cblx0aWYgdmFyIGtsYXNzID0gSW1iYS5TSU5HTEVUT05TW2lkXVxuXHRcdHJldHVybiBrbGFzcy5JbnN0YW5jZSBpZiBrbGFzcyBhbmQga2xhc3MuSW5zdGFuY2UgXG5cblx0XHQjIG5vIGluc3RhbmNlIC0gY2hlY2sgZm9yIGVsZW1lbnRcblx0XHRpZiBkb20gPSBJbWJhLmRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKVxuXHRcdFx0IyB3ZSBoYXZlIGEgbGl2ZSBpbnN0YW5jZSAtIHdoZW4gZmluZGluZyBpdCB0aHJvdWdoIGEgc2VsZWN0b3Igd2Ugc2hvdWxkIGF3YWtlIGl0LCBubz9cblx0XHRcdCMgY29uc29sZS5sb2coJ2NyZWF0aW5nIHRoZSBzaW5nbGV0b24gZnJvbSBleGlzdGluZyBub2RlIGluIGRvbT8nLGlkLHR5cGUpXG5cdFx0XHRub2RlID0ga2xhc3MuSW5zdGFuY2UgPSBrbGFzcy5uZXcoZG9tKVxuXHRcdFx0bm9kZS5hd2FrZW4oZG9tKSAjIHNob3VsZCBvbmx5IGF3YWtlblxuXHRcdFx0cmV0dXJuIG5vZGVcblxuXHRcdGRvbSA9IGtsYXNzLmNyZWF0ZU5vZGVcblx0XHRkb206aWQgPSBpZFxuXHRcdG5vZGUgPSBrbGFzcy5JbnN0YW5jZSA9IGtsYXNzLm5ldyhkb20pXG5cdFx0bm9kZS5lbmQuYXdha2VuKGRvbSlcblx0XHRyZXR1cm4gbm9kZVxuXHRlbGlmIGRvbSA9IEltYmEuZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoaWQpXG5cdFx0cmV0dXJuIEltYmEuZ2V0VGFnRm9yRG9tKGRvbSlcblxudmFyIHN2Z1N1cHBvcnQgPSB0eXBlb2YgU1ZHRWxlbWVudCAhPT0gJ3VuZGVmaW5lZCdcblxuZGVmIEltYmEuZ2V0VGFnRm9yRG9tIGRvbVxuXHRyZXR1cm4gbnVsbCB1bmxlc3MgZG9tXG5cdHJldHVybiBkb20gaWYgZG9tLkBkb20gIyBjb3VsZCB1c2UgaW5oZXJpdGFuY2UgaW5zdGVhZFxuXHRyZXR1cm4gZG9tLkB0YWcgaWYgZG9tLkB0YWdcblx0cmV0dXJuIG51bGwgdW5sZXNzIGRvbTpub2RlTmFtZVxuXG5cdHZhciBucyAgID0gbnVsbFxuXHR2YXIgaWQgICA9IGRvbTppZFxuXHR2YXIgdHlwZSA9IGRvbTpub2RlTmFtZS50b0xvd2VyQ2FzZVxuXHR2YXIgdGFncyA9IEltYmEuVEFHU1xuXHR2YXIgbmF0aXZlID0gdHlwZVxuXHR2YXIgY2xzICA9IGRvbTpjbGFzc05hbWVcblxuXHRpZiBpZCBhbmQgSW1iYS5TSU5HTEVUT05TW2lkXVxuXHRcdCMgRklYTUUgY29udHJvbCB0aGF0IGl0IGlzIHRoZSBzYW1lIHNpbmdsZXRvbj9cblx0XHQjIG1pZ2h0IGNvbGxpZGUgLS0gbm90IGdvb2Q/XG5cdFx0cmV0dXJuIEltYmEuZ2V0VGFnU2luZ2xldG9uKGlkKVxuXHQjIGxvb2sgZm9yIGlkIC0gc2luZ2xldG9uXG5cblx0IyBuZWVkIGJldHRlciB0ZXN0IGhlcmVcblx0aWYgc3ZnU3VwcG9ydCBhbmQgZG9tIGlzYSBTVkdFbGVtZW50XG5cdFx0bnMgPSBcInN2Z1wiIFxuXHRcdGNscyA9IGRvbTpjbGFzc05hbWU6YmFzZVZhbFxuXHRcdHRhZ3MgPSB0YWdzLlNWR1xuXG5cdHZhciBzcGF3bmVyXG5cblx0aWYgY2xzXG5cdFx0IyB0aGVyZSBjYW4gYmUgc2V2ZXJhbCBtYXRjaGVzIGhlcmUgLSBzaG91bGQgY2hvb3NlIHRoZSBsYXN0XG5cdFx0IyBzaG91bGQgZmFsbCBiYWNrIHRvIGxlc3Mgc3BlY2lmaWMgbGF0ZXI/IC0gb3RoZXJ3aXNlIHRoaW5ncyBtYXkgZmFpbFxuXHRcdCMgVE9ETyByZXdvcmsgdGhpc1xuXHRcdGlmIHZhciBtID0gY2xzLm1hdGNoKC9cXGJfKFthLXpcXC1dKylcXGIoPyFcXHMqX1thLXpcXC1dKykvKVxuXHRcdFx0dHlwZSA9IG1bMV0gIyAucmVwbGFjZSgvLS9nLCdfJylcblxuXHRcdGlmIG0gPSBjbHMubWF0Y2goL1xcYihbQS1aXFwtXSspX1xcYi8pXG5cdFx0XHRucyA9IG1bMV1cblxuXG5cdHNwYXduZXIgPSB0YWdzW3R5cGVdIG9yIHRhZ3NbbmF0aXZlXVxuXHRzcGF3bmVyID8gc3Bhd25lci5uZXcoZG9tKS5hd2FrZW4oZG9tKSA6IG51bGxcblxudGFnJCA9IEltYmEuVEFHU1xudCQgPSBJbWJhOnRhZ1xudGMkID0gSW1iYTp0YWdXaXRoRmxhZ3NcbnRpJCA9IEltYmE6dGFnV2l0aElkXG50aWMkID0gSW1iYTp0YWdXaXRoSWRBbmRGbGFnc1xuaWQkID0gSW1iYTpnZXRUYWdTaW5nbGV0b25cbnRhZyR3cmFwID0gSW1iYTpnZXRUYWdGb3JEb21cblxuXG5cblxuLyoqIFdFQlBBQ0sgRk9PVEVSICoqXG4gKiogc3JjL2ltYmEvdGFnLmltYmFcbiAqKi8iLCJcbmRlZiBJbWJhLmRvY3VtZW50XG5cdHdpbmRvdzpkb2N1bWVudFxuXG4jIyNcblJldHVybnMgdGhlIGJvZHkgZWxlbWVudCB3cmFwcGVkIGluIGFuIEltYmEuVGFnXG4jIyNcbmRlZiBJbWJhLnJvb3Rcblx0dGFnKEltYmEuZG9jdW1lbnQ6Ym9keSlcblxudGFnIGh0bWxlbGVtZW50IDwgZWxlbWVudFxuXG5cdCMjI1xuXHRDYWxsZWQgd2hlbiBhIHRhZyB0eXBlIGlzIGJlaW5nIHN1YmNsYXNzZWQuXG5cdCMjI1xuXHRkZWYgc2VsZi5pbmhlcml0IGNoaWxkXG5cdFx0Y2hpbGQ6cHJvdG90eXBlLkBlbXB0eSA9IHllc1xuXHRcdGNoaWxkLkBwcm90b0RvbSA9IG51bGxcblxuXHRcdGlmIEBub2RlVHlwZVxuXHRcdFx0Y2hpbGQuQG5vZGVUeXBlID0gQG5vZGVUeXBlXG5cblx0XHRcdHZhciBjbGFzc05hbWUgPSBcIl9cIiArIGNoaWxkLkBuYW1lLnJlcGxhY2UoL18vZywgJy0nKVxuXHRcdFx0Y2hpbGQuQGNsYXNzZXMgPSBAY2xhc3Nlcy5jb25jYXQoY2xhc3NOYW1lKSB1bmxlc3MgY2hpbGQuQG5hbWVbMF0gPT0gJyMnXG5cdFx0ZWxzZVxuXHRcdFx0Y2hpbGQuQG5vZGVUeXBlID0gY2hpbGQuQG5hbWVcblx0XHRcdGNoaWxkLkBjbGFzc2VzID0gW11cblxuXHRkZWYgc2VsZi5idWlsZE5vZGVcblx0XHR2YXIgZG9tID0gSW1iYS5kb2N1bWVudC5jcmVhdGVFbGVtZW50KEBub2RlVHlwZSlcblx0XHR2YXIgY2xzID0gQGNsYXNzZXMuam9pbihcIiBcIilcblx0XHRkb206Y2xhc3NOYW1lID0gY2xzIGlmIGNsc1xuXHRcdGRvbVxuXG5cdGRlZiBzZWxmLmNyZWF0ZU5vZGVcblx0XHR2YXIgcHJvdG8gPSAoQHByb3RvRG9tIHx8PSBidWlsZE5vZGUpXG5cdFx0cHJvdG8uY2xvbmVOb2RlKGZhbHNlKVxuXG5cdGRlZiBzZWxmLmRvbVxuXHRcdEBwcm90b0RvbSB8fD0gYnVpbGROb2RlXG5cblx0YXR0ciBpZFxuXHRhdHRyIHRhYmluZGV4XG5cdGF0dHIgdGl0bGVcblx0YXR0ciByb2xlXG5cblx0ZGVmIHdpZHRoXG5cdFx0QGRvbTpvZmZzZXRXaWR0aFxuXG5cdGRlZiBoZWlnaHRcblx0XHRAZG9tOm9mZnNldEhlaWdodFxuXG5cdGRlZiBzZXRDaGlsZHJlbiBub2RlcywgdHlwZVxuXHRcdEBlbXB0eSA/IGFwcGVuZChub2RlcykgOiBlbXB0eS5hcHBlbmQobm9kZXMpXG5cdFx0QGNoaWxkcmVuID0gbnVsbFxuXHRcdHNlbGZcblxuXHQjIyNcblx0U2V0IGlubmVyIGh0bWwgb2Ygbm9kZVxuXHQjIyNcblx0ZGVmIGh0bWw9IGh0bWxcblx0XHRAZG9tOmlubmVySFRNTCA9IGh0bWxcblx0XHRzZWxmXG5cblx0IyMjXG5cdEdldCBpbm5lciBodG1sIG9mIG5vZGVcblx0IyMjXG5cdGRlZiBodG1sXG5cdFx0QGRvbTppbm5lckhUTUxcblxuXHQjIyNcblx0UmVtb3ZlIGFsbCBjb250ZW50IGluc2lkZSBub2RlXG5cdCMjI1xuXHRkZWYgZW1wdHlcblx0XHRAZG9tLnJlbW92ZUNoaWxkKEBkb206Zmlyc3RDaGlsZCkgd2hpbGUgQGRvbTpmaXJzdENoaWxkXG5cdFx0QGNoaWxkcmVuID0gbnVsbFxuXHRcdEBlbXB0eSA9IHllc1xuXHRcdHNlbGZcblxuXHQjIyNcblx0UmVtb3ZlIHNwZWNpZmllZCBjaGlsZCBmcm9tIGN1cnJlbnQgbm9kZS5cblx0IyMjXG5cdGRlZiByZW1vdmUgY2hpbGRcblx0XHR2YXIgcGFyID0gZG9tXG5cdFx0dmFyIGVsID0gY2hpbGQgYW5kIGNoaWxkLmRvbVxuXHRcdHBhci5yZW1vdmVDaGlsZChlbCkgaWYgZWwgYW5kIGVsOnBhcmVudE5vZGUgPT0gcGFyXG5cdFx0c2VsZlxuXHRcdFxuXHRkZWYgZW1pdCBuYW1lLCBkYXRhOiBudWxsLCBidWJibGU6IHllc1xuXHRcdEltYmEuRXZlbnRzLnRyaWdnZXIgbmFtZSwgc2VsZiwgZGF0YTogZGF0YSwgYnViYmxlOiBidWJibGVcblx0XHRyZXR1cm4gc2VsZlxuXG5cdGRlZiBkYXRhc2V0IGtleSwgdmFsXG5cdFx0aWYga2V5IGlzYSBPYmplY3Rcblx0XHRcdGRhdGFzZXQoayx2KSBmb3Igb3duIGssdiBvZiBrZXlcblx0XHRcdHJldHVybiBzZWxmXG5cblx0XHRpZiBhcmd1bWVudHM6bGVuZ3RoID09IDJcblx0XHRcdHNldEF0dHJpYnV0ZShcImRhdGEte2tleX1cIix2YWwpXG5cdFx0XHRyZXR1cm4gc2VsZlxuXG5cdFx0aWYga2V5XG5cdFx0XHRyZXR1cm4gZ2V0QXR0cmlidXRlKFwiZGF0YS17a2V5fVwiKVxuXG5cdFx0dmFyIGRhdGFzZXQgPSBkb206ZGF0YXNldFxuXG5cdFx0dW5sZXNzIGRhdGFzZXRcblx0XHRcdGRhdGFzZXQgPSB7fVxuXHRcdFx0Zm9yIGF0cixpIGluIGRvbTphdHRyaWJ1dGVzXG5cdFx0XHRcdGlmIGF0cjpuYW1lLnN1YnN0cigwLDUpID09ICdkYXRhLSdcblx0XHRcdFx0XHRkYXRhc2V0W0ltYmEudG9DYW1lbENhc2UoYXRyOm5hbWUuc2xpY2UoNSkpXSA9IGF0cjp2YWx1ZVxuXG5cdFx0cmV0dXJuIGRhdGFzZXRcblxuXHQjIyNcblx0R2V0IGRlc2NlbmRhbnRzIG9mIGN1cnJlbnQgbm9kZSwgb3B0aW9uYWxseSBtYXRjaGluZyBzZWxlY3RvclxuXHRAcmV0dXJuIHtJbWJhLlNlbGVjdG9yfVxuXHQjIyNcblx0ZGVmIGZpbmQgc2VsXG5cdFx0SW1iYS5TZWxlY3Rvci5uZXcoc2VsLHNlbGYpXG5cblx0IyMjXG5cdEdldCB0aGUgZmlyc3QgbWF0Y2hpbmcgY2hpbGQgb2Ygbm9kZVxuXG5cdEByZXR1cm4ge0ltYmEuVGFnfVxuXHQjIyNcblx0ZGVmIGZpcnN0IHNlbFxuXHRcdHNlbCA/IGZpbmQoc2VsKS5maXJzdCA6IHRhZyhkb206Zmlyc3RFbGVtZW50Q2hpbGQpXG5cblx0IyMjXG5cdEdldCB0aGUgbGFzdCBtYXRjaGluZyBjaGlsZCBvZiBub2RlXG5cblx0XHRub2RlLmxhc3QgIyByZXR1cm5zIHRoZSBsYXN0IGNoaWxkIG9mIG5vZGVcblx0XHRub2RlLmxhc3QgJXNwYW4gIyByZXR1cm5zIHRoZSBsYXN0IHNwYW4gaW5zaWRlIG5vZGVcblx0XHRub2RlLmxhc3QgZG8gfGVsfCBlbC50ZXh0ID09ICdIaScgIyByZXR1cm4gbGFzdCBub2RlIHdpdGggdGV4dCBIaVxuXG5cdEByZXR1cm4ge0ltYmEuVGFnfVxuXHQjIyNcblx0ZGVmIGxhc3Qgc2VsXG5cdFx0c2VsID8gZmluZChzZWwpLmxhc3QgOiB0YWcoZG9tOmxhc3RFbGVtZW50Q2hpbGQpXG5cblx0IyMjXG5cdEdldCB0aGUgY2hpbGQgYXQgaW5kZXhcblx0IyMjXG5cdGRlZiBjaGlsZCBpXG5cdFx0dGFnKGRvbTpjaGlsZHJlbltpIG9yIDBdKVxuXG5cdGRlZiBjaGlsZHJlbiBzZWxcblx0XHR2YXIgbm9kZXMgPSBJbWJhLlNlbGVjdG9yLm5ldyhudWxsLCBzZWxmLCBAZG9tOmNoaWxkcmVuKVxuXHRcdHNlbCA/IG5vZGVzLmZpbHRlcihzZWwpIDogbm9kZXNcblx0XG5cdGRlZiBvcnBoYW5pemVcblx0XHRwYXIucmVtb3ZlQ2hpbGQoQGRvbSkgaWYgbGV0IHBhciA9IGRvbTpwYXJlbnROb2RlXG5cdFx0cmV0dXJuIHNlbGZcblx0XG5cdGRlZiBtYXRjaGVzIHNlbFxuXHRcdGlmIHNlbCBpc2EgRnVuY3Rpb25cblx0XHRcdHJldHVybiBzZWwoc2VsZilcblxuXHRcdHNlbCA9IHNlbC5xdWVyeSBpZiBzZWw6cXVlcnlcblx0XHRpZiB2YXIgZm4gPSAoQGRvbTptYXRjaGVzIG9yIEBkb206bWF0Y2hlc1NlbGVjdG9yIG9yIEBkb206d2Via2l0TWF0Y2hlc1NlbGVjdG9yIG9yIEBkb206bXNNYXRjaGVzU2VsZWN0b3Igb3IgQGRvbTptb3pNYXRjaGVzU2VsZWN0b3IpXG5cdFx0XHRyZXR1cm4gZm4uY2FsbChAZG9tLHNlbClcblxuXHQjIyNcblx0R2V0IHRoZSBmaXJzdCBlbGVtZW50IG1hdGNoaW5nIHN1cHBsaWVkIHNlbGVjdG9yIC8gZmlsdGVyXG5cdHRyYXZlcnNpbmcgdXB3YXJkcywgYnV0IGluY2x1ZGluZyB0aGUgbm9kZSBpdHNlbGYuXG5cdEByZXR1cm4ge0ltYmEuVGFnfVxuXHQjIyNcblx0ZGVmIGNsb3Nlc3Qgc2VsXG5cdFx0cmV0dXJuIHBhcmVudCB1bmxlc3Mgc2VsICMgc2hvdWxkIHJldHVybiBzZWxmPyFcblx0XHR2YXIgbm9kZSA9IHNlbGZcblx0XHRzZWwgPSBzZWwucXVlcnkgaWYgc2VsOnF1ZXJ5XG5cblx0XHR3aGlsZSBub2RlXG5cdFx0XHRyZXR1cm4gbm9kZSBpZiBub2RlLm1hdGNoZXMoc2VsKVxuXHRcdFx0bm9kZSA9IG5vZGUucGFyZW50XG5cdFx0cmV0dXJuIG51bGxcblxuXHQjIyNcblx0R2V0IHRoZSBjbG9zZXN0IGFuY2VzdG9yIG9mIG5vZGUgdGhhdCBtYXRjaGVzXG5cdHNwZWNpZmllZCBzZWxlY3RvciAvIG1hdGNoZXIuXG5cblx0QHJldHVybiB7SW1iYS5UYWd9XG5cdCMjI1xuXHRkZWYgdXAgc2VsXG5cdFx0cmV0dXJuIHBhcmVudCB1bmxlc3Mgc2VsXG5cdFx0cGFyZW50IGFuZCBwYXJlbnQuY2xvc2VzdChzZWwpXG5cblx0ZGVmIHBhdGggc2VsXG5cdFx0dmFyIG5vZGUgPSBzZWxmXG5cdFx0dmFyIG5vZGVzID0gW11cblx0XHRzZWwgPSBzZWwucXVlcnkgaWYgc2VsIGFuZCBzZWw6cXVlcnlcblxuXHRcdHdoaWxlIG5vZGVcblx0XHRcdG5vZGVzLnB1c2gobm9kZSkgaWYgIXNlbCBvciBub2RlLm1hdGNoZXMoc2VsKVxuXHRcdFx0bm9kZSA9IG5vZGUucGFyZW50XG5cdFx0cmV0dXJuIG5vZGVzXG5cblx0ZGVmIHBhcmVudHMgc2VsXG5cdFx0dmFyIHBhciA9IHBhcmVudFxuXHRcdHBhciA/IHBhci5wYXRoKHNlbCkgOiBbXVxuXG5cdFxuXG5cdGRlZiBzaWJsaW5ncyBzZWxcblx0XHRyZXR1cm4gW10gdW5sZXNzIHZhciBwYXIgPSBwYXJlbnQgIyBGSVhNRVxuXHRcdHZhciBhcnkgPSBkb206cGFyZW50Tm9kZTpjaGlsZHJlblxuXHRcdHZhciBub2RlcyA9IEltYmEuU2VsZWN0b3IubmV3KG51bGwsIHNlbGYsIGFyeSlcblx0XHRub2Rlcy5maWx0ZXIofG58IG4gIT0gc2VsZiAmJiAoIXNlbCB8fCBuLm1hdGNoZXMoc2VsKSkpXG5cblx0IyMjXG5cdEdldCB0aGUgaW1tZWRpYXRlbHkgZm9sbG93aW5nIHNpYmxpbmcgb2Ygbm9kZS5cblx0IyMjXG5cdGRlZiBuZXh0IHNlbFxuXHRcdGlmIHNlbFxuXHRcdFx0dmFyIGVsID0gc2VsZlxuXHRcdFx0d2hpbGUgZWwgPSBlbC5uZXh0XG5cdFx0XHRcdHJldHVybiBlbCBpZiBlbC5tYXRjaGVzKHNlbClcblx0XHRcdHJldHVybiBudWxsXG5cdFx0dGFnKGRvbTpuZXh0RWxlbWVudFNpYmxpbmcpXG5cblx0IyMjXG5cdEdldCB0aGUgaW1tZWRpYXRlbHkgcHJlY2VlZGluZyBzaWJsaW5nIG9mIG5vZGUuXG5cdCMjI1xuXHRkZWYgcHJldiBzZWxcblx0XHRpZiBzZWxcblx0XHRcdHZhciBlbCA9IHNlbGZcblx0XHRcdHdoaWxlIGVsID0gZWwucHJldlxuXHRcdFx0XHRyZXR1cm4gZWwgaWYgZWwubWF0Y2hlcyhzZWwpXG5cdFx0XHRyZXR1cm4gbnVsbFxuXHRcdHRhZyhkb206cHJldmlvdXNFbGVtZW50U2libGluZylcblxuXHRkZWYgY29udGFpbnMgbm9kZVxuXHRcdGRvbS5jb250YWlucyhub2RlIGFuZCBub2RlLkBkb20gb3Igbm9kZSlcblxuXHRkZWYgaW5kZXhcblx0XHR2YXIgaSA9IDBcblx0XHR2YXIgZWwgPSBkb21cblx0XHR3aGlsZSBlbDpwcmV2aW91c1NpYmxpbmdcblx0XHRcdGVsID0gZWw6cHJldmlvdXNTaWJsaW5nXG5cdFx0XHRpKytcblx0XHRyZXR1cm4gaVxuXG5cblx0IyMjXG5cdFxuXHRAZGVwcmVjYXRlZFxuXHQjIyNcblx0ZGVmIGluc2VydCBub2RlLCBiZWZvcmU6IG51bGwsIGFmdGVyOiBudWxsXG5cdFx0YmVmb3JlID0gYWZ0ZXIubmV4dCBpZiBhZnRlclxuXHRcdGlmIG5vZGUgaXNhIEFycmF5XG5cdFx0XHRub2RlID0gKDxmcmFnbWVudD4gbm9kZSlcblx0XHRpZiBiZWZvcmVcblx0XHRcdGRvbS5pbnNlcnRCZWZvcmUobm9kZS5kb20sYmVmb3JlLmRvbSlcblx0XHRlbHNlXG5cdFx0XHRhcHBlbmQobm9kZSlcblx0XHRzZWxmXHRcblxuXHQjIyNcblx0Rm9jdXMgb24gY3VycmVudCBub2RlXG5cdEByZXR1cm4ge3NlbGZ9XG5cdCMjI1xuXHRkZWYgZm9jdXNcblx0XHRkb20uZm9jdXNcblx0XHRzZWxmXG5cblx0IyMjXG5cdFJlbW92ZSBmb2N1cyBmcm9tIGN1cnJlbnQgbm9kZVxuXHRAcmV0dXJuIHtzZWxmfVxuXHQjIyNcblx0ZGVmIGJsdXJcblx0XHRkb20uYmx1clxuXHRcdHNlbGZcblxuXHRkZWYgdGVtcGxhdGVcblx0XHRudWxsXG5cblx0IyMjXG5cdEB0b2RvIFNob3VsZCBzdXBwb3J0IG11bHRpcGxlIGFyZ3VtZW50cyBsaWtlIGFwcGVuZFxuXG5cdFRoZSAucHJlcGVuZCBtZXRob2QgaW5zZXJ0cyB0aGUgc3BlY2lmaWVkIGNvbnRlbnQgYXMgdGhlIGZpcnN0XG5cdGNoaWxkIG9mIHRoZSB0YXJnZXQgbm9kZS4gSWYgdGhlIGNvbnRlbnQgaXMgYWxyZWFkeSBhIGNoaWxkIG9mIFxuXHRub2RlIGl0IHdpbGwgYmUgbW92ZWQgdG8gdGhlIHN0YXJ0LlxuXHRcbiAgICBcdG5vZGUucHJlcGVuZCA8ZGl2LnRvcD4gIyBwcmVwZW5kIG5vZGVcbiAgICBcdG5vZGUucHJlcGVuZCBcInNvbWUgdGV4dFwiICMgcHJlcGVuZCB0ZXh0XG4gICAgXHRub2RlLnByZXBlbmQgWzx1bD4sPHVsPl0gIyBwcmVwZW5kIGFycmF5XG5cblx0IyMjXG5cdGRlZiBwcmVwZW5kIGl0ZW1cblx0XHR2YXIgZmlyc3QgPSBAZG9tOmNoaWxkTm9kZXNbMF1cblx0XHRmaXJzdCA/IGluc2VydEJlZm9yZShpdGVtLCBmaXJzdCkgOiBhcHBlbmRDaGlsZChpdGVtKVxuXHRcdHNlbGZcblxuXHQjIyNcblx0VGhlIC5hcHBlbmQgbWV0aG9kIGluc2VydHMgdGhlIHNwZWNpZmllZCBjb250ZW50IGFzIHRoZSBsYXN0IGNoaWxkXG5cdG9mIHRoZSB0YXJnZXQgbm9kZS4gSWYgdGhlIGNvbnRlbnQgaXMgYWxyZWFkeSBhIGNoaWxkIG9mIG5vZGUgaXRcblx0d2lsbCBiZSBtb3ZlZCB0byB0aGUgZW5kLlxuXHRcblx0IyBleGFtcGxlXG5cdCAgICB2YXIgcm9vdCA9IDxkaXYucm9vdD5cblx0ICAgIHZhciBpdGVtID0gPGRpdi5pdGVtPiBcIlRoaXMgaXMgYW4gaXRlbVwiXG5cdCAgICByb290LmFwcGVuZCBpdGVtICMgYXBwZW5kcyBpdGVtIHRvIHRoZSBlbmQgb2Ygcm9vdFxuXG5cdCAgICByb290LnByZXBlbmQgXCJzb21lIHRleHRcIiAjIGFwcGVuZCB0ZXh0XG5cdCAgICByb290LnByZXBlbmQgWzx1bD4sPHVsPl0gIyBhcHBlbmQgYXJyYXlcblx0IyMjXG5cdGRlZiBhcHBlbmQgaXRlbVxuXHRcdCMgcG9zc2libGUgdG8gYXBwZW5kIGJsYW5rXG5cdFx0IyBwb3NzaWJsZSB0byBzaW1wbGlmeSBvbiBzZXJ2ZXI/XG5cdFx0cmV0dXJuIHNlbGYgdW5sZXNzIGl0ZW1cblxuXHRcdGlmIGl0ZW0gaXNhIEFycmF5XG5cdFx0XHRtZW1iZXIgJiYgYXBwZW5kKG1lbWJlcikgZm9yIG1lbWJlciBpbiBpdGVtXG5cblx0XHRlbGlmIGl0ZW0gaXNhIFN0cmluZyBvciBpdGVtIGlzYSBOdW1iZXJcblx0XHRcdHZhciBub2RlID0gSW1iYS5kb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShpdGVtKVxuXHRcdFx0QGRvbS5hcHBlbmRDaGlsZChub2RlKVxuXHRcdFx0QGVtcHR5ID0gbm8gaWYgQGVtcHR5XHRcdFx0XG5cdFx0ZWxzZVxuXHRcdFx0QGRvbS5hcHBlbmRDaGlsZChpdGVtLkBkb20gb3IgaXRlbSlcblx0XHRcdEBlbXB0eSA9IG5vIGlmIEBlbXB0eVxuXG5cdFx0cmV0dXJuIHNlbGZcblxuXHQjIyNcblx0SW5zZXJ0IGEgbm9kZSBpbnRvIHRoZSBjdXJyZW50IG5vZGUgKHNlbGYpLCBiZWZvcmUgYW5vdGhlci5cblx0VGhlIHJlbGF0aXZlIG5vZGUgbXVzdCBiZSBhIGNoaWxkIG9mIGN1cnJlbnQgbm9kZS4gXG5cdCMjI1xuXHRkZWYgaW5zZXJ0QmVmb3JlIG5vZGUsIHJlbFxuXHRcdG5vZGUgPSBJbWJhLmRvY3VtZW50LmNyZWF0ZVRleHROb2RlKG5vZGUpIGlmIG5vZGUgaXNhIFN0cmluZyBcblx0XHRkb20uaW5zZXJ0QmVmb3JlKCAobm9kZS5AZG9tIG9yIG5vZGUpLCAocmVsLkBkb20gb3IgcmVsKSApIGlmIG5vZGUgYW5kIHJlbFxuXHRcdHNlbGZcblxuXHQjIyNcblx0QXBwZW5kIGEgc2luZ2xlIGl0ZW0gKG5vZGUgb3Igc3RyaW5nKSB0byB0aGUgY3VycmVudCBub2RlLlxuXHRJZiBzdXBwbGllZCBpdGVtIGlzIGEgc3RyaW5nIGl0IHdpbGwgYXV0b21hdGljYWxseS4gVGhpcyBpcyB1c2VkXG5cdGJ5IEltYmEgaW50ZXJuYWxseSwgYnV0IHdpbGwgcHJhY3RpY2FsbHkgbmV2ZXIgYmUgdXNlZCBleHBsaWNpdGx5LlxuXHQjIyNcblx0ZGVmIGFwcGVuZENoaWxkIG5vZGVcblx0XHRub2RlID0gSW1iYS5kb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShub2RlKSBpZiBub2RlIGlzYSBTdHJpbmdcblx0XHRkb20uYXBwZW5kQ2hpbGQobm9kZS5AZG9tIG9yIG5vZGUpIGlmIG5vZGVcblx0XHRzZWxmXG5cblx0IyMjXG5cdFJlbW92ZSBhIHNpbmdsZSBjaGlsZCBmcm9tIHRoZSBjdXJyZW50IG5vZGUuXG5cdFVzZWQgYnkgSW1iYSBpbnRlcm5hbGx5LlxuXHQjIyNcblx0ZGVmIHJlbW92ZUNoaWxkIG5vZGVcblx0XHRkb20ucmVtb3ZlQ2hpbGQobm9kZS5AZG9tIG9yIG5vZGUpIGlmIG5vZGVcblx0XHRzZWxmXG5cblx0ZGVmIHRvU3RyaW5nXG5cdFx0QGRvbS50b1N0cmluZyAjIHJlYWxseT9cblxuXHQjIyNcblx0QGRlcHJlY2F0ZWRcblx0IyMjXG5cdGRlZiBjbGFzc2VzXG5cdFx0Y29uc29sZS5sb2cgJ0ltYmEuVGFnI2NsYXNzZXMgaXMgZGVwcmVjYXRlZCdcblx0XHRAZG9tOmNsYXNzTGlzdFxuXG50YWcgc3ZnZWxlbWVudCA8IGh0bWxlbGVtZW50XG5cblxuXG4vKiogV0VCUEFDSyBGT09URVIgKipcbiAqKiBzcmMvaW1iYS9kb20uaW1iYVxuICoqLyIsIlxuIyBwcmVkZWZpbmUgYWxsIHN1cHBvcnRlZCBodG1sIHRhZ3NcbnRhZyBmcmFnbWVudCA8IGh0bWxlbGVtZW50XG5cdFxuXHRkZWYgc2VsZi5jcmVhdGVOb2RlXG5cdFx0SW1iYS5kb2N1bWVudC5jcmVhdGVEb2N1bWVudEZyYWdtZW50XG5cbnRhZyBhXG5cdGF0dHIgaHJlZlxuXG50YWcgYWJiclxudGFnIGFkZHJlc3NcbnRhZyBhcmVhXG50YWcgYXJ0aWNsZVxudGFnIGFzaWRlXG50YWcgYXVkaW9cbnRhZyBiXG50YWcgYmFzZVxudGFnIGJkaVxudGFnIGJkb1xudGFnIGJpZ1xudGFnIGJsb2NrcXVvdGVcbnRhZyBib2R5XG50YWcgYnJcblxudGFnIGJ1dHRvblxuXHRhdHRyIGF1dG9mb2N1c1xuXHRhdHRyIHR5cGVcblx0YXR0ciBkaXNhYmxlZFxuXG50YWcgY2FudmFzXG5cdGRlZiB3aWR0aD0gdmFsXG5cdFx0ZG9tOndpZHRoID0gdmFsIHVubGVzcyB3aWR0aCA9PSB2YWxcblx0XHRzZWxmXG5cblx0ZGVmIGhlaWdodD0gdmFsXG5cdFx0ZG9tOmhlaWdodCA9IHZhbCB1bmxlc3MgaGVpZ2h0ID09IHZhbFxuXHRcdHNlbGZcblxuXHRkZWYgd2lkdGhcblx0XHRkb206d2lkdGhcblxuXHRkZWYgaGVpZ2h0XG5cdFx0ZG9tOmhlaWdodFxuXG5cdGRlZiBjb250ZXh0IHR5cGUgPSAnMmQnXG5cdFx0ZG9tLmdldENvbnRleHQodHlwZSlcblxudGFnIGNhcHRpb25cbnRhZyBjaXRlXG50YWcgY29kZVxudGFnIGNvbFxudGFnIGNvbGdyb3VwXG50YWcgZGF0YVxudGFnIGRhdGFsaXN0XG50YWcgZGRcbnRhZyBkZWxcbnRhZyBkZXRhaWxzXG50YWcgZGZuXG50YWcgZGl2XG50YWcgZGxcbnRhZyBkdFxudGFnIGVtXG50YWcgZW1iZWRcbnRhZyBmaWVsZHNldFxudGFnIGZpZ2NhcHRpb25cbnRhZyBmaWd1cmVcbnRhZyBmb290ZXJcblxudGFnIGZvcm1cblx0YXR0ciBtZXRob2Rcblx0YXR0ciBhY3Rpb25cblxudGFnIGgxXG50YWcgaDJcbnRhZyBoM1xudGFnIGg0XG50YWcgaDVcbnRhZyBoNlxudGFnIGhlYWRcbnRhZyBoZWFkZXJcbnRhZyBoclxudGFnIGh0bWxcbnRhZyBpXG5cbnRhZyBpZnJhbWVcblx0YXR0ciBzcmNcblxudGFnIGltZ1xuXHRhdHRyIHNyY1xuXG50YWcgaW5wdXRcblx0IyBjYW4gdXNlIGF0dHIgaW5zdGVhZFxuXHRhdHRyIG5hbWVcblx0YXR0ciB0eXBlXG5cdGF0dHIgcmVxdWlyZWRcblx0YXR0ciBkaXNhYmxlZFxuXHRhdHRyIGF1dG9mb2N1c1xuXG5cdGRlZiB2YWx1ZVxuXHRcdGRvbTp2YWx1ZVxuXG5cdGRlZiB2YWx1ZT0gdlxuXHRcdGRvbTp2YWx1ZSA9IHYgdW5sZXNzIHYgPT0gZG9tOnZhbHVlXG5cdFx0c2VsZlxuXG5cdGRlZiBwbGFjZWhvbGRlcj0gdlxuXHRcdGRvbTpwbGFjZWhvbGRlciA9IHYgdW5sZXNzIHYgPT0gZG9tOnBsYWNlaG9sZGVyXG5cdFx0c2VsZlxuXG5cdGRlZiBwbGFjZWhvbGRlclxuXHRcdGRvbTpwbGFjZWhvbGRlclxuXG5cdGRlZiBjaGVja2VkXG5cdFx0ZG9tOmNoZWNrZWRcblxuXHRkZWYgY2hlY2tlZD0gYm9vbFxuXHRcdGRvbTpjaGVja2VkID0gYm9vbCB1bmxlc3MgYm9vbCA9PSBkb206Y2hlY2tlZFxuXHRcdHNlbGZcblxudGFnIGluc1xudGFnIGtiZFxudGFnIGtleWdlblxudGFnIGxhYmVsXG50YWcgbGVnZW5kXG50YWcgbGlcblxudGFnIGxpbmtcblx0YXR0ciByZWxcblx0YXR0ciB0eXBlXG5cdGF0dHIgaHJlZlxuXHRhdHRyIG1lZGlhXG5cbnRhZyBtYWluXG50YWcgbWFwXG50YWcgbWFya1xudGFnIG1lbnVcbnRhZyBtZW51aXRlbVxuXG50YWcgbWV0YVxuXHRhdHRyIG5hbWVcblx0YXR0ciBjb250ZW50XG5cdGF0dHIgY2hhcnNldFxuXG50YWcgbWV0ZXJcbnRhZyBuYXZcbnRhZyBub3NjcmlwdFxudGFnIG9iamVjdFxudGFnIG9sXG50YWcgb3B0Z3JvdXBcblxudGFnIG9wdGlvblxuXHRhdHRyIHZhbHVlXG5cbnRhZyBvdXRwdXRcbnRhZyBwXG50YWcgcGFyYW1cbnRhZyBwcmVcbnRhZyBwcm9ncmVzc1xudGFnIHFcbnRhZyBycFxudGFnIHJ0XG50YWcgcnVieVxudGFnIHNcbnRhZyBzYW1wXG5cbnRhZyBzY3JpcHRcblx0YXR0ciBzcmNcblx0YXR0ciB0eXBlXG5cdGF0dHIgYXN5bmNcblx0YXR0ciBkZWZlclxuXG50YWcgc2VjdGlvblxuXG50YWcgc2VsZWN0XG5cdGF0dHIgbmFtZVxuXHRhdHRyIG11bHRpcGxlXG5cdGF0dHIgcmVxdWlyZWRcblx0YXR0ciBkaXNhYmxlZFxuXHRcblx0ZGVmIHZhbHVlXG5cdFx0ZG9tOnZhbHVlXG5cblx0ZGVmIHZhbHVlPSB2XG5cdFx0ZG9tOnZhbHVlID0gdiB1bmxlc3MgdiA9PSBkb206dmFsdWVcblx0XHRzZWxmXG5cblxudGFnIHNtYWxsXG50YWcgc291cmNlXG50YWcgc3BhblxudGFnIHN0cm9uZ1xudGFnIHN0eWxlXG50YWcgc3ViXG50YWcgc3VtbWFyeVxudGFnIHN1cFxudGFnIHRhYmxlXG50YWcgdGJvZHlcbnRhZyB0ZFxuXG50YWcgdGV4dGFyZWFcblx0YXR0ciBuYW1lXG5cdGF0dHIgZGlzYWJsZWRcblx0YXR0ciByZXF1aXJlZFxuXHRhdHRyIHJvd3Ncblx0YXR0ciBjb2xzXG5cdGF0dHIgYXV0b2ZvY3VzXG5cblx0ZGVmIHZhbHVlXG5cdFx0ZG9tOnZhbHVlXG5cblx0ZGVmIHZhbHVlPSB2XG5cdFx0ZG9tOnZhbHVlID0gdiB1bmxlc3MgdiA9PSBkb206dmFsdWVcblx0XHRzZWxmXG5cblx0ZGVmIHBsYWNlaG9sZGVyPSB2XG5cdFx0ZG9tOnBsYWNlaG9sZGVyID0gdiB1bmxlc3MgdiA9PSBkb206cGxhY2Vob2xkZXJcblx0XHRzZWxmXG5cblx0ZGVmIHBsYWNlaG9sZGVyXG5cdFx0ZG9tOnBsYWNlaG9sZGVyXG5cbnRhZyB0Zm9vdFxudGFnIHRoXG50YWcgdGhlYWRcbnRhZyB0aW1lXG50YWcgdGl0bGVcbnRhZyB0clxudGFnIHRyYWNrXG50YWcgdVxudGFnIHVsXG50YWcgdmlkZW9cbnRhZyB3YnJcblxuXG5cbi8qKiBXRUJQQUNLIEZPT1RFUiAqKlxuICoqIHNyYy9pbWJhL2RvbS5odG1sLmltYmFcbiAqKi8iLCJcbnRhZyBzdmc6c3ZnZWxlbWVudFxuXG5cdGRlZiBzZWxmLm5hbWVzcGFjZVVSSVxuXHRcdFwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIlxuXG5cdGxldCB0eXBlcyA9IFwiY2lyY2xlIGRlZnMgZWxsaXBzZSBnIGxpbmUgbGluZWFyR3JhZGllbnQgbWFzayBwYXRoIHBhdHRlcm4gcG9seWdvbiBwb2x5bGluZSByYWRpYWxHcmFkaWVudCByZWN0IHN0b3Agc3ZnIHRleHQgdHNwYW5cIi5zcGxpdChcIiBcIilcblxuXHRkZWYgc2VsZi5idWlsZE5vZGVcblx0XHR2YXIgZG9tID0gSW1iYS5kb2N1bWVudC5jcmVhdGVFbGVtZW50TlMobmFtZXNwYWNlVVJJLEBub2RlVHlwZSlcblx0XHR2YXIgY2xzID0gQGNsYXNzZXMuam9pbihcIiBcIilcblx0XHRkb206Y2xhc3NOYW1lOmJhc2VWYWwgPSBjbHMgaWYgY2xzXG5cdFx0ZG9tXG5cblx0ZGVmIHNlbGYuaW5oZXJpdCBjaGlsZFxuXHRcdGNoaWxkLkBwcm90b0RvbSA9IG51bGxcblxuXHRcdGlmIGNoaWxkLkBuYW1lIGluIHR5cGVzXG5cdFx0XHRjaGlsZC5Abm9kZVR5cGUgPSBjaGlsZC5AbmFtZVxuXHRcdFx0Y2hpbGQuQGNsYXNzZXMgPSBbXVxuXHRcdGVsc2Vcblx0XHRcdGNoaWxkLkBub2RlVHlwZSA9IEBub2RlVHlwZVxuXHRcdFx0dmFyIGNsYXNzTmFtZSA9IFwiX1wiICsgY2hpbGQuQG5hbWUucmVwbGFjZSgvXy9nLCAnLScpXG5cdFx0XHRjaGlsZC5AY2xhc3NlcyA9IEBjbGFzc2VzLmNvbmNhdChjbGFzc05hbWUpXG5cblxuXHRhdHRyIHggaW5saW5lOiBub1xuXHRhdHRyIHkgaW5saW5lOiBub1xuXG5cdGF0dHIgd2lkdGggaW5saW5lOiBub1xuXHRhdHRyIGhlaWdodCBpbmxpbmU6IG5vXG5cblx0YXR0ciBzdHJva2UgaW5saW5lOiBub1xuXHRhdHRyIHN0cm9rZS13aWR0aCBpbmxpbmU6IG5vXG5cbnRhZyBzdmc6c3ZnXG5cdGF0dHIgdmlld2JveCBpbmxpbmU6IG5vXG5cbnRhZyBzdmc6Z1xuXG50YWcgc3ZnOmRlZnNcblxudGFnIHN2ZzpzeW1ib2xcblx0YXR0ciBwcmVzZXJ2ZUFzcGVjdFJhdGlvIGlubGluZTogbm9cblx0YXR0ciB2aWV3Qm94IGlubGluZTogbm9cblxudGFnIHN2ZzptYXJrZXJcblx0YXR0ciBtYXJrZXJVbml0cyBpbmxpbmU6IG5vXG5cdGF0dHIgcmVmWCBpbmxpbmU6IG5vXG5cdGF0dHIgcmVmWSBpbmxpbmU6IG5vXG5cdGF0dHIgbWFya2VyV2lkdGggaW5saW5lOiBub1xuXHRhdHRyIG1hcmtlckhlaWdodCBpbmxpbmU6IG5vXG5cdGF0dHIgb3JpZW50IGlubGluZTogbm9cblxuXG4jIEJhc2ljIHNoYXBlc1xuXG50YWcgc3ZnOnJlY3Rcblx0YXR0ciByeCBpbmxpbmU6IG5vXG5cdGF0dHIgcnkgaW5saW5lOiBub1xuXG50YWcgc3ZnOmNpcmNsZVxuXHRhdHRyIGN4IGlubGluZTogbm9cblx0YXR0ciBjeSBpbmxpbmU6IG5vXG5cdGF0dHIgciBpbmxpbmU6IG5vXG5cbnRhZyBzdmc6ZWxsaXBzZVxuXHRhdHRyIGN4IGlubGluZTogbm9cblx0YXR0ciBjeSBpbmxpbmU6IG5vXG5cdGF0dHIgcnggaW5saW5lOiBub1xuXHRhdHRyIHJ5IGlubGluZTogbm9cblxudGFnIHN2ZzpwYXRoXG5cdGF0dHIgZCBpbmxpbmU6IG5vXG5cdGF0dHIgcGF0aExlbmd0aCBpbmxpbmU6IG5vXG5cbnRhZyBzdmc6bGluZVxuXHRhdHRyIHgxIGlubGluZTogbm9cblx0YXR0ciB4MiBpbmxpbmU6IG5vXG5cdGF0dHIgeTEgaW5saW5lOiBub1xuXHRhdHRyIHkyIGlubGluZTogbm9cblxudGFnIHN2Zzpwb2x5bGluZVxuXHRhdHRyIHBvaW50cyBpbmxpbmU6IG5vXG5cbnRhZyBzdmc6cG9seWdvblxuXHRhdHRyIHBvaW50cyBpbmxpbmU6IG5vXG5cbnRhZyBzdmc6dGV4dFxuXHRhdHRyIGR4IGlubGluZTogbm9cblx0YXR0ciBkeSBpbmxpbmU6IG5vXG5cdGF0dHIgdGV4dC1hbmNob3IgaW5saW5lOiBub1xuXHRhdHRyIHJvdGF0ZSBpbmxpbmU6IG5vXG5cdGF0dHIgdGV4dExlbmd0aCBpbmxpbmU6IG5vXG5cdGF0dHIgbGVuZ3RoQWRqdXN0IGlubGluZTogbm9cblxudGFnIHN2Zzp0c3BhblxuXHRhdHRyIGR4IGlubGluZTogbm9cblx0YXR0ciBkeSBpbmxpbmU6IG5vXG5cdGF0dHIgcm90YXRlIGlubGluZTogbm9cblx0YXR0ciB0ZXh0TGVuZ3RoIGlubGluZTogbm9cblx0YXR0ciBsZW5ndGhBZGp1c3QgaW5saW5lOiBub1xuXG5cbi8qKiBXRUJQQUNLIEZPT1RFUiAqKlxuICoqIHNyYy9pbWJhL2RvbS5zdmcuaW1iYVxuICoqLyIsIiMgRXh0ZW5kaW5nIEltYmEuVGFnI2NzcyB0byB3b3JrIHdpdGhvdXQgcHJlZml4ZXMgYnkgaW5zcGVjdGluZ1xuIyB0aGUgcHJvcGVydGllcyBvZiBhIENTU1N0eWxlRGVjbGFyYXRpb24gYW5kIGNyZWF0aW5nIGEgbWFwXG5cbiMgdmFyIHByZWZpeGVzID0gWyctd2Via2l0LScsJy1tcy0nLCctbW96LScsJy1vLScsJy1ibGluay0nXVxuIyB2YXIgcHJvcHMgPSBbJ3RyYW5zZm9ybScsJ3RyYW5zaXRpb24nLCdhbmltYXRpb24nXVxuXG5pZiBJbWJhLkNMSUVOVFxuXHR2YXIgc3R5bGVzID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoZG9jdW1lbnQ6ZG9jdW1lbnRFbGVtZW50LCAnJylcblxuXHRJbWJhLkNTU0tleU1hcCA9IHt9XG5cblx0Zm9yIHByZWZpeGVkIGluIHN0eWxlc1xuXHRcdHZhciB1bnByZWZpeGVkID0gcHJlZml4ZWQucmVwbGFjZSgvXi0od2Via2l0fG1zfG1venxvfGJsaW5rKS0vLCcnKVxuXHRcdHZhciBjYW1lbENhc2UgPSB1bnByZWZpeGVkLnJlcGxhY2UoLy0oXFx3KS9nKSBkbyB8bSxhfCBhLnRvVXBwZXJDYXNlXG5cblx0XHQjIGlmIHRoZXJlIGV4aXN0cyBhbiB1bnByZWZpeGVkIHZlcnNpb24gLS0gYWx3YXlzIHVzZSB0aGlzXG5cdFx0aWYgcHJlZml4ZWQgIT0gdW5wcmVmaXhlZFxuXHRcdFx0Y29udGludWUgaWYgc3R5bGVzLmhhc093blByb3BlcnR5KHVucHJlZml4ZWQpXG5cblx0XHQjIHJlZ2lzdGVyIHRoZSBwcmVmaXhlc1xuXHRcdEltYmEuQ1NTS2V5TWFwW3VucHJlZml4ZWRdID0gSW1iYS5DU1NLZXlNYXBbY2FtZWxDYXNlXSA9IHByZWZpeGVkXG5cblx0ZXh0ZW5kIHRhZyBlbGVtZW50XG5cblx0XHQjIG92ZXJyaWRlIHRoZSBvcmlnaW5hbCBjc3MgbWV0aG9kXG5cdFx0ZGVmIGNzcyBrZXksIHZhbFxuXHRcdFx0aWYga2V5IGlzYSBPYmplY3Rcblx0XHRcdFx0Y3NzKGssdikgZm9yIG93biBrLHYgb2Yga2V5XG5cdFx0XHRcdHJldHVybiBzZWxmXG5cblx0XHRcdGtleSA9IEltYmEuQ1NTS2V5TWFwW2tleV0gb3Iga2V5XG5cblx0XHRcdGlmIHZhbCA9PSBudWxsXG5cdFx0XHRcdGRvbTpzdHlsZS5yZW1vdmVQcm9wZXJ0eShrZXkpXG5cdFx0XHRlbGlmIHZhbCA9PSB1bmRlZmluZWRcblx0XHRcdFx0cmV0dXJuIGRvbTpzdHlsZVtrZXldXG5cdFx0XHRlbHNlXG5cdFx0XHRcdGlmIHZhbCBpc2EgTnVtYmVyIGFuZCBrZXkubWF0Y2goL3dpZHRofGhlaWdodHxsZWZ0fHJpZ2h0fHRvcHxib3R0b20vKVxuXHRcdFx0XHRcdHZhbCA9IHZhbCArIFwicHhcIlxuXHRcdFx0XHRkb206c3R5bGVba2V5XSA9IHZhbFxuXHRcdFx0c2VsZlxuXHRcdFx0XG5cdHVubGVzcyBkb2N1bWVudDpkb2N1bWVudEVsZW1lbnQ6Y2xhc3NMaXN0XG5cdFx0ZXh0ZW5kIHRhZyBlbGVtZW50XG5cblx0XHRcdGRlZiBoYXNGbGFnIHJlZlxuXHRcdFx0XHRyZXR1cm4gUmVnRXhwLm5ldygnKF58XFxcXHMpJyArIHJlZiArICcoXFxcXHN8JCknKS50ZXN0KEBkb206Y2xhc3NOYW1lKVxuXG5cdFx0XHRkZWYgYWRkRmxhZyByZWZcblx0XHRcdFx0cmV0dXJuIHNlbGYgaWYgaGFzRmxhZyhyZWYpXG5cdFx0XHRcdEBkb206Y2xhc3NOYW1lICs9IChAZG9tOmNsYXNzTmFtZSA/ICcgJyA6ICcnKSArIHJlZlxuXHRcdFx0XHRyZXR1cm4gc2VsZlxuXG5cdFx0XHRkZWYgdW5mbGFnIHJlZlxuXHRcdFx0XHRyZXR1cm4gc2VsZiB1bmxlc3MgaGFzRmxhZyhyZWYpXG5cdFx0XHRcdHZhciByZWdleCA9IFJlZ0V4cC5uZXcoJyhefFxcXFxzKSonICsgcmVmICsgJyhcXFxcc3wkKSonLCAnZycpXG5cdFx0XHRcdEBkb206Y2xhc3NOYW1lID0gQGRvbTpjbGFzc05hbWUucmVwbGFjZShyZWdleCwgJycpXG5cdFx0XHRcdHJldHVybiBzZWxmXG5cblx0XHRcdGRlZiB0b2dnbGVGbGFnIHJlZlxuXHRcdFx0XHRoYXNGbGFnKHJlZikgPyB1bmZsYWcocmVmKSA6IGZsYWcocmVmKVxuXG5cdFx0XHRkZWYgZmxhZyByZWYsIGJvb2xcblx0XHRcdFx0aWYgYXJndW1lbnRzOmxlbmd0aCA9PSAyIGFuZCAhIWJvb2wgPT09IG5vXG5cdFx0XHRcdFx0cmV0dXJuIHVuZmxhZyhyZWYpXG5cdFx0XHRcdHJldHVybiBhZGRGbGFnKHJlZilcblx0XHR0cnVlXG5cblxuLyoqIFdFQlBBQ0sgRk9PVEVSICoqXG4gKiogc3JjL2ltYmEvZG9tLmNsaWVudC5pbWJhXG4gKiovIiwidmFyIGRvYyA9IGRvY3VtZW50XG52YXIgd2luID0gd2luZG93XG5cbnZhciBoYXNUb3VjaEV2ZW50cyA9IHdpbmRvdyAmJiB3aW5kb3c6b250b3VjaHN0YXJ0ICE9PSB1bmRlZmluZWRcblxuY2xhc3MgSW1iYS5Qb2ludGVyXG5cblx0IyBiZWdhbiwgbW92ZWQsIHN0YXRpb25hcnksIGVuZGVkLCBjYW5jZWxsZWRcblxuXHRwcm9wIHBoYXNlXG5cdHByb3AgcHJldkV2ZW50XG5cdHByb3AgYnV0dG9uXG5cdHByb3AgZXZlbnRcblx0cHJvcCBkaXJ0eVxuXHRwcm9wIGV2ZW50c1xuXHRwcm9wIHRvdWNoXG5cblx0ZGVmIGluaXRpYWxpemVcblx0XHRidXR0b24gPSAtMVxuXHRcdGV2ZW50ID0ge3g6IDAsIHk6IDAsIHR5cGU6ICd1bmluaXRpYWxpemVkJ31cblx0XHRyZXR1cm4gc2VsZlxuXG5cdGRlZiB1cGRhdGUgZVxuXHRcdGV2ZW50ID0gZVxuXHRcdGRpcnR5ID0geWVzXG5cdFx0c2VsZlxuXG5cdCMgdGhpcyBpcyBqdXN0IGZvciByZWd1bGFyIG1vdXNlIG5vd1xuXHRkZWYgcHJvY2Vzc1xuXHRcdHZhciBlMSA9IGV2ZW50XG5cblx0XHRpZiBkaXJ0eVxuXHRcdFx0cHJldkV2ZW50ID0gZTFcblx0XHRcdGRpcnR5ID0gbm9cblxuXHRcdFx0IyBidXR0b24gc2hvdWxkIG9ubHkgY2hhbmdlIG9uIG1vdXNlZG93biBldGNcblx0XHRcdGlmIGUxOnR5cGUgPT0gJ21vdXNlZG93bidcblx0XHRcdFx0YnV0dG9uID0gZTE6YnV0dG9uXG5cblx0XHRcdFx0IyBkbyBub3QgY3JlYXRlIHRvdWNoIGZvciByaWdodCBjbGlja1xuXHRcdFx0XHRpZiBidXR0b24gPT0gMiBvciAodG91Y2ggYW5kIGJ1dHRvbiAhPSAwKVxuXHRcdFx0XHRcdHJldHVyblxuXG5cdFx0XHRcdCMgY2FuY2VsIHRoZSBwcmV2aW91cyB0b3VjaFxuXHRcdFx0XHR0b3VjaC5jYW5jZWwgaWYgdG91Y2hcblx0XHRcdFx0dG91Y2ggPSBJbWJhLlRvdWNoLm5ldyhlMSxzZWxmKVxuXHRcdFx0XHR0b3VjaC5tb3VzZWRvd24oZTEsZTEpXG5cblx0XHRcdGVsaWYgZTE6dHlwZSA9PSAnbW91c2Vtb3ZlJ1xuXHRcdFx0XHR0b3VjaC5tb3VzZW1vdmUoZTEsZTEpIGlmIHRvdWNoXG5cblx0XHRcdGVsaWYgZTE6dHlwZSA9PSAnbW91c2V1cCdcblx0XHRcdFx0YnV0dG9uID0gLTFcblxuXHRcdFx0XHRpZiB0b3VjaCBhbmQgdG91Y2guYnV0dG9uID09IGUxOmJ1dHRvblxuXHRcdFx0XHRcdHRvdWNoLm1vdXNldXAoZTEsZTEpXG5cdFx0XHRcdFx0dG91Y2ggPSBudWxsXG5cdFx0XHRcdCMgdHJpZ2dlciBwb2ludGVydXBcblx0XHRlbHNlXG5cdFx0XHR0b3VjaC5pZGxlIGlmIHRvdWNoXG5cdFx0c2VsZlxuXHRcdFxuXHRkZWYgY2xlYW51cFxuXHRcdEltYmEuUE9JTlRFUlNcblxuXHRkZWYgeCBkbyBldmVudDp4XG5cdGRlZiB5IGRvIGV2ZW50OnlcblxuXHQjIGRlcHJlY2F0ZWQgLS0gc2hvdWxkIHJlbW92ZVxuXHRkZWYgc2VsZi51cGRhdGUgXG5cdFx0IyBjb25zb2xlLmxvZygndXBkYXRlIHRvdWNoJylcblx0XHRmb3IgcHRyLGkgaW4gSW1iYS5QT0lOVEVSU1xuXHRcdFx0cHRyLnByb2Nlc3Ncblx0XHQjIG5lZWQgdG8gYmUgYWJsZSB0byBwcmV2ZW50IHRoZSBkZWZhdWx0IGJlaGF2aW91ciBvZiB0b3VjaCwgbm8/XG5cdFx0d2luLnJlcXVlc3RBbmltYXRpb25GcmFtZShJbWJhLlBvaW50ZXI6dXBkYXRlKVxuXHRcdHNlbGZcblxudmFyIGxhc3ROYXRpdmVUb3VjaFRpbWVTdGFtcCA9IDBcbnZhciBsYXN0TmF0aXZlVG91Y2hUaW1lb3V0ID0gNTBcblxuIyBJbWJhLlRvdWNoXG4jIEJlZ2FuXHRBIGZpbmdlciB0b3VjaGVkIHRoZSBzY3JlZW4uXG4jIE1vdmVkXHRBIGZpbmdlciBtb3ZlZCBvbiB0aGUgc2NyZWVuLlxuIyBTdGF0aW9uYXJ5XHRBIGZpbmdlciBpcyB0b3VjaGluZyB0aGUgc2NyZWVuIGJ1dCBoYXNuJ3QgbW92ZWQuXG4jIEVuZGVkXHRBIGZpbmdlciB3YXMgbGlmdGVkIGZyb20gdGhlIHNjcmVlbi4gVGhpcyBpcyB0aGUgZmluYWwgcGhhc2Ugb2YgYSB0b3VjaC5cbiMgQ2FuY2VsZWQgVGhlIHN5c3RlbSBjYW5jZWxsZWQgdHJhY2tpbmcgZm9yIHRoZSB0b3VjaC5cblxuIyMjXG5Db25zb2xpZGF0ZXMgbW91c2UgYW5kIHRvdWNoIGV2ZW50cy4gVG91Y2ggb2JqZWN0cyBwZXJzaXN0IGFjcm9zcyBhIHRvdWNoLFxuZnJvbSB0b3VjaHN0YXJ0IHVudGlsIGVuZC9jYW5jZWwuIFdoZW4gYSB0b3VjaCBzdGFydHMsIGl0IHdpbGwgdHJhdmVyc2VcbmRvd24gZnJvbSB0aGUgaW5uZXJtb3N0IHRhcmdldCwgdW50aWwgaXQgZmluZHMgYSBub2RlIHRoYXQgcmVzcG9uZHMgdG9cbm9udG91Y2hzdGFydC4gVW5sZXNzIHRoZSB0b3VjaCBpcyBleHBsaWNpdGx5IHJlZGlyZWN0ZWQsIHRoZSB0b3VjaCB3aWxsXG5jYWxsIG9udG91Y2htb3ZlIGFuZCBvbnRvdWNoZW5kIC8gb250b3VjaGNhbmNlbCBvbiB0aGUgcmVzcG9uZGVyIHdoZW4gYXBwcm9wcmlhdGUuXG5cblx0dGFnIGRyYWdnYWJsZVxuXHRcdCMgY2FsbGVkIHdoZW4gYSB0b3VjaCBzdGFydHNcblx0XHRkZWYgb250b3VjaHN0YXJ0IHRvdWNoXG5cdFx0XHRmbGFnICdkcmFnZ2luZydcblx0XHRcdHNlbGZcblx0XHRcblx0XHQjIGNhbGxlZCB3aGVuIHRvdWNoIG1vdmVzIC0gc2FtZSB0b3VjaCBvYmplY3Rcblx0XHRkZWYgb250b3VjaG1vdmUgdG91Y2hcblx0XHRcdCMgbW92ZSB0aGUgbm9kZSB3aXRoIHRvdWNoXG5cdFx0XHRjc3MgdG9wOiB0b3VjaC5keSwgbGVmdDogdG91Y2guZHhcblx0XHRcblx0XHQjIGNhbGxlZCB3aGVuIHRvdWNoIGVuZHNcblx0XHRkZWYgb250b3VjaGVuZCB0b3VjaFxuXHRcdFx0dW5mbGFnICdkcmFnZ2luZydcblxuQGluYW1lIHRvdWNoXG4jIyNcbmNsYXNzIEltYmEuVG91Y2hcblxuXHR2YXIgdG91Y2hlcyA9IFtdXG5cdHZhciBjb3VudCA9IDBcblx0dmFyIGlkZW50aWZpZXJzID0ge31cblxuXHRkZWYgc2VsZi5jb3VudFxuXHRcdGNvdW50XG5cblx0ZGVmIHNlbGYubG9va3VwIGl0ZW1cblx0XHRyZXR1cm4gaXRlbSBhbmQgKGl0ZW06X190b3VjaF9fIG9yIGlkZW50aWZpZXJzW2l0ZW06aWRlbnRpZmllcl0pXG5cblx0ZGVmIHNlbGYucmVsZWFzZSBpdGVtLHRvdWNoXG5cdFx0ZGVsZXRlIGlkZW50aWZpZXJzW2l0ZW06aWRlbnRpZmllcl1cblx0XHRkZWxldGUgaXRlbTpfX3RvdWNoX19cblx0XHRyZXR1cm5cblxuXHRkZWYgc2VsZi5vbnRvdWNoc3RhcnQgZVxuXHRcdGZvciB0IGluIGU6Y2hhbmdlZFRvdWNoZXNcblx0XHRcdGNvbnRpbnVlIGlmIGxvb2t1cCh0KVxuXHRcdFx0dmFyIHRvdWNoID0gaWRlbnRpZmllcnNbdDppZGVudGlmaWVyXSA9IHNlbGYubmV3KGUpICMgKGUpXG5cdFx0XHR0Ol9fdG91Y2hfXyA9IHRvdWNoXG5cdFx0XHR0b3VjaGVzLnB1c2godG91Y2gpXG5cdFx0XHRjb3VudCsrXG5cdFx0XHR0b3VjaC50b3VjaHN0YXJ0KGUsdClcblx0XHRzZWxmXG5cblx0ZGVmIHNlbGYub250b3VjaG1vdmUgZVxuXHRcdGZvciB0IGluIGU6Y2hhbmdlZFRvdWNoZXNcblx0XHRcdGlmIHZhciB0b3VjaCA9IGxvb2t1cCh0KVxuXHRcdFx0XHR0b3VjaC50b3VjaG1vdmUoZSx0KVxuXG5cdFx0c2VsZlxuXG5cdGRlZiBzZWxmLm9udG91Y2hlbmQgZVxuXHRcdGZvciB0IGluIGU6Y2hhbmdlZFRvdWNoZXNcblx0XHRcdGlmIHZhciB0b3VjaCA9IGxvb2t1cCh0KVxuXHRcdFx0XHR0b3VjaC50b3VjaGVuZChlLHQpXG5cdFx0XHRcdHJlbGVhc2UodCx0b3VjaClcblx0XHRcdFx0Y291bnQtLVxuXG5cdFx0IyBlLnByZXZlbnREZWZhdWx0XG5cdFx0IyBub3QgYWx3YXlzIHN1cHBvcnRlZCFcblx0XHQjIHRvdWNoZXMgPSB0b3VjaGVzLmZpbHRlcih8fClcblx0XHRzZWxmXG5cblx0ZGVmIHNlbGYub250b3VjaGNhbmNlbCBlXG5cdFx0Zm9yIHQgaW4gZTpjaGFuZ2VkVG91Y2hlc1xuXHRcdFx0aWYgdmFyIHRvdWNoID0gbG9va3VwKHQpXG5cdFx0XHRcdHRvdWNoLnRvdWNoY2FuY2VsKGUsdClcblx0XHRcdFx0cmVsZWFzZSh0LHRvdWNoKVxuXHRcdFx0XHRjb3VudC0tXG5cdFx0c2VsZlxuXG5cdGRlZiBzZWxmLm9ubW91c2Vkb3duIGVcblx0XHRzZWxmXG5cblx0ZGVmIHNlbGYub25tb3VzZW1vdmUgZVxuXHRcdHNlbGZcblxuXHRkZWYgc2VsZi5vbm1vdXNldXAgZVxuXHRcdHNlbGZcblxuXG5cdHByb3AgcGhhc2Vcblx0cHJvcCBhY3RpdmVcblx0cHJvcCBldmVudFxuXHRwcm9wIHBvaW50ZXJcblx0cHJvcCB0YXJnZXRcblx0cHJvcCBoYW5kbGVyXG5cdHByb3AgdXBkYXRlc1xuXHRwcm9wIHN1cHByZXNzXG5cdHByb3AgZGF0YVxuXHRwcm9wIGJ1YmJsZSBjaGFpbmFibGU6IHllc1xuXG5cdHByb3AgZ2VzdHVyZXNcblxuXHQjIyNcblx0XG5cblx0QGludGVybmFsXG5cdEBjb25zdHJ1Y3RvclxuXHQjIyNcblx0ZGVmIGluaXRpYWxpemUgZXZlbnQsIHBvaW50ZXJcblx0XHQjIEBuYXRpdmUgID0gZmFsc2Vcblx0XHRzZWxmLmV2ZW50ID0gZXZlbnRcblx0XHRkYXRhID0ge31cblx0XHRhY3RpdmUgPSB5ZXNcblx0XHRAYnV0dG9uID0gZXZlbnQgYW5kIGV2ZW50OmJ1dHRvbiBvciAwXG5cdFx0QHN1cHByZXNzID0gbm8gIyBkZXByZWNhdGVkXG5cdFx0QGNhcHR1cmVkID0gbm9cblx0XHRidWJibGUgPSBub1xuXHRcdHBvaW50ZXIgPSBwb2ludGVyXG5cdFx0dXBkYXRlcyA9IDBcblx0XHRyZXR1cm4gc2VsZlxuXG5cdGRlZiBjYXB0dXJlXG5cdFx0QGNhcHR1cmVkID0geWVzXG5cdFx0QGV2ZW50IGFuZCBAZXZlbnQucHJldmVudERlZmF1bHRcblx0XHRzZWxmXG5cblx0ZGVmIGlzQ2FwdHVyZWRcblx0XHQhIUBjYXB0dXJlZFxuXG5cdCMjI1xuXHRFeHRlbmQgdGhlIHRvdWNoIHdpdGggYSBwbHVnaW4gLyBnZXN0dXJlLiBcblx0QWxsIGV2ZW50cyAodG91Y2hzdGFydCxtb3ZlIGV0YykgZm9yIHRoZSB0b3VjaFxuXHR3aWxsIGJlIHRyaWdnZXJlZCBvbiB0aGUgcGx1Z2lucyBpbiB0aGUgb3JkZXIgdGhleVxuXHRhcmUgYWRkZWQuXG5cdCMjI1xuXHRkZWYgZXh0ZW5kIHBsdWdpblxuXHRcdCMgY29uc29sZS5sb2cgXCJhZGRlZCBnZXN0dXJlISEhXCJcblx0XHRAZ2VzdHVyZXMgfHw9IFtdXG5cdFx0QGdlc3R1cmVzLnB1c2gocGx1Z2luKVxuXHRcdHNlbGZcblxuXHQjIyNcblx0UmVkaXJlY3QgdG91Y2ggdG8gc3BlY2lmaWVkIHRhcmdldC4gb250b3VjaHN0YXJ0IHdpbGwgYWx3YXlzIGJlXG5cdGNhbGxlZCBvbiB0aGUgbmV3IHRhcmdldC5cblx0QHJldHVybiB7TnVtYmVyfVxuXHQjIyNcblx0ZGVmIHJlZGlyZWN0IHRhcmdldFxuXHRcdEByZWRpcmVjdCA9IHRhcmdldFxuXHRcdHNlbGZcblxuXHQjIyNcblx0U3VwcHJlc3MgdGhlIGRlZmF1bHQgYmVoYXZpb3VyLiBXaWxsIGNhbGwgcHJldmVudERlZmF1bHQgZm9yXG5cdGFsbCBuYXRpdmUgZXZlbnRzIHRoYXQgYXJlIHBhcnQgb2YgdGhlIHRvdWNoLlxuXHQjIyNcblx0ZGVmIHN1cHByZXNzXG5cdFx0IyBjb2xsaXNpb24gd2l0aCB0aGUgc3VwcHJlc3MgcHJvcGVydHlcblx0XHRAYWN0aXZlID0gbm9cblx0XHRzZWxmXG5cblx0ZGVmIHN1cHByZXNzPSB2YWx1ZVxuXHRcdGNvbnNvbGUud2FybiAnSW1iYS5Ub3VjaCNzdXBwcmVzcz0gaXMgZGVwcmVjYXRlZCdcblx0XHRAc3VwcmVzcyA9IHZhbHVlXG5cdFx0c2VsZlxuXG5cdGRlZiB0b3VjaHN0YXJ0IGUsdFxuXHRcdEBldmVudCA9IGVcblx0XHRAdG91Y2ggPSB0XG5cdFx0QGJ1dHRvbiA9IDBcblx0XHRAeCA9IHQ6Y2xpZW50WFxuXHRcdEB5ID0gdDpjbGllbnRZXG5cdFx0YmVnYW5cblx0XHRlLnByZXZlbnREZWZhdWx0IGlmIGUgYW5kIGlzQ2FwdHVyZWRcblx0XHRzZWxmXG5cblx0ZGVmIHRvdWNobW92ZSBlLHRcblx0XHRAZXZlbnQgPSBlXG5cdFx0QHggPSB0OmNsaWVudFhcblx0XHRAeSA9IHQ6Y2xpZW50WVxuXHRcdHVwZGF0ZVxuXHRcdGUucHJldmVudERlZmF1bHQgaWYgZSBhbmQgaXNDYXB0dXJlZFxuXHRcdHNlbGZcblxuXHRkZWYgdG91Y2hlbmQgZSx0XG5cdFx0QGV2ZW50ID0gZVxuXHRcdEB4ID0gdDpjbGllbnRYXG5cdFx0QHkgPSB0OmNsaWVudFlcblx0XHRlbmRlZFxuXG5cdFx0bGFzdE5hdGl2ZVRvdWNoVGltZVN0YW1wID0gZTp0aW1lU3RhbXBcblxuXHRcdGlmIEBtYXhkciA8IDIwXG5cdFx0XHR2YXIgdGFwID0gSW1iYS5FdmVudC5uZXcoZSlcblx0XHRcdHRhcC50eXBlID0gJ3RhcCdcblx0XHRcdHRhcC5wcm9jZXNzXG5cdFx0XHRlLnByZXZlbnREZWZhdWx0IGlmIHRhcC5AcmVzcG9uZGVyXHRcblxuXHRcdGlmIGUgYW5kIGlzQ2FwdHVyZWRcblx0XHRcdGUucHJldmVudERlZmF1bHRcblxuXHRcdHNlbGZcblxuXHRkZWYgdG91Y2hjYW5jZWwgZSx0XG5cdFx0Y2FuY2VsXG5cblx0ZGVmIG1vdXNlZG93biBlLHRcblx0XHRAZXZlbnQgPSBlXG5cdFx0QGJ1dHRvbiA9IGU6YnV0dG9uXG5cdFx0QHggPSB0OmNsaWVudFhcblx0XHRAeSA9IHQ6Y2xpZW50WVxuXHRcdGJlZ2FuXG5cblx0XHRAbW91c2Vtb3ZlID0gKHxlfCBtb3VzZW1vdmUoZSxlKSApXG5cdFx0ZG9jLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsQG1vdXNlbW92ZSx5ZXMpXG5cdFx0c2VsZlxuXG5cdGRlZiBtb3VzZW1vdmUgZSx0XG5cdFx0QHggPSB0OmNsaWVudFhcblx0XHRAeSA9IHQ6Y2xpZW50WVxuXHRcdEBldmVudCA9IGVcblx0XHRlLnByZXZlbnREZWZhdWx0IGlmIGlzQ2FwdHVyZWRcblx0XHR1cGRhdGVcblx0XHRtb3ZlXG5cdFx0c2VsZlxuXG5cdGRlZiBtb3VzZXVwIGUsdFxuXHRcdEB4ID0gdDpjbGllbnRYXG5cdFx0QHkgPSB0OmNsaWVudFlcblx0XHRlbmRlZFxuXHRcdGRvYy5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLEBtb3VzZW1vdmUseWVzKVxuXHRcdEBtb3VzZW1vdmUgPSBudWxsXG5cdFx0c2VsZlxuXG5cdGRlZiBpZGxlXG5cdFx0dXBkYXRlXG5cblx0ZGVmIGJlZ2FuXG5cdFx0QG1heGRyID0gQGRyID0gMFxuXHRcdEB4MCA9IEB4XG5cdFx0QHkwID0gQHlcblxuXHRcdHZhciBkb20gPSBldmVudDp0YXJnZXRcblx0XHR2YXIgbm9kZSA9IG51bGxcblxuXHRcdEBzb3VyY2VUYXJnZXQgPSBkb20gYW5kIHRhZyhkb20pXG5cblx0XHR3aGlsZSBkb21cblx0XHRcdG5vZGUgPSB0YWcoZG9tKVxuXHRcdFx0aWYgbm9kZSAmJiBub2RlOm9udG91Y2hzdGFydFxuXHRcdFx0XHRAYnViYmxlID0gbm9cblx0XHRcdFx0dGFyZ2V0ID0gbm9kZVxuXHRcdFx0XHR0YXJnZXQub250b3VjaHN0YXJ0KHNlbGYpXG5cdFx0XHRcdGJyZWFrIHVubGVzcyBAYnViYmxlXG5cdFx0XHRkb20gPSBkb206cGFyZW50Tm9kZVxuXG5cdFx0QHVwZGF0ZXMrK1xuXHRcdHNlbGZcblxuXHRkZWYgdXBkYXRlXG5cdFx0cmV0dXJuIHNlbGYgdW5sZXNzIEBhY3RpdmVcblxuXHRcdHZhciBkciA9IE1hdGguc3FydChkeCpkeCArIGR5KmR5KVxuXHRcdEBtYXhkciA9IGRyIGlmIGRyID4gQGRyXG5cdFx0QGRyID0gZHJcblxuXHRcdCMgY2F0Y2hpbmcgYSB0b3VjaC1yZWRpcmVjdD8hP1xuXHRcdGlmIEByZWRpcmVjdFxuXHRcdFx0aWYgQHRhcmdldCBhbmQgQHRhcmdldDpvbnRvdWNoY2FuY2VsXG5cdFx0XHRcdEB0YXJnZXQub250b3VjaGNhbmNlbChzZWxmKVxuXHRcdFx0dGFyZ2V0ID0gQHJlZGlyZWN0XG5cdFx0XHRAcmVkaXJlY3QgPSBudWxsXG5cdFx0XHR0YXJnZXQub250b3VjaHN0YXJ0KHNlbGYpIGlmIHRhcmdldDpvbnRvdWNoc3RhcnRcblxuXG5cdFx0QHVwZGF0ZXMrK1xuXHRcdGlmIEBnZXN0dXJlc1xuXHRcdFx0Zy5vbnRvdWNodXBkYXRlKHNlbGYpIGZvciBnIGluIEBnZXN0dXJlc1xuXG5cdFx0dGFyZ2V0Py5vbnRvdWNodXBkYXRlKHNlbGYpXG5cdFx0c2VsZlxuXG5cdGRlZiBtb3ZlXG5cdFx0cmV0dXJuIHNlbGYgdW5sZXNzIEBhY3RpdmVcblxuXHRcdGlmIEBnZXN0dXJlc1xuXHRcdFx0Zm9yIGcgaW4gQGdlc3R1cmVzXG5cdFx0XHRcdGcub250b3VjaG1vdmUoc2VsZixAZXZlbnQpIGlmIGc6b250b3VjaG1vdmVcblxuXHRcdHRhcmdldD8ub250b3VjaG1vdmUoc2VsZixAZXZlbnQpXG5cdFx0c2VsZlxuXG5cdGRlZiBlbmRlZFxuXHRcdHJldHVybiBzZWxmIHVubGVzcyBAYWN0aXZlXG5cblx0XHRAdXBkYXRlcysrXG5cblx0XHRpZiBAZ2VzdHVyZXNcblx0XHRcdGcub250b3VjaGVuZChzZWxmKSBmb3IgZyBpbiBAZ2VzdHVyZXNcblxuXHRcdHRhcmdldD8ub250b3VjaGVuZChzZWxmKVxuXG5cdFx0c2VsZlxuXG5cdGRlZiBjYW5jZWxcblx0XHR1bmxlc3MgQGNhbmNlbGxlZFxuXHRcdFx0QGNhbmNlbGxlZCA9IHllc1xuXHRcdFx0Y2FuY2VsbGVkXG5cdFx0XHRkb2MucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJyxAbW91c2Vtb3ZlLHllcykgaWYgQG1vdXNlbW92ZVxuXHRcdHNlbGZcblxuXHRkZWYgY2FuY2VsbGVkXG5cdFx0cmV0dXJuIHNlbGYgdW5sZXNzIEBhY3RpdmVcblxuXHRcdEBjYW5jZWxsZWQgPSB5ZXNcblx0XHRAdXBkYXRlcysrXG5cblx0XHRpZiBAZ2VzdHVyZXNcblx0XHRcdGZvciBnIGluIEBnZXN0dXJlc1xuXHRcdFx0XHRnLm9udG91Y2hjYW5jZWwoc2VsZikgaWYgZzpvbnRvdWNoY2FuY2VsXG5cblx0XHR0YXJnZXQ/Lm9udG91Y2hjYW5jZWwoc2VsZilcblx0XHRzZWxmXG5cblx0IyMjXG5cdFRoZSBhYnNvbHV0ZSBkaXN0YW5jZSB0aGUgdG91Y2ggaGFzIG1vdmVkIGZyb20gc3RhcnRpbmcgcG9zaXRpb24gXG5cdEByZXR1cm4ge051bWJlcn1cblx0IyMjXG5cdGRlZiBkciBkbyBAZHJcblxuXHQjIyNcblx0VGhlIGRpc3RhbmNlIHRoZSB0b3VjaCBoYXMgbW92ZWQgaG9yaXpvbnRhbGx5XG5cdEByZXR1cm4ge051bWJlcn1cblx0IyMjXG5cdGRlZiBkeCBkbyBAeCAtIEB4MFxuXG5cdCMjI1xuXHRUaGUgZGlzdGFuY2UgdGhlIHRvdWNoIGhhcyBtb3ZlZCB2ZXJ0aWNhbGx5XG5cdEByZXR1cm4ge051bWJlcn1cblx0IyMjXG5cdGRlZiBkeSBkbyBAeSAtIEB5MFxuXG5cdCMjI1xuXHRJbml0aWFsIGhvcml6b250YWwgcG9zaXRpb24gb2YgdG91Y2hcblx0QHJldHVybiB7TnVtYmVyfVxuXHQjIyNcblx0ZGVmIHgwIGRvIEB4MFxuXG5cdCMjI1xuXHRJbml0aWFsIHZlcnRpY2FsIHBvc2l0aW9uIG9mIHRvdWNoXG5cdEByZXR1cm4ge051bWJlcn1cblx0IyMjXG5cdGRlZiB5MCBkbyBAeTBcblxuXHQjIyNcblx0SG9yaXpvbnRhbCBwb3NpdGlvbiBvZiB0b3VjaFxuXHRAcmV0dXJuIHtOdW1iZXJ9XG5cdCMjI1xuXHRkZWYgeCBkbyBAeFxuXG5cdCMjI1xuXHRWZXJ0aWNhbCBwb3NpdGlvbiBvZiB0b3VjaFxuXHRAcmV0dXJuIHtOdW1iZXJ9XG5cdCMjI1xuXHRkZWYgeSBkbyBAeVxuXG5cdCMjI1xuXHRIb3Jpem9udGFsIHBvc2l0aW9uIG9mIHRvdWNoIHJlbGF0aXZlIHRvIHRhcmdldFxuXHRAcmV0dXJuIHtOdW1iZXJ9XG5cdCMjI1xuXHRkZWYgdHggZG9cblx0XHRAdGFyZ2V0Qm94IHx8PSBAdGFyZ2V0LmRvbS5nZXRCb3VuZGluZ0NsaWVudFJlY3Rcblx0XHRAeCAtIEB0YXJnZXRCb3g6bGVmdFxuXG5cdCMjI1xuXHRWZXJ0aWNhbCBwb3NpdGlvbiBvZiB0b3VjaCByZWxhdGl2ZSB0byB0YXJnZXRcblx0QHJldHVybiB7TnVtYmVyfVxuXHQjIyNcblx0ZGVmIHR5XG5cdFx0QHRhcmdldEJveCB8fD0gQHRhcmdldC5kb20uZ2V0Qm91bmRpbmdDbGllbnRSZWN0XG5cdFx0QHkgLSBAdGFyZ2V0Qm94OnRvcFxuXG5cdCMjI1xuXHRCdXR0b24gcHJlc3NlZCBpbiB0aGlzIHRvdWNoLiBOYXRpdmUgdG91Y2hlcyBkZWZhdWx0cyB0byBsZWZ0LWNsaWNrICgwKVxuXHRAcmV0dXJuIHtOdW1iZXJ9XG5cdCMjI1xuXHRkZWYgYnV0dG9uIGRvIEBidXR0b24gIyBAcG9pbnRlciA/IEBwb2ludGVyLmJ1dHRvbiA6IDBcblxuXHRkZWYgc291cmNlVGFyZ2V0XG5cdFx0QHNvdXJjZVRhcmdldFxuXG5cbmNsYXNzIEltYmEuVG91Y2hHZXN0dXJlXG5cblx0cHJvcCBhY3RpdmUgZGVmYXVsdDogbm9cblxuXHRkZWYgb250b3VjaHN0YXJ0IGVcblx0XHRzZWxmXG5cblx0ZGVmIG9udG91Y2h1cGRhdGUgZVxuXHRcdHNlbGZcblxuXHRkZWYgb250b3VjaGVuZCBlXG5cdFx0c2VsZlxuXG5cbiMgQSBUb3VjaC1ldmVudCBpcyBjcmVhdGVkIG9uIG1vdXNlZG93biAoYWx3YXlzKVxuIyBhbmQgd2hpbGUgaXQgZXhpc3RzLCBtb3VzZW1vdmUgYW5kIG1vdXNldXAgd2lsbFxuIyBiZSBkZWxlZ2F0ZWQgdG8gdGhpcyBhY3RpdmUgZXZlbnQuXG5JbWJhLlBPSU5URVIgPSBJbWJhLlBvaW50ZXIubmV3XG5JbWJhLlBPSU5URVJTID0gW0ltYmEuUE9JTlRFUl1cblxuXG4jIHJlZ3VsYXIgZXZlbnQgc3R1ZmZcbkltYmEuS0VZTUFQID0ge1xuXHRcIjhcIjogJ2JhY2tzcGFjZSdcblx0XCI5XCI6ICd0YWInXG5cdFwiMTNcIjogJ2VudGVyJ1xuXHRcIjE2XCI6ICdzaGlmdCdcblx0XCIxN1wiOiAnY3RybCdcblx0XCIxOFwiOiAnYWx0J1xuXHRcIjE5XCI6ICdicmVhaydcblx0XCIyMFwiOiAnY2Fwcydcblx0XCIyN1wiOiAnZXNjJ1xuXHRcIjMyXCI6ICdzcGFjZSdcblx0XCIzNVwiOiAnZW5kJ1xuXHRcIjM2XCI6ICdob21lJ1xuXHRcIjM3XCI6ICdsYXJyJ1xuXHRcIjM4XCI6ICd1YXJyJ1xuXHRcIjM5XCI6ICdyYXJyJ1xuXHRcIjQwXCI6ICdkYXJyJ1xuXHRcIjQ1XCI6ICdpbnNlcnQnXG5cdFwiNDZcIjogJ2RlbGV0ZSdcblx0XCIxMDdcIjogJ3BsdXMnXG5cdFwiMTA2XCI6ICdtdWx0J1xuXHRcIjkxXCI6ICdtZXRhJ1xufVxuXG5JbWJhLkNIQVJNQVAgPSB7XG5cdFwiJVwiOiAnbW9kdWxvJ1xuXHRcIipcIjogJ211bHRpcGx5J1xuXHRcIitcIjogJ2FkZCdcblx0XCItXCI6ICdzdWInXG5cdFwiL1wiOiAnZGl2aWRlJ1xuXHRcIi5cIjogJ2RvdCdcbn1cblxuIyMjXG5JbWJhIGhhbmRsZXMgYWxsIGV2ZW50cyBpbiB0aGUgZG9tIHRocm91Z2ggYSBzaW5nbGUgbWFuYWdlcixcbmxpc3RlbmluZyBhdCB0aGUgcm9vdCBvZiB5b3VyIGRvY3VtZW50LiBJZiBJbWJhIGZpbmRzIGEgdGFnXG50aGF0IGxpc3RlbnMgdG8gYSBjZXJ0YWluIGV2ZW50LCB0aGUgZXZlbnQgd2lsbCBiZSB3cmFwcGVkIFxuaW4gYW4gYEltYmEuRXZlbnRgLCB3aGljaCBub3JtYWxpemVzIHNvbWUgb2YgdGhlIHF1aXJrcyBhbmQgXG5icm93c2VyIGRpZmZlcmVuY2VzLlxuXG5AaW5hbWUgZXZlbnRcbiMjI1xuY2xhc3MgSW1iYS5FdmVudFxuXG5cdCMjIyByZWZlcmVuY2UgdG8gdGhlIG5hdGl2ZSBldmVudCAjIyNcblx0cHJvcCBldmVudFxuXG5cdCMjIyByZWZlcmVuY2UgdG8gdGhlIG5hdGl2ZSBldmVudCAjIyNcblx0cHJvcCBwcmVmaXhcblxuXHRwcm9wIGRhdGFcblxuXHQjIyNcblx0c2hvdWxkIHJlbW92ZSB0aGlzIGFsbHRvZ2V0aGVyP1xuXHRAZGVwcmVjYXRlZFxuXHQjIyNcblx0cHJvcCBzb3VyY2VcblxuXHQjIyMgQSB7Qm9vbGVhbn0gaW5kaWNhdGluZyB3aGV0aGVyIHRoZSBldmVudCBidWJibGVzIHVwIG9yIG5vdCAjIyNcblx0cHJvcCBidWJibGUgdHlwZTogQm9vbGVhbiwgY2hhaW5hYmxlOiB5ZXNcblxuXHRkZWYgc2VsZi53cmFwIGVcblx0XHRzZWxmLm5ldyhlKVxuXHRcblx0ZGVmIGluaXRpYWxpemUgZVxuXHRcdGV2ZW50ID0gZVxuXHRcdGJ1YmJsZSA9IHllc1xuXG5cdGRlZiB0eXBlPSB0eXBlXG5cdFx0QHR5cGUgPSB0eXBlXG5cdFx0c2VsZlxuXG5cdCMjI1xuXHRAcmV0dXJuIHtTdHJpbmd9IFRoZSBuYW1lIG9mIHRoZSBldmVudCAoY2FzZS1pbnNlbnNpdGl2ZSlcblx0IyMjXG5cdGRlZiB0eXBlXG5cdFx0QHR5cGUgfHwgZXZlbnQ6dHlwZVxuXG5cdGRlZiBuYW1lXG5cdFx0QG5hbWUgfHw9IHR5cGUudG9Mb3dlckNhc2UucmVwbGFjZSgvXFw6L2csJycpXG5cblx0IyBtaW1jIGdldHNldFxuXHRkZWYgYnViYmxlIHZcblx0XHRpZiB2ICE9IHVuZGVmaW5lZFxuXHRcdFx0c2VsZi5idWJibGUgPSB2XG5cdFx0XHRyZXR1cm4gc2VsZlxuXHRcdHJldHVybiBAYnViYmxlXG5cblx0IyMjXG5cdFByZXZlbnRzIGZ1cnRoZXIgcHJvcGFnYXRpb24gb2YgdGhlIGN1cnJlbnQgZXZlbnQuXG5cdEByZXR1cm4ge3NlbGZ9XG5cdCMjI1xuXHRkZWYgaGFsdFxuXHRcdGJ1YmJsZSA9IG5vXG5cdFx0c2VsZlxuXG5cdCMjI1xuXHRDYW5jZWwgdGhlIGV2ZW50IChpZiBjYW5jZWxhYmxlKS4gSW4gdGhlIGNhc2Ugb2YgbmF0aXZlIGV2ZW50cyBpdFxuXHR3aWxsIGNhbGwgYHByZXZlbnREZWZhdWx0YCBvbiB0aGUgd3JhcHBlZCBldmVudCBvYmplY3QuXG5cdEByZXR1cm4ge3NlbGZ9XG5cdCMjI1xuXHRkZWYgY2FuY2VsXG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQgaWYgZXZlbnQ6cHJldmVudERlZmF1bHRcblx0XHRAY2FuY2VsID0geWVzXG5cdFx0c2VsZlxuXG5cdGRlZiBzaWxlbmNlXG5cdFx0QHNpbGVuY2VkID0geWVzXG5cdFx0c2VsZlxuXG5cdGRlZiBpc1NpbGVuY2VkXG5cdFx0ISFAc2lsZW5jZWRcblxuXHQjIyNcblx0SW5kaWNhdGVzIHdoZXRoZXIgb3Igbm90IGV2ZW50LmNhbmNlbCBoYXMgYmVlbiBjYWxsZWQuXG5cblx0QHJldHVybiB7Qm9vbGVhbn1cblx0IyMjXG5cdGRlZiBpc1ByZXZlbnRlZFxuXHRcdGV2ZW50IGFuZCBldmVudDpkZWZhdWx0UHJldmVudGVkIG9yIEBjYW5jZWxcblxuXHQjIyNcblx0QSByZWZlcmVuY2UgdG8gdGhlIGluaXRpYWwgdGFyZ2V0IG9mIHRoZSBldmVudC5cblx0IyMjXG5cdGRlZiB0YXJnZXRcblx0XHR0YWcoZXZlbnQ6X3RhcmdldCBvciBldmVudDp0YXJnZXQpXG5cblx0IyMjXG5cdEEgcmVmZXJlbmNlIHRvIHRoZSBvYmplY3QgcmVzcG9uZGluZyB0byB0aGUgZXZlbnQuXG5cdCMjI1xuXHRkZWYgcmVzcG9uZGVyXG5cdFx0QHJlc3BvbmRlclxuXG5cdCMjI1xuXHRSZWRpcmVjdCB0aGUgZXZlbnQgdG8gbmV3IHRhcmdldFxuXHQjIyNcblx0ZGVmIHJlZGlyZWN0IG5vZGVcblx0XHRAcmVkaXJlY3QgPSBub2RlXG5cdFx0c2VsZlxuXG5cdCMjI1xuXHRHZXQgdGhlIG5vcm1hbGl6ZWQgY2hhcmFjdGVyIGZvciBLZXlib2FyZEV2ZW50L1RleHRFdmVudFxuXHRAcmV0dXJuIHtTdHJpbmd9XG5cdCMjI1xuXHRkZWYga2V5Y2hhclxuXHRcdGlmIGV2ZW50IGlzYSBLZXlib2FyZEV2ZW50XG5cdFx0XHR2YXIga2kgPSBldmVudDprZXlJZGVudGlmaWVyXG5cdFx0XHR2YXIgc3ltID0gSW1iYS5LRVlNQVBbZXZlbnQ6a2V5Q29kZV1cblxuXHRcdFx0aWYgIXN5bSBhbmQga2kuc3Vic3RyKDAsMikgPT0gXCJVK1wiXG5cdFx0XHRcdHN5bSA9IFN0cmluZy5mcm9tQ2hhckNvZGUocGFyc2VJbnQoa2kuc3Vic3RyKDIpLCAxNikpXG5cdFx0XHRyZXR1cm4gc3ltXG5cblx0XHRlbGlmIGV2ZW50IGlzYSAod2luZG93LlRleHRFdmVudCBvciB3aW5kb3cuSW5wdXRFdmVudClcblx0XHRcdHJldHVybiBldmVudDpkYXRhXG5cblx0XHRyZXR1cm4gbnVsbFxuXG5cdCMjI1xuXHRAZGVwcmVjYXRlZFxuXHQjIyNcblx0ZGVmIGtleWNvbWJvXG5cdFx0cmV0dXJuIHVubGVzcyB2YXIgc3ltID0ga2V5Y2hhclxuXHRcdHN5bSA9IEltYmEuQ0hBUk1BUFtzeW1dIG9yIHN5bVxuXHRcdHZhciBjb21ibyA9IFtdLCBlID0gZXZlbnRcblx0XHRjb21iby5wdXNoKDpjdHJsKSBpZiBlOmN0cmxLZXlcblx0XHRjb21iby5wdXNoKDpzaGlmdCkgaWYgZTpzaGlmdEtleVxuXHRcdGNvbWJvLnB1c2goOmFsdCkgaWYgZTphbHRLZXlcblx0XHRjb21iby5wdXNoKDpjbWQpIGlmIGU6bWV0YUtleVxuXHRcdGNvbWJvLnB1c2goc3ltKVxuXHRcdGNvbWJvLmpvaW4oXCJfXCIpLnRvTG93ZXJDYXNlXG5cblxuXHRkZWYgcHJvY2Vzc1xuXHRcdHZhciBtZXRoID0gXCJvbntAcHJlZml4IG9yICcnfXtuYW1lfVwiXG5cdFx0dmFyIGFyZ3MgPSBudWxsXG5cdFx0dmFyIGRvbXRhcmdldCA9IGV2ZW50Ol90YXJnZXQgb3IgZXZlbnQ6dGFyZ2V0XHRcdFxuXHRcdCMgdmFyIG5vZGUgPSA8e2RvbXRhcmdldDpfcmVzcG9uZGVyIG9yIGRvbXRhcmdldH0+XG5cdFx0IyBuZWVkIHRvIGNsZWFuIHVwIGFuZCBkb2N1bWVudCB0aGlzIGJlaGF2aW91clxuXG5cdFx0dmFyIGRvbW5vZGUgPSBkb210YXJnZXQ6X3Jlc3BvbmRlciBvciBkb210YXJnZXRcblx0XHQjIEB0b2RvIG5lZWQgdG8gc3RvcCBpbmZpbml0ZSByZWRpcmVjdC1ydWxlcyBoZXJlXG5cblx0XHR3aGlsZSBkb21ub2RlXG5cdFx0XHRAcmVkaXJlY3QgPSBudWxsXG5cdFx0XHRpZiB2YXIgbm9kZSA9IHRhZyhkb21ub2RlKSAjIG5vdCBvbmx5IHRhZyBcblxuXHRcdFx0XHRpZiBub2RlW21ldGhdIGlzYSBTdHJpbmdcblx0XHRcdFx0XHQjIHNob3VsZCByZW1lbWJlciB0aGUgcmVjZWl2ZXIgb2YgdGhlIGV2ZW50XG5cdFx0XHRcdFx0bWV0aCA9IG5vZGVbbWV0aF1cblx0XHRcdFx0XHRjb250aW51ZSAjIHNob3VsZCBub3QgY29udGludWU/XG5cblx0XHRcdFx0aWYgbm9kZVttZXRoXSBpc2EgQXJyYXlcblx0XHRcdFx0XHRhcmdzID0gbm9kZVttZXRoXS5jb25jYXQobm9kZSlcblx0XHRcdFx0XHRtZXRoID0gYXJncy5zaGlmdFxuXHRcdFx0XHRcdGNvbnRpbnVlICMgc2hvdWxkIG5vdCBjb250aW51ZT9cblxuXHRcdFx0XHRpZiBub2RlW21ldGhdIGlzYSBGdW5jdGlvblxuXHRcdFx0XHRcdEByZXNwb25kZXIgfHw9IG5vZGVcblx0XHRcdFx0XHQjIHNob3VsZCBhdXRvc3RvcCBidWJibGUgaGVyZT9cblx0XHRcdFx0XHRhcmdzID8gbm9kZVttZXRoXS5hcHBseShub2RlLGFyZ3MpIDogbm9kZVttZXRoXShzZWxmLGRhdGEpXG5cdFx0XHRcdFx0XG5cdFx0XHQjIGFkZCBub2RlLm5leHRFdmVudFJlc3BvbmRlciBhcyBhIHNlcGFyYXRlIG1ldGhvZCBoZXJlP1xuXHRcdFx0dW5sZXNzIGJ1YmJsZSBhbmQgZG9tbm9kZSA9IChAcmVkaXJlY3Qgb3IgKG5vZGUgPyBub2RlLnBhcmVudCA6IGRvbW5vZGU6cGFyZW50Tm9kZSkpXG5cdFx0XHRcdGJyZWFrXG5cblx0XHRwcm9jZXNzZWRcblx0XHRyZXR1cm4gc2VsZlxuXG5cblx0ZGVmIHByb2Nlc3NlZFxuXHRcdEltYmEuZW1pdChJbWJhLCdldmVudCcsW3NlbGZdKSB1bmxlc3MgQHNpbGVuY2VkXG5cdFx0c2VsZlxuXG5cdCMjI1xuXHRSZXR1cm4gdGhlIHgvbGVmdCBjb29yZGluYXRlIG9mIHRoZSBtb3VzZSAvIHBvaW50ZXIgZm9yIHRoaXMgZXZlbnRcblx0QHJldHVybiB7TnVtYmVyfSB4IGNvb3JkaW5hdGUgb2YgbW91c2UgLyBwb2ludGVyIGZvciBldmVudFxuXHQjIyNcblx0ZGVmIHggZG8gZXZlbnQ6eFxuXG5cdCMjI1xuXHRSZXR1cm4gdGhlIHkvdG9wIGNvb3JkaW5hdGUgb2YgdGhlIG1vdXNlIC8gcG9pbnRlciBmb3IgdGhpcyBldmVudFxuXHRAcmV0dXJuIHtOdW1iZXJ9IHkgY29vcmRpbmF0ZSBvZiBtb3VzZSAvIHBvaW50ZXIgZm9yIGV2ZW50XG5cdCMjI1xuXHRkZWYgeSBkbyBldmVudDp5XG5cblx0IyMjXG5cdFJldHVybnMgYSBOdW1iZXIgcmVwcmVzZW50aW5nIGEgc3lzdGVtIGFuZCBpbXBsZW1lbnRhdGlvblxuXHRkZXBlbmRlbnQgbnVtZXJpYyBjb2RlIGlkZW50aWZ5aW5nIHRoZSB1bm1vZGlmaWVkIHZhbHVlIG9mIHRoZVxuXHRwcmVzc2VkIGtleTsgdGhpcyBpcyB1c3VhbGx5IHRoZSBzYW1lIGFzIGtleUNvZGUuXG5cblx0Rm9yIG1vdXNlLWV2ZW50cywgdGhlIHJldHVybmVkIHZhbHVlIGluZGljYXRlcyB3aGljaCBidXR0b24gd2FzXG5cdHByZXNzZWQgb24gdGhlIG1vdXNlIHRvIHRyaWdnZXIgdGhlIGV2ZW50LlxuXG5cdEByZXR1cm4ge051bWJlcn1cblx0IyMjXG5cdGRlZiB3aGljaCBkbyBldmVudDp3aGljaFxuXG5cbiMjI1xuXG5NYW5hZ2VyIGZvciBsaXN0ZW5pbmcgdG8gYW5kIGRlbGVnYXRpbmcgZXZlbnRzIGluIEltYmEuIEEgc2luZ2xlIGluc3RhbmNlXG5pcyBhbHdheXMgY3JlYXRlZCBieSBJbWJhIChhcyBgSW1iYS5FdmVudHNgKSwgd2hpY2ggaGFuZGxlcyBhbmQgZGVsZWdhdGVzIGFsbFxuZXZlbnRzIGF0IHRoZSB2ZXJ5IHJvb3Qgb2YgdGhlIGRvY3VtZW50LiBJbWJhIGRvZXMgbm90IGNhcHR1cmUgYWxsIGV2ZW50c1xuYnkgZGVmYXVsdCwgc28gaWYgeW91IHdhbnQgdG8gbWFrZSBzdXJlIGV4b3RpYyBvciBjdXN0b20gRE9NRXZlbnRzIGFyZSBkZWxlZ2F0ZWRcbmluIEltYmEgeW91IHdpbGwgbmVlZCB0byByZWdpc3RlciB0aGVtIGluIGBJbWJhLkV2ZW50cy5yZWdpc3RlcihteUN1c3RvbUV2ZW50TmFtZSlgXG5cbkBpbmFtZSBtYW5hZ2VyXG5cbiMjI1xuY2xhc3MgSW1iYS5FdmVudE1hbmFnZXJcblxuXHRwcm9wIHJvb3Rcblx0cHJvcCBjb3VudFxuXHRwcm9wIGVuYWJsZWQgZGVmYXVsdDogbm8sIHdhdGNoOiB5ZXNcblx0cHJvcCBsaXN0ZW5lcnNcblx0cHJvcCBkZWxlZ2F0b3JzXG5cdHByb3AgZGVsZWdhdG9yXG5cblx0ZGVmIGVuYWJsZWQtZGlkLXNldCBib29sXG5cdFx0Ym9vbCA/IG9uZW5hYmxlIDogb25kaXNhYmxlXG5cdFx0c2VsZlxuXG5cdGRlZiBpbml0aWFsaXplIG5vZGUsIGV2ZW50czogW11cblx0XHRyb290ID0gbm9kZVxuXHRcdGNvdW50ID0gMFxuXHRcdGxpc3RlbmVycyA9IFtdXG5cdFx0ZGVsZWdhdG9ycyA9IHt9XG5cdFx0ZGVsZWdhdG9yID0gZG8gfGV8IFxuXHRcdFx0IyBjb25zb2xlLmxvZyBcImRlbGVnYXRpbmcgZXZlbnQ/ISB7ZX1cIlxuXHRcdFx0ZGVsZWdhdGUoZSlcblx0XHRcdHJldHVybiB0cnVlXG5cblx0XHRmb3IgZXZlbnQgaW4gZXZlbnRzXG5cdFx0XHRyZWdpc3RlcihldmVudClcblxuXHRcdHJldHVybiBzZWxmXG5cblx0IyMjXG5cblx0VGVsbCB0aGUgY3VycmVudCBFdmVudE1hbmFnZXIgdG8gaW50ZXJjZXB0IGFuZCBoYW5kbGUgZXZlbnQgb2YgYSBjZXJ0YWluIG5hbWUuXG5cdEJ5IGRlZmF1bHQsIEltYmEuRXZlbnRzIHdpbGwgcmVnaXN0ZXIgaW50ZXJjZXB0b3JzIGZvcjogKmtleWRvd24qLCAqa2V5dXAqLCBcblx0KmtleXByZXNzKiwgKnRleHRJbnB1dCosICppbnB1dCosICpjaGFuZ2UqLCAqc3VibWl0KiwgKmZvY3VzaW4qLCAqZm9jdXNvdXQqLCBcblx0KmJsdXIqLCAqY29udGV4dG1lbnUqLCAqZGJsY2xpY2sqLCAqbW91c2V3aGVlbCosICp3aGVlbCpcblxuXHQjIyNcblx0ZGVmIHJlZ2lzdGVyIG5hbWUsIGhhbmRsZXIgPSB0cnVlXG5cdFx0aWYgbmFtZSBpc2EgQXJyYXlcblx0XHRcdHJlZ2lzdGVyKHYsaGFuZGxlcikgZm9yIHYgaW4gbmFtZVxuXHRcdFx0cmV0dXJuIHNlbGZcblxuXHRcdHJldHVybiBzZWxmIGlmIGRlbGVnYXRvcnNbbmFtZV1cblx0XHQjIGNvbnNvbGUubG9nKFwicmVnaXN0ZXIgZm9yIGV2ZW50IHtuYW1lfVwiKVxuXHRcdHZhciBmbiA9IGRlbGVnYXRvcnNbbmFtZV0gPSBoYW5kbGVyIGlzYSBGdW5jdGlvbiA/IGhhbmRsZXIgOiBkZWxlZ2F0b3Jcblx0XHRyb290LmFkZEV2ZW50TGlzdGVuZXIobmFtZSxmbix5ZXMpIGlmIGVuYWJsZWRcblxuXHRkZWYgbGlzdGVuIG5hbWUsIGhhbmRsZXIsIGNhcHR1cmUgPSB5ZXNcblx0XHRsaXN0ZW5lcnMucHVzaChbbmFtZSxoYW5kbGVyLGNhcHR1cmVdKVxuXHRcdHJvb3QuYWRkRXZlbnRMaXN0ZW5lcihuYW1lLGhhbmRsZXIsY2FwdHVyZSkgaWYgZW5hYmxlZFxuXHRcdHNlbGZcblxuXHRkZWYgZGVsZWdhdGUgZVxuXHRcdGNvdW50ICs9IDFcblx0XHR2YXIgZXZlbnQgPSBJbWJhLkV2ZW50LndyYXAoZSlcblx0XHRldmVudC5wcm9jZXNzXG5cdFx0c2VsZlxuXG5cdGRlZiBjcmVhdGUgdHlwZSwgdGFyZ2V0LCBkYXRhOiBudWxsLCBzb3VyY2U6IG51bGxcblx0XHR2YXIgZXZlbnQgPSBJbWJhLkV2ZW50LndyYXAgdHlwZTogdHlwZSwgdGFyZ2V0OiB0YXJnZXRcblx0XHRldmVudC5kYXRhID0gZGF0YSBpZiBkYXRhXG5cdFx0ZXZlbnQuc291cmNlID0gc291cmNlIGlmIHNvdXJjZVxuXHRcdGV2ZW50XG5cblx0IyB1c2UgY3JlYXRlIGluc3RlYWQ/XG5cdGRlZiB0cmlnZ2VyXG5cdFx0Y3JlYXRlKCphcmd1bWVudHMpLnByb2Nlc3NcblxuXHRkZWYgb25lbmFibGVcblx0XHRmb3Igb3duIG5hbWUsaGFuZGxlciBvZiBkZWxlZ2F0b3JzXG5cdFx0XHRyb290LmFkZEV2ZW50TGlzdGVuZXIobmFtZSxoYW5kbGVyLHllcylcblxuXHRcdGZvciBpdGVtIGluIGxpc3RlbmVyc1xuXHRcdFx0cm9vdC5hZGRFdmVudExpc3RlbmVyKGl0ZW1bMF0saXRlbVsxXSxpdGVtWzJdKVxuXHRcdHNlbGZcblxuXHRkZWYgb25kaXNhYmxlXG5cdFx0Zm9yIG93biBuYW1lLGhhbmRsZXIgb2YgZGVsZWdhdG9yc1xuXHRcdFx0cm9vdC5yZW1vdmVFdmVudExpc3RlbmVyKG5hbWUsaGFuZGxlcix5ZXMpXG5cblx0XHRmb3IgaXRlbSBpbiBsaXN0ZW5lcnNcblx0XHRcdHJvb3QucmVtb3ZlRXZlbnRMaXN0ZW5lcihpdGVtWzBdLGl0ZW1bMV0saXRlbVsyXSlcblx0XHRzZWxmXG5cdFx0XG5cbkVEID0gSW1iYS5FdmVudHMgPSBJbWJhLkV2ZW50TWFuYWdlci5uZXcoZG9jdW1lbnQsIGV2ZW50czogW1xuXHQ6a2V5ZG93biw6a2V5dXAsOmtleXByZXNzLDp0ZXh0SW5wdXQsOmlucHV0LDpjaGFuZ2UsOnN1Ym1pdCxcblx0OmZvY3VzaW4sOmZvY3Vzb3V0LDpibHVyLDpjb250ZXh0bWVudSw6ZGJsY2xpY2ssXG5cdDptb3VzZXdoZWVsLDp3aGVlbCw6c2Nyb2xsXG5dKVxuXG4jIHNob3VsZCBzZXQgdGhlc2UgdXAgaW5zaWRlIHRoZSBJbWJhLkV2ZW50cyBvYmplY3QgaXRzZWxmXG4jIHNvIHRoYXQgd2UgY2FuIGhhdmUgZGlmZmVyZW50IEV2ZW50TWFuYWdlciBmb3IgZGlmZmVyZW50IHJvb3RzXG5cbmlmIGhhc1RvdWNoRXZlbnRzXG5cdEltYmEuRXZlbnRzLmxpc3Rlbig6dG91Y2hzdGFydCkgZG8gfGV8XG5cdFx0SW1iYS5FdmVudHMuY291bnQrK1xuXHRcdEltYmEuVG91Y2gub250b3VjaHN0YXJ0KGUpXG5cblx0SW1iYS5FdmVudHMubGlzdGVuKDp0b3VjaG1vdmUpIGRvIHxlfFxuXHRcdEltYmEuRXZlbnRzLmNvdW50Kytcblx0XHRJbWJhLlRvdWNoLm9udG91Y2htb3ZlKGUpXG5cblx0SW1iYS5FdmVudHMubGlzdGVuKDp0b3VjaGVuZCkgZG8gfGV8XG5cdFx0SW1iYS5FdmVudHMuY291bnQrK1xuXHRcdEltYmEuVG91Y2gub250b3VjaGVuZChlKVxuXG5cdEltYmEuRXZlbnRzLmxpc3Rlbig6dG91Y2hjYW5jZWwpIGRvIHxlfFxuXHRcdEltYmEuRXZlbnRzLmNvdW50Kytcblx0XHRJbWJhLlRvdWNoLm9udG91Y2hjYW5jZWwoZSlcblxuSW1iYS5FdmVudHMucmVnaXN0ZXIoOmNsaWNrKSBkbyB8ZXxcblx0IyBPbmx5IGZvciBtYWluIG1vdXNlYnV0dG9uLCBubz9cblx0aWYgKGU6dGltZVN0YW1wIC0gbGFzdE5hdGl2ZVRvdWNoVGltZVN0YW1wKSA+IGxhc3ROYXRpdmVUb3VjaFRpbWVvdXRcblx0XHR2YXIgdGFwID0gSW1iYS5FdmVudC5uZXcoZSlcblx0XHR0YXAudHlwZSA9ICd0YXAnXG5cdFx0dGFwLnByb2Nlc3Ncblx0XHRpZiB0YXAuQHJlc3BvbmRlclxuXHRcdFx0cmV0dXJuIGUucHJldmVudERlZmF1bHRcblx0IyBkZWxlZ2F0ZSB0aGUgcmVhbCBjbGljayBldmVudFxuXHRJbWJhLkV2ZW50cy5kZWxlZ2F0ZShlKVxuXG5JbWJhLkV2ZW50cy5saXN0ZW4oOm1vdXNlZG93bikgZG8gfGV8XG5cdGlmIChlOnRpbWVTdGFtcCAtIGxhc3ROYXRpdmVUb3VjaFRpbWVTdGFtcCkgPiBsYXN0TmF0aXZlVG91Y2hUaW1lb3V0XG5cdFx0SW1iYS5QT0lOVEVSLnVwZGF0ZShlKS5wcm9jZXNzIGlmIEltYmEuUE9JTlRFUlxuXG4jIEltYmEuRXZlbnRzLmxpc3Rlbig6bW91c2Vtb3ZlKSBkbyB8ZXxcbiMgXHQjIGNvbnNvbGUubG9nICdtb3VzZW1vdmUnLGU6dGltZVN0YW1wXG4jIFx0aWYgKGU6dGltZVN0YW1wIC0gbGFzdE5hdGl2ZVRvdWNoVGltZVN0YW1wKSA+IGxhc3ROYXRpdmVUb3VjaFRpbWVvdXRcbiMgXHRcdEltYmEuUE9JTlRFUi51cGRhdGUoZSkucHJvY2VzcyBpZiBJbWJhLlBPSU5URVIgIyAucHJvY2VzcyBpZiB0b3VjaCAjIHNob3VsZCBub3QgaGFwcGVuPyBXZSBwcm9jZXNzIHRocm91Z2ggXG5cbkltYmEuRXZlbnRzLmxpc3Rlbig6bW91c2V1cCkgZG8gfGV8XG5cdCMgY29uc29sZS5sb2cgJ21vdXNldXAnLGU6dGltZVN0YW1wXG5cdGlmIChlOnRpbWVTdGFtcCAtIGxhc3ROYXRpdmVUb3VjaFRpbWVTdGFtcCkgPiBsYXN0TmF0aXZlVG91Y2hUaW1lb3V0XG5cdFx0SW1iYS5QT0lOVEVSLnVwZGF0ZShlKS5wcm9jZXNzIGlmIEltYmEuUE9JTlRFUlxuXG5cbkltYmEuRXZlbnRzLnJlZ2lzdGVyKFs6bW91c2Vkb3duLDptb3VzZXVwXSlcbkltYmEuRXZlbnRzLmVuYWJsZWQgPSB5ZXNcblxuXG4vKiogV0VCUEFDSyBGT09URVIgKipcbiAqKiBzcmMvaW1iYS9kb20uZXZlbnRzLmltYmFcbiAqKi8iLCJ2YXIgSW1iYVRhZyA9IEltYmEuVEFHUzplbGVtZW50XG5cbmRlZiByZW1vdmVOZXN0ZWQgcm9vdCwgbm9kZSwgY2FyZXRcblx0IyBpZiBub2RlL25vZGVzIGlzYSBTdHJpbmdcblx0IyBcdHdlIG5lZWQgdG8gdXNlIHRoZSBjYXJldCB0byByZW1vdmUgZWxlbWVudHNcblx0IyBcdGZvciBub3cgd2Ugd2lsbCBzaW1wbHkgbm90IHN1cHBvcnQgdGhpc1xuXHRpZiBub2RlIGlzYSBJbWJhVGFnXG5cdFx0cm9vdC5yZW1vdmVDaGlsZChub2RlKVxuXHRlbGlmIG5vZGUgaXNhIEFycmF5XG5cdFx0cmVtb3ZlTmVzdGVkKHJvb3QsbWVtYmVyLGNhcmV0KSBmb3IgbWVtYmVyIGluIG5vZGVcblx0ZWxzZVxuXHRcdCMgd2hhdCBpZiB0aGlzIGlzIG5vdCBudWxsPyE/IT9cblx0XHQjIHRha2UgYSBjaGFuY2UgYW5kIHJlbW92ZSBhIHRleHQtZWxlbWVudG5nXG5cdFx0bGV0IG5leHQgPSBjYXJldCA/IGNhcmV0Om5leHRTaWJsaW5nIDogcm9vdC5AZG9tOmZpcnN0Q2hpbGRcblx0XHRpZiBuZXh0IGlzYSBUZXh0IGFuZCBuZXh0OnRleHRDb250ZW50ID09IG5vZGVcblx0XHRcdHJvb3QucmVtb3ZlQ2hpbGQobmV4dClcblx0XHRlbHNlXG5cdFx0XHR0aHJvdyAnY2Fubm90IHJlbW92ZSBzdHJpbmcnXG5cblx0cmV0dXJuIGNhcmV0XG5cbmRlZiBhcHBlbmROZXN0ZWQgcm9vdCwgbm9kZVxuXHRpZiBub2RlIGlzYSBJbWJhVGFnXG5cdFx0cm9vdC5hcHBlbmRDaGlsZChub2RlKVxuXG5cdGVsaWYgbm9kZSBpc2EgQXJyYXlcblx0XHRhcHBlbmROZXN0ZWQocm9vdCxtZW1iZXIpIGZvciBtZW1iZXIgaW4gbm9kZVxuXG5cdGVsaWYgbm9kZSAhPSBudWxsIGFuZCBub2RlICE9PSBmYWxzZVxuXHRcdHJvb3QuYXBwZW5kQ2hpbGQgSW1iYS5kb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShub2RlKVxuXG5cdHJldHVyblxuXG5cbiMgaW5zZXJ0IG5vZGVzIGJlZm9yZSBhIGNlcnRhaW4gbm9kZVxuIyBkb2VzIG5vdCBuZWVkIHRvIHJldHVybiBhbnkgdGFpbCwgYXMgYmVmb3JlXG4jIHdpbGwgc3RpbGwgYmUgY29ycmVjdCB0aGVyZVxuIyBiZWZvcmUgbXVzdCBiZSBhbiBhY3R1YWwgZG9tbm9kZVxuZGVmIGluc2VydE5lc3RlZEJlZm9yZSByb290LCBub2RlLCBiZWZvcmVcblx0aWYgbm9kZSBpc2EgSW1iYVRhZ1xuXHRcdHJvb3QuaW5zZXJ0QmVmb3JlKG5vZGUsYmVmb3JlKVxuXHRlbGlmIG5vZGUgaXNhIEFycmF5XG5cdFx0aW5zZXJ0TmVzdGVkQmVmb3JlKHJvb3QsbWVtYmVyLGJlZm9yZSkgZm9yIG1lbWJlciBpbiBub2RlXG5cdGVsaWYgbm9kZSAhPSBudWxsIGFuZCBub2RlICE9PSBmYWxzZVxuXHRcdHJvb3QuaW5zZXJ0QmVmb3JlKEltYmEuZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUobm9kZSksYmVmb3JlKVxuXG5cdHJldHVybiBiZWZvcmVcblxuIyBhZnRlciBtdXN0IGJlIGFuIGFjdHVhbCBkb21ub2RlXG5kZWYgaW5zZXJ0TmVzdGVkQWZ0ZXIgcm9vdCwgbm9kZSwgYWZ0ZXJcblx0dmFyIGJlZm9yZSA9IGFmdGVyID8gYWZ0ZXI6bmV4dFNpYmxpbmcgOiByb290LkBkb206Zmlyc3RDaGlsZFxuXG5cdGlmIGJlZm9yZVxuXHRcdGluc2VydE5lc3RlZEJlZm9yZShyb290LG5vZGUsYmVmb3JlKVxuXHRcdHJldHVybiBiZWZvcmU6cHJldmlvdXNTaWJsaW5nXG5cdGVsc2Vcblx0XHRhcHBlbmROZXN0ZWQocm9vdCxub2RlKVxuXHRcdHJldHVybiByb290LkBkb206bGFzdENoaWxkXG5cbmRlZiByZWNvbmNpbGVDb2xsZWN0aW9uQ2hhbmdlcyByb290LCBuZXcsIG9sZCwgY2FyZXRcblxuXHR2YXIgbmV3TGVuID0gbmV3Omxlbmd0aFxuXHR2YXIgbGFzdE5ldyA9IG5ld1tuZXdMZW4gLSAxXVxuXG5cdCMgVGhpcyByZS1vcmRlciBhbGdvcml0aG0gaXMgYmFzZWQgb24gdGhlIGZvbGxvd2luZyBwcmluY2lwbGU6XG5cdCMgXG5cdCMgV2UgYnVpbGQgYSBcImNoYWluXCIgd2hpY2ggc2hvd3Mgd2hpY2ggaXRlbXMgYXJlIGFscmVhZHkgc29ydGVkLlxuXHQjIElmIHdlJ3JlIGdvaW5nIGZyb20gWzEsIDIsIDNdIC0+IFsyLCAxLCAzXSwgdGhlIHRyZWUgbG9va3MgbGlrZTpcblx0I1xuXHQjIFx0MyAtPiAgMCAoaWR4KVxuXHQjIFx0MiAtPiAtMSAoaWR4KVxuXHQjIFx0MSAtPiAtMSAoaWR4KVxuXHQjXG5cdCMgVGhpcyB0ZWxscyB1cyB0aGF0IHdlIGhhdmUgdHdvIGNoYWlucyBvZiBvcmRlcmVkIGl0ZW1zOlxuXHQjIFxuXHQjIFx0KDEsIDMpIGFuZCAoMilcblx0IyBcblx0IyBUaGUgb3B0aW1hbCByZS1vcmRlcmluZyB0aGVuIGJlY29tZXMgdHdvIGtlZXAgdGhlIGxvbmdlc3QgY2hhaW4gaW50YWN0LFxuXHQjIGFuZCBtb3ZlIGFsbCB0aGUgb3RoZXIgaXRlbXMuXG5cblx0dmFyIG5ld1Bvc2l0aW9uID0gW11cblxuXHQjIFRoZSB0cmVlL2dyYXBoIGl0c2VsZlxuXHR2YXIgcHJldkNoYWluID0gW11cblx0IyBUaGUgbGVuZ3RoIG9mIHRoZSBjaGFpblxuXHR2YXIgbGVuZ3RoQ2hhaW4gPSBbXVxuXG5cdCMgS2VlcCB0cmFjayBvZiB0aGUgbG9uZ2VzdCBjaGFpblxuXHR2YXIgbWF4Q2hhaW5MZW5ndGggPSAwXG5cdHZhciBtYXhDaGFpbkVuZCA9IDBcblxuXHRmb3Igbm9kZSwgaWR4IGluIG9sZFxuXHRcdHZhciBuZXdQb3MgPSBuZXcuaW5kZXhPZihub2RlKVxuXHRcdG5ld1Bvc2l0aW9uLnB1c2gobmV3UG9zKVxuXG5cdFx0aWYgbmV3UG9zID09IC0xXG5cdFx0XHRyb290LnJlbW92ZUNoaWxkKG5vZGUpXG5cdFx0XHRwcmV2Q2hhaW4ucHVzaCgtMSlcblx0XHRcdGxlbmd0aENoYWluLnB1c2goLTEpXG5cdFx0XHRjb250aW51ZVxuXG5cdFx0dmFyIHByZXZJZHggPSBuZXdQb3NpdGlvbjpsZW5ndGggLSAyXG5cblx0XHQjIEJ1aWxkIHRoZSBjaGFpbjpcblx0XHR3aGlsZSBwcmV2SWR4ID49IDBcblx0XHRcdGlmIG5ld1Bvc2l0aW9uW3ByZXZJZHhdID09IC0xXG5cdFx0XHRcdHByZXZJZHgtLVxuXHRcdFx0ZWxpZiBuZXdQb3MgPiBuZXdQb3NpdGlvbltwcmV2SWR4XVxuXHRcdFx0XHQjIFlheSwgd2UncmUgYmlnZ2VyIHRoYW4gdGhlIHByZXZpb3VzIVxuXHRcdFx0XHRicmVha1xuXHRcdFx0ZWxzZVxuXHRcdFx0XHQjIE5vcGUsIGxldCdzIHdhbGsgYmFjayB0aGUgY2hhaW5cblx0XHRcdFx0cHJldklkeCA9IHByZXZDaGFpbltwcmV2SWR4XVxuXG5cdFx0cHJldkNoYWluLnB1c2gocHJldklkeClcblxuXHRcdHZhciBjdXJyTGVuZ3RoID0gKHByZXZJZHggPT0gLTEpID8gMCA6IGxlbmd0aENoYWluW3ByZXZJZHhdKzFcblxuXHRcdGlmIGN1cnJMZW5ndGggPiBtYXhDaGFpbkxlbmd0aFxuXHRcdFx0bWF4Q2hhaW5MZW5ndGggPSBjdXJyTGVuZ3RoXG5cdFx0XHRtYXhDaGFpbkVuZCA9IGlkeFxuXG5cdFx0bGVuZ3RoQ2hhaW4ucHVzaChjdXJyTGVuZ3RoKVxuXG5cdHZhciBzdGlja3lOb2RlcyA9IFtdXG5cblx0IyBOb3cgd2UgY2FuIHdhbGsgdGhlIGxvbmdlc3QgY2hhaW4gYmFja3dhcmRzIGFuZCBtYXJrIHRoZW0gYXMgXCJzdGlja3lcIixcblx0IyB3aGljaCBpbXBsaWVzIHRoYXQgdGhleSBzaG91bGQgbm90IGJlIG1vdmVkXG5cdHZhciBjdXJzb3IgPSBuZXdQb3NpdGlvbjpsZW5ndGggLSAxXG5cdHdoaWxlIGN1cnNvciA+PSAwXG5cdFx0aWYgY3Vyc29yID09IG1heENoYWluRW5kIGFuZCBuZXdQb3NpdGlvbltjdXJzb3JdICE9IC0xXG5cdFx0XHRzdGlja3lOb2Rlc1tuZXdQb3NpdGlvbltjdXJzb3JdXSA9IHRydWVcblx0XHRcdG1heENoYWluRW5kID0gcHJldkNoYWluW21heENoYWluRW5kXVxuXHRcdFxuXHRcdGN1cnNvciAtPSAxXG5cblx0IyBBbmQgbGV0J3MgaXRlcmF0ZSBmb3J3YXJkLCBidXQgb25seSBtb3ZlIG5vbi1zdGlja3kgbm9kZXNcblx0Zm9yIG5vZGUsIGlkeCBpbiBuZXdcblx0XHRpZiAhc3RpY2t5Tm9kZXNbaWR4XVxuXHRcdFx0dmFyIGFmdGVyID0gbmV3W2lkeCAtIDFdXG5cdFx0XHRpbnNlcnROZXN0ZWRBZnRlcihyb290LCBub2RlLCAoYWZ0ZXIgYW5kIGFmdGVyLkBkb20pIG9yIGNhcmV0KVxuXG5cdCMgc2hvdWxkIHRydXN0IHRoYXQgdGhlIGxhc3QgaXRlbSBpbiBuZXcgbGlzdCBpcyB0aGUgY2FyZXRcblx0cmV0dXJuIGxhc3ROZXcgYW5kIGxhc3ROZXcuQGRvbSBvciBjYXJldFxuXG5cbiMgZXhwZWN0cyBhIGZsYXQgbm9uLXNwYXJzZSBhcnJheSBvZiBub2RlcyBpbiBib3RoIG5ldyBhbmQgb2xkLCBhbHdheXNcbmRlZiByZWNvbmNpbGVDb2xsZWN0aW9uIHJvb3QsIG5ldywgb2xkLCBjYXJldFxuXHR2YXIgayA9IG5ldzpsZW5ndGhcblx0dmFyIGkgPSBrXG5cdHZhciBsYXN0ID0gbmV3W2sgLSAxXVxuXG5cblx0aWYgayA9PSBvbGQ6bGVuZ3RoIGFuZCBuZXdbMF0gPT09IG9sZFswXVxuXHRcdCMgcnVubmluZyB0aHJvdWdoIHRvIGNvbXBhcmVcblx0XHR3aGlsZSBpLS1cblx0XHRcdGJyZWFrIGlmIG5ld1tpXSAhPT0gb2xkW2ldXG5cblx0aWYgaSA9PSAtMVxuXHRcdHJldHVybiBsYXN0IGFuZCBsYXN0LkBkb20gb3IgY2FyZXRcblx0ZWxzZVxuXHRcdHJldHVybiByZWNvbmNpbGVDb2xsZWN0aW9uQ2hhbmdlcyhyb290LG5ldyxvbGQsY2FyZXQpXG5cbiMgdGhlIGdlbmVyYWwgcmVjb25jaWxlciB0aGF0IHJlc3BlY3RzIGNvbmRpdGlvbnMgZXRjXG4jIGNhcmV0IGlzIHRoZSBjdXJyZW50IG5vZGUgd2Ugd2FudCB0byBpbnNlcnQgdGhpbmdzIGFmdGVyXG5kZWYgcmVjb25jaWxlTmVzdGVkIHJvb3QsIG5ldywgb2xkLCBjYXJldFxuXG5cdCMgaWYgbmV3ID09IG51bGwgb3IgbmV3ID09PSBmYWxzZSBvciBuZXcgPT09IHRydWVcblx0IyBcdGlmIG5ldyA9PT0gb2xkXG5cdCMgXHRcdHJldHVybiBjYXJldFxuXHQjIFx0aWYgb2xkICYmIG5ldyAhPSBvbGRcblx0IyBcdFx0cmVtb3ZlTmVzdGVkKHJvb3Qsb2xkLGNhcmV0KSBpZiBvbGRcblx0IyBcblx0IyBcdHJldHVybiBjYXJldFxuXG5cdCMgdmFyIHNraXBuZXcgPSBuZXcgPT0gbnVsbCBvciBuZXcgPT09IGZhbHNlIG9yIG5ldyA9PT0gdHJ1ZVxuXHR2YXIgbmV3SXNOdWxsID0gbmV3ID09IG51bGwgb3IgbmV3ID09PSBmYWxzZVxuXHR2YXIgb2xkSXNOdWxsID0gb2xkID09IG51bGwgb3Igb2xkID09PSBmYWxzZVxuXG5cblx0aWYgbmV3ID09PSBvbGRcblx0XHQjIHJlbWVtYmVyIHRoYXQgdGhlIGNhcmV0IG11c3QgYmUgYW4gYWN0dWFsIGRvbSBlbGVtZW50XG5cdFx0IyB3ZSBzaG91bGQgaW5zdGVhZCBtb3ZlIHRoZSBhY3R1YWwgY2FyZXQ/IC0gdHJ1c3Rcblx0XHRpZiBuZXdJc051bGxcblx0XHRcdHJldHVybiBjYXJldFxuXHRcdGVsaWYgbmV3IGFuZCBuZXcuQGRvbVxuXHRcdFx0cmV0dXJuIG5ldy5AZG9tXG5cdFx0ZWxzZVxuXHRcdFx0cmV0dXJuIGNhcmV0ID8gY2FyZXQ6bmV4dFNpYmxpbmcgOiByb290LkBkb206Zmlyc3RDaGlsZFxuXG5cdGVsaWYgbmV3IGlzYSBBcnJheVxuXHRcdGlmIG9sZCBpc2EgQXJyYXlcblx0XHRcdGlmIG5ldzpzdGF0aWMgb3Igb2xkOnN0YXRpY1xuXHRcdFx0XHQjIGlmIHRoZSBzdGF0aWMgaXMgbm90IG5lc3RlZCAtIHdlIGNvdWxkIGdldCBhIGhpbnQgZnJvbSBjb21waWxlclxuXHRcdFx0XHQjIGFuZCBqdXN0IHNraXAgaXRcblx0XHRcdFx0aWYgbmV3OnN0YXRpYyA9PSBvbGQ6c3RhdGljXG5cdFx0XHRcdFx0Zm9yIGl0ZW0saSBpbiBuZXdcblx0XHRcdFx0XHRcdCMgdGhpcyBpcyB3aGVyZSB3ZSBjb3VsZCBkbyB0aGUgdHJpcGxlIGVxdWFsIGRpcmVjdGx5XG5cdFx0XHRcdFx0XHRjYXJldCA9IHJlY29uY2lsZU5lc3RlZChyb290LGl0ZW0sb2xkW2ldLGNhcmV0KVxuXHRcdFx0XHRcdHJldHVybiBjYXJldFxuXHRcdFx0XHRlbHNlXG5cdFx0XHRcdFx0cmVtb3ZlTmVzdGVkKHJvb3Qsb2xkLGNhcmV0KVxuXHRcdFx0XHRcdFxuXHRcdFx0XHQjIGlmIHRoZXkgYXJlIG5vdCB0aGUgc2FtZSB3ZSBjb250aW51ZSB0aHJvdWdoIHRvIHRoZSBkZWZhdWx0XG5cdFx0XHRlbHNlXG5cdFx0XHRcdHJldHVybiByZWNvbmNpbGVDb2xsZWN0aW9uKHJvb3QsbmV3LG9sZCxjYXJldClcblxuXHRcdGVsaWYgb2xkIGlzYSBJbWJhVGFnXG5cdFx0XHRyb290LnJlbW92ZUNoaWxkKG9sZClcblx0XHRlbGlmICFvbGRJc051bGxcblx0XHRcdCMgb2xkIHdhcyBhIHN0cmluZy1saWtlIG9iamVjdD9cblx0XHRcdHJvb3QucmVtb3ZlQ2hpbGQoY2FyZXQgPyBjYXJldDpuZXh0U2libGluZyA6IHJvb3QuQGRvbTpmaXJzdENoaWxkKVx0XHRcdFxuXG5cdFx0cmV0dXJuIGluc2VydE5lc3RlZEFmdGVyKHJvb3QsbmV3LGNhcmV0KVxuXHRcdCMgcmVtb3ZlIG9sZFxuXG5cdGVsaWYgbmV3IGlzYSBJbWJhVGFnXG5cdFx0cmVtb3ZlTmVzdGVkKHJvb3Qsb2xkLGNhcmV0KSB1bmxlc3Mgb2xkSXNOdWxsXG5cdFx0aW5zZXJ0TmVzdGVkQWZ0ZXIocm9vdCxuZXcsY2FyZXQpXG5cdFx0cmV0dXJuIG5ld1xuXG5cdGVsaWYgbmV3SXNOdWxsXG5cdFx0cmVtb3ZlTmVzdGVkKHJvb3Qsb2xkLGNhcmV0KSB1bmxlc3Mgb2xkSXNOdWxsXG5cdFx0cmV0dXJuIGNhcmV0XG5cdGVsc2Vcblx0XHQjIGlmIG9sZCBkaWQgbm90IGV4aXN0IHdlIG5lZWQgdG8gYWRkIGEgbmV3IGRpcmVjdGx5XG5cdFx0bGV0IG5leHROb2RlXG5cdFx0IyBpZiBvbGQgd2FzIGFycmF5IG9yIGltYmF0YWcgd2UgbmVlZCB0byByZW1vdmUgaXQgYW5kIHRoZW4gYWRkXG5cdFx0aWYgb2xkIGlzYSBBcnJheVxuXHRcdFx0cmVtb3ZlTmVzdGVkKHJvb3Qsb2xkLGNhcmV0KVxuXHRcdGVsaWYgb2xkIGlzYSBJbWJhVGFnXG5cdFx0XHRyb290LnJlbW92ZUNoaWxkKG9sZClcblx0XHRlbGlmICFvbGRJc051bGxcblx0XHRcdCMgLi4uXG5cdFx0XHRuZXh0Tm9kZSA9IGNhcmV0ID8gY2FyZXQ6bmV4dFNpYmxpbmcgOiByb290LkBkb206Zmlyc3RDaGlsZFxuXHRcdFx0aWYgbmV4dE5vZGUgaXNhIFRleHQgYW5kIG5leHROb2RlOnRleHRDb250ZW50ICE9IG5ld1xuXHRcdFx0XHRuZXh0Tm9kZTp0ZXh0Q29udGVudCA9IG5ld1xuXHRcdFx0XHRyZXR1cm4gbmV4dE5vZGVcblxuXHRcdCMgbm93IGFkZCB0aGUgdGV4dG5vZGVcblx0XHRyZXR1cm4gaW5zZXJ0TmVzdGVkQWZ0ZXIocm9vdCxuZXcsY2FyZXQpXG5cblxuZXh0ZW5kIHRhZyBodG1sZWxlbWVudFxuXHRcblx0ZGVmIHNldENoaWxkcmVuIG5ldywgdHlwXG5cdFx0dmFyIG9sZCA9IEBjaGlsZHJlblxuXHRcdCMgdmFyIGlzQXJyYXkgPSBub2RlcyBpc2EgQXJyYXlcblx0XHRpZiBuZXcgPT09IG9sZFxuXHRcdFx0cmV0dXJuIHNlbGZcblxuXHRcdGlmICFvbGRcblx0XHRcdGVtcHR5XG5cdFx0XHRhcHBlbmROZXN0ZWQoc2VsZixuZXcpXG5cblx0XHRlbGlmIHR5cCA9PSAyXG5cdFx0XHRyZXR1cm4gc2VsZlxuXG5cdFx0ZWxpZiB0eXAgPT0gMVxuXHRcdFx0IyBoZXJlIHdlIF9rbm93IF90aGF0IGl0IGlzIGFuIGFycmF5IHdpdGggdGhlIHNhbWUgc2hhcGVcblx0XHRcdCMgZXZlcnkgdGltZVxuXHRcdFx0bGV0IGNhcmV0ID0gbnVsbFxuXHRcdFx0Zm9yIGl0ZW0saSBpbiBuZXdcblx0XHRcdFx0IyBwcmV2ID0gb2xkW2ldXG5cdFx0XHRcdGNhcmV0ID0gcmVjb25jaWxlTmVzdGVkKHNlbGYsaXRlbSxvbGRbaV0sY2FyZXQpXG5cblx0XHRlbGlmIHR5cCA9PSAzXG5cdFx0XHQjIHRoaXMgaXMgcG9zc2libHkgZnVsbHkgZHluYW1pYy4gSXQgb2Z0ZW4gaXNcblx0XHRcdCMgYnV0IHRoZSBvbGQgb3IgbmV3IGNvdWxkIGJlIHN0YXRpYyB3aGlsZSB0aGUgb3RoZXIgaXMgbm90XG5cdFx0XHQjIHRoaXMgaXMgbm90IGhhbmRsZWQgbm93XG5cdFx0XHQjIHdoYXQgaWYgaXQgd2FzIHByZXZpb3VzbHkgYSBzdGF0aWMgYXJyYXk/IGVkZ2VjYXNlIC0gYnV0IG11c3Qgd29ya1xuXHRcdFx0aWYgbmV3IGlzYSBJbWJhVGFnXG5cdFx0XHRcdGVtcHR5XG5cdFx0XHRcdGFwcGVuZENoaWxkKG5ldylcblxuXHRcdFx0IyBjaGVjayBpZiBvbGQgYW5kIG5ldyBpc2EgYXJyYXlcblx0XHRcdGVsaWYgbmV3IGlzYSBBcnJheVxuXHRcdFx0XHRpZiBvbGQgaXNhIEFycmF5XG5cdFx0XHRcdFx0IyBpcyB0aGlzIG5vdCB0aGUgc2FtZSBhcyBzZXR0aW5nIHN0YXRpY0NoaWxkcmVuIG5vdyBidXQgd2l0aCB0aGVcblx0XHRcdFx0XHRyZWNvbmNpbGVDb2xsZWN0aW9uKHNlbGYsbmV3LG9sZCxudWxsKVxuXHRcdFx0XHRlbHNlXG5cdFx0XHRcdFx0ZW1wdHlcblx0XHRcdFx0XHRhcHBlbmROZXN0ZWQoc2VsZixuZXcpXG5cdFx0XHRcdFxuXHRcdFx0ZWxzZVxuXHRcdFx0XHR0ZXh0ID0gbmV3XG5cdFx0XHRcdHJldHVybiBzZWxmXG5cblx0XHRlbGlmIG5ldyBpc2EgQXJyYXkgYW5kIG9sZCBpc2EgQXJyYXlcblx0XHRcdHJlY29uY2lsZUNvbGxlY3Rpb24oc2VsZixuZXcsb2xkLG51bGwpXG5cdFx0ZWxzZVxuXHRcdFx0ZW1wdHlcblx0XHRcdGFwcGVuZE5lc3RlZChzZWxmLG5ldylcblxuXHRcdEBjaGlsZHJlbiA9IG5ld1xuXHRcdHJldHVybiBzZWxmXG5cblxuXHQjIG9ubHkgZXZlciBjYWxsZWQgd2l0aCBhcnJheSBhcyBhcmd1bWVudFxuXHRkZWYgc2V0U3RhdGljQ2hpbGRyZW4gbmV3XG5cdFx0dmFyIG9sZCA9IEBjaGlsZHJlblxuXG5cdFx0bGV0IGNhcmV0ID0gbnVsbFxuXHRcdGZvciBpdGVtLGkgaW4gbmV3XG5cdFx0XHQjIHByZXYgPSBvbGRbaV1cblx0XHRcdGNhcmV0ID0gcmVjb25jaWxlTmVzdGVkKHNlbGYsaXRlbSxvbGRbaV0sY2FyZXQpXG5cblx0XHRAY2hpbGRyZW4gPSBuZXdcblx0XHRyZXR1cm4gc2VsZlxuXG5cdGRlZiBjb250ZW50XG5cdFx0QGNvbnRlbnQgb3IgY2hpbGRyZW4udG9BcnJheVxuXG5cdGRlZiB0ZXh0PSB0ZXh0XG5cdFx0aWYgdGV4dCAhPSBAY2hpbGRyZW5cblx0XHRcdEBjaGlsZHJlbiA9IHRleHRcblx0XHRcdGRvbTp0ZXh0Q29udGVudCA9IHRleHQgPT0gbnVsbCBvciB0ZXh0ID09PSBmYWxzZSA/ICcnIDogdGV4dFxuXHRcdHNlbGZcblxuXG4vKiogV0VCUEFDSyBGT09URVIgKipcbiAqKiBzcmMvaW1iYS9kb20uc3RhdGljLmltYmFcbiAqKi8iLCJcbiMjI1xuVGhlIHNwZWNpYWwgc3ludGF4IGZvciBzZWxlY3RvcnMgaW4gSW1iYSBjcmVhdGVzIEltYmEuU2VsZWN0b3Jcbmluc3RhbmNlcy5cbiMjI1xuY2xhc3MgSW1iYS5TZWxlY3RvclxuXHRcblx0ZGVmIHNlbGYub25lIHNlbCwgc2NvcGVcblx0XHR2YXIgZWwgPSAoc2NvcGUgfHwgSW1iYS5kb2N1bWVudCkucXVlcnlTZWxlY3RvcihzZWwpXG5cdFx0ZWwgJiYgdGFnKGVsKSB8fCBudWxsXG5cblx0ZGVmIHNlbGYuYWxsIHNlbCwgc2NvcGVcblx0XHRJbWJhLlNlbGVjdG9yLm5ldyhzZWwsc2NvcGUpXG5cblx0cHJvcCBxdWVyeVxuXG5cdGRlZiBpbml0aWFsaXplIHNlbCwgc2NvcGUsIG5vZGVzXG5cblx0XHRAcXVlcnkgPSBzZWwgaXNhIEltYmEuU2VsZWN0b3IgPyBzZWwucXVlcnkgOiBzZWxcblx0XHRAY29udGV4dCA9IHNjb3BlXG5cblx0XHRpZiBub2Rlc1xuXHRcdFx0QG5vZGVzID0gKHRhZyhub2RlKSBmb3Igbm9kZSBpbiBub2RlcylcblxuXHRcdEBsYXp5ID0gIW5vZGVzXG5cdFx0cmV0dXJuIHNlbGZcblxuXHRkZWYgcmVsb2FkXG5cdFx0QG5vZGVzID0gbnVsbFxuXHRcdHNlbGZcblxuXHRkZWYgc2NvcGVcblx0XHRyZXR1cm4gQHNjb3BlIGlmIEBzY29wZVxuXHRcdHJldHVybiBJbWJhLmRvY3VtZW50IHVubGVzcyB2YXIgY3R4ID0gQGNvbnRleHRcblx0XHRAc2NvcGUgPSBjdHg6dG9TY29wZSA/IGN0eC50b1Njb3BlIDogY3R4XG5cblx0IyMjXG5cdEByZXR1cm5zIHtJbWJhLlRhZ30gZmlyc3Qgbm9kZSBtYXRjaGluZyB0aGlzIHNlbGVjdG9yXG5cdCMjI1xuXHRkZWYgZmlyc3Rcblx0XHRpZiBAbGF6eSB0aGVuIHRhZyhAZmlyc3QgfHw9IHNjb3BlLnF1ZXJ5U2VsZWN0b3IocXVlcnkpKVxuXHRcdGVsc2Ugbm9kZXNbMF1cblxuXHQjIyNcblx0QHJldHVybnMge0ltYmEuVGFnfSBsYXN0IG5vZGUgbWF0Y2hpbmcgdGhpcyBzZWxlY3RvclxuXHQjIyNcblx0ZGVmIGxhc3Rcblx0XHRub2Rlc1tAbm9kZXM6bGVuZ3RoIC0gMV1cblxuXHQjIyNcblx0QHJldHVybnMgW0ltYmEuVGFnXSBhbGwgbm9kZXMgbWF0Y2hpbmcgdGhpcyBzZWxlY3RvclxuXHQjIyNcblx0ZGVmIG5vZGVzXG5cdFx0cmV0dXJuIEBub2RlcyBpZiBAbm9kZXNcblx0XHR2YXIgaXRlbXMgPSBzY29wZS5xdWVyeVNlbGVjdG9yQWxsKHF1ZXJ5KVxuXHRcdEBub2RlcyA9ICh0YWcobm9kZSkgZm9yIG5vZGUgaW4gaXRlbXMpXG5cdFx0QGxhenkgPSBub1xuXHRcdEBub2Rlc1xuXHRcblx0IyMjXG5cdFRoZSBudW1iZXIgb2Ygbm9kZXMgbWF0Y2hpbmcgdGhpcyBzZWxlY3RvclxuXHQjIyNcblx0ZGVmIGNvdW50IGRvIG5vZGVzOmxlbmd0aFxuXG5cdGRlZiBsZW4gZG8gbm9kZXM6bGVuZ3RoXG5cblx0IyMjXG5cdEB0b2RvIEFkZCBzdXBwb3J0IGZvciBibG9jayBvciBzZWxlY3Rvcj9cblx0IyMjXG5cdGRlZiBzb21lXG5cdFx0Y291bnQgPj0gMVxuXHRcblx0IyMjXG5cdEdldCBub2RlIGF0IGluZGV4XG5cdCMjI1xuXHRkZWYgYXQgaWR4XG5cdFx0bm9kZXNbaWR4XVxuXG5cdCMjI1xuXHRMb29wIHRocm91Z2ggbm9kZXNcblx0IyMjXG5cdGRlZiBmb3JFYWNoIGJsb2NrXG5cdFx0bm9kZXMuZm9yRWFjaChibG9jaylcblx0XHRzZWxmXG5cblx0IyMjXG5cdE1hcCBub2Rlc1xuXHQjIyNcblx0ZGVmIG1hcCBibG9ja1xuXHRcdG5vZGVzLm1hcChibG9jaylcblxuXHQjIyNcblx0UmV0dXJucyBhIHBsYWluIGFycmF5IGNvbnRhaW5pbmcgbm9kZXMuIEltcGxpY2l0bHkgY2FsbGVkXG5cdHdoZW4gaXRlcmF0aW5nIG92ZXIgYSBzZWxlY3RvciBpbiBJbWJhIGAobm9kZSBmb3Igbm9kZSBpbiAkKHNlbGVjdG9yKSlgXG5cdCMjI1xuXHRkZWYgdG9BcnJheVxuXHRcdG5vZGVzXG5cdFxuXHQjIEdldCB0aGUgZmlyc3QgZWxlbWVudCB0aGF0IG1hdGNoZXMgdGhlIHNlbGVjdG9yLCBcblx0IyBiZWdpbm5pbmcgYXQgdGhlIGN1cnJlbnQgZWxlbWVudCBhbmQgcHJvZ3Jlc3NpbmcgdXAgdGhyb3VnaCB0aGUgRE9NIHRyZWVcblx0ZGVmIGNsb3Nlc3Qgc2VsXG5cdFx0IyBzZWVtcyBzdHJhbmdlIHRoYXQgd2UgYWx0ZXIgdGhpcyBzZWxlY3Rvcj9cblx0XHRAbm9kZXMgPSBtYXAgZG8gfG5vZGV8IG5vZGUuY2xvc2VzdChzZWwpXG5cdFx0c2VsZlxuXG5cdCMgR2V0IHRoZSBzaWJsaW5ncyBvZiBlYWNoIGVsZW1lbnQgaW4gdGhlIHNldCBvZiBtYXRjaGVkIGVsZW1lbnRzLCBcblx0IyBvcHRpb25hbGx5IGZpbHRlcmVkIGJ5IGEgc2VsZWN0b3IuXG5cdCMgVE9ETyByZW1vdmUgZHVwbGljYXRlcz9cblx0ZGVmIHNpYmxpbmdzIHNlbFxuXHRcdEBub2RlcyA9IG1hcCBkbyB8bm9kZXwgbm9kZS5zaWJsaW5ncyhzZWwpXG5cdFx0c2VsZlxuXG5cdCMgR2V0IHRoZSBkZXNjZW5kYW50cyBvZiBlYWNoIGVsZW1lbnQgaW4gdGhlIGN1cnJlbnQgc2V0IG9mIG1hdGNoZWQgXG5cdCMgZWxlbWVudHMsIGZpbHRlcmVkIGJ5IGEgc2VsZWN0b3IuXG5cdGRlZiBmaW5kIHNlbFxuXHRcdEBub2RlcyA9IF9fcXVlcnlfXyhzZWwucXVlcnksIG5vZGVzKVxuXHRcdHNlbGZcblxuXHRkZWYgcmVqZWN0IGJsa1xuXHRcdGZpbHRlcihibGssbm8pXG5cblx0IyMjXG5cdEZpbHRlciB0aGUgbm9kZXMgaW4gc2VsZWN0b3IgYnkgYSBmdW5jdGlvbiBvciBvdGhlciBzZWxlY3RvclxuXHQjIyNcblx0ZGVmIGZpbHRlciBibGssIGJvb2wgPSB5ZXNcblx0XHR2YXIgZm4gPSBibGsgaXNhIEZ1bmN0aW9uIGFuZCBibGsgb3IgKHxufCBuLm1hdGNoZXMoYmxrKSApXG5cdFx0dmFyIGFyeSA9IG5vZGVzLmZpbHRlcih8bnwgZm4obikgPT0gYm9vbClcblx0XHQjIGlmIHdlIHdhbnQgdG8gcmV0dXJuIGEgbmV3IHNlbGVjdG9yIGZvciB0aGlzLCB3ZSBzaG91bGQgZG8gdGhhdCBmb3Jcblx0XHQjIG90aGVycyBhcyB3ZWxsXG5cdFx0SW1iYS5TZWxlY3Rvci5uZXcoXCJcIiwgQHNjb3BlLCBhcnkpXG5cblx0ZGVmIF9fcXVlcnlfXyBxdWVyeSwgY29udGV4dHNcblx0XHR2YXIgbm9kZXMgPSBbXVxuXHRcdHZhciBpID0gMFxuXHRcdHZhciBsID0gY29udGV4dHM6bGVuZ3RoXG5cblx0XHR3aGlsZSBpIDwgbFxuXHRcdFx0bm9kZXMucHVzaCgqY29udGV4dHNbaSsrXS5xdWVyeVNlbGVjdG9yQWxsKHF1ZXJ5KSlcblx0XHRyZXR1cm4gbm9kZXNcblxuXHRkZWYgX19tYXRjaGVzX19cblx0XHRyZXR1cm4geWVzXG5cblx0IyMjXG5cdEFkZCBzcGVjaWZpZWQgZmxhZyB0byBhbGwgbm9kZXMgaW4gc2VsZWN0b3Jcblx0IyMjXG5cdGRlZiBmbGFnIGZsYWdcblx0XHRmb3JFYWNoIGRvIHxufCBuLmZsYWcoZmxhZylcblxuXHQjIyNcblx0UmVtb3ZlIHNwZWNpZmllZCBmbGFnIGZyb20gYWxsIG5vZGVzIGluIHNlbGVjdG9yXG5cdCMjI1xuXHRkZWYgdW5mbGFnIGZsYWdcblx0XHRmb3JFYWNoIGRvIHxufCBuLnVuZmxhZyhmbGFnKVxuXG5cbiMgZGVmIEltYmEucXVlcnlTZWxlY3RvckFsbFxucSQgPSBkbyB8c2VsLHNjb3BlfCBJbWJhLlNlbGVjdG9yLm5ldyhzZWwsIHNjb3BlKVxuXG4jIGRlZiBJbWJhLlNlbGVjdG9yLm9uZVxucSQkID0gZG8gfHNlbCxzY29wZXwgXG5cdHZhciBlbCA9IChzY29wZSB8fCBJbWJhLmRvY3VtZW50KS5xdWVyeVNlbGVjdG9yKHNlbClcblx0ZWwgJiYgdGFnKGVsKSB8fCBuaWxcblxuXG4jIGV4dGVuZGluZyB0YWdzIHdpdGggcXVlcnktbWV0aG9kc1xuIyBtdXN0IGJlIGEgYmV0dGVyIHdheSB0byByZW9wZW4gY2xhc3Nlc1xuZXh0ZW5kIHRhZyBlbGVtZW50XG5cdGRlZiBxdWVyeVNlbGVjdG9yQWxsIHEgZG8gQGRvbS5xdWVyeVNlbGVjdG9yQWxsIHFcblx0ZGVmIHF1ZXJ5U2VsZWN0b3IgcSBkbyBAZG9tLnF1ZXJ5U2VsZWN0b3IgcVxuXG5cdCMgc2hvdWxkIGJlIG1vdmVkIHRvIEltYmEuVGFnIGluc3RlYWQ/XG5cdCMgb3Igd2Ugc2hvdWxkIGltcGxlbWVudCBhbGwgb2YgdGhlbSBoZXJlXG5cdGRlZiBmaW5kIHNlbCBkbyBJbWJhLlNlbGVjdG9yLm5ldyhzZWwsc2VsZilcblxuXG5cblxuLyoqIFdFQlBBQ0sgRk9PVEVSICoqXG4gKiogc3JjL2ltYmEvc2VsZWN0b3IuaW1iYVxuICoqLyJdLCJzb3VyY2VSb290IjoiIn0=