Vai al contenuto
LF Lomazzi Federico

Home/Software/JAVASCRIPT

JAVASCRIPT

Questo gioco è tornato otto anni dopo, e non l'ho più scritto io.

Vecchi giochi, nuove competenze

Lomazzi Federico MIT index-98e7f.txt · 146 KB 1 riga

Nel 2018 avevo scritto per mio figlio un piccolo gioco educativo in JavaScript usando Phaser, impiegandoci tre o quattro serate. Otto anni dopo lui lo ha ripreso ed in una frazione di quel tempo ne ha costruito una versione enormemente più ricca usando l'AI come esecutore tecnico. La parte interessante non è che l'AI sappia programmare, ma che il collo di bottiglia si sia spostato dal codice alla capacità di progettare, verificare e correggere.

Provala qui

Nessuna installazione: l’applicazione è quella vera, in esecuzione dentro questa pagina. L’icona in alto a destra la porta a tutto schermo.

Nel 2018 avevo messo insieme un giochino per mio figlio in tre, forse quattro dopocena, una di quelle idee vagamente pedagogiche che vengono ai genitori quando i figli vanno alle elementari: una navicella, degli asteroidi da abbattere, numeri ed operazioni infilati dentro al gioco con la speranza abbastanza trasparente di fargli ripassare qualcosa senza fargli sembrare che stesse facendo i compiti. Lo avevo scritto in JavaScript puro appoggiandomi a Phaser, che in quel periodo era grossomodo una delle scelte quasi obbligate se volevate realizzare un gioco 2D nel browser senza reinventarvi da soli ciclo di rendering, sprite, input e collisioni. Funzionava. Non era bello, non aveva nessuna pretesa particolare, ma funzionava ed ha fatto il suo mestiere, poi come succede a moltissimi piccoli programmi domestici è sparito dentro una chiavetta USB e lì è rimasto per anni.

Otto anni dopo mio figlio lo ha ripreso in mano ed è qui che la storia ha cominciato ad interessarmi davvero, perché non riguarda soltanto quel gioco ma secondo me riguarda praticamente tutti quelli che scrivono codice per mestiere. Non ha semplicemente chiesto ad un'AI "fammi un gioco di asteroidi" aspettando che da una frase uscisse per miracolo un prodotto finito, perché se avete mai provato una richiesta del genere saprete certamente cosa succede: arriva una demo, magari anche simpatica, ma quasi sempre mediocre e soprattutto lontanissima da quello che avevate realmente in testa. Lui ha fatto una cosa diversa, ha saputo INSTRADARE il lavoro, decidere cosa voleva ottenere, descrivere il comportamento invece di dettare l'implementazione ed individuare i problemi mentre giocava. Quando, per esempio, trascinando la navicella questa sparava contemporaneamente finendo per colpire a caso anche i bonus negativi, non ha chiesto semplicemente di "sistemare il touch", ha descritto esattamente il comportamento osservato e preteso che venisse eliminata la causa. Sembra una differenza piccola, ma è praticamente il mestiere di un capo progetto tecnico: dire cosa deve succedere, riconoscere quando non succede ed impedire che una toppa nasconda il problema invece di risolverlo.

Il risultato è un gioco che rispetto al mio del 2018 sembra provenire da un altro pianeta, con una colonna sonora, effetti, un abisso cosmico in parallasse, ombre, particelle, esplosioni, due livelli bonus matematici ed una quantità di dettagli che io nelle mie quattro serate non avrei nemmeno cominciato ad implementare. Ma il vecchio programmatore che è in me si è dovuto ricredere soprattutto osservando quello che NON c'è. Non c'è Phaser, non c'è React, non c'è un bundler, non c'è package.json, non c'è la solita foresta di node_modules e non esiste una struttura di progetto costruita per sostenere un'architettura che questo programma semplicemente non necessita. C'è sostanzialmente un documento HTML di poco più di duemilaseicento righe con markup, CSS e JavaScript, qualche asset esterno indispensabile ed un punto di ingresso che si apre con un doppio clic anche da locale o da una chiavetta. Una banalità che oggi sembra quasi rivoluzionaria.

Sotto tutto questo l'impianto è quello vecchissimo, semplice ed ancora imbattibile del game loop, ovvero requestAnimationFrame() che richiama l'aggiornamento dello stato, quindi update(dt), poi il rendering con render(dt) ed infine ricomincia. Nessuna architettura con un nome importante, nessun livello di astrazione costruito perché "si fa così", lo stato del mondo è dentro una manciata di array normalissimi che contengono asteroidi, proiettili, scintille, detriti, fumo ed onde d'urto e ad ogni fotogramma il programma arriva ad aggiornare ciò che si muove, eliminare ciò che non serve più e disegnare quello che deve comparire sul <canvas>. Tutto qui. Ed è proprio questa semplicità che mi piace, perché il codice non cerca di dimostrare quanto sia bravo chi lo ha scritto, cerca soltanto di FAR GIRARE IL GIOCO.

Le parti interessanti arrivano quando si guarda come sono stati risolti i dettagli. Il principio usato praticamente ovunque è uno dei più vecchi dell'informatica grafica, ovvero PRE-CALCOLA QUELLO CHE NON CAMBIA E CALCOLA AD OGNI FOTOGRAMMA SOLTANTO QUELLO CHE SI MUOVE. L'abisso cosmico del fondale, per esempio, non è una gigantesca scena ridisegnata continuamente da zero ma una pila di otto piani a profondità differente con nebulose, polveri, pianeti lontani, relitti sfocati, stelle ed infine un pulviscolo in primo piano che passa davanti alla navicella; i piani continui vengono preparati una volta su canvas fuori schermo e poi fatti scorrere copiandoli con pochissime chiamate a drawImage, quindi il costo per fotogramma resta praticamente costante e non aumenta perché avete deciso di mettere altre cento stelle sullo sfondo. È una di quelle cose che quando la vedete funzionare sembrano ovvie, ma sono proprio le cose ovvie fatte bene a fare la differenza fra un programma che regge ed uno che comincia ad arrancare appena gli aggiungete qualcosa.

Poi ci sono le ombre, ed anche qui la soluzione è quasi irritante per quanto è semplice. Gli oggetti che stanno sul piano di gioco proiettano un'ombra sul fondo dell'abisso seguendo una direzione divergente dal centro dello schermo, quindi basta ricavare un vettore, allungarlo in funzione della posizione e disegnare la sagoma traslata. Tre righe di trigonometria, per così dire, e la scena che prima appariva piatta improvvisamente acquista una profondità che il mio vecchio giochino non aveva nemmeno lontanamente. E poi particelle, fumo, detriti, esplosioni, parallasse ed altri piccoli accorgimenti dei quali, guardando il risultato, mi viene soltanto da dire CHAPEAU, non perché siano invenzioni rivoluzionarie prese una per una ma perché qualcuno ha saputo vedere che mancavano, chiederle, provarle ed eliminare quelle che non funzionavano.

Ed è qui che arriva la parte che secondo me conta veramente. Nel 2018 io avevo bisogno di Phaser perché scrivere personalmente il ciclo di rendering, la gestione degli oggetti, le collisioni, gli input ed il resto mi sarebbe costato più delle tre o quattro serate che avevo a disposizione, quindi il framework era una soluzione perfettamente razionale. Oggi quel codice può essere prodotto direttamente in una frazione del tempo e questo rende nuovamente conveniente scrivere proprio quelle piccole infrastrutture che per anni abbiamo delegato alle librerie. Non significa che i framework non servano più, sarebbe una conclusione abbastanza sciocca, significa che È CAMBIATO IL COSTO DEL CODICE e quindi alcune decisioni architetturali che prima erano economicamente ovvie oggi meritano almeno di essere ricalcolate.

Se una libreria complessa mi evita settimane di lavoro continua ad essere un affare, se invece porto dentro migliaia di funzioni, dipendenze, build system ed astrazioni soltanto per risparmiarmi duecento righe che un'AI può produrre, modificare e testare mentre io descrivo il comportamento che voglio, allora il conto è diventato diverso. La quantità di codice non è nemmeno il punto, perché duemilaseicento righe scritte direttamente possono essere molto più semplici da distribuire di trecento righe che dipendono da un ecosistema intero; quello che conta è quanta complessità dobbiamo capire, mantenere ed attraversare quando qualcosa non funziona.

E naturalmente l'AI sbaglia, anzi proprio questo progetto secondo me dimostra perché l'idea del "programmare senza sapere nulla" è raccontata male. Quando la navicella spara mentre viene trascinata dovete ACCORGERVI che quel comportamento è sbagliato, capire in quale situazione compare, distinguerlo da un problema grafico ed essere abbastanza precisi da far correggere la causa. Quando il parallasse sembra finto dovete riconoscere che la velocità relativa dei piani non restituisce profondità, quando un'esplosione costa troppo dovete capire che qualcosa viene ricostruito ad ogni frame senza motivo, quando la collisione produce un effetto assurdo dovete riuscire almeno a localizzare logicamente il problema. La capacità richiesta si sta quindi spostando dal ricordare la sintassi della riga giusta al SAPER RICONOSCERE QUALE RIGA È SBAGLIATA E PERCHÉ, che poi è sempre stata la parte difficile della programmazione ed è anche quella che non si impara leggendo soltanto manuali.

Mio figlio questa capacità non credo l'abbia imparata da me, o almeno non principalmente. Probabilmente gliel'hanno insegnata molto di più le ore passate a giocare, osservare interfacce, capire perché un gioco risponde bene ed un altro male, smontare mentalmente le regole dei videogiochi degli altri e riconoscere immediatamente quando qualcosa "non torna". È una competenza strana perché fino a pochi anni fa sembrava accessoria alla programmazione, mentre con l'AI rischia di diventare una delle competenze CENTRALI: l'esecutore può scrivere molto velocemente, ma qualcuno deve continuare a sapere che cosa vale la pena scrivere e soprattutto quando quello che è stato scritto è sbagliato.

Alla fine quel piccolo gioco educativo del 2018 ha fatto esattamente il suo dovere, soltanto che la lezione non era quella che pensavo di avergli messo dentro. Io avevo costruito una navicella che sparava agli asteroidi per insegnargli qualcosa di matematica, otto anni dopo lui ha preso la stessa idea e senza quasi toccare direttamente il mestiere che avevo imparato io ha finito per mostrarmi dove sta andando il nostro mestiere: meno tempo passato a produrre meccanicamente codice e molto più tempo a capire, progettare, provare e correggere, USANDO L'AI PER SCRIVERE QUELLO CHE ABBIAMO DAVVERO CAPITO DI VOLERE!

Il codice

index-98e7f.txt · JAVASCRIPT · 1 riga · MIT

<script>document.write(decodeURIComponent(escape(atob("PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9Iml0Ij4KPGhlYWQ+CjxtZXRhIGNoYXJzZXQ9InV0Zi04Ij4KPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCxpbml0aWFsLXNjYWxlPTEsbWF4aW11bS1zY2FsZT0xLHVzZXItc2NhbGFibGU9bm8sdmlld3BvcnQtZml0PWNvdmVyIj4KPG1ldGEgbmFtZT0idGhlbWUtY29sb3IiIGNvbnRlbnQ9IiMwNTA2MGQiPgo8dGl0bGU+QVNURVJPSUQgUlVOTkVSIOKAlCBkZW1vPC90aXRsZT4KPHN0eWxlPgovKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KICAgVE9LRU5TCiAgID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqLwo6cm9vdHsKICAtLXZvaWQ6IzA1MDYwZDsKICAtLWRlZXA6IzBiMTAyMDsKICAtLWlvbjojNDZlNmZmOwogIC0tYW1iZXI6I2ZmYjAyMDsKICAtLXBsYXNtYTojZmYyZTZiOwogIC0tYm9uZTojZThmMGZmOwogIC0tbW9ubzp1aS1tb25vc3BhY2UsIlNGIE1vbm8iLE1lbmxvLENvbnNvbGFzLCJSb2JvdG8gTW9ubyIsbW9ub3NwYWNlOwogIC0tcGFkOm1heCgxNHB4LGVudihzYWZlLWFyZWEtaW5zZXQtdG9wKSkgbWF4KDE0cHgsZW52KHNhZmUtYXJlYS1pbnNldC1yaWdodCkpIG1heCgxNHB4LGVudihzYWZlLWFyZWEtaW5zZXQtYm90dG9tKSkgbWF4KDE0cHgsZW52KHNhZmUtYXJlYS1pbnNldC1sZWZ0KSk7Cn0KKnttYXJnaW46MDtwYWRkaW5nOjA7Ym94LXNpemluZzpib3JkZXItYm94fQpodG1sLGJvZHl7aGVpZ2h0OjEwMCU7b3ZlcmZsb3c6aGlkZGVuO2JhY2tncm91bmQ6dmFyKC0tdm9pZCk7Y29sb3I6dmFyKC0tYm9uZSk7Zm9udC1mYW1pbHk6dmFyKC0tbW9ubyk7LXdlYmtpdC10YXAtaGlnaGxpZ2h0LWNvbG9yOnRyYW5zcGFyZW50fQpib2R5e3RvdWNoLWFjdGlvbjpub25lO3VzZXItc2VsZWN0Om5vbmU7LXdlYmtpdC11c2VyLXNlbGVjdDpub25lfQoKI3N0YWdle3Bvc2l0aW9uOmZpeGVkO2luc2V0OjA7ZGlzcGxheTpibG9jaztiYWNrZ3JvdW5kOgogIHJhZGlhbC1ncmFkaWVudCgxMjAlIDgwJSBhdCA1MCUgMCUsIzEwMWEzYSAwJSwjMDcwYjE4IDQ1JSwjMDQwNTBjIDEwMCUpfQoKLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiAgIEhVRCDigJQgdGVsZW1ldHJpYSBkaSBwbGFuY2lhLCBub24gdW4gcGFubmVsbG8gcHVudGVnZ2lvCiAgID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqLwojaHVke3Bvc2l0aW9uOmZpeGVkO2luc2V0OjA7cGFkZGluZzp2YXIoLS1wYWQpO3BvaW50ZXItZXZlbnRzOm5vbmU7ZGlzcGxheTpmbGV4O2ZsZXgtZGlyZWN0aW9uOmNvbHVtbjtqdXN0aWZ5LWNvbnRlbnQ6c3BhY2UtYmV0d2Vlbn0KLnJvd3tkaXNwbGF5OmZsZXg7YWxpZ24taXRlbXM6ZmxleC1zdGFydDtqdXN0aWZ5LWNvbnRlbnQ6c3BhY2UtYmV0d2VlbjtnYXA6MTJweH0KCi5ibG9ja3twb3NpdGlvbjpyZWxhdGl2ZTtwYWRkaW5nOjhweCAxMnB4IDhweCAxNHB4O2JhY2tncm91bmQ6bGluZWFyLWdyYWRpZW50KDkwZGVnLHJnYmEoNzAsMjMwLDI1NSwuMDgpLHRyYW5zcGFyZW50IDg1JSk7Ym9yZGVyLWxlZnQ6MnB4IHNvbGlkIHZhcigtLWlvbil9Ci5ibG9jay53YXJue2JhY2tncm91bmQ6bGluZWFyLWdyYWRpZW50KDkwZGVnLHJnYmEoMjU1LDE3NiwzMiwuMTApLHRyYW5zcGFyZW50IDg1JSk7Ym9yZGVyLWxlZnQtY29sb3I6dmFyKC0tYW1iZXIpfQoubGJse2ZvbnQtc2l6ZTo5cHg7bGV0dGVyLXNwYWNpbmc6LjM0ZW07dGV4dC10cmFuc2Zvcm06dXBwZXJjYXNlO2NvbG9yOnJnYmEoMjMyLDI0MCwyNTUsLjQ1KX0KLnZhbHtmb250LXNpemU6Y2xhbXAoMjRweCw3dncsNDBweCk7Zm9udC13ZWlnaHQ6NzAwO2xpbmUtaGVpZ2h0OjE7bGV0dGVyLXNwYWNpbmc6LS4wMmVtO2ZvbnQtdmFyaWFudC1udW1lcmljOnRhYnVsYXItbnVtczsKICB0ZXh0LXNoYWRvdzowIDAgMThweCByZ2JhKDcwLDIzMCwyNTUsLjU1KX0KLmJsb2NrLndhcm4gLnZhbHt0ZXh0LXNoYWRvdzowIDAgMThweCByZ2JhKDI1NSwxNzYsMzIsLjU1KX0KI3Njb3Jle3RyYW5zaXRpb246dHJhbnNmb3JtIC4wN3MgZWFzZS1vdXR9CiNzY29yZS5wb3B7dHJhbnNmb3JtOnNjYWxlKDEuMTMpfQoKLyogYmFycmEgY2FyaWNhIGxpdmVsbG8gKi8KI2dhdWdle21hcmdpbi10b3A6N3B4O3dpZHRoOjExMnB4O2hlaWdodDo0cHg7YmFja2dyb3VuZDpyZ2JhKDI1NSwyNTUsMjU1LC4xMCk7b3ZlcmZsb3c6aGlkZGVufQojZ2F1Z2VGaWxse2hlaWdodDoxMDAlO3dpZHRoOjA7YmFja2dyb3VuZDp2YXIoLS1hbWJlcik7Ym94LXNoYWRvdzowIDAgMTBweCB2YXIoLS1hbWJlcik7dHJhbnNpdGlvbjp3aWR0aCAuMThzIGxpbmVhcn0KCi8qIHNjYWZpIHJlc2lkdWk6IGNoZXZyb24sIG5vbiBjdW9yaWNpbmkgKi8KI2h1bGxze2Rpc3BsYXk6ZmxleDtnYXA6NnB4O21hcmdpbi10b3A6OXB4O2p1c3RpZnktY29udGVudDpmbGV4LWVuZH0KLmh1bGx7d2lkdGg6MTJweDtoZWlnaHQ6MTRweDtiYWNrZ3JvdW5kOnZhcigtLWlvbik7Y2xpcC1wYXRoOnBvbHlnb24oNTAlIDAsMTAwJSAxMDAlLDUwJSA3NiUsMCAxMDAlKTtib3gtc2hhZG93OjAgMCAxMHB4IHJnYmEoNzAsMjMwLDI1NSwuNyl9Ci5odWxsLm9mZntiYWNrZ3JvdW5kOnJnYmEoMjU1LDI1NSwyNTUsLjE0KTtib3gtc2hhZG93Om5vbmV9CgovKiBmaXJtYTogdGVsZW1ldHJpYSBhIHNjb3JyaW1lbnRvIHN1bCBmb25kbyAqLwouZm9vdHtkaXNwbGF5OmZsZXg7YWxpZ24taXRlbXM6Y2VudGVyO2dhcDoxMHB4fQojdGlja2Vye2ZsZXg6MTttaW4td2lkdGg6MDtmb250LXNpemU6OXB4O2xldHRlci1zcGFjaW5nOi4zZW07Y29sb3I6cmdiYSgyMzIsMjQwLDI1NSwuMzApO3doaXRlLXNwYWNlOm5vd3JhcDtvdmVyZmxvdzpoaWRkZW59CiN0aWNrZXIgYntjb2xvcjp2YXIoLS1wbGFzbWEpO2ZvbnQtd2VpZ2h0OjQwMH0KCi8qIGNvbnRyb2xsbyBtdXNpY2E6IGZ1b3JpIGRhbGwnYXJlYSBkaSB2b2xvLCBzdWwgZmlsbyBkZWwgZm9uZG8gKi8KLm1idG57cG9pbnRlci1ldmVudHM6YXV0bztmbGV4Om5vbmU7d2lkdGg6MzhweDtoZWlnaHQ6MzhweDtkaXNwbGF5OmdyaWQ7cGxhY2UtaXRlbXM6Y2VudGVyOwogIGJhY2tncm91bmQ6cmdiYSg2LDEwLDIyLC43NCk7Ym9yZGVyOjFweCBzb2xpZCByZ2JhKDcwLDIzMCwyNTUsLjMyKTtib3JkZXItcmFkaXVzOjUwJTsKICBjb2xvcjp2YXIoLS1pb24pO2N1cnNvcjpwb2ludGVyO3BhZGRpbmc6MDstd2Via2l0LWFwcGVhcmFuY2U6bm9uZTsKICB0cmFuc2l0aW9uOmNvbG9yIC4ycyxib3JkZXItY29sb3IgLjJzLGJveC1zaGFkb3cgLjJzLG9wYWNpdHkgLjJzfQoubWJ0biBzdmd7d2lkdGg6MTlweDtoZWlnaHQ6MTlweDtkaXNwbGF5OmJsb2NrfQoubWJ0bi5vbntib3JkZXItY29sb3I6cmdiYSg3MCwyMzAsMjU1LC44NSk7Ym94LXNoYWRvdzowIDAgMTZweCByZ2JhKDcwLDIzMCwyNTUsLjMyKX0KLm1idG4ub2Zme2NvbG9yOnJnYmEoMjMyLDI0MCwyNTUsLjQyKTtib3JkZXItY29sb3I6cmdiYSgyMzIsMjQwLDI1NSwuMTgpfQoubWJ0bi5kZWFke2NvbG9yOnJnYmEoMjMyLDI0MCwyNTUsLjIwKTtib3JkZXItY29sb3I6cmdiYSgyMzIsMjQwLDI1NSwuMTApO2N1cnNvcjpub3QtYWxsb3dlZH0KLm1idG4uc2Nhbntjb2xvcjpyZ2JhKDIzMiwyNDAsMjU1LC40MCk7Ym9yZGVyLWNvbG9yOnJnYmEoMjMyLDI0MCwyNTUsLjE2KTthbmltYXRpb246bXB1bHNlIDEuMnMgZWFzZS1pbi1vdXQgaW5maW5pdGV9Ci5tYnRuOmZvY3VzLXZpc2libGV7b3V0bGluZToycHggc29saWQgdmFyKC0tYW1iZXIpO291dGxpbmUtb2Zmc2V0OjNweH0KQGtleWZyYW1lcyBtcHVsc2V7NTAle29wYWNpdHk6LjM1fX0KI210cmt7ZmxleDpub25lO2ZvbnQtc2l6ZTo5cHg7bGV0dGVyLXNwYWNpbmc6LjIwZW07Y29sb3I6cmdiYSg3MCwyMzAsMjU1LC43KTsKICBmb250LXZhcmlhbnQtbnVtZXJpYzp0YWJ1bGFyLW51bXM7bWluLXdpZHRoOjMwcHh9Ci5tYnRuLnZpcy5vbntjb2xvcjp2YXIoLS1hbWJlcik7Ym9yZGVyLWNvbG9yOnJnYmEoMjU1LDE3NiwzMiwuOSk7Ym94LXNoYWRvdzowIDAgMThweCByZ2JhKDI1NSwxNzYsMzIsLjQyKX0KCi8qIGF0dGl2YXppb25lIHZpc29yZTogc2ZvY2F0dXJhIGdhdXNzaWFuYSBlIHZpcmF0YSBhbCBiaWFuY28sIHBvaSByaWVudHJvICovCiNibG9vbXtwb3NpdGlvbjpmaXhlZDtpbnNldDowO2JhY2tncm91bmQ6I2ZmZjtvcGFjaXR5OjA7cG9pbnRlci1ldmVudHM6bm9uZTt6LWluZGV4OjV9CkBrZXlmcmFtZXMgdmlzb3JCbHVyewogIDAle2ZpbHRlcjpub25lfQogIDE4JXtmaWx0ZXI6Ymx1cigxMHB4KSBzYXR1cmF0ZSgyLjYpIGJyaWdodG5lc3MoMS42KX0KICA0NCV7ZmlsdGVyOmJsdXIoNnB4KSBzYXR1cmF0ZSguMTgpIGJyaWdodG5lc3MoMi40KX0KICAxMDAle2ZpbHRlcjpub25lfQp9CkBrZXlmcmFtZXMgdmlzb3JCbG9vbXsKICAwJXtvcGFjaXR5OjB9CiAgMjAle29wYWNpdHk6LjM1fQogIDQ0JXtvcGFjaXR5Oi44Nn0KICAxMDAle29wYWNpdHk6MH0KfQojc3RhZ2Uudmlzb3IsI2h1ZC52aXNvcnthbmltYXRpb246dmlzb3JCbHVyIC41NHMgY3ViaWMtYmV6aWVyKC4yLC43NSwuMjUsMSl9CiNibG9vbS52aXNvcnthbmltYXRpb246dmlzb3JCbG9vbSAuNTRzIGN1YmljLWJlemllciguMiwuNzUsLjI1LDEpfQpAbWVkaWEocHJlZmVycy1yZWR1Y2VkLW1vdGlvbjpyZWR1Y2UpewogICNzdGFnZS52aXNvciwjaHVkLnZpc29yLCNibG9vbS52aXNvcnthbmltYXRpb246bm9uZX0KfQoKI3RvYXN0e3Bvc2l0aW9uOmZpeGVkO2xlZnQ6NTAlO3RvcDozNCU7dHJhbnNmb3JtOnRyYW5zbGF0ZSgtNTAlLC01MCUpIHNjYWxlKC45KTtvcGFjaXR5OjA7CiAgZm9udC1zaXplOmNsYW1wKDI4cHgsOXZ3LDU0cHgpO2ZvbnQtd2VpZ2h0OjcwMDtsZXR0ZXItc3BhY2luZzouMTJlbTtjb2xvcjp2YXIoLS1hbWJlcik7CiAgdGV4dC1zaGFkb3c6MCAwIDI2cHggcmdiYSgyNTUsMTc2LDMyLC44KTtwb2ludGVyLWV2ZW50czpub25lO3doaXRlLXNwYWNlOm5vd3JhcH0KQGtleWZyYW1lcyB0b2FzdEluezAle29wYWNpdHk6MDt0cmFuc2Zvcm06dHJhbnNsYXRlKC01MCUsLTUwJSkgc2NhbGUoLjgyKX0xOCV7b3BhY2l0eToxO3RyYW5zZm9ybTp0cmFuc2xhdGUoLTUwJSwtNTAlKSBzY2FsZSgxLjA0KX03MiV7b3BhY2l0eToxfTEwMCV7b3BhY2l0eTowO3RyYW5zZm9ybTp0cmFuc2xhdGUoLTUwJSwtNTAlKSBzY2FsZSgxKX19CiN0b2FzdC5vbnthbmltYXRpb246dG9hc3RJbiAxLjE1cyBlYXNlLW91dH0KCi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQogICBTQ0hFUk1BVEUKICAgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICovCi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQogICBBUEVSVFVSQSDigJQgLi9pbWcvbWF0aGVtaWkuanBnICgxNjk2eDI1MjgsIHZlcnRpY2FsZSkKICAgRHVlIHNlY29uZGkgZGkgcG9zYSwgcG9pIGwnaW1tYWdpbmUgc2JpYW5jYSBlIHNmdW1hIGluCiAgIGdhdXNzaWFuYSBzdmFuZW5kbzogc290dG8gY29tcGFyZSBpbCBnaW9jby4KICAgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICovCiNzcGxhc2h7cG9zaXRpb246Zml4ZWQ7aW5zZXQ6MDt6LWluZGV4OjIwO2JhY2tncm91bmQ6IzA1MDYwZDsKICBkaXNwbGF5OmdyaWQ7cGxhY2UtaXRlbXM6Y2VudGVyO292ZXJmbG93OmhpZGRlbn0KI3NwbGFzaCBpbWd7bWF4LXdpZHRoOjEwMCU7bWF4LWhlaWdodDoxMDAlO3dpZHRoOmF1dG87aGVpZ2h0OmF1dG87CiAgb2JqZWN0LWZpdDpjb250YWluO2Rpc3BsYXk6YmxvY2s7LXdlYmtpdC11c2VyLWRyYWc6bm9uZX0KI3NwbGFzaC5vdXR7YW5pbWF0aW9uOnNwbGFzaFdoaXRlIC44MnMgY3ViaWMtYmV6aWVyKC4zMiwuNjIsLjI1LDEpIGZvcndhcmRzfQojc3BsYXNoLm91dCBpbWd7YW5pbWF0aW9uOnNwbGFzaEJ1cm4gLjgycyBjdWJpYy1iZXppZXIoLjMyLC42MiwuMjUsMSkgZm9yd2FyZHN9CiNzcGxhc2guZ29uZXtkaXNwbGF5Om5vbmV9CkBrZXlmcmFtZXMgc3BsYXNoQnVybnsKICAwJXtmaWx0ZXI6Ymx1cigwKSBicmlnaHRuZXNzKDEpIHNhdHVyYXRlKDEpO29wYWNpdHk6MX0KICAzOCV7ZmlsdGVyOmJsdXIoMTBweCkgYnJpZ2h0bmVzcygyLjMpIHNhdHVyYXRlKC4zNCk7b3BhY2l0eToxfQogIDEwMCV7ZmlsdGVyOmJsdXIoMzZweCkgYnJpZ2h0bmVzcyg1LjUpIHNhdHVyYXRlKDApO29wYWNpdHk6MH0KfQpAa2V5ZnJhbWVzIHNwbGFzaFdoaXRlewogIDAle2JhY2tncm91bmQ6IzA1MDYwZH0KICAzOCV7YmFja2dyb3VuZDojZmZmZmZmfQogIDEwMCV7YmFja2dyb3VuZDpyZ2JhKDI1NSwyNTUsMjU1LDApfQp9CkBtZWRpYShwcmVmZXJzLXJlZHVjZWQtbW90aW9uOnJlZHVjZSl7CiAgI3NwbGFzaC5vdXQsI3NwbGFzaC5vdXQgaW1ne2FuaW1hdGlvbjpub25lO29wYWNpdHk6MH0KfQoKI3ZlaWx7cG9zaXRpb246Zml4ZWQ7aW5zZXQ6MDtkaXNwbGF5OmZsZXg7ZmxleC1kaXJlY3Rpb246Y29sdW1uO2FsaWduLWl0ZW1zOmNlbnRlcjtqdXN0aWZ5LWNvbnRlbnQ6Y2VudGVyO2dhcDoyMHB4OwogIHBhZGRpbmc6dmFyKC0tcGFkKTt0ZXh0LWFsaWduOmNlbnRlcjtiYWNrZ3JvdW5kOnJnYmEoNCw1LDEyLC43OCk7YmFja2Ryb3AtZmlsdGVyOmJsdXIoM3B4KX0KI3ZlaWwuaGlkZXtkaXNwbGF5Om5vbmV9CiN2ZWlsIGgxe2ZvbnQtc2l6ZTpjbGFtcCgzMHB4LDEwdncsNjhweCk7Zm9udC13ZWlnaHQ6ODAwO2xldHRlci1zcGFjaW5nOi0uMDNlbTtsaW5lLWhlaWdodDouOTJ9CiN2ZWlsIGgxIHNwYW57ZGlzcGxheTpibG9jaztmb250LXNpemU6LjM0ZW07Zm9udC13ZWlnaHQ6NDAwO2xldHRlci1zcGFjaW5nOi40MmVtO2NvbG9yOnZhcigtLWlvbik7dGV4dC1zaGFkb3c6MCAwIDIwcHggcmdiYSg3MCwyMzAsMjU1LC42KTttYXJnaW4tYm90dG9tOi43ZW19CiN2ZWlsIHB7Zm9udC1zaXplOjEycHg7bGV0dGVyLXNwYWNpbmc6LjE2ZW07Y29sb3I6cmdiYSgyMzIsMjQwLDI1NSwuNTUpO2xpbmUtaGVpZ2h0OjI7bWF4LXdpZHRoOjM0Y2h9CiN2ZWlsIHAgZW17Y29sb3I6dmFyKC0tYm9uZSk7Zm9udC1zdHlsZTpub3JtYWx9CiNmaW5hbHtmb250LXNpemU6Y2xhbXAoNDBweCwxM3Z3LDc4cHgpO2ZvbnQtd2VpZ2h0OjgwMDtjb2xvcjp2YXIoLS1hbWJlcik7dGV4dC1zaGFkb3c6MCAwIDMwcHggcmdiYSgyNTUsMTc2LDMyLC42KTtmb250LXZhcmlhbnQtbnVtZXJpYzp0YWJ1bGFyLW51bXM7ZGlzcGxheTpub25lfQojYnRue3BvaW50ZXItZXZlbnRzOmF1dG87Y3Vyc29yOnBvaW50ZXI7Ym9yZGVyOjA7YmFja2dyb3VuZDp2YXIoLS1pb24pO2NvbG9yOiMwNDA1MGM7Zm9udC1mYW1pbHk6dmFyKC0tbW9ubyk7Zm9udC13ZWlnaHQ6NzAwOwogIGZvbnQtc2l6ZToxM3B4O2xldHRlci1zcGFjaW5nOi4zZW07cGFkZGluZzoxNXB4IDM0cHg7dGV4dC10cmFuc2Zvcm06dXBwZXJjYXNlO2JveC1zaGFkb3c6MCAwIDM0cHggcmdiYSg3MCwyMzAsMjU1LC40NSl9CiNidG46YWN0aXZle3RyYW5zZm9ybTp0cmFuc2xhdGVZKDJweCl9CiNidG46Zm9jdXMtdmlzaWJsZXtvdXRsaW5lOjJweCBzb2xpZCB2YXIoLS1hbWJlcik7b3V0bGluZS1vZmZzZXQ6NHB4fQpAbWVkaWEocHJlZmVycy1yZWR1Y2VkLW1vdGlvbjpyZWR1Y2UpeyN0b2FzdC5vbnthbmltYXRpb24tZHVyYXRpb246LjAxcztvcGFjaXR5OjB9fQo8L3N0eWxlPgo8L2hlYWQ+Cjxib2R5Pgo8Y2FudmFzIGlkPSJzdGFnZSI+PC9jYW52YXM+CjxkaXYgaWQ9ImJsb29tIj48L2Rpdj4KCjxkaXYgaWQ9Imh1ZCIgYXJpYS1oaWRkZW49InRydWUiPgogIDxkaXYgY2xhc3M9InJvdyI+CiAgICA8ZGl2IGNsYXNzPSJibG9jayI+CiAgICAgIDxkaXYgY2xhc3M9ImxibCI+UHVudGVnZ2lvPC9kaXY+CiAgICAgIDxkaXYgY2xhc3M9InZhbCIgaWQ9InNjb3JlIj4wPC9kaXY+CiAgICA8L2Rpdj4KICAgIDxkaXYgc3R5bGU9InRleHQtYWxpZ246cmlnaHQiPgogICAgICA8ZGl2IGNsYXNzPSJibG9jayB3YXJuIiBzdHlsZT0iYm9yZGVyLWxlZnQ6MDtib3JkZXItcmlnaHQ6MnB4IHNvbGlkIHZhcigtLWFtYmVyKTtiYWNrZ3JvdW5kOmxpbmVhci1ncmFkaWVudCgyNzBkZWcscmdiYSgyNTUsMTc2LDMyLC4xMCksdHJhbnNwYXJlbnQgODUlKTtwYWRkaW5nOjhweCAxNHB4IDhweCAxMnB4Ij4KICAgICAgICA8ZGl2IGNsYXNzPSJsYmwiPkxpdmVsbG88L2Rpdj4KICAgICAgICA8ZGl2IGNsYXNzPSJ2YWwiIGlkPSJsZXZlbCI+MTwvZGl2PgogICAgICAgIDxkaXYgaWQ9ImdhdWdlIj48ZGl2IGlkPSJnYXVnZUZpbGwiPjwvZGl2PjwvZGl2PgogICAgICA8L2Rpdj4KICAgICAgPGRpdiBpZD0iaHVsbHMiPjwvZGl2PgogICAgPC9kaXY+CiAgPC9kaXY+CiAgPGRpdiBjbGFzcz0iZm9vdCI+CiAgICA8YnV0dG9uIGlkPSJtYnRuIiBjbGFzcz0ibWJ0biBzY2FuIiB0eXBlPSJidXR0b24iIGFyaWEtbGFiZWw9Ik11c2ljYSIgYXJpYS1wcmVzc2VkPSJmYWxzZSIgZGlzYWJsZWQ+PC9idXR0b24+CiAgICA8YnV0dG9uIGlkPSJ2YnRuIiBjbGFzcz0ibWJ0biB2aXMgb2ZmIiB0eXBlPSJidXR0b24iIGFyaWEtbGFiZWw9Ik1vZGFsaXTDoCBzZWxlemlvbmEgZSBzcGFyYSIgYXJpYS1wcmVzc2VkPSJmYWxzZSI+PC9idXR0b24+CiAgICA8c3BhbiBpZD0ibXRyayI+PC9zcGFuPgogICAgPGRpdiBpZD0idGlja2VyIj5TRVRULiBQUk9QVUxTSU9ORSA8Yj5PSzwvYj4gwrcgQ0FOTk9ORSBNSy1JSSA8Yj5DQVJJQ088L2I+IMK3IFJPVFRBIDxiPkNJTlRVUkEgRVNURVJOQTwvYj4gwrcgMTUwIFBUIC8gSU1QQVRUTzwvZGl2PgogIDwvZGl2Pgo8L2Rpdj4KCjxkaXYgaWQ9InRvYXN0Ij48L2Rpdj4KCjxkaXYgaWQ9InNwbGFzaCI+PGltZyBpZD0ic3BsYXNoaW1nIiBzcmM9Ii4vaW1nL21hdGhlbWlpLmpwZyIgYWx0PSIiIHdpZHRoPSIxNjk2IiBoZWlnaHQ9IjI1MjgiPjwvZGl2PgoKPGRpdiBpZD0idmVpbCI+CiAgPGgxPjxzcGFuPkFzdGVyb2lkPC9zcGFuPlJVTk5FUjwvaDE+CiAgPGRpdiBpZD0iZmluYWwiPjA8L2Rpdj4KICA8cCBpZD0iaGludCI+CiAgICA8ZW0+VHJhc2NpbmE8L2VtPiBwZXIgdmlyYXJlIGUgc3BhcmFyZTxicj4KICAgIDxlbT7ihpAg4oaSPC9lbT4gbyA8ZW0+QSAvIEQ8L2VtPiBwZXIgdmlyYXJlIMK3IDxlbT5TcGF6aW88L2VtPiBwZXIgc3BhcmFyZTxicj4KICAgIE9nbmkgYXN0ZXJvaWRlIHZhbGUgPGVtPjE1MCBwdW50aTwvZW0+IMK3IHZlbG9jaXTDoCArMSBvZ25pIDxlbT4xNTAwPC9lbT48YnI+CiAgICBBIHNvZ2xpYSBwaWVuYSBzY2F0dGEgdW4gPGVtPnNldHRvcmUgYm9udXM8L2VtPiBhIHNvcnRlOjxicj4KICAgIGNhdGVuYSBhcml0bWV0aWNhIDxlbT4rNTAwMDwvZW0+IMK3IGNhY2NpYSBhaSBwcmltaSA8ZW0+KzMwMDA8L2VtPiAvIDxlbT4mbWludXM7MjAwMDwvZW0+CiAgPC9wPgogIDxidXR0b24gaWQ9ImJ0biI+QXZ2aWEgbWlzc2lvbmU8L2J1dHRvbj4KPC9kaXY+Cgo8c2NyaXB0PgoidXNlIHN0cmljdCI7Ci8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQogICBBU1RFUk9JRCBSVU5ORVIg4oCUIGRlbW8gYXJjYWRlIHNpbmdsZS1maWxlLCBjYW52YXMgMkQsIHplcm8gZGVwcwogICBSZWdvbGU6IDE1MCBwdCBwZXIgYXN0ZXJvaWRlIMK3IGxpdmVsbG8gPSBmbG9vcihwdW50ZWdnaW8gLyAxNTAwKQogICA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gKi8KKGZ1bmN0aW9uKCl7CgovKiAtLS0tLS0tLS0tIGNhbnZhcyAmIHZpZXdwb3J0IC0tLS0tLS0tLS0gKi8KY29uc3QgY3YgID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3N0YWdlJyk7CmNvbnN0IGVsU3RhZ2UgPSBjdjsKY29uc3QgY3R4ID0gY3YuZ2V0Q29udGV4dCgnMmQnLCB7YWxwaGE6ZmFsc2V9KTsKbGV0IFc9MCwgSD0wLCBEUFI9MTsKCmZ1bmN0aW9uIHJlc2l6ZSgpewogIERQUiA9IE1hdGgubWluKHdpbmRvdy5kZXZpY2VQaXhlbFJhdGlvfHwxLCAyKTsKICBXID0gd2luZG93LmlubmVyV2lkdGg7IEggPSB3aW5kb3cuaW5uZXJIZWlnaHQ7CiAgY3Yud2lkdGggPSBNYXRoLnJvdW5kKFcqRFBSKTsgY3YuaGVpZ2h0ID0gTWF0aC5yb3VuZChIKkRQUik7CiAgY3Yuc3R5bGUud2lkdGggPSBXKydweCc7IGN2LnN0eWxlLmhlaWdodCA9IEgrJ3B4JzsKICBjdHguc2V0VHJhbnNmb3JtKERQUiwwLDAsRFBSLDAsMCk7CiAgaWYgKHNoaXApIHNoaXAueSA9IEggLSA5NjsKICBidWlsZEFieXNzKCk7Cn0KYWRkRXZlbnRMaXN0ZW5lcigncmVzaXplJywgcmVzaXplLCB7cGFzc2l2ZTp0cnVlfSk7CmFkZEV2ZW50TGlzdGVuZXIoJ29yaWVudGF0aW9uY2hhbmdlJywgKCk9PnNldFRpbWVvdXQocmVzaXplLDEyMCksIHtwYXNzaXZlOnRydWV9KTsKCi8qIC0tLS0tLS0tLS0gY29zdGFudGkgZGkgYmlsYW5jaWFtZW50byAtLS0tLS0tLS0tICovCmNvbnN0IFBUU19QRVJfUk9DSyAgPSAxNTA7CmNvbnN0IFBUU19QRVJfTEVWRUwgPSAxNTAwOyAgICAgIC8vIGxpdmVsbG8gPSBmbG9vcihzY29yZSAvIDE1MDApCmNvbnN0IEZJUkVfTVMgICAgICAgPSAxMTg7CmNvbnN0IEJVTExFVF9WICAgICAgPSA4MjA7CmNvbnN0IFNISVBfViAgICAgICAgPSA1NjA7CmNvbnN0IExJVkVTICAgICAgICAgPSAzOwpjb25zdCBSRURVQ0VEID0gbWF0Y2hNZWRpYSgnKHByZWZlcnMtcmVkdWNlZC1tb3Rpb246IHJlZHVjZSknKS5tYXRjaGVzOwoKLyogLS0tLS0tLS0tLSBzdGF0byAtLS0tLS0tLS0tICovCmxldCBzaGlwPW51bGwsIGJ1bGxldHM9W10sIHJvY2tzPVtdLCBzcGFya3M9W10sIGRlYnJpcz1bXSwgc21va2U9W10sIGJhbGxzPVtdLCB3YXZlcz1bXSwgZmxvYXRzPVtdOwpsZXQgYWltTG9jaz0wLCBub3RpY2U9JycsIG5vdGljZVN1Yj0nJywgbm90aWNlVD0wOwpsZXQgc2NvcmU9MCwgZ2F0ZVByb2c9MCwga2lsbHM9MCwgbGV2ZWw9MCwgbGl2ZXM9TElWRVMsIHJ1bm5pbmc9ZmFsc2UsIG92ZXI9ZmFsc2U7CmxldCBzaGFrZT0wLCBmbGFzaD0wLCBzcGF3blQ9MCwgbGFzdEZpcmU9MCwgdD0wOwoKLyogLS0tLS0tLS0tLSBET00gcmVmcyAtLS0tLS0tLS0tICovCmNvbnN0IGVsU2NvcmU9ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3Njb3JlJyksIGVsTGV2ZWw9ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2xldmVsJyksCiAgICAgIGVsR2F1Z2U9ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2dhdWdlRmlsbCcpLCBlbEh1bGxzPWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdodWxscycpLAogICAgICBlbFRvYXN0PWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd0b2FzdCcpLCAgZWxWZWlsPWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd2ZWlsJyksCiAgICAgIGVsVGlja2VyPWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd0aWNrZXInKSwKICAgICAgZWxNYnRuPWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdtYnRuJyksICAgZWxNdHJrPWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdtdHJrJyksCiAgICAgIGVsVmJ0bj1kb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndmJ0bicpLCAgIGVsQmxvb209ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2Jsb29tJyksCiAgICAgIGVsSHVkPWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdodWQnKSwKICAgICAgZWxGaW5hbD1kb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZmluYWwnKSwgIGVsSGludD1kb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnaGludCcpLAogICAgICBlbEJ0bj1kb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnYnRuJyksICAgICAgZWxIMT1lbFZlaWwucXVlcnlTZWxlY3RvcignaDEnKTsKCi8qIC0tLS0tLS0tLS0gdXRpbCAtLS0tLS0tLS0tICovCmNvbnN0IHJuZCAgPShhLGIpPT5hK01hdGgucmFuZG9tKCkqKGItYSk7CmNvbnN0IHJuZGkgPShhLGIpPT5NYXRoLmZsb29yKHJuZChhLGIrMSkpOwpjb25zdCBjbGFtcD0odixhLGIpPT52PGE/YTp2PmI/Yjp2Owpjb25zdCBUQVUgID0gTWF0aC5QSSoyOwoKLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiAgIEFVRElPIOKAlCBzaW50ZXNpIFdlYkF1ZGlvLCBuZXNzdW4gYXNzZXQgZXN0ZXJubwogICA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gKi8KbGV0IEFDPW51bGw7CmZ1bmN0aW9uIGF1ZGlvKCl7IGlmKCFBQyl7IGNvbnN0IEM9d2luZG93LkF1ZGlvQ29udGV4dHx8d2luZG93LndlYmtpdEF1ZGlvQ29udGV4dDsgaWYoQykgQUM9bmV3IEMoKTsgfQogIGlmKEFDICYmIEFDLnN0YXRlPT09J3N1c3BlbmRlZCcpIEFDLnJlc3VtZSgpOyByZXR1cm4gQUM7IH0KCmZ1bmN0aW9uIHNmeFNob3QoKXsKICBjb25zdCBhPWF1ZGlvKCk7IGlmKCFhKSByZXR1cm47CiAgY29uc3Qgbz1hLmNyZWF0ZU9zY2lsbGF0b3IoKSwgZz1hLmNyZWF0ZUdhaW4oKSwgZj1hLmNyZWF0ZUJpcXVhZEZpbHRlcigpOwogIGYudHlwZT0nYmFuZHBhc3MnOyBmLmZyZXF1ZW5jeS52YWx1ZT0xNTAwOyBmLlEudmFsdWU9MjsKICBvLnR5cGU9J3NxdWFyZSc7IG8uZnJlcXVlbmN5LnNldFZhbHVlQXRUaW1lKDg4MCxhLmN1cnJlbnRUaW1lKTsKICBvLmZyZXF1ZW5jeS5leHBvbmVudGlhbFJhbXBUb1ZhbHVlQXRUaW1lKDE4MCxhLmN1cnJlbnRUaW1lKy4wOSk7CiAgZy5nYWluLnNldFZhbHVlQXRUaW1lKC4wNDUsYS5jdXJyZW50VGltZSk7CiAgZy5nYWluLmV4cG9uZW50aWFsUmFtcFRvVmFsdWVBdFRpbWUoLjAwMDEsYS5jdXJyZW50VGltZSsuMDkpOwogIG8uY29ubmVjdChmKTsgZi5jb25uZWN0KGcpOyBnLmNvbm5lY3QoYS5kZXN0aW5hdGlvbik7IG8uc3RhcnQoKTsgby5zdG9wKGEuY3VycmVudFRpbWUrLjEpOwp9CmZ1bmN0aW9uIHNmeEJvb20oc2l6ZSl7CiAgY29uc3QgYT1hdWRpbygpOyBpZighYSkgcmV0dXJuOwogIGNvbnN0IGR1cj0uMzQsIG49YS5zYW1wbGVSYXRlKmR1ciwgYnVmPWEuY3JlYXRlQnVmZmVyKDEsbixhLnNhbXBsZVJhdGUpLCBkPWJ1Zi5nZXRDaGFubmVsRGF0YSgwKTsKICBmb3IobGV0IGk9MDtpPG47aSsrKXsgY29uc3Qgaz0xLWkvbjsgZFtpXT0oTWF0aC5yYW5kb20oKSoyLTEpKmsqazsgfQogIGNvbnN0IHNyYz1hLmNyZWF0ZUJ1ZmZlclNvdXJjZSgpOyBzcmMuYnVmZmVyPWJ1ZjsKICBjb25zdCBmPWEuY3JlYXRlQmlxdWFkRmlsdGVyKCk7IGYudHlwZT0nbG93cGFzcyc7CiAgZi5mcmVxdWVuY3kuc2V0VmFsdWVBdFRpbWUoMTgwMC1zaXplKjEwLGEuY3VycmVudFRpbWUpOwogIGYuZnJlcXVlbmN5LmV4cG9uZW50aWFsUmFtcFRvVmFsdWVBdFRpbWUoOTAsYS5jdXJyZW50VGltZStkdXIpOwogIGNvbnN0IGc9YS5jcmVhdGVHYWluKCk7CiAgZy5nYWluLnNldFZhbHVlQXRUaW1lKGNsYW1wKHNpemUvMjMwLC4wNSwuMzApLGEuY3VycmVudFRpbWUpOwogIGcuZ2Fpbi5leHBvbmVudGlhbFJhbXBUb1ZhbHVlQXRUaW1lKC4wMDAxLGEuY3VycmVudFRpbWUrZHVyKTsKICBzcmMuY29ubmVjdChmKTsgZi5jb25uZWN0KGcpOyBnLmNvbm5lY3QoYS5kZXN0aW5hdGlvbik7IHNyYy5zdGFydCgpOwogIC8vIHN1Yi10aHVtcAogIGNvbnN0IG89YS5jcmVhdGVPc2NpbGxhdG9yKCksIG9nPWEuY3JlYXRlR2FpbigpOwogIG8udHlwZT0nc2luZSc7IG8uZnJlcXVlbmN5LnNldFZhbHVlQXRUaW1lKDE1MCxhLmN1cnJlbnRUaW1lKTsKICBvLmZyZXF1ZW5jeS5leHBvbmVudGlhbFJhbXBUb1ZhbHVlQXRUaW1lKDM4LGEuY3VycmVudFRpbWUrLjIyKTsKICBvZy5nYWluLnNldFZhbHVlQXRUaW1lKGNsYW1wKHNpemUvMzAwLC4wMywuMjIpLGEuY3VycmVudFRpbWUpOwogIG9nLmdhaW4uZXhwb25lbnRpYWxSYW1wVG9WYWx1ZUF0VGltZSguMDAwMSxhLmN1cnJlbnRUaW1lKy4yNCk7CiAgby5jb25uZWN0KG9nKTsgb2cuY29ubmVjdChhLmRlc3RpbmF0aW9uKTsgby5zdGFydCgpOyBvLnN0b3AoYS5jdXJyZW50VGltZSsuMjUpOwp9CmZ1bmN0aW9uIHNmeExldmVsKCl7CiAgY29uc3QgYT1hdWRpbygpOyBpZighYSkgcmV0dXJuOwogIFs1MjMsNjU5LDg4MF0uZm9yRWFjaCgoaHosaSk9PnsKICAgIGNvbnN0IG89YS5jcmVhdGVPc2NpbGxhdG9yKCksIGc9YS5jcmVhdGVHYWluKCksIHQwPWEuY3VycmVudFRpbWUraSouMDc1OwogICAgby50eXBlPSd0cmlhbmdsZSc7IG8uZnJlcXVlbmN5LnZhbHVlPWh6OwogICAgZy5nYWluLnNldFZhbHVlQXRUaW1lKC4wMDEsdDApOyBnLmdhaW4uZXhwb25lbnRpYWxSYW1wVG9WYWx1ZUF0VGltZSguMDksdDArLjAyKTsKICAgIGcuZ2Fpbi5leHBvbmVudGlhbFJhbXBUb1ZhbHVlQXRUaW1lKC4wMDAxLHQwKy4yMCk7CiAgICBvLmNvbm5lY3QoZyk7IGcuY29ubmVjdChhLmRlc3RpbmF0aW9uKTsgby5zdGFydCh0MCk7IG8uc3RvcCh0MCsuMjIpOwogIH0pOwp9Ci8qIC0tLSBzZXR0b3JlIG1hdGVtYXRpY28gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovCmZ1bmN0aW9uIHNmeEFycml2YWwoKXsKICBjb25zdCBhPWF1ZGlvKCk7IGlmKCFhKSByZXR1cm47CiAgY29uc3Qgbz1hLmNyZWF0ZU9zY2lsbGF0b3IoKSwgZz1hLmNyZWF0ZUdhaW4oKSwgZj1hLmNyZWF0ZUJpcXVhZEZpbHRlcigpOwogIGYudHlwZT0nbG93cGFzcyc7IGYuZnJlcXVlbmN5LnNldFZhbHVlQXRUaW1lKDEyMCxhLmN1cnJlbnRUaW1lKTsKICBmLmZyZXF1ZW5jeS5leHBvbmVudGlhbFJhbXBUb1ZhbHVlQXRUaW1lKDkwMCxhLmN1cnJlbnRUaW1lKzEuNCk7CiAgby50eXBlPSdzYXd0b290aCc7IG8uZnJlcXVlbmN5LnNldFZhbHVlQXRUaW1lKDI4LGEuY3VycmVudFRpbWUpOwogIG8uZnJlcXVlbmN5LmV4cG9uZW50aWFsUmFtcFRvVmFsdWVBdFRpbWUoNjIsYS5jdXJyZW50VGltZSsxLjQpOwogIGcuZ2Fpbi5zZXRWYWx1ZUF0VGltZSguMDAxLGEuY3VycmVudFRpbWUpOwogIGcuZ2Fpbi5leHBvbmVudGlhbFJhbXBUb1ZhbHVlQXRUaW1lKC4xNixhLmN1cnJlbnRUaW1lKy41KTsKICBnLmdhaW4uZXhwb25lbnRpYWxSYW1wVG9WYWx1ZUF0VGltZSguMDAwMSxhLmN1cnJlbnRUaW1lKzEuNyk7CiAgby5jb25uZWN0KGYpOyBmLmNvbm5lY3QoZyk7IGcuY29ubmVjdChhLmRlc3RpbmF0aW9uKTsgby5zdGFydCgpOyBvLnN0b3AoYS5jdXJyZW50VGltZSsxLjc1KTsKfQpmdW5jdGlvbiBzZnhMb2NrKHN0ZXApewogIGNvbnN0IGE9YXVkaW8oKTsgaWYoIWEpIHJldHVybjsKICBjb25zdCBvPWEuY3JlYXRlT3NjaWxsYXRvcigpLCBnPWEuY3JlYXRlR2FpbigpOwogIGNvbnN0IGh6PTQ0MCpNYXRoLnBvdygxLjI2LE1hdGgubWluKHN0ZXAsNikpOwogIG8udHlwZT0nc3F1YXJlJzsgby5mcmVxdWVuY3kuc2V0VmFsdWVBdFRpbWUoaHoqLjUsYS5jdXJyZW50VGltZSk7CiAgby5mcmVxdWVuY3kuZXhwb25lbnRpYWxSYW1wVG9WYWx1ZUF0VGltZShoeixhLmN1cnJlbnRUaW1lKy4wNik7CiAgZy5nYWluLnNldFZhbHVlQXRUaW1lKC4wNixhLmN1cnJlbnRUaW1lKTsKICBnLmdhaW4uZXhwb25lbnRpYWxSYW1wVG9WYWx1ZUF0VGltZSguMDAwMSxhLmN1cnJlbnRUaW1lKy4xNik7CiAgby5jb25uZWN0KGcpOyBnLmNvbm5lY3QoYS5kZXN0aW5hdGlvbik7IG8uc3RhcnQoKTsgby5zdG9wKGEuY3VycmVudFRpbWUrLjE3KTsKfQpmdW5jdGlvbiBzZnhFcnIoKXsKICBjb25zdCBhPWF1ZGlvKCk7IGlmKCFhKSByZXR1cm47CiAgY29uc3Qgbz1hLmNyZWF0ZU9zY2lsbGF0b3IoKSwgZz1hLmNyZWF0ZUdhaW4oKTsKICBvLnR5cGU9J3Nhd3Rvb3RoJzsgby5mcmVxdWVuY3kuc2V0VmFsdWVBdFRpbWUoMjIwLGEuY3VycmVudFRpbWUpOwogIG8uZnJlcXVlbmN5LmV4cG9uZW50aWFsUmFtcFRvVmFsdWVBdFRpbWUoNTgsYS5jdXJyZW50VGltZSsuMzApOwogIGcuZ2Fpbi5zZXRWYWx1ZUF0VGltZSguMTAsYS5jdXJyZW50VGltZSk7CiAgZy5nYWluLmV4cG9uZW50aWFsUmFtcFRvVmFsdWVBdFRpbWUoLjAwMDEsYS5jdXJyZW50VGltZSsuMzIpOwogIG8uY29ubmVjdChnKTsgZy5jb25uZWN0KGEuZGVzdGluYXRpb24pOyBvLnN0YXJ0KCk7IG8uc3RvcChhLmN1cnJlbnRUaW1lKy4zMyk7Cn0KZnVuY3Rpb24gc2Z4QWxhcm0oKXsKICBjb25zdCBhPWF1ZGlvKCk7IGlmKCFhKSByZXR1cm47CiAgZm9yKGxldCBpPTA7aTwyO2krKyl7CiAgICBjb25zdCBvPWEuY3JlYXRlT3NjaWxsYXRvcigpLCBnPWEuY3JlYXRlR2FpbigpLCB0MD1hLmN1cnJlbnRUaW1lK2kqLjIyOwogICAgby50eXBlPSdzcXVhcmUnOyBvLmZyZXF1ZW5jeS5zZXRWYWx1ZUF0VGltZSg4ODAsdDApOwogICAgby5mcmVxdWVuY3kuZXhwb25lbnRpYWxSYW1wVG9WYWx1ZUF0VGltZSgxODAsdDArLjE5KTsKICAgIGcuZ2Fpbi5zZXRWYWx1ZUF0VGltZSguMDAxLHQwKTsgZy5nYWluLmV4cG9uZW50aWFsUmFtcFRvVmFsdWVBdFRpbWUoLjEwLHQwKy4wMik7CiAgICBnLmdhaW4uZXhwb25lbnRpYWxSYW1wVG9WYWx1ZUF0VGltZSguMDAwMSx0MCsuMjEpOwogICAgby5jb25uZWN0KGcpOyBnLmNvbm5lY3QoYS5kZXN0aW5hdGlvbik7IG8uc3RhcnQodDApOyBvLnN0b3AodDArLjIyKTsKICB9CiAgY29uc3Qgbj1hLmNyZWF0ZU9zY2lsbGF0b3IoKSwgbmc9YS5jcmVhdGVHYWluKCk7CiAgbi50eXBlPSdzYXd0b290aCc7IG4uZnJlcXVlbmN5LnNldFZhbHVlQXRUaW1lKDcwLGEuY3VycmVudFRpbWUpOwogIG4uZnJlcXVlbmN5LmV4cG9uZW50aWFsUmFtcFRvVmFsdWVBdFRpbWUoMjYsYS5jdXJyZW50VGltZSsuNik7CiAgbmcuZ2Fpbi5zZXRWYWx1ZUF0VGltZSguMTQsYS5jdXJyZW50VGltZSk7CiAgbmcuZ2Fpbi5leHBvbmVudGlhbFJhbXBUb1ZhbHVlQXRUaW1lKC4wMDAxLGEuY3VycmVudFRpbWUrLjYyKTsKICBuLmNvbm5lY3QobmcpOyBuZy5jb25uZWN0KGEuZGVzdGluYXRpb24pOyBuLnN0YXJ0KCk7IG4uc3RvcChhLmN1cnJlbnRUaW1lKy42NCk7Cn0KZnVuY3Rpb24gc2Z4SmFja3BvdCgpewogIGNvbnN0IGE9YXVkaW8oKTsgaWYoIWEpIHJldHVybjsKICBbMzkyLDUyMyw2NTksNzg0LDEwNDcsMTMxOV0uZm9yRWFjaCgoaHosaSk9PnsKICAgIGNvbnN0IG89YS5jcmVhdGVPc2NpbGxhdG9yKCksIGc9YS5jcmVhdGVHYWluKCksIHQwPWEuY3VycmVudFRpbWUraSouMDYyOwogICAgby50eXBlPSd0cmlhbmdsZSc7IG8uZnJlcXVlbmN5LnZhbHVlPWh6OwogICAgZy5nYWluLnNldFZhbHVlQXRUaW1lKC4wMDEsdDApOyBnLmdhaW4uZXhwb25lbnRpYWxSYW1wVG9WYWx1ZUF0VGltZSguMTEsdDArLjAxNSk7CiAgICBnLmdhaW4uZXhwb25lbnRpYWxSYW1wVG9WYWx1ZUF0VGltZSguMDAwMSx0MCsuNDIpOwogICAgby5jb25uZWN0KGcpOyBnLmNvbm5lY3QoYS5kZXN0aW5hdGlvbik7IG8uc3RhcnQodDApOyBvLnN0b3AodDArLjQ0KTsKICB9KTsKfQoKLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiAgIEFCSVNTTyBDT1NNSUNPIOKAlCBwaWxhIGRpIHBpYW5pIGEgcHJvZm9uZGl0w6AgY3Jlc2NlbnRlCiAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogICB6ID0gInZpY2luYW56YSI6IDAuMDUgPSBmb25kbyBkZWxsJ2FiaXNzbyDCtyAxLjAwID0gcGlhbm8gZGkgZ2lvY28KICAgICAgICAgICAgICAgICAgICAxLjkwID0gcHVsdmlzY29sbyBjaGUgc2ZpbGEgZGF2YW50aSBhbGwnb2JpZXR0aXZvCiAgIEkgcGlhbmkgY29udGludWkgKG5lYnVsb3NlLCBwb2x2ZXJpLCBzdGVsbGUpIHNvbm8gcHJlLXJlbmRlcml6emF0aQogICBVTkEgdm9sdGEgc3UgY2FudmFzIG9mZnNjcmVlbiBlIHNjb3Jyb25vIGNvbiAyIHNvbGUgZHJhd0ltYWdlOgogICBjb3N0byBwZXIgZnJhbWUgY29zdGFudGUsIGluZGlwZW5kZW50ZSBkYWwgbnVtZXJvIGRpIHN0ZWxsZS4KICAgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICovCmNvbnN0IEFCWSA9IHtzaGVldHM6W10sIGJvZGllczpbXSwgaHVsa3M6W10sIG1vdGVzOltdLCBjYW1YOjAsIHRCb2R5OjEuMiwgdEh1bGs6LjYsIHZpZ246bnVsbH07CmNvbnN0IFNDUk9MTCA9IDEzMjsgICAgICAgICAgICAgICAgICAgICAgIC8vIHB4L3MgZGkgcmlmZXJpbWVudG8gYSB6ID0gMQpjb25zdCBNQVJHSU4gPSA5MDsgICAgICAgICAgICAgICAgICAgICAgICAvLyBtYXJnaW5lIGxhdGVyYWxlIHBlciBsYSBkZXJpdmEgb3JpenpvbnRhbGUKCi8qIC0tLSBmYWJicmljYSBkaSBjYW52YXMgb2Zmc2NyZWVuIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqLwpmdW5jdGlvbiBzaGVldCh3LGgscGFpbnQpewogIGNvbnN0IGM9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7IGMud2lkdGg9dzsgYy5oZWlnaHQ9aDsKICBwYWludChjLmdldENvbnRleHQoJzJkJyksIHcsIGgpOyByZXR1cm4gYzsKfQoKLyogc3RlbGxlOiB3cmFwIHZlcnRpY2FsZSByZXBsaWNhbmRvIGkgY29ycGkgYSBjYXZhbGxvIGRlbGxhIGN1Y2l0dXJhICovCmZ1bmN0aW9uIHN0YXJTaGVldCh3LGgsbixvKXsKICByZXR1cm4gc2hlZXQodyxoLGc9PnsKICAgIGZvcihsZXQgaT0wO2k8bjtpKyspewogICAgICBjb25zdCB4PXJuZCgwLHcpLCB5PXJuZCgwLGgpLCByPXJuZChvLnJtaW4sby5ybWF4KSwgYT1ybmQoby5hbWluLG8uYW1heCk7CiAgICAgIGNvbnN0IHB1dD15eT0+ewogICAgICAgIGlmKHI+MS4yNSl7CiAgICAgICAgICBjb25zdCBncj1nLmNyZWF0ZVJhZGlhbEdyYWRpZW50KHgseXksMCx4LHl5LHIqMy40KTsKICAgICAgICAgIGdyLmFkZENvbG9yU3RvcCgwLGByZ2JhKCR7by50aW50fSwke2F9KWApOwogICAgICAgICAgZ3IuYWRkQ29sb3JTdG9wKC4zMixgcmdiYSgke28udGludH0sJHthKi4zfSlgKTsKICAgICAgICAgIGdyLmFkZENvbG9yU3RvcCgxLGByZ2JhKCR7by50aW50fSwwKWApOwogICAgICAgICAgZy5maWxsU3R5bGU9Z3I7IGcuYmVnaW5QYXRoKCk7IGcuYXJjKHgseXksciozLjQsMCxUQVUpOyBnLmZpbGwoKTsKICAgICAgICB9CiAgICAgICAgZy5maWxsU3R5bGU9YHJnYmEoJHtvLmNvcmV8fG8udGludH0sJHtNYXRoLm1pbigxLGEqMS4zNSl9KWA7CiAgICAgICAgZy5maWxsUmVjdCh4LXIvMiwgeXktci8yLCByLCByKTsKICAgICAgfTsKICAgICAgcHV0KHkpOwogICAgICBpZih5IDwgaCouMTApIHB1dCh5K2gpOyBlbHNlIGlmKHkgPiBoKi45MCkgcHV0KHktaCk7CiAgICB9CiAgfSk7Cn0KCi8qIG5lYnVsb3NlOiBtYXNzZSBkaWZmdXNlLCBpbCBmb25kbyBjcm9tYXRpY28gZGVsbCdhYmlzc28gKi8KZnVuY3Rpb24gbmVidWxhU2hlZXQodyxoKXsKICBjb25zdCBjb2xzPVtbODYsNDQsMTg2XSxbMjIsNzQsMTc4XSxbMTcyLDMwLDExNl0sWzE0LDQ0LDEyMF0sWzQwLDE2MCwxOTBdXTsKICByZXR1cm4gc2hlZXQodyxoLGc9PnsKICAgIGZvcihsZXQgaT0wO2k8MjQ7aSsrKXsKICAgICAgY29uc3QgeD1ybmQoLXcqLjE1LHcqMS4xNSksIHk9cm5kKDAsaCksIHI9cm5kKGgqLjE0LGgqLjQ2KSwKICAgICAgICAgICAgYz1jb2xzW3JuZGkoMCxjb2xzLmxlbmd0aC0xKV0sIGE9cm5kKC4wNDUsLjE1KTsKICAgICAgY29uc3QgcHV0PXl5PT57CiAgICAgICAgY29uc3QgZ3I9Zy5jcmVhdGVSYWRpYWxHcmFkaWVudCh4LHl5LDAseCx5eSxyKTsKICAgICAgICBnci5hZGRDb2xvclN0b3AoMCwgIGByZ2JhKCR7Y1swXX0sJHtjWzFdfSwke2NbMl19LCR7YX0pYCk7CiAgICAgICAgZ3IuYWRkQ29sb3JTdG9wKC41LCBgcmdiYSgke2NbMF19LCR7Y1sxXX0sJHtjWzJdfSwke2EqLjR9KWApOwogICAgICAgIGdyLmFkZENvbG9yU3RvcCgxLCAgYHJnYmEoJHtjWzBdfSwke2NbMV19LCR7Y1syXX0sMClgKTsKICAgICAgICBnLmZpbGxTdHlsZT1ncjsgZy5iZWdpblBhdGgoKTsgZy5hcmMoeCx5eSxyLDAsVEFVKTsgZy5maWxsKCk7CiAgICAgIH07CiAgICAgIHB1dCh5KTsgcHV0KHktaCk7IHB1dCh5K2gpOwogICAgfQogIH0pOwp9CgovKiB2aWduZXR0YXR1cmE6IGNoaXVkZSBpIGJvcmRpIGUgc2NhdmEgaWwgY2VudHJvIOKAlCBzZW5zYXppb25lIGRpIHBvenpvICovCmZ1bmN0aW9uIHZpZ25ldHRlU2hlZXQoKXsKICByZXR1cm4gc2hlZXQoVyxILChnLHcsaCk9PnsKICAgIGNvbnN0IGdyPWcuY3JlYXRlUmFkaWFsR3JhZGllbnQody8yLGgqLjU1LE1hdGgubWluKHcsaCkqLjE4LHcvMixoKi41NSxNYXRoLm1heCh3LGgpKi43OCk7CiAgICBnci5hZGRDb2xvclN0b3AoMCwncmdiYSgwLDAsMCwwKScpOwogICAgZ3IuYWRkQ29sb3JTdG9wKC41NSwncmdiYSgyLDMsMTAsLjI4KScpOwogICAgZ3IuYWRkQ29sb3JTdG9wKDEsJ3JnYmEoMSwyLDcsLjgyKScpOwogICAgZy5maWxsU3R5bGU9Z3I7IGcuZmlsbFJlY3QoMCwwLHcsaCk7CiAgfSk7Cn0KCmZ1bmN0aW9uIGJ1aWxkQWJ5c3MoKXsKICBjb25zdCB3ID0gVyArIE1BUkdJTioyOwogIEFCWS5zaGVldHMgPSBbCiAgICB7YzpuZWJ1bGFTaGVldCh3LEgpLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB6Oi4wNSwgeTowLCBhOjEgIH0sCiAgICB7YzpzdGFyU2hlZXQodyxILCBNYXRoLnJvdW5kKFcqSC81MjAwKSwge3JtaW46LjUscm1heDoxLjEsYW1pbjouMDgsYW1heDouMjYsdGludDonMTMyLDE2NCwyMjQnfSksIHo6LjEyLCB5OjAsIGE6MX0sCiAgICB7YzpzdGFyU2hlZXQodyxILCBNYXRoLnJvdW5kKFcqSC85MDAwKSwge3JtaW46Ljgscm1heDoxLjcsYW1pbjouMjIsYW1heDouNDgsdGludDonMTc2LDIwMCwyNDYnfSksIHo6LjM0LCB5OjAsIGE6MX0sCiAgICB7YzpzdGFyU2hlZXQodyxILCBNYXRoLnJvdW5kKFcqSC8xNjAwMCkse3JtaW46MS4xLHJtYXg6Mi40LGFtaW46LjQ1LGFtYXg6Ljk1LHRpbnQ6JzE1MCwyMTQsMjU1Jyxjb3JlOicyMzgsMjQ4LDI1NSd9KSwgejouNzgsIHk6MCwgYToxfQogIF07CiAgQUJZLnZpZ24gPSB2aWduZXR0ZVNoZWV0KCk7CiAgQUJZLmJvZGllcy5sZW5ndGggPSBBQlkuaHVsa3MubGVuZ3RoID0gMDsKCiAgLyogcHVsdmlzY29sbyBkaSBwcmltbyBwaWFubzogdW5pY28gc3RyYXRvIGNoZSBzZmlsYSBTT1BSQSBsYSBuYXZpY2VsbGEgKi8KICBBQlkubW90ZXMubGVuZ3RoPTA7CiAgZm9yKGxldCBpPTA7aTwxNDtpKyspCiAgICBBQlkubW90ZXMucHVzaCh7eDpybmQoMCxXKSwgeTpybmQoMCxIKSwgcjpybmQoMyw5KSwgejpybmQoMS41LDIuMyksIGE6cm5kKC4wNiwuMTYpfSk7Cn0KCi8qIC0tLSBjb3JwaSBjZWxlc3RpOiBwaWFuZXRpIGxvbnRhbmlzc2ltaSwgcXVhc2kgaW1tb2JpbGkgLS0tLS0tLS0tLSAqLwpmdW5jdGlvbiBzcGF3bkJvZHkoKXsKICBjb25zdCByID0gcm5kKFcqLjEyLCBXKi4zNCk7CiAgQUJZLmJvZGllcy5wdXNoKHsKICAgIHg6IHJuZCgtciouMzUsIFcrciouMzUpLCB5OiAtcioxLjUsIHIsCiAgICB6OiBybmQoLjA5LC4yMCksIGh1ZTogcm5kKDE4NSwzMjUpLCBhOiBybmQoLjMwLC41MiksCiAgICByaW5nOiBNYXRoLnJhbmRvbSgpPC4zMiwgdGlsdDogcm5kKC0uNSwuNSkKICB9KTsKfQpmdW5jdGlvbiBkcmF3Qm9keShiKXsKICBjb25zdCB4PWIueCArIEFCWS5jYW1YKk1BUkdJTipiLnoqLTEsIHk9Yi55OwogIC8qIGFsb25lIGF0bW9zZmVyaWNvICovCiAgY29uc3QgaD1jdHguY3JlYXRlUmFkaWFsR3JhZGllbnQoeCx5LGIuciouOTIseCx5LGIucioxLjMpOwogIGguYWRkQ29sb3JTdG9wKDAsYGhzbGEoJHtiLmh1ZX0sNzAlLDYwJSwke2IuYSouMjJ9KWApOwogIGguYWRkQ29sb3JTdG9wKDEsYGhzbGEoJHtiLmh1ZX0sNzAlLDYwJSwwKWApOwogIGN0eC5maWxsU3R5bGU9aDsgY3R4LmJlZ2luUGF0aCgpOyBjdHguYXJjKHgseSxiLnIqMS4zLDAsVEFVKTsgY3R4LmZpbGwoKTsKICAvKiBkaXNjbywgaWxsdW1pbmF0byBkYWxsJ2FsdG8gYSBzaW5pc3RyYSAqLwogIGNvbnN0IGc9Y3R4LmNyZWF0ZVJhZGlhbEdyYWRpZW50KHgtYi5yKi40Mix5LWIuciouNDIsYi5yKi4wNCx4LHksYi5yKTsKICBnLmFkZENvbG9yU3RvcCgwLCAgYGhzbGEoJHtiLmh1ZX0sNDYlLDU0JSwke2IuYX0pYCk7CiAgZy5hZGRDb2xvclN0b3AoLjUsIGBoc2xhKCR7Yi5odWV9LDQyJSwyNSUsJHtiLmF9KWApOwogIGcuYWRkQ29sb3JTdG9wKDEsICBgaHNsYSgke2IuaHVlfSw1MiUsNiUsJHtiLmF9KWApOwogIGN0eC5maWxsU3R5bGU9ZzsgY3R4LmJlZ2luUGF0aCgpOyBjdHguYXJjKHgseSxiLnIsMCxUQVUpOyBjdHguZmlsbCgpOwogIGlmKGIucmluZyl7CiAgICBjdHguc2F2ZSgpOyBjdHgudHJhbnNsYXRlKHgseSk7IGN0eC5yb3RhdGUoYi50aWx0KTsKICAgIGN0eC5zdHJva2VTdHlsZT1gaHNsYSgke2IuaHVlfSw0MCUsNjglLCR7Yi5hKi40fSlgOyBjdHgubGluZVdpZHRoPWIuciouMDk7CiAgICBjdHguYmVnaW5QYXRoKCk7IGN0eC5lbGxpcHNlKDAsMCxiLnIqMS40MixiLnIqLjMwLDAsMCxUQVUpOyBjdHguc3Ryb2tlKCk7CiAgICBjdHgucmVzdG9yZSgpOwogIH0KfQoKLyogLS0tIHJlbGl0dGk6IHJvY2NlIGRlbCBwaWFubyBwcm9mb25kbywgZnVvcmkgZnVvY28gZSBkZXNhdHVyYXRlIC0tLSAqLwpmdW5jdGlvbiBzcGF3bkh1bGsoKXsKICBjb25zdCB6ID0gcm5kKC4yNCwuNTYpLCByID0gcm5kKDksMzIpOwogIGNvbnN0IHZlcnRzPVtdLCBuPXJuZGkoNywxMCk7CiAgZm9yKGxldCBpPTA7aTxuO2krKykgdmVydHMucHVzaCh7YTooaS9uKSpUQVUsIG06cm5kKC43LDEuMTUpfSk7CiAgQUJZLmh1bGtzLnB1c2goe3g6cm5kKC00MCxXKzQwKSwgeTotNjAsIHIsIHosIHZlcnRzLCByb3Q6cm5kKDAsVEFVKSwgdnJvdDpybmQoLS41LC41KX0pOwp9CmZ1bmN0aW9uIGRyYXdIdWxrKGspewogIGNvbnN0IHg9ay54ICsgQUJZLmNhbVgqTUFSR0lOKmsueiotMSwgYT0uMjAray56Ki41NTsKICBjdHguc2F2ZSgpOyBjdHgudHJhbnNsYXRlKHgsay55KTsgY3R4LnJvdGF0ZShrLnJvdCk7CiAgY3R4LmJlZ2luUGF0aCgpOwogIGZvcihsZXQgaT0wO2k8ay52ZXJ0cy5sZW5ndGg7aSsrKXsKICAgIGNvbnN0IHY9ay52ZXJ0c1tpXSwgcHg9TWF0aC5jb3Modi5hKSprLnIqdi5tLCBweT1NYXRoLnNpbih2LmEpKmsucip2Lm07CiAgICBpPyBjdHgubGluZVRvKHB4LHB5KSA6IGN0eC5tb3ZlVG8ocHgscHkpOwogIH0KICBjdHguY2xvc2VQYXRoKCk7CiAgY29uc3QgZz1jdHguY3JlYXRlUmFkaWFsR3JhZGllbnQoLWsuciouMywtay5yKi4zLGsuciouMSwwLDAsay5yKjEuMik7CiAgZy5hZGRDb2xvclN0b3AoMCxgcmdiYSg1OCw3NiwxMTYsJHthfSlgKTsKICBnLmFkZENvbG9yU3RvcCgxLGByZ2JhKDgsMTIsMjYsJHthfSlgKTsKICBjdHguZmlsbFN0eWxlPWc7IGN0eC5maWxsKCk7CiAgY3R4LmxpbmVXaWR0aD0xOyBjdHguc3Ryb2tlU3R5bGU9YHJnYmEoOTYsMTM4LDIwOCwke2EqLjMwfSlgOyBjdHguc3Ryb2tlKCk7CiAgY3R4LnJlc3RvcmUoKTsKfQoKLyogLS0tIGRpc2Vnbm8gZGVsbCdpbnRlcmEgcGlsYSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovCmZ1bmN0aW9uIGRyYXdBYnlzcyhkdCwgbXVsKXsKICAvKiBkZXJpdmEgbGF0ZXJhbGU6IGxhIG5hdmljZWxsYSAic3Bvc3RhIiBsYSBwYXJhbGxhc3NlIGNvbWUgdW5hIGNhbWVyYSAqLwogIGNvbnN0IHJhdyA9IHNoaXAgJiYgTnVtYmVyLmlzRmluaXRlKHNoaXAueCkgPyAoc2hpcC54LVcvMikvKFcvMikgOiAwOwogIGNvbnN0IHRndCA9IGNsYW1wKHJhdywtMSwxKTsKICBBQlkuY2FtWCArPSAodGd0LUFCWS5jYW1YKSAqIE1hdGgubWluKDEsIGR0KjIuNik7CiAgaWYoIU51bWJlci5pc0Zpbml0ZShBQlkuY2FtWCkpIEFCWS5jYW1YPTA7CgogIC8qIHBpYW5pIGNvbnRpbnVpICovCiAgZm9yKGxldCBpPTA7aTxBQlkuc2hlZXRzLmxlbmd0aDtpKyspewogICAgY29uc3Qgcz1BQlkuc2hlZXRzW2ldOwogICAgcy55ID0gKHMueSArIFNDUk9MTCpzLnoqbXVsKmR0KSAlIEg7CiAgICBjb25zdCB4ID0gLU1BUkdJTiAtIEFCWS5jYW1YKk1BUkdJTipzLno7CiAgICBjdHguZHJhd0ltYWdlKHMuYywgeCwgcy55IC0gSCk7CiAgICBjdHguZHJhd0ltYWdlKHMuYywgeCwgcy55KTsKICAgIC8qIHBzZXVkbyBtb3Rpb24tYmx1ciBzdWwgcGlhbm8gcGnDuSB2aWNpbm8gYWxsZSBhbHRlIHZlbG9jaXTDoCAqLwogICAgaWYocy56Pi42ICYmIG11bD4xLjI1KXsKICAgICAgY3R4Lmdsb2JhbEFscGhhPS4zMDsKICAgICAgY29uc3Qgb2ZmPTEwKihtdWwtMSk7CiAgICAgIGN0eC5kcmF3SW1hZ2Uocy5jLCB4LCBzLnktSC1vZmYpOyBjdHguZHJhd0ltYWdlKHMuYywgeCwgcy55LW9mZik7CiAgICAgIGN0eC5nbG9iYWxBbHBoYT0xOwogICAgfQogIH0KCiAgLyogY29ycGkgY2VsZXN0aSAqLwogIEFCWS50Qm9keS09ZHQ7CiAgaWYoQUJZLnRCb2R5PD0wICYmIEFCWS5ib2RpZXMubGVuZ3RoPDIpeyBzcGF3bkJvZHkoKTsgQUJZLnRCb2R5PXJuZCg5LDIwKTsgfQogIGZvcihsZXQgaT1BQlkuYm9kaWVzLmxlbmd0aC0xO2k+PTA7aS0tKXsKICAgIGNvbnN0IGI9QUJZLmJvZGllc1tpXTsKICAgIGIueSArPSBTQ1JPTEwqYi56Km11bCpkdDsKICAgIGlmKGIueS1iLnIqMS40ID4gSCl7IEFCWS5ib2RpZXMuc3BsaWNlKGksMSk7IGNvbnRpbnVlOyB9CiAgICBkcmF3Qm9keShiKTsKICB9CgogIC8qIHJlbGl0dGkgZGVsIHBpYW5vIGludGVybWVkaW8gKi8KICBBQlkudEh1bGstPWR0OwogIGlmKEFCWS50SHVsazw9MCl7IHNwYXduSHVsaygpOyBBQlkudEh1bGs9cm5kKDEuMSwzLjQpOyB9CiAgZm9yKGxldCBpPUFCWS5odWxrcy5sZW5ndGgtMTtpPj0wO2ktLSl7CiAgICBjb25zdCBrPUFCWS5odWxrc1tpXTsKICAgIGsueSArPSBTQ1JPTEwqay56KjEuNyptdWwqZHQ7IGsucm90ICs9IGsudnJvdCpkdDsKICAgIGlmKGsueS1rLnIgPiBIKzQwKXsgQUJZLmh1bGtzLnNwbGljZShpLDEpOyBjb250aW51ZTsgfQogICAgZHJhd0h1bGsoayk7CiAgfQoKICBjdHguZHJhd0ltYWdlKEFCWS52aWduLCAwLCAwKTsKfQoKLyogcHVsdmlzY29sbyBpbiBwcmltbyBwaWFubyDigJQgZGlzZWduYXRvIERPUE8gbGEgbmF2aWNlbGxhICovCmZ1bmN0aW9uIGRyYXdNb3RlcyhkdCwgbXVsKXsKICBjdHguc2F2ZSgpOyBjdHguZ2xvYmFsQ29tcG9zaXRlT3BlcmF0aW9uPSdsaWdodGVyJzsKICBmb3IobGV0IGk9MDtpPEFCWS5tb3Rlcy5sZW5ndGg7aSsrKXsKICAgIGNvbnN0IG09QUJZLm1vdGVzW2ldOwogICAgbS55ICs9IFNDUk9MTCptLnoqMi40Km11bCpkdDsKICAgIGlmKG0ueS1tLnIgPiBIKXsgbS55PS1tLnIqMjsgbS54PXJuZCgwLFcpOyB9CiAgICBjb25zdCB4ID0gbS54IC0gQUJZLmNhbVgqTUFSR0lOKm0ueiouNTU7CiAgICBjb25zdCBnPWN0eC5jcmVhdGVSYWRpYWxHcmFkaWVudCh4LG0ueSwwLHgsbS55LG0ucik7CiAgICBnLmFkZENvbG9yU3RvcCgwLGByZ2JhKDE5MCwyMjQsMjU1LCR7bS5hfSlgKTsKICAgIGcuYWRkQ29sb3JTdG9wKDEsJ3JnYmEoMTkwLDIyNCwyNTUsMCknKTsKICAgIGN0eC5maWxsU3R5bGU9ZzsgY3R4LmJlZ2luUGF0aCgpOyBjdHguYXJjKHgsbS55LG0uciwwLFRBVSk7IGN0eC5maWxsKCk7CiAgfQogIGN0eC5yZXN0b3JlKCk7Cn0KCi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQogICBPTUJSRSBQUk9JRVRUQVRFIOKAlCBwcm9pZXppb25lIGNlbnRyYWxlIGRhbCBwdW50byBkaSB2aXN0YQogICBUdXR0byBjacOyIGNoZSBzdGEgc3VsIHBpYW5vIGRpIGdpb2NvIGdldHRhIGxhIHByb3ByaWEgb21icmEgc3VsCiAgIGZvbmRvIGRlbGwnYWJpc3NvOiDDqCBpbCBzZWduYWxlIGNoZSBkaWNlICJzdG8gdm9sYW5kbyBTT1BSQSIuCiAgID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqLwpjb25zdCBTSF9TUFJFQUQgPSAxLjE5OyAgICAgICAgICAgICAgICAgICAvLyBkaXZlcmdlbnphIGRlbGxhIHByb2llemlvbmUKZnVuY3Rpb24gcHJvalgoeCl7IHJldHVybiBXLzIgKyAoeC1XLzIpKlNIX1NQUkVBRDsgfQpmdW5jdGlvbiBwcm9qWSh5KXsgcmV0dXJuIEgqLjQyICsgKHktSCouNDIpKlNIX1NQUkVBRDsgfQoKZnVuY3Rpb24gc2hhZG93Um9jayhhKXsKICBjb25zdCB4PXByb2pYKGEueCksIHk9cHJvalkoYS55KSwgcj1hLnIqLjg2OwogIGN0eC5nbG9iYWxBbHBoYT0uMzA7CiAgY29uc3QgZz1jdHguY3JlYXRlUmFkaWFsR3JhZGllbnQoeCx5LHIqLjIseCx5LHIqMS4yNSk7CiAgZy5hZGRDb2xvclN0b3AoMCwncmdiYSgwLDAsMCwuODUpJyk7IGcuYWRkQ29sb3JTdG9wKDEsJ3JnYmEoMCwwLDAsMCknKTsKICBjdHguZmlsbFN0eWxlPWc7IGN0eC5iZWdpblBhdGgoKTsgY3R4LmFyYyh4LHkscioxLjI1LDAsVEFVKTsgY3R4LmZpbGwoKTsKICBjdHguZ2xvYmFsQWxwaGE9MTsKfQpmdW5jdGlvbiBzaGFkb3dTaGlwKHMpewogIGlmKHMuaW52PjAgJiYgTWF0aC5mbG9vcihzLmludioxNCklMj09PTApIHJldHVybjsKICBjdHguc2F2ZSgpOwogIGN0eC50cmFuc2xhdGUocHJvalgocy54KSwgcHJvalkocy55KSk7CiAgY3R4LnJvdGF0ZShzLnRpbHQqLjcpOwogIGZvcihsZXQgaT0wO2k8MztpKyspeyAgICAgICAgICAgICAgICAgICAgLy8gMyBwYXNzYXRlID0gc2ZvY2F0dXJhIGEgY29zdG8gemVybwogICAgY3R4LnNhdmUoKTsgY3R4LnNjYWxlKC44MCtpKi4xMywgLjgwK2kqLjEzKTsKICAgIGN0eC5nbG9iYWxBbHBoYT0uMTQ7CiAgICBjdHguYmVnaW5QYXRoKCk7CiAgICBjdHgubW92ZVRvKDAsLTIyKTsgY3R4LmxpbmVUbygxMywxMyk7IGN0eC5saW5lVG8oNSw4KTsKICAgIGN0eC5saW5lVG8oMCwxMik7ICBjdHgubGluZVRvKC01LDgpOyAgY3R4LmxpbmVUbygtMTMsMTMpOwogICAgY3R4LmNsb3NlUGF0aCgpOyBjdHguZmlsbFN0eWxlPScjMDAwJzsgY3R4LmZpbGwoKTsKICAgIGN0eC5yZXN0b3JlKCk7CiAgfQogIGN0eC5yZXN0b3JlKCk7Cn0KCi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQogICBOQVZJQ0VMTEEKICAgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICovCmZ1bmN0aW9uIG1ha2VTaGlwKCl7CiAgcmV0dXJuIHt4OlcvMiwgeTpILTk2LCB2eDowLCB0aWx0OjAsIHI6MTUsIGludjoyLjIsIGFsaXZlOnRydWUsIHRocjowfTsKfQpmdW5jdGlvbiBkcmF3U2hpcChzKXsKICBpZihzLmludj4wICYmIE1hdGguZmxvb3Iocy5pbnYqMTQpJTI9PT0wKSByZXR1cm47ICAvLyBsYW1wZWdnaW8gaW52dWxuZXJhYmlsaXTDoAogIGN0eC5zYXZlKCk7CiAgY3R4LnRyYW5zbGF0ZShzLngsIHMueSk7CiAgY3R4LnJvdGF0ZShzLnRpbHQpOwoKICAvKiBzY2lhIG1vdG9yZSAqLwogIGNvbnN0IGZsID0gMTggKyBNYXRoLnNpbih0KjQwKSo1ICsgcy50aHIqMTA7CiAgY3R4Lmdsb2JhbENvbXBvc2l0ZU9wZXJhdGlvbj0nbGlnaHRlcic7CiAgY29uc3QgZmcgPSBjdHguY3JlYXRlTGluZWFyR3JhZGllbnQoMCw4LDAsOCtmbCk7CiAgZmcuYWRkQ29sb3JTdG9wKDAsJ3JnYmEoMjU1LDI1NSwyNTUsLjk1KScpOwogIGZnLmFkZENvbG9yU3RvcCguMzUsJ3JnYmEoNzAsMjMwLDI1NSwuNzUpJyk7CiAgZmcuYWRkQ29sb3JTdG9wKDEsJ3JnYmEoNzAsMjMwLDI1NSwwKScpOwogIGN0eC5maWxsU3R5bGU9Zmc7CiAgY3R4LmJlZ2luUGF0aCgpOyBjdHgubW92ZVRvKC01LDgpOyBjdHgubGluZVRvKDUsOCk7IGN0eC5saW5lVG8oMCw4K2ZsKTsgY3R4LmNsb3NlUGF0aCgpOyBjdHguZmlsbCgpOwogIGN0eC5nbG9iYWxDb21wb3NpdGVPcGVyYXRpb249J3NvdXJjZS1vdmVyJzsKCiAgLyogc2NhZm8gKi8KICBjdHguYmVnaW5QYXRoKCk7CiAgY3R4Lm1vdmVUbygwLC0yMik7IGN0eC5saW5lVG8oMTMsMTMpOyBjdHgubGluZVRvKDUsOCk7CiAgY3R4LmxpbmVUbygwLDEyKTsgIGN0eC5saW5lVG8oLTUsOCk7ICBjdHgubGluZVRvKC0xMywxMyk7CiAgY3R4LmNsb3NlUGF0aCgpOwogIGNvbnN0IGhnPWN0eC5jcmVhdGVMaW5lYXJHcmFkaWVudCgwLC0yMiwwLDEzKTsKICBoZy5hZGRDb2xvclN0b3AoMCwnI2YyZjdmZicpOyBoZy5hZGRDb2xvclN0b3AoLjUsJyM5ZmI0ZDgnKTsgaGcuYWRkQ29sb3JTdG9wKDEsJyMzZDRhNjgnKTsKICBjdHguZmlsbFN0eWxlPWhnOyBjdHguZmlsbCgpOwogIGN0eC5saW5lV2lkdGg9MS40OyBjdHguc3Ryb2tlU3R5bGU9J3JnYmEoNzAsMjMwLDI1NSwuOSknOwogIGN0eC5zaGFkb3dDb2xvcj0ncmdiYSg3MCwyMzAsMjU1LC44KSc7IGN0eC5zaGFkb3dCbHVyPTEyOyBjdHguc3Ryb2tlKCk7IGN0eC5zaGFkb3dCbHVyPTA7CgogIC8qIHBvenpldHRvICovCiAgY3R4LmJlZ2luUGF0aCgpOyBjdHguZWxsaXBzZSgwLC02LDQsNywwLDAsVEFVKTsKICBjdHguZmlsbFN0eWxlPSdyZ2JhKDI1NSw0NiwxMDcsLjkpJzsgY3R4LmZpbGwoKTsKICBjdHgucmVzdG9yZSgpOwp9CgovKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KICAgQVNURVJPSURJIOKAlCBwZWxsZSBwZXIgY2ludHVyYSBkaSBsaXZlbGxvICsgY2FyaWNhIHNwZWNpYWxlCiAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogICBPZ25pIGxpdmVsbG8gYXR0cmF2ZXJzYSB1bmEgY2ludHVyYSBkaXZlcnNhOiBmb3JtYSwgc3BpZ29sb3NpdMOgLAogICBudW1lcm8gZGkgY3JhdGVyaSBlIGNyb21hdGlzbW8gY2FtYmlhbm8uIERhbCBsaXZlbGxvIDMgdW5hIHBhcnRlCiAgIGRlZ2xpIGFzdGVyb2lkaSB0cmFzcG9ydGEgdW5hIGNhcmljYSwgbWFyY2hpYXRhIHN1bCBjb3Jwby4KICAgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICovCmNvbnN0IFNLSU5TPVsKICB7bm9tZTonQ0lOVFVSQSBESSBST0NDSUEnLCAgIGh1ZToyNiwgIHNhdDoyNiwgbGl0OjM2LCBuOls5LDEzXSwgIGphZzpbLjcyLDEuMTRdLCBjcmF0OlsyLDRdfSwKICB7bm9tZTonQ0FNUE8gREkgR0hJQUNDSU8nLCAgIGh1ZToxOTgsIHNhdDozMCwgbGl0OjQ4LCBuOls3LDldLCAgIGphZzpbLjYwLDEuMjJdLCBjcmF0OlsxLDJdfSwKICB7bm9tZTonU0NPUklFIEZFUlJPU0UnLCAgICAgIGh1ZTo4LCAgIHNhdDozMiwgbGl0OjMwLCBuOlsxMSwxNV0sIGphZzpbLjgyLDEuMDZdLCBjcmF0OlszLDVdfSwKICB7bm9tZTonVkVOQSBDUklTVEFMTElOQScsICAgIGh1ZToyODIsIHNhdDo0MCwgbGl0OjQyLCBuOls1LDddLCAgIGphZzpbLjUyLDEuMjhdLCBjcmF0OlswLDFdfSwKICB7bm9tZTonTlVCRSBUT1NTSUNBJywgICAgICAgIGh1ZTo5NiwgIHNhdDozNiwgbGl0OjM0LCBuOlsxMCwxNF0sIGphZzpbLjcwLDEuMTZdLCBjcmF0OlsyLDRdfSwKICB7bm9tZTonQkFOQ08gREkgT1NTSURJQU5BJywgIGh1ZToyMjIsIHNhdDoxNCwgbGl0OjIwLCBuOls2LDhdLCAgIGphZzpbLjU4LDEuMjRdLCBjcmF0OlsxLDNdfQpdOwpmdW5jdGlvbiBza2luRm9yKGx2bCl7CiAgY29uc3Qgcz1TS0lOU1tsdmwlU0tJTlMubGVuZ3RoXSwgZ2lybz1NYXRoLmZsb29yKGx2bC9TS0lOUy5sZW5ndGgpOwogIHJldHVybiB7bm9tZTpzLm5vbWUsIGh1ZToocy5odWUrZ2lybyo0NyklMzYwLCBzYXQ6cy5zYXQsIGxpdDpzLmxpdCwKICAgICAgICAgIG46cy5uLCBqYWc6cy5qYWcsIGNyYXQ6cy5jcmF0fTsKfQoKY29uc3QgTUFYTD02OyAgICAgICAgICAgICAgICAgICAgICAgLy8gc2NhZmkgYWNjdW11bGFiaWxpCmNvbnN0IENBUkdPX0xWPTM7ICAgICAgICAgICAgICAgICAgIC8vIGxpdmVsbG8gZGFsIHF1YWxlIGNvbXBhaW9ubyBsZSBjYXJpY2hlCgpmdW5jdGlvbiBwaWNrQ2FyZ28obHZsKXsKICBpZihsdmw8Q0FSR09fTFYpIHJldHVybiBudWxsOwogIGNvbnN0IG51a2U9TWF0aC5taW4oLjA4LCAuMDQwK2x2bCouMDA0KTsKICBjb25zdCByPU1hdGgucmFuZG9tKCk7CiAgaWYocjwuMTE1KSByZXR1cm4ge3Q6J3BsdXMnLCAgdmFsOiBybmRpKDIsMTIpKjI1MH07CiAgaWYocjwuMjA1KSByZXR1cm4ge3Q6J21pbnVzJywgdmFsOi1ybmRpKDIsMTIpKjI1MH07CiAgaWYocjwuMjU1KSByZXR1cm4ge3Q6J2xpZmUnLCAgbjogTWF0aC5yYW5kb20oKTwuNjI/MTooTWF0aC5yYW5kb20oKTwuNzU/MjozKX07CiAgaWYocjwuMjY4KSByZXR1cm4ge3Q6J211bHQnLCAgbTogTWF0aC5yYW5kb20oKTwuNzU/MjozfTsgICAgICAvLyB+MS4zJTogbW9sdG8gcmFybwogIGlmKHI8LjI2OCtudWtlKSByZXR1cm4ge3Q6J251a2UnfTsKICByZXR1cm4gbnVsbDsKfQoKZnVuY3Rpb24gc3Bhd25Sb2NrKCl7CiAgY29uc3Qgc2s9c2tpbkZvcihsZXZlbCksIGNhcmdvPXBpY2tDYXJnbyhsZXZlbCk7CiAgbGV0IHI9cm5kKDE1LDQ0KTsKICBpZihjYXJnbykgciA9IChjYXJnby50PT09J211bHQnfHxjYXJnby50PT09J2xpZmUnKSA/IHJuZCgzNiw1MCkgOiBybmQoMjcsNDQpOwogIGNvbnN0IHZlcnRzPVtdLCBuPXJuZGkoc2sublswXSxzay5uWzFdKTsKICBmb3IobGV0IGk9MDtpPG47aSsrKSB2ZXJ0cy5wdXNoKHthOihpL24pKlRBVSwgbTpybmQoc2suamFnWzBdLHNrLmphZ1sxXSl9KTsKICBjb25zdCBjcmF0ZXJzPVtdOwogIGlmKCFjYXJnbykgZm9yKGxldCBpPTA7aTxybmRpKHNrLmNyYXRbMF0sc2suY3JhdFsxXSk7aSsrKXsKICAgIGNvbnN0IGE9cm5kKDAsVEFVKSwgZD1ybmQoMCxyKi41KTsKICAgIGNyYXRlcnMucHVzaCh7eDpNYXRoLmNvcyhhKSpkLCB5Ok1hdGguc2luKGEpKmQsIHI6cm5kKHIqLjEwLHIqLjI2KX0pOwogIH0KICBsZXQgc3BkID0gcm5kKDgwLDE1MCkqc3BlZWRNdWwoKTsKICBpZihjYXJnbykgc3BkICo9IC44MjsgICAgICAgICAgICAgLy8gbGUgY2FyaWNoZSB2YW5ubyBjb2xwaXRlOiByYWxsZW50YW5vCiAgcm9ja3MucHVzaCh7CiAgICB4OiBybmQociwgVy1yKSwgeTogLXItMTAsIHIsIHZlcnRzLCBjcmF0ZXJzLCBzaywgY2FyZ28sCiAgICB2eDogY2FyZ28/IHJuZCgtMzAsMzApIDogcm5kKC01Miw1MiksIHZ5OiBzcGQsCiAgICByb3Q6IHJuZCgwLFRBVSksIHZyb3Q6IHJuZCgtMS41LDEuNSkqKDMwL3IpLAogICAgaHVlOiBzay5odWUrcm5kKC05LDkpLCBib3JuOnQKICB9KTsKfQoKLyogLS0tIG1hcmNoaSBkZWxsZSBjYXJpY2hlIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovCmZ1bmN0aW9uIGdseXBoU2hpcChzKXsgICAgICAgICAgICAgICAgICAgICAgICAvLyBzYWdvbWEgZGVsbGEgbmF2aWNlbGxhIGluIG1pbmlhdHVyYQogIGN0eC5iZWdpblBhdGgoKTsKICBjdHgubW92ZVRvKDAsLTEuMSpzKTsgY3R4LmxpbmVUbyguNjUqcywuNjUqcyk7IGN0eC5saW5lVG8oLjI1KnMsLjQqcyk7CiAgY3R4LmxpbmVUbygwLC42KnMpOyAgIGN0eC5saW5lVG8oLS4yNSpzLC40KnMpOyBjdHgubGluZVRvKC0uNjUqcywuNjUqcyk7CiAgY3R4LmNsb3NlUGF0aCgpOwp9CmZ1bmN0aW9uIGdseXBoVHJlZm9pbChSKXsgICAgICAgICAgICAgICAgICAgICAvLyBzaW1ib2xvIGRpIHJhZGlvYXR0aXZpdMOgCiAgZm9yKGxldCBpPTA7aTwzO2krKyl7CiAgICBjb25zdCBjPS1NYXRoLlBJLzIraSpUQVUvMywgYTA9Yy1NYXRoLlBJLzYsIGExPWMrTWF0aC5QSS82OwogICAgY3R4LmJlZ2luUGF0aCgpOwogICAgY3R4LmFyYygwLDAsUixhMCxhMSk7IGN0eC5hcmMoMCwwLFIqLjM0LGExLGEwLHRydWUpOwogICAgY3R4LmNsb3NlUGF0aCgpOyBjdHguZmlsbCgpOwogIH0KICBjdHguYmVnaW5QYXRoKCk7IGN0eC5hcmMoMCwwLFIqLjIwLDAsVEFVKTsgY3R4LmZpbGwoKTsKfQoKZnVuY3Rpb24gY2FyZ29BdXJhKGEpewogIGNvbnN0IGM9YS5jYXJnbywgaz0oTWF0aC5zaW4odCo1K2EuYm9ybio3KSsxKS8yOwogIGlmKGMudD09PSdtdWx0J3x8Yy50PT09J2xpZmUnKXsKICAgIGNvbnN0IGNvbCA9IGMudD09PSdtdWx0JyA/ICcyNTUsMTk2LDQ0JyA6ICcxMTAsMjQwLDIwMCc7CiAgICBjdHguc2F2ZSgpOyBjdHguZ2xvYmFsQ29tcG9zaXRlT3BlcmF0aW9uPSdsaWdodGVyJzsKICAgIGNvbnN0IFI9YS5yKigyLjErayouNTUpOwogICAgY29uc3QgZz1jdHguY3JlYXRlUmFkaWFsR3JhZGllbnQoYS54LGEueSxhLnIqLjcsYS54LGEueSxSKTsKICAgIGcuYWRkQ29sb3JTdG9wKDAsYHJnYmEoJHtjb2x9LCR7LjM0K2sqLjI2fSlgKTsKICAgIGcuYWRkQ29sb3JTdG9wKC41NSxgcmdiYSgke2NvbH0sJHsuMTArayouMTB9KWApOwogICAgZy5hZGRDb2xvclN0b3AoMSxgcmdiYSgke2NvbH0sMClgKTsKICAgIGN0eC5maWxsU3R5bGU9ZzsgY3R4LmJlZ2luUGF0aCgpOyBjdHguYXJjKGEueCxhLnksUiwwLFRBVSk7IGN0eC5maWxsKCk7CiAgICAvKiByYWdnaSBkaSBsZW50ZSBpbmNyb2NpYXRpOiBzaSBub3Rhbm8gYW5jaGUgY29uIGxhIGNvZGEgZGVsbCdvY2NoaW8gKi8KICAgIGN0eC5zdHJva2VTdHlsZT1gcmdiYSgke2NvbH0sJHsuMzArayouM30pYDsgY3R4LmxpbmVXaWR0aD0yOwogICAgY29uc3QgTD1hLnIqKDIuNitrKi42KTsKICAgIGN0eC5iZWdpblBhdGgoKTsgY3R4Lm1vdmVUbyhhLngtTCxhLnkpOyBjdHgubGluZVRvKGEueCtMLGEueSk7CiAgICAgICAgICAgICAgICAgICAgIGN0eC5tb3ZlVG8oYS54LGEueS1MKTsgY3R4LmxpbmVUbyhhLngsYS55K0wpOyBjdHguc3Ryb2tlKCk7CiAgICBjdHgucmVzdG9yZSgpOwogIH0gZWxzZSBpZihjLnQ9PT0nbnVrZScpewogICAgY3R4LnNhdmUoKTsKICAgIGNvbnN0IFI9YS5yKigxLjcrayouMjUpOwogICAgY29uc3QgZz1jdHguY3JlYXRlUmFkaWFsR3JhZGllbnQoYS54LGEueSxhLnIqLjg1LGEueCxhLnksUik7CiAgICBnLmFkZENvbG9yU3RvcCgwLGByZ2JhKDI1NSwyMTQsMTAsJHsuMTYrayouMTR9KWApOwogICAgZy5hZGRDb2xvclN0b3AoMSwncmdiYSgyNTUsNjAsMTAsMCknKTsKICAgIGN0eC5maWxsU3R5bGU9ZzsgY3R4LmJlZ2luUGF0aCgpOyBjdHguYXJjKGEueCxhLnksUiwwLFRBVSk7IGN0eC5maWxsKCk7CiAgICBjdHgucmVzdG9yZSgpOwogIH0KfQoKZnVuY3Rpb24gY2FyZ29NYXJrKGEpewogIGNvbnN0IGM9YS5jYXJnbywgaz0oTWF0aC5zaW4odCo1K2EuYm9ybio3KSsxKS8yOwogIGN0eC5zYXZlKCk7IGN0eC50cmFuc2xhdGUoYS54LGEueSk7CgogIGlmKGMudD09PSdwbHVzJyB8fCBjLnQ9PT0nbWludXMnKXsKICAgIGNvbnN0IHBvcz1jLnQ9PT0ncGx1cycsIGNvbD1wb3M/JzExMCwyNDAsMTYwJzonMjU1LDQ2LDEwNyc7CiAgICBjb25zdCB0eHQ9KHBvcz8nKyc6J+KIkicpK01hdGguYWJzKGMudmFsKTsKICAgIGNvbnN0IGZzPU1hdGgubWF4KDExLCBhLnIqLjQ2KTsKICAgIGN0eC5mb250PWA4MDAgJHtNYXRoLnJvdW5kKGZzKX1weCB1aS1tb25vc3BhY2UsU0ZNb25vLVJlZ3VsYXIsTWVubG8sbW9ub3NwYWNlYDsKICAgIGNvbnN0IHR3PWN0eC5tZWFzdXJlVGV4dCh0eHQpLndpZHRoLCBwdz10dysxNCwgcGg9ZnMqMS41OwogICAgY3R4LmZpbGxTdHlsZT0ncmdiYSg0LDcsMTYsLjgyKSc7IHJyZWN0KC1wdy8yLC1waC8yLHB3LHBoLHBoKi4zKTsgY3R4LmZpbGwoKTsKICAgIGN0eC5saW5lV2lkdGg9MS42OyBjdHguc3Ryb2tlU3R5bGU9YHJnYmEoJHtjb2x9LC45NSlgOwogICAgY3R4LnNoYWRvd0NvbG9yPWByZ2JhKCR7Y29sfSwuOSlgOyBjdHguc2hhZG93Qmx1cj0xMjsgY3R4LnN0cm9rZSgpOwogICAgY3R4LnRleHRBbGlnbj0nY2VudGVyJzsgY3R4LnRleHRCYXNlbGluZT0nbWlkZGxlJzsKICAgIGN0eC5maWxsU3R5bGU9cG9zPycjYzhmZmRkJzonI2ZmZDBkZCc7IGN0eC5maWxsVGV4dCh0eHQsMCwxKTsKCiAgfSBlbHNlIGlmKGMudD09PSdsaWZlJyl7CiAgICBjb25zdCBzPWEuciouNDAsIHNwPXMqMS41NSwgeDA9LShjLm4tMSkqc3AvMjsKICAgIGN0eC5zYXZlKCk7IGN0eC5nbG9iYWxDb21wb3NpdGVPcGVyYXRpb249J2xpZ2h0ZXInOwogICAgZm9yKGxldCBpPTA7aTxjLm47aSsrKXsKICAgICAgY3R4LnNhdmUoKTsgY3R4LnRyYW5zbGF0ZSh4MCtpKnNwLCAwKTsgY3R4LnNjYWxlKDErayouMDYsMStrKi4wNik7CiAgICAgIGdseXBoU2hpcChzKTsKICAgICAgY3R4LmZpbGxTdHlsZT0ncmdiYSgyMjAsMjU1LDI0NSwuOTUpJzsKICAgICAgY3R4LnNoYWRvd0NvbG9yPSdyZ2JhKDExMCwyNDAsMjAwLDEpJzsgY3R4LnNoYWRvd0JsdXI9MTY7IGN0eC5maWxsKCk7CiAgICAgIGN0eC5yZXN0b3JlKCk7CiAgICB9CiAgICBjdHgucmVzdG9yZSgpOwogICAgY3R4LmJlZ2luUGF0aCgpOyBjdHguYXJjKDAsMCxhLnIqKC44NitrKi4wNiksMCxUQVUpOwogICAgY3R4LmxpbmVXaWR0aD0yLjI7IGN0eC5zdHJva2VTdHlsZT1gcmdiYSgxMTAsMjQwLDIwMCwkey41K2sqLjR9KWA7CiAgICBjdHguc2V0TGluZURhc2goWzYsN10pOyBjdHgubGluZURhc2hPZmZzZXQ9LXQqMzA7IGN0eC5zdHJva2UoKTsgY3R4LnNldExpbmVEYXNoKFtdKTsKCiAgfSBlbHNlIGlmKGMudD09PSdtdWx0Jyl7CiAgICBjb25zdCBmcz1NYXRoLm1heCgxOCwgYS5yKi44Nik7CiAgICBjdHguZm9udD1gOTAwICR7TWF0aC5yb3VuZChmcyl9cHggdWktbW9ub3NwYWNlLFNGTW9uby1SZWd1bGFyLE1lbmxvLG1vbm9zcGFjZWA7CiAgICBjdHgudGV4dEFsaWduPSdjZW50ZXInOyBjdHgudGV4dEJhc2VsaW5lPSdtaWRkbGUnOwogICAgY3R4LmxpbmVXaWR0aD00OyBjdHguc3Ryb2tlU3R5bGU9J3JnYmEoOTAsNDQsMCwuOSknOwogICAgY3R4LnN0cm9rZVRleHQoJ8OXJytjLm0sMCwxKTsKICAgIGN0eC5maWxsU3R5bGU9JyNmZmY2ZDgnOwogICAgY3R4LnNoYWRvd0NvbG9yPSdyZ2JhKDI1NSwyMTQsODAsMSknOyBjdHguc2hhZG93Qmx1cj0yMjsKICAgIGN0eC5maWxsVGV4dCgnw5cnK2MubSwwLDEpOwogICAgY3R4LnNoYWRvd0JsdXI9MDsKICAgIGN0eC5yb3RhdGUodCoxLjEpOwogICAgY3R4LmJlZ2luUGF0aCgpOyBjdHguYXJjKDAsMCxhLnIqMS4wMiwwLFRBVSk7CiAgICBjdHgubGluZVdpZHRoPTIuNDsgY3R4LnN0cm9rZVN0eWxlPWByZ2JhKDI1NSwyMTQsODAsJHsuNTUrayouNH0pYDsKICAgIGN0eC5zZXRMaW5lRGFzaChbYS5yKi41LCBhLnIqLjM0XSk7IGN0eC5zdHJva2UoKTsgY3R4LnNldExpbmVEYXNoKFtdKTsKCiAgfSBlbHNlIGlmKGMudD09PSdudWtlJyl7CiAgICBjdHguZmlsbFN0eWxlPWByZ2JhKDI1NSwyMTQsMTAsJHsuODYrayouMTR9KWA7CiAgICBjdHguc2hhZG93Q29sb3I9J3JnYmEoMjU1LDE5MCwwLC45KSc7IGN0eC5zaGFkb3dCbHVyPTE0OwogICAgZ2x5cGhUcmVmb2lsKGEuciouNjIpOwogIH0KICBjdHgucmVzdG9yZSgpOwp9CgpmdW5jdGlvbiBkcmF3Um9jayhhKXsKICBjb25zdCBjPWEuY2FyZ287CiAgaWYoYykgY2FyZ29BdXJhKGEpOwoKICBjdHguc2F2ZSgpOwogIGN0eC50cmFuc2xhdGUoYS54LGEueSk7IGN0eC5yb3RhdGUoYS5yb3QpOwogIGN0eC5iZWdpblBhdGgoKTsKICBmb3IobGV0IGk9MDtpPGEudmVydHMubGVuZ3RoO2krKyl7CiAgICBjb25zdCB2PWEudmVydHNbaV0sIHB4Mj1NYXRoLmNvcyh2LmEpKmEucip2Lm0sIHB5Mj1NYXRoLnNpbih2LmEpKmEucip2Lm07CiAgICBpPyBjdHgubGluZVRvKHB4MixweTIpIDogY3R4Lm1vdmVUbyhweDIscHkyKTsKICB9CiAgY3R4LmNsb3NlUGF0aCgpOwoKICBjb25zdCBzaz1hLnNrfHxTS0lOU1swXTsKICBsZXQgZzsKICBpZihjICYmIGMudD09PSdudWtlJyl7ICAgICAgICAgICAgICAgICAgICAgICAvLyBuZXJvIGJvcmRhdG8gZGkgZ2lhbGxvCiAgICBnPWN0eC5jcmVhdGVSYWRpYWxHcmFkaWVudCgtYS5yKi4zLC1hLnIqLjMsYS5yKi4xLDAsMCxhLnIqMS4xNSk7CiAgICBnLmFkZENvbG9yU3RvcCgwLCcjMjIyNDJhJyk7IGcuYWRkQ29sb3JTdG9wKC42LCcjMTAxMTE2Jyk7IGcuYWRkQ29sb3JTdG9wKDEsJyMwNTA1MDcnKTsKICAgIGN0eC5maWxsU3R5bGU9ZzsgY3R4LmZpbGwoKTsKICAgIGN0eC5saW5lV2lkdGg9My4yOyBjdHguc3Ryb2tlU3R5bGU9J3JnYmEoMjU1LDIxNCwxMCwuOTUpJzsKICAgIGN0eC5zaGFkb3dDb2xvcj0ncmdiYSgyNTUsMTk2LDAsLjgpJzsgY3R4LnNoYWRvd0JsdXI9MTQ7IGN0eC5zdHJva2UoKTsgY3R4LnNoYWRvd0JsdXI9MDsKICB9IGVsc2UgaWYoYyAmJiBjLnQ9PT0nbXVsdCcpeyAgICAgICAgICAgICAgICAvLyBkb3JhdG8KICAgIGc9Y3R4LmNyZWF0ZVJhZGlhbEdyYWRpZW50KC1hLnIqLjM1LC1hLnIqLjM1LGEuciouMSwwLDAsYS5yKjEuMTUpOwogICAgZy5hZGRDb2xvclN0b3AoMCwnI2ZmZjFiZCcpOyBnLmFkZENvbG9yU3RvcCguNDIsJyNlMGE1MjEnKTsgZy5hZGRDb2xvclN0b3AoMSwnIzZiM2YwNCcpOwogICAgY3R4LmZpbGxTdHlsZT1nOyBjdHguZmlsbCgpOwogICAgY3R4LmxpbmVXaWR0aD0yLjQ7IGN0eC5zdHJva2VTdHlsZT0ncmdiYSgyNTUsMjM2LDE2MCwuOTUpJzsKICAgIGN0eC5zaGFkb3dDb2xvcj0ncmdiYSgyNTUsMjE0LDgwLC45KSc7IGN0eC5zaGFkb3dCbHVyPTE4OyBjdHguc3Ryb2tlKCk7IGN0eC5zaGFkb3dCbHVyPTA7CiAgfSBlbHNlIHsKICAgIGc9Y3R4LmNyZWF0ZVJhZGlhbEdyYWRpZW50KC1hLnIqLjM1LC1hLnIqLjM1LGEuciouMTIsMCwwLGEucioxLjE1KTsKICAgIGcuYWRkQ29sb3JTdG9wKDAsICBgaHNsKCR7YS5odWV9LCR7c2suc2F0fSUsJHtzay5saXQrMjJ9JSlgKTsKICAgIGcuYWRkQ29sb3JTdG9wKC41NSxgaHNsKCR7YS5odWV9LCR7c2suc2F0LTR9JSwke3NrLmxpdC0xfSUpYCk7CiAgICBnLmFkZENvbG9yU3RvcCgxLCAgYGhzbCgke2EuaHVlfSwke3NrLnNhdH0lLCR7TWF0aC5tYXgoNixzay5saXQtMjEpfSUpYCk7CiAgICBjdHguZmlsbFN0eWxlPWc7IGN0eC5maWxsKCk7CiAgICBjdHgubGluZVdpZHRoPTEuMTsgY3R4LnN0cm9rZVN0eWxlPSdyZ2JhKDEyLDE2LDI4LC44NSknOyBjdHguc3Ryb2tlKCk7CiAgICBpZihjKXsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYm9yZG8gdGludG8gc2Vjb25kbyBsYSBjYXJpY2EKICAgICAgY29uc3QgY29sID0gYy50PT09J2xpZmUnPyAnMTEwLDI0MCwyMDAnIDogYy50PT09J3BsdXMnPyAnMTEwLDI0MCwxNjAnIDogJzI1NSw0NiwxMDcnOwogICAgICBjdHgubGluZVdpZHRoPTIuMjsgY3R4LnN0cm9rZVN0eWxlPWByZ2JhKCR7Y29sfSwuODUpYDsKICAgICAgY3R4LnNoYWRvd0NvbG9yPWByZ2JhKCR7Y29sfSwuOClgOyBjdHguc2hhZG93Qmx1cj0xMjsgY3R4LnN0cm9rZSgpOyBjdHguc2hhZG93Qmx1cj0wOwogICAgfQogIH0KCiAgY3R4LmZpbGxTdHlsZT0ncmdiYSgxMCwxMiwyMCwuMzQpJzsKICBmb3IobGV0IGk9MDtpPGEuY3JhdGVycy5sZW5ndGg7aSsrKXsKICAgIGNvbnN0IGNyPWEuY3JhdGVyc1tpXTsKICAgIGN0eC5iZWdpblBhdGgoKTsgY3R4LmVsbGlwc2UoY3IueCxjci55LGNyLnIsY3IuciouNzgsY3IueCwwLFRBVSk7IGN0eC5maWxsKCk7CiAgfQogIGN0eC5yZXN0b3JlKCk7CgogIGlmKGMpIGNhcmdvTWFyayhhKTsgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlsIG1hcmNoaW8gbm9uIHJ1b3RhOiByZXN0YSBsZWdnaWJpbGUKfQoKLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiAgIEVTUExPU0lPTkUg4oCUIGZsYXNoICsgcGFsbGEgZGkgZnVvY28gKyBvbmRhIGQndXJ0byArIHNjaGVnZ2UgKyBmdW1vCiAgIFR1dHRvIHN1Yi01MDAgbXM6IGltcGF0dG8gaXN0YW50YW5lbywgbmVzc3VuYSBjb2RhIG1vbGxlLgogICA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gKi8KY29uc3QgVE9ORSA9IHsKICByb2NrOntkZWVwOicyMDAsNDYsMjAnLCAgd2F2ZTonMjU1LDIxNCwxNDAnLCB0YWlsOicyNTUsOTIsMjYnfSwKICBzaGlwOntkZWVwOicyNTUsNDYsMTA3Jywgd2F2ZTonMjU1LDE1MCwxNzAnLCB0YWlsOicyNTUsOTIsMTUwJ30sCiAgZGF0YTp7ZGVlcDonMjYsMTIwLDIzMCcsIHdhdmU6JzE1MCwyMzYsMjU1JywgdGFpbDonODAsMTkwLDI1NSd9LAogIGdvbGQ6e2RlZXA6JzIyNCwxNDAsOCcsICB3YXZlOicyNTUsMjM4LDE1MCcsIHRhaWw6JzI1NSwxOTYsNDQnfQp9OwpmdW5jdGlvbiBleHBsb2RlKHgseSxyLHRvbmUpewogIGNvbnN0IHMgPSByLzI2OwoKICAvKiAxLiBudWNsZWkgaW5jYW5kZXNjZW50aSBzZmFsc2F0aSAoZmlyZWJhbGwgbXVsdGktc3RyYXRvKSAqLwogIGZvcihsZXQgaT0wO2k8MztpKyspCiAgICBiYWxscy5wdXNoKHt4Ongrcm5kKC1yKi4yLHIqLjIpLCB5Onkrcm5kKC1yKi4yLHIqLjIpLAogICAgICAgICAgICAgICAgcjA6cipybmQoLjQ1LC44NSksIHIxOnIqcm5kKDEuNSwyLjQpLAogICAgICAgICAgICAgICAgbGlmZTowLCBtYXg6cm5kKC4xMCwuMTkpLCBkZWxheTppKi4wMjIsIHRvbmV9KTsKCiAgLyogMi4gb25kZSBkJ3VydG8gKi8KICB3YXZlcy5wdXNoKHt4LHkscjA6ciouNSxyMTpyKnJuZCgzLjQsNC42KSxsaWZlOjAsbWF4Oi4yNix3OjIuNix0b25lfSk7CiAgaWYocj4yNikgd2F2ZXMucHVzaCh7eCx5LHIwOnIqLjMscjE6ciozLjAsbGlmZTowLG1heDouMTksdzoxLjQsdG9uZX0pOwoKICAvKiAzLiBzY2ludGlsbGUgYmFsaXN0aWNoZSBjb24gc2NpYSAqLwogIGNvbnN0IG5zID0gTWF0aC5yb3VuZCgxNityKi44NSk7CiAgZm9yKGxldCBpPTA7aTxucztpKyspewogICAgY29uc3QgYT1ybmQoMCxUQVUpLCB2PXJuZCgxODAsNzYwKSooLjU1K3MqLjQ1KTsKICAgIHNwYXJrcy5wdXNoKHt4LHkscHg6eCxweTp5LHZ4Ok1hdGguY29zKGEpKnYsdnk6TWF0aC5zaW4oYSkqdiwKICAgICAgICAgICAgICAgICBsaWZlOjAsbWF4OnJuZCguMTQsLjQyKSx3OnJuZCguOSwyLjMpLHRvbmV9KTsKICB9CgogIC8qIDQuIHNjaGVnZ2UgZGkgcm9jY2lhIHJvdGFudGkgKi8KICBmb3IobGV0IGk9MDtpPE1hdGgucm91bmQoNCtyKi4xNCk7aSsrKXsKICAgIGNvbnN0IGE9cm5kKDAsVEFVKSwgdj1ybmQoNzAsMjkwKTsKICAgIGRlYnJpcy5wdXNoKHt4LHksdng6TWF0aC5jb3MoYSkqdix2eTpNYXRoLnNpbihhKSp2LTMwLAogICAgICAgICAgICAgICAgIHI6cm5kKDIsTWF0aC5tYXgoMyxyKi4yMikpLHJvdDpybmQoMCxUQVUpLHZyb3Q6cm5kKC05LDkpLAogICAgICAgICAgICAgICAgIGxpZmU6MCxtYXg6cm5kKC40NSwuODUpfSk7CiAgfQoKICAvKiA1LiBmdW1vIHJlc2lkdW8sIHNpIGRpbGF0YSBsZW50YW1lbnRlICovCiAgZm9yKGxldCBpPTA7aTxNYXRoLnJvdW5kKDMrciouMDkpO2krKykKICAgIHNtb2tlLnB1c2goe3g6eCtybmQoLXIqLjQsciouNCksIHk6eStybmQoLXIqLjQsciouNCksCiAgICAgICAgICAgICAgICByOnIqcm5kKC4zLC42KSwgZ3I6cm5kKDI4LDcwKSwKICAgICAgICAgICAgICAgIHZ4OnJuZCgtMjYsMjYpLCB2eTpybmQoLTQwLDEwKSwgbGlmZTowLCBtYXg6cm5kKC40LC44KX0pOwoKICBpZighUkVEVUNFRCl7IHNoYWtlID0gTWF0aC5taW4oMjYsIHNoYWtlICsgciouNDIpOyBmbGFzaCA9IE1hdGgubWluKC43LCBmbGFzaCArIHIvMjMwKTsgfQogIHNmeEJvb20ocik7Cn0KCmZ1bmN0aW9uIGRyYXdGWChkdCl7CiAgY3R4LnNhdmUoKTsKICBjdHguZ2xvYmFsQ29tcG9zaXRlT3BlcmF0aW9uPSdsaWdodGVyJzsKCiAgLyogZnVtbyDigJQgc290dG8gYWwgZnVvY28sIGluIHNvdXJjZS1vdmVyICovCiAgY3R4Lmdsb2JhbENvbXBvc2l0ZU9wZXJhdGlvbj0nc291cmNlLW92ZXInOwogIGZvcihsZXQgaT1zbW9rZS5sZW5ndGgtMTtpPj0wO2ktLSl7CiAgICBjb25zdCBwPXNtb2tlW2ldOyBwLmxpZmUrPWR0OwogICAgaWYocC5saWZlPj1wLm1heCl7IHNtb2tlLnNwbGljZShpLDEpOyBjb250aW51ZTsgfQogICAgY29uc3Qgaz1wLmxpZmUvcC5tYXg7CiAgICBwLngrPXAudngqZHQ7IHAueSs9cC52eSpkdDsgcC52eSo9Ljk0OyBwLnZ4Kj0uOTQ7CiAgICBjb25zdCBycj1wLnIrcC5nciprOwogICAgY29uc3QgZz1jdHguY3JlYXRlUmFkaWFsR3JhZGllbnQocC54LHAueSwwLHAueCxwLnkscnIpOwogICAgZy5hZGRDb2xvclN0b3AoMCxgcmdiYSg1OCw1Miw0OCwkey4zNCooMS1rKX0pYCk7CiAgICBnLmFkZENvbG9yU3RvcCgxLCdyZ2JhKDI4LDI2LDI2LDApJyk7CiAgICBjdHguZmlsbFN0eWxlPWc7IGN0eC5iZWdpblBhdGgoKTsgY3R4LmFyYyhwLngscC55LHJyLDAsVEFVKTsgY3R4LmZpbGwoKTsKICB9CgogIC8qIHNjaGVnZ2UgKi8KICBmb3IobGV0IGk9ZGVicmlzLmxlbmd0aC0xO2k+PTA7aS0tKXsKICAgIGNvbnN0IHA9ZGVicmlzW2ldOyBwLmxpZmUrPWR0OwogICAgaWYocC5saWZlPj1wLm1heCl7IGRlYnJpcy5zcGxpY2UoaSwxKTsgY29udGludWU7IH0KICAgIGNvbnN0IGs9cC5saWZlL3AubWF4OwogICAgcC52eSs9NDYwKmR0OyBwLngrPXAudngqZHQ7IHAueSs9cC52eSpkdDsgcC5yb3QrPXAudnJvdCpkdDsKICAgIGN0eC5zYXZlKCk7IGN0eC50cmFuc2xhdGUocC54LHAueSk7IGN0eC5yb3RhdGUocC5yb3QpOwogICAgY3R4Lmdsb2JhbEFscGhhPTEtayprOwogICAgY3R4LmZpbGxTdHlsZT0nIzRhNDAzOCc7CiAgICBjdHguYmVnaW5QYXRoKCk7IGN0eC5tb3ZlVG8oLXAuciwtcC5yKi42KTsgY3R4LmxpbmVUbyhwLnIqLjgsLXAucik7CiAgICBjdHgubGluZVRvKHAucixwLnIqLjcpOyBjdHgubGluZVRvKC1wLnIqLjUscC5yKTsgY3R4LmNsb3NlUGF0aCgpOyBjdHguZmlsbCgpOwogICAgY3R4LnJlc3RvcmUoKTsKICB9CiAgY3R4Lmdsb2JhbEFscGhhPTE7CiAgY3R4Lmdsb2JhbENvbXBvc2l0ZU9wZXJhdGlvbj0nbGlnaHRlcic7CgogIC8qIHBhbGxlIGRpIGZ1b2NvICovCiAgZm9yKGxldCBpPWJhbGxzLmxlbmd0aC0xO2k+PTA7aS0tKXsKICAgIGNvbnN0IGI9YmFsbHNbaV07CiAgICBpZihiLmRlbGF5PjApeyBiLmRlbGF5LT1kdDsgY29udGludWU7IH0KICAgIGIubGlmZSs9ZHQ7CiAgICBpZihiLmxpZmU+PWIubWF4KXsgYmFsbHMuc3BsaWNlKGksMSk7IGNvbnRpbnVlOyB9CiAgICBjb25zdCBrPWIubGlmZS9iLm1heCwgcnI9Yi5yMCsoYi5yMS1iLnIwKSpNYXRoLnNxcnQoayksIGFsPTEtazsKICAgIGNvbnN0IGc9Y3R4LmNyZWF0ZVJhZGlhbEdyYWRpZW50KGIueCxiLnksMCxiLngsYi55LHJyKTsKICAgIGcuYWRkQ29sb3JTdG9wKDAsICAgYHJnYmEoMjU1LDI1NSwyNDAsJHthbH0pYCk7CiAgICBnLmFkZENvbG9yU3RvcCguMjgsIGByZ2JhKDI1NSwyMjYsMTMwLCR7YWwqLjk1fSlgKTsKICAgIGcuYWRkQ29sb3JTdG9wKC41NSwgYHJnYmEoMjU1LDE0MCw0MCwke2FsKi43fSlgKTsKICAgIGcuYWRkQ29sb3JTdG9wKC44MiwgYHJnYmEoJHsoVE9ORVtiLnRvbmVdfHxUT05FLnJvY2spLmRlZXB9LCR7YWwqLjM1fSlgKTsKICAgIGcuYWRkQ29sb3JTdG9wKDEsICAgJ3JnYmEoODAsMTAsMCwwKScpOwogICAgY3R4LmZpbGxTdHlsZT1nOyBjdHguYmVnaW5QYXRoKCk7IGN0eC5hcmMoYi54LGIueSxyciwwLFRBVSk7IGN0eC5maWxsKCk7CiAgfQoKICAvKiBvbmRlIGQndXJ0byAqLwogIGZvcihsZXQgaT13YXZlcy5sZW5ndGgtMTtpPj0wO2ktLSl7CiAgICBjb25zdCB3PXdhdmVzW2ldOyB3LmxpZmUrPWR0OwogICAgaWYody5saWZlPj13Lm1heCl7IHdhdmVzLnNwbGljZShpLDEpOyBjb250aW51ZTsgfQogICAgY29uc3Qgaz13LmxpZmUvdy5tYXgsIHJyPXcucjArKHcucjEtdy5yMCkqKDEtTWF0aC5wb3coMS1rLDIuNCkpOwogICAgY3R4LmxpbmVXaWR0aD13LncqKDEtaykrLjM7CiAgICBjdHguc3Ryb2tlU3R5bGU9YHJnYmEoJHsoVE9ORVt3LnRvbmVdfHxUT05FLnJvY2spLndhdmV9LCR7KDEtaykqLjh9KWA7CiAgICBjdHguYmVnaW5QYXRoKCk7IGN0eC5hcmMody54LHcueSxyciwwLFRBVSk7IGN0eC5zdHJva2UoKTsKICB9CgogIC8qIHNjaW50aWxsZSBjb24gc2NpYSAqLwogIGN0eC5saW5lQ2FwPSdyb3VuZCc7CiAgZm9yKGxldCBpPXNwYXJrcy5sZW5ndGgtMTtpPj0wO2ktLSl7CiAgICBjb25zdCBwPXNwYXJrc1tpXTsgcC5saWZlKz1kdDsKICAgIGlmKHAubGlmZT49cC5tYXgpeyBzcGFya3Muc3BsaWNlKGksMSk7IGNvbnRpbnVlOyB9CiAgICBjb25zdCBrPXAubGlmZS9wLm1heDsKICAgIHAucHg9cC54OyBwLnB5PXAueTsKICAgIHAudngqPS45MDsgcC52eT1wLnZ5Ki45MCszMzAqZHQ7CiAgICBwLngrPXAudngqZHQ7IHAueSs9cC52eSpkdDsKICAgIGNvbnN0IGFsPTEtazsKICAgIGN0eC5zdHJva2VTdHlsZSA9IGs8LjM1ID8gYHJnYmEoMjU1LDI1NSwyMzUsJHthbH0pYAogICAgICAgICAgICAgICAgICAgIDogazwuNyAgPyBgcmdiYSgyNTUsMTk2LDkwLCR7YWx9KWAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogYHJnYmEoJHsoVE9ORVtwLnRvbmVdfHxUT05FLnJvY2spLnRhaWx9LCR7YWx9KWA7CiAgICBjdHgubGluZVdpZHRoPXAudyphbDsKICAgIGN0eC5iZWdpblBhdGgoKTsgY3R4Lm1vdmVUbyhwLnB4LHAucHkpOyBjdHgubGluZVRvKHAueCxwLnkpOyBjdHguc3Ryb2tlKCk7CiAgfQogIGN0eC5yZXN0b3JlKCk7Cn0KCi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQogICBTRVRUT1JFIE1BVEVNQVRJQ08g4oCUIGxpdmVsbG8gYm9udXMsIHNjYXR0YSBhbCByaWVtcGlyc2kgZGVsbGEgc29nbGlhCiAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogICBVbmEgbmF2ZSBtYWRyZSBlbnRyYSwgYXp6ZXJhIGlsIGNhbXBvIGNvbiB1biBpbXB1bHNvLCByaWxhc2NpYQogICA2IG51bWVyaSArIDMgb3BlcmF0b3JpIGUgc2kgcml0aXJhIHZlcnNvIGwnYWx0bzogbGEgc3VhIHF1b3RhIEUnIGlsCiAgIGNyb25vbWV0cm8uIFRyYSBpIDYgbnVtZXJpIGVzaXN0ZSBzZW1wcmUgYWxtZW5vIHVuYSByZWxhemlvbmUgZGVsCiAgIHRpcG8gIGEg4oiYIGIgPSBjICBvcHB1cmUgIGEg4oiYIGIg4oiYIGMgPSBkLgogICBDYXRlbmE6IE5VTUVSTyDihpIgT1BFUkFUT1JFIOKGkiBOVU1FUk8g4oaSICjigKYpIOKGkiBSSVNVTFRBVE8uCiAgIFZhbHV0YXppb25lIFNFTVBSRSBkYSBzaW5pc3RyYSBhIGRlc3RyYSwgc2VuemEgcHJlY2VkZW56YSBvcGVyYXRvcmkuCiAgID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqLwpjb25zdCBPUEYgPSB7JysnOihhLGIpPT5hK2IsICfiiJInOihhLGIpPT5hLWIsICfDlyc6KGEsYik9PmEqYiwgJ8O3JzooYSxiKT0+YS9ifTsKY29uc3QgQk9OVVNfUFRTID0gNTAwMDsKY29uc3QgQk9OVVMgPSB7b246ZmFsc2UsIGtpbmQ6J2NoYWluJywgcGg6JycsIHB0OjAsIHQ6MCwgdG1heDoxLCBtb3RoZXI6bnVsbCwgcG9kczpbXSwgd3JlY2tzOltdLAogICAgICAgICAgICAgICBzdGVwczpbXSwgYWNjOm51bGwsIHBlbmQ6bnVsbCwga2l0OltdLCBzb2x2ZWQ6ZmFsc2UsCiAgICAgICAgICAgICAgIG1zZzonJywgbXNnVDowLCBtc2dDb2w6JycsIHF1ZXVlOjAsIGRvbmU6MH07CgovKiAtLS0gZ2VuZXJhdG9yZSBkaSBlbmlnbWkgcmlzb2x2aWJpbGkgcGVyIGNvc3RydXppb25lIC0tLS0tLS0tLS0tLS0tICovCmZ1bmN0aW9uIG1ha2VQdXp6bGUobHZsKXsKICBjb25zdCBwb29sPVsnKycsJ+KIkicsJ8OXJywnw7cnXTsKICBmb3IobGV0IGF0dGVtcHQ9MDsgYXR0ZW1wdDw2MDA7IGF0dGVtcHQrKyl7CiAgICBjb25zdCBzaD1wb29sLnNsaWNlKCk7CiAgICBmb3IobGV0IGk9c2gubGVuZ3RoLTE7aT4wO2ktLSl7IGNvbnN0IGo9cm5kaSgwLGkpLCB0bXA9c2hbaV07IHNoW2ldPXNoW2pdOyBzaFtqXT10bXA7IH0KICAgIGNvbnN0IGtpdCA9IHNoLnNsaWNlKDAsMyk7ICAgICAgICAgICAgICAgICAgICAgICAvLyBpIDMgb3BlcmF0b3JpIHJpbGFzY2lhdGkKICAgIGNvbnN0IG9wcyA9IChsdmw+PTIgJiYgTWF0aC5yYW5kb20oKTwuNikgPyAyIDogMTsgLy8gbi4gZGkgb3BlcmF6aW9uaSBkZWxsYSBzb2x1emlvbmUKICAgIC8qIERpIG9nbmkgb3BlcmF0b3JlIGVzaXN0ZSBVTiBTT0xPIHBvZDogbGEgc29sdXppb25lIG5vbiBwdcOyIHJpdXNhcmxvLiAqLwogICAgY29uc3QgcGljayA9IGtpdC5zbGljZSgpOwogICAgZm9yKGxldCBpPXBpY2subGVuZ3RoLTE7aT4wO2ktLSl7IGNvbnN0IGo9cm5kaSgwLGkpLCB0bXA9cGlja1tpXTsgcGlja1tpXT1waWNrW2pdOyBwaWNrW2pdPXRtcDsgfQogICAgbGV0IGFjYyA9IHJuZGkoMywyNCk7IGNvbnN0IGNoYWluPVthY2NdOyBsZXQgb2s9dHJ1ZTsKCiAgICBmb3IobGV0IHM9MDsgczxvcHM7IHMrKyl7CiAgICAgIGNvbnN0IG9wID0gcGlja1tzXTsKICAgICAgbGV0IGIgPSBudWxsOwogICAgICBpZihvcD09PSfDtycpewogICAgICAgIGNvbnN0IGQ9W107IGZvcihsZXQgaz0yO2s8PTEyO2srKykgaWYoYWNjJWs9PT0wICYmIGFjYy9rPj0yKSBkLnB1c2goayk7CiAgICAgICAgaWYoZC5sZW5ndGgpIGI9ZFtybmRpKDAsZC5sZW5ndGgtMSldOwogICAgICB9IGVsc2UgaWYob3A9PT0nw5cnKXsKICAgICAgICBjb25zdCBsaW09TWF0aC5mbG9vcig5Ni9hY2MpOyBpZihsaW0+PTIpIGI9cm5kaSgyLE1hdGgubWluKGxpbSwxMikpOwogICAgICB9IGVsc2UgaWYob3A9PT0n4oiSJyl7CiAgICAgICAgaWYoYWNjPj01KSBiPXJuZGkoMixhY2MtMik7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgaWYoYWNjPD05MCkgYj1ybmRpKDIsTWF0aC5taW4oNDQsOTYtYWNjKSk7CiAgICAgIH0KICAgICAgaWYoYj09PW51bGwpeyBvaz1mYWxzZTsgYnJlYWs7IH0KICAgICAgY29uc3Qgcj1PUEZbb3BdKGFjYyxiKTsKICAgICAgaWYoIU51bWJlci5pc0ludGVnZXIocil8fHI8Mnx8cj45OXx8cj09PWFjYyl7IG9rPWZhbHNlOyBicmVhazsgfQogICAgICBjaGFpbi5wdXNoKG9wLGIpOyBhY2M9cjsKICAgIH0KICAgIGlmKCFvaykgY29udGludWU7CgogICAgY29uc3QgbnVtcz1bXTsgZm9yKGxldCBpPTA7aTxjaGFpbi5sZW5ndGg7aSs9MikgbnVtcy5wdXNoKGNoYWluW2ldKTsKICAgIG51bXMucHVzaChhY2MpOwogICAgaWYobmV3IFNldChudW1zKS5zaXplICE9PSBudW1zLmxlbmd0aCkgY29udGludWU7ICAgLy8gbmllbnRlIGRvcHBpb25pOiB6ZXJvIGFtYmlndWl0w6AKCiAgICBsZXQgZ3VhcmQ9MDsKICAgIHdoaWxlKG51bXMubGVuZ3RoPDYgJiYgZ3VhcmQrKzwzMDApewogICAgICBjb25zdCBmPXJuZGkoMiwgTWF0aC5taW4oOTksIDI2K2x2bCoxMCkpOwogICAgICBpZihudW1zLmluZGV4T2YoZik8MCkgbnVtcy5wdXNoKGYpOwogICAgfQogICAgaWYobnVtcy5sZW5ndGg8NikgY29udGludWU7CiAgICBmb3IobGV0IGk9bnVtcy5sZW5ndGgtMTtpPjA7aS0tKXsgY29uc3Qgaj1ybmRpKDAsaSksIHRtcD1udW1zW2ldOyBudW1zW2ldPW51bXNbal07IG51bXNbal09dG1wOyB9CiAgICByZXR1cm4ge251bXMsIGtpdCwgc29sOmNoYWluLmNvbmNhdChbJz0nLGFjY10pfTsKICB9CiAgcmV0dXJuIHtudW1zOls2LDMsMTgsNywyNSwxMV0sIGtpdDpbJysnLCfDlycsJ+KIkiddLCBzb2w6WzYsJ8OXJywzLCc9JywxOF19Owp9CgovKiAtLS0gYXZ2aW86IGkgZHVlIHNldHRvcmkgYm9udXMgc2kgZXN0cmFnZ29ubyBhIHNvcnRlIC0tLS0tLS0tLS0tLS0gKi8KZnVuY3Rpb24gc3RhcnRCb251cygpewogIC8qIGlsIGRpdG8gcHXDsiBlc3NlcmUgZ2nDoCBwcmVtdXRvIGUgaW4gdHJhc2NpbmFtZW50bzogaWwgZ2VzdG8gaW4gY29yc28KICAgICB2YSByaXByZXNvIGRhIGNhcG8sIGFsdHJpbWVudGkgaWwgcHJpbW8gZGVsdGEgw6ggcHJpdm8gZGkgcmlmZXJpbWVudG8gKi8KICBwdHIubHg9cHRyLng7IHB0ci54MD1wdHIueDsgcHRyLnkwPXB0ci55OyBwdHIubW92ZWQ9ZmFsc2U7IHB0ci50YXA9bnVsbDsgYWltTG9jaz0uMjsKICBCT05VUy5vbj10cnVlOyBCT05VUy5waD0naW4nOyBCT05VUy5wdD0wOyBCT05VUy5zb2x2ZWQ9ZmFsc2U7CiAgQk9OVVMucG9kcz1bXTsgQk9OVVMud3JlY2tzPVtdOyBCT05VUy5xdWV1ZT0wOyBCT05VUy5kb25lPTA7CiAgQk9OVVMua2luZCA9IE1hdGgucmFuZG9tKCk8LjUgPyAnY2hhaW4nIDogJ3ByaW1pJzsKICAoQk9OVVMua2luZD09PSdjaGFpbic/IHN0YXJ0Q2hhaW4gOiBzdGFydFByaW1pKSgpOwogIHNmeEFycml2YWwoKTsKfQpmdW5jdGlvbiBzdGFydENoYWluKCl7CiAgY29uc3QgcCA9IG1ha2VQdXp6bGUobGV2ZWwpOwogIEJPTlVTLnN0ZXBzPVtdOyBCT05VUy5hY2M9bnVsbDsgQk9OVVMucGVuZD1udWxsOwogIEJPTlVTLmtpdD1wLmtpdDsgQk9OVVMubnVtcz1wLm51bXM7CiAgQk9OVVMudGFyZ2V0PXAuc29sW3Auc29sLmxlbmd0aC0xXTsgICAvLyBpbCBudW1lcm8gZGEgb3R0ZW5lcmUsIG1vc3RyYXRvIGFsIGdpb2NhdG9yZQogIEJPTlVTLmJhbm5lcj0wOwogIEJPTlVTLnRtYXggPSBNYXRoLm1heCgxNSwgMjQtbGV2ZWwpOyBCT05VUy50PUJPTlVTLnRtYXg7IEJPTlVTLmhvbGQ9aG9sZFRpbWUoKTsKICBCT05VUy5tb3RoZXI9e3g6Vy8yLCB5Oi1XKi40MiwgdzpNYXRoLm1pbihXKi42NCwzNDApLCB2eTowLCBoaXQ6MH07CiAgYm9udXNNc2coJ1NFVFRPUkUgTUFURU1BVElDTycsICc3MCwyMzAsMjU1JywgMi4yKTsKfQpmdW5jdGlvbiBib251c01zZyh0eHQsY29sLGR1cil7IEJPTlVTLm1zZz10eHQ7IEJPTlVTLm1zZ0NvbD1jb2w7IEJPTlVTLm1zZ1Q9ZHVyOyB9CgovKiAtLS0gZGlzcG9zaXppb25lOiA5IGNvcnNpZSBvcml6em9udGFsaSBlcXVpZGlzdGFudGkgLS0tLS0tLS0tLS0tLS0tCiAgIElsIHB1bnRhbWVudG8gw6ggbW9ub2RpbWVuc2lvbmFsZSwgcXVpbmRpIGNpw7IgY2hlIGNvbnRhIMOoIGxhIGRpc3RhbnphCiAgIHN1bGwnYXNzZSBYLiBEaXN0cmlidWlzY28gaSA5IHBvZCBzdSA5IGNvcnNpZSBhIHBhc3NvIGNvc3RhbnRlOiDDqCBsYQogICBzZXBhcmF6aW9uZSBtYXNzaW1hIG90dGVuaWJpbGUsIGUgbmVzc3VuYSBjb3BwaWEgcmVzdGEgYW1iaWd1YS4gICAgICovCmZ1bmN0aW9uIHBvZFIoKXsgcmV0dXJuIE1hdGgubWF4KDE3LCBNYXRoLm1pbigyOCwgVy8xNSkpOyB9CmZ1bmN0aW9uIHBvZFNsb3RzKCl7CiAgY29uc3QgUj1wb2RSKCksIG09TWF0aC5tYXgoMjYsIFIrMTIpLCBzdGVwPShXLW0qMikvODsKICBCT05VUy5sYW5lPXN0ZXA7CiAgY29uc3Qgcm93cz1bSCouMjcsIEgqLjQxNSwgSCouNTZdLCByMD1ybmRpKDAsMiksIGZsaXA9TWF0aC5yYW5kb20oKTwuNT8xOjI7CiAgY29uc3Qgb3V0PVtdOwogIGZvcihsZXQgaT0wO2k8OTtpKyspCiAgICBvdXQucHVzaCh7eDptK3N0ZXAqaSwgeTpyb3dzWyhyMCtpKmZsaXApJTNdK3JuZCgtNyw3KX0pOwogIHJldHVybiBvdXQ7ICAgLy8gbGUgWCByZXN0YW5vIGZpc3NlIGUgb3JkaW5hdGU6IGNvcnNpZSBzZW1wcmUgZGlzdGludGUKfQpmdW5jdGlvbiBidWlsZFBvZHMoKXsKICBjb25zdCBzbG90cz1wb2RTbG90cygpOwogIGNvbnN0IFI9cG9kUigpOwogIGNvbnN0IGl0ZW1zPVtdOwogIGZvcihsZXQgaT0wO2k8NjtpKyspIGl0ZW1zLnB1c2goe2tpbmQ6J251bScsIHZhbDpCT05VUy5udW1zW2ldLCByOlJ9KTsKICBmb3IobGV0IGk9MDtpPDM7aSsrKSBpdGVtcy5wdXNoKHtraW5kOidvcCcsICB2YWw6Qk9OVVMua2l0W2ldLCAgcjpSKi44OH0pOwogIGZvcihsZXQgaT1pdGVtcy5sZW5ndGgtMTtpPjA7aS0tKXsgY29uc3Qgaj1ybmRpKDAsaSksIHQyPWl0ZW1zW2ldOyBpdGVtc1tpXT1pdGVtc1tqXTsgaXRlbXNbal09dDI7IH0KICBCT05VUy5wb2RzID0gaXRlbXMubWFwKChpdCxpKT0+KHsKICAgIGtpbmQ6aXQua2luZCwgdmFsOml0LnZhbCwgcjppdC5yLAogICAgaHg6c2xvdHNbaV0ueCwgaHk6c2xvdHNbaV0ueSwKICAgIHg6Qk9OVVMubW90aGVyLngsIHk6Qk9OVVMubW90aGVyLnksIHN4OkJPTlVTLm1vdGhlci54LCBzeTpCT05VUy5tb3RoZXIueSwKICAgIHZ4OjAsIHZ5OjAsIHJvdDpybmQoMCxUQVUpLCB2cm90OnJuZCgtLjQ1LC40NSksCiAgICB0dDotMSwgdGFrZW46ZmFsc2UsIHB1bHNlOjAKICB9KSk7Cn0KCi8qIEZpbmVzdHJhIGRpIHJhZ2lvbmFtZW50bzogaSBwb2QgcmVzdGFubyBpbW1vYmlsaSwgcG9pIHNjaXZvbGFubyBpbiBudW92ZQogICBwb3NpemlvbmkuIFNlcnZlIHRlbXBvIHBlciBsZWdnZXJlIGkgbnVtZXJpIGUgYWxsaW5lYXJlIGxhIG5hdmljZWxsYS4gKi8KZnVuY3Rpb24gaG9sZFRpbWUoKXsgcmV0dXJuIE1hdGgubWF4KDMuMiwgNi41IC0gbGV2ZWwqLjMpOyB9CmZ1bmN0aW9uIHJlc2h1ZmZsZVBvZHMoKXsKICBjb25zdCBzbG90cz1wb2RTbG90cygpOwogIGxldCBrPTA7CiAgZm9yKGxldCBpPTA7aTxCT05VUy5wb2RzLmxlbmd0aDtpKyspewogICAgY29uc3QgcD1CT05VUy5wb2RzW2ldOwogICAgaWYocC50YWtlbiB8fCBwLnR0PDApeyBrKys7IGNvbnRpbnVlOyB9CiAgICBwLnN4PXAueDsgcC5zeT1wLnk7IHAuaHg9c2xvdHNba10ueDsgcC5oeT1zbG90c1trXS55OyBwLnR0PTA7IHAucHVsc2U9Ljc7IGsrKzsKICB9CiAgQk9OVVMuaG9sZD1ob2xkVGltZSgpOwp9CgovKiAtLS0gaW1wdWxzbyBkJ2Fycml2bzogcmlwdWxpc2NlIGlsIGNhbXBvIGRhZ2xpIGFzdGVyb2lkaSAtLS0tLS0tLS0tICovCmZ1bmN0aW9uIGJvbnVzRU1QKCl7CiAgZm9yKGxldCBpPXJvY2tzLmxlbmd0aC0xO2k+PTA7aS0tKXsgY29uc3QgYT1yb2Nrc1tpXTsgYS5kZWFkPXRydWU7IGV4cGxvZGUoYS54LGEueSxhLnIsJ2RhdGEnKTsgfQogIHJvY2tzLmxlbmd0aD0wOyBidWxsZXRzLmxlbmd0aD0wOwogIGZvcihsZXQgaT0wO2k8MztpKyspCiAgICB3YXZlcy5wdXNoKHt4OlcvMiwgeTpCT05VUy5tb3RoZXIueSwgcjA6NDAraSo3MCwgcjE6TWF0aC5tYXgoVyxIKSoxLjUsCiAgICAgICAgICAgICAgICBsaWZlOjAsIG1heDouNytpKi4xMiwgdzozLCB0b25lOidkYXRhJ30pOwogIGlmKCFSRURVQ0VEKXsgc2hha2U9TWF0aC5taW4oMjYsc2hha2UrMTYpOyBmbGFzaD1NYXRoLm1pbiguNyxmbGFzaCsuMzUpOyB9Cn0KCi8qIC0tLSBjYXRlbmEgZGkgY2FsY29sbyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqLwpmdW5jdGlvbiBhZGRUaW1lKHMpewogIEJPTlVTLnQ9TWF0aC5taW4oQk9OVVMudG1heCwgQk9OVVMudCtzKTsKICBjb25zdCBtPUJPTlVTLm1vdGhlcjsKICBpZihCT05VUy5raW5kPT09J2NoYWluJyAmJiBtKSBtLnZ5PShtLnkgKyBtLncqLjc1ICsgNjApL01hdGgubWF4KC42LEJPTlVTLnQpOwp9CmZ1bmN0aW9uIGNoYWluQnJlYWsod2h5KXsKICBmb3IobGV0IGk9MDtpPEJPTlVTLnBvZHMubGVuZ3RoO2krKyl7CiAgICBjb25zdCBwPUJPTlVTLnBvZHNbaV07CiAgICBpZihwLnRha2VuKXsKICAgICAgcC50YWtlbj1mYWxzZTsgcC5zeD1wLng7IHAuc3k9cC55OyBwLnR0PTA7IHAucHVsc2U9MTsgICAvLyByaWVudHJvIGRhbCBwdW50byBpbiBjdWkgZXJhCiAgICAgIHdhdmVzLnB1c2goe3g6cC54LHk6cC55LHIwOnAuciouNCxyMTpwLnIqMi42LGxpZmU6MCxtYXg6LjMsdzoyLHRvbmU6J3NoaXAnfSk7CiAgICB9CiAgfQogIEJPTlVTLnN0ZXBzPVtdOyBCT05VUy5hY2M9bnVsbDsgQk9OVVMucGVuZD1udWxsOwogIEJPTlVTLnQ9TWF0aC5tYXgoMi4yLCBCT05VUy50LTIpOwogIGFkZFRpbWUoMCk7CiAgQk9OVVMuYmFubmVyPU1hdGgubWF4KEJPTlVTLmJhbm5lcnx8MCwgMi42KTsKICBib251c01zZyh3aHl8fCdDQVRFTkEgSU5URVJST1RUQScsJzI1NSw0NiwxMDcnLDEuNCk7CiAgaWYoIVJFRFVDRUQpIHNoYWtlPU1hdGgubWluKDIwLHNoYWtlKzExKTsKICBzZnhFcnIoKTsKfQpmdW5jdGlvbiBib251c1NvbHZlKHApewogIEJPTlVTLnNvbHZlZD10cnVlOyBCT05VUy5waD0nd2luJzsgQk9OVVMucHQ9MDsKICBleHBsb2RlKHAueCxwLnkscC5yKjIuMiwnZ29sZCcpOwogIGZvcihsZXQgaT0wO2k8NTtpKyspCiAgICB3YXZlcy5wdXNoKHt4OnAueCx5OnAueSxyMDozMCtpKjUwLHIxOk1hdGgubWF4KFcsSCkqMS42LGxpZmU6MCxtYXg6LjY1K2kqLjEsdzozLjIsdG9uZTonZ29sZCd9KTsKICBhZGRTY29yZShCT05VU19QVFMsZmFsc2UpOwogIGJvbnVzTXNnKCcrJytCT05VU19QVFMrJyAgQ0FURU5BIFJJU09MVEEnLCcyNTUsMTk2LDQ0JywyLjYpOwogIHRvYXN0KCdTVVBFUiBCT05VUycpOwogIGlmKCFSRURVQ0VEKXsgc2hha2U9TWF0aC5taW4oMzAsc2hha2UrMjIpOyBmbGFzaD1NYXRoLm1pbiguOCxmbGFzaCsuNSk7IH0KICBzZnhKYWNrcG90KCk7Cn0KZnVuY3Rpb24gaGl0UG9kKHApewogIC8qIG9wZXJhdG9yZSAqLwogIGlmKHAua2luZD09PSdvcCcpewogICAgaWYoQk9OVVMuYWNjPT09bnVsbCB8fCBCT05VUy5wZW5kIT09bnVsbCl7IGNoYWluQnJlYWsoKTsgcmV0dXJuOyB9CiAgICBCT05VUy5wZW5kPXAudmFsOyBCT05VUy5zdGVwcy5wdXNoKHAudmFsKTsgcC50YWtlbj10cnVlOwogICAgZXhwbG9kZShwLngscC55LHAuciouOSwnZGF0YScpOyBzZnhMb2NrKEJPTlVTLnN0ZXBzLmxlbmd0aCk7IGFkZFRpbWUoMS4yKTsKICAgIHJldHVybjsKICB9CiAgLyogcHJpbW8gbnVtZXJvOiBhcHJlIGxhIGNhdGVuYSAqLwogIGlmKEJPTlVTLmFjYz09PW51bGwpewogICAgQk9OVVMuYWNjPXAudmFsOyBCT05VUy5zdGVwcz1bcC52YWxdOyBwLnRha2VuPXRydWU7CiAgICBleHBsb2RlKHAueCxwLnkscC5yLCdkYXRhJyk7IHNmeExvY2soMSk7IGFkZFRpbWUoMS4yKTsKICAgIGJvbnVzTXNnKCdDQVRFTkEgQVZWSUFUQScsJzcwLDIzMCwyNTUnLDEuMCk7CiAgICByZXR1cm47CiAgfQogIC8qIGF0dGVzbyBvcGVyYXRvcmU6IGwndW5pY28gbnVtZXJvIGxlY2l0byDDqCBpbCByaXN1bHRhdG8gKi8KICBpZihCT05VUy5wZW5kPT09bnVsbCl7CiAgICBpZihCT05VUy5zdGVwcy5sZW5ndGg+PTMgJiYgcC52YWw9PT1CT05VUy5hY2MpeyBwLnRha2VuPXRydWU7IGJvbnVzU29sdmUocCk7IH0KICAgIGVsc2UgY2hhaW5CcmVhaygpOwogICAgcmV0dXJuOwogIH0KICAvKiBzZWNvbmRvIG9wZXJhbmRvICovCiAgY29uc3Qgcj1PUEZbQk9OVVMucGVuZF0oQk9OVVMuYWNjLCBwLnZhbCk7CiAgaWYoIU51bWJlci5pc0ludGVnZXIocikgfHwgcjwwKXsgY2hhaW5CcmVhaygpOyByZXR1cm47IH0gICAvLyBkaXZpc2lvbmUgbm9uIGludGVyYSDihpIgZXJyb3JlCiAgQk9OVVMuYWNjPXI7IEJPTlVTLnN0ZXBzLnB1c2gocC52YWwpOyBCT05VUy5wZW5kPW51bGw7IHAudGFrZW49dHJ1ZTsKICBleHBsb2RlKHAueCxwLnkscC5yLCdkYXRhJyk7IHNmeExvY2soQk9OVVMuc3RlcHMubGVuZ3RoKTsgYWRkVGltZSgxLjYpOwp9CmZ1bmN0aW9uIGNsb3NhYmxlKCl7CiAgcmV0dXJuIEJPTlVTLmFjYyE9PW51bGwgJiYgQk9OVVMucGVuZD09PW51bGwgJiYgQk9OVVMuc3RlcHMubGVuZ3RoPj0zOwp9Ci8qIElsIGdpb2NhdG9yZSBwdcOyIGJydWNpYXJlIGNvbWUgb3BlcmFuZG8gaWwgbnVtZXJvIGNoZSBlcmEgaWwgcmlzdWx0YXRvOgogICBpbiBxdWVsIGNhc28gbGEgY2F0ZW5hIG5vbiDDqCBwacO5IGNoaXVkaWJpbGUuIExvIHJpbGV2byBlIGxhIHNjaW9sZ28gaW8sCiAgIGludmVjZSBkaSBsYXNjaWFybG8gYSBzYmF0dGVyZSBmaW5vIGFsbG8gc2NhZGVyZSBkZWwgdGVtcG8uICovCmZ1bmN0aW9uIGRlYWRFbmQoKXsKICBjb25zdCBudW1zPVtdLCBvcHM9W107CiAgZm9yKGxldCBpPTA7aTxCT05VUy5wb2RzLmxlbmd0aDtpKyspewogICAgY29uc3QgcD1CT05VUy5wb2RzW2ldOwogICAgaWYocC50YWtlbikgY29udGludWU7CiAgICAocC5raW5kPT09J251bSc/IG51bXMgOiBvcHMpLnB1c2gocC52YWwpOwogIH0KICBpZihCT05VUy5hY2M9PT1udWxsKSByZXR1cm4gZmFsc2U7CiAgaWYoQk9OVVMucGVuZCE9PW51bGwpIHJldHVybiBudW1zLmxlbmd0aD09PTA7ICAgICAgICAgICAgICAvLyBtYW5jYSBsJ29wZXJhbmRvCiAgaWYoQk9OVVMuc3RlcHMubGVuZ3RoPj0zICYmIG51bXMuaW5kZXhPZihCT05VUy5hY2MpPj0wKSByZXR1cm4gZmFsc2U7ICAvLyBjaGl1ZGliaWxlCiAgaWYoIW9wcy5sZW5ndGggfHwgIW51bXMubGVuZ3RoKSByZXR1cm4gdHJ1ZTsgICAgICAgICAgICAgICAvLyBub24gc2kgcHXDsiBwcm9zZWd1aXJlCiAgcmV0dXJuIGZhbHNlOwp9CgovKiAtLS0gYWdnaW9ybmFtZW50byAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi8KZnVuY3Rpb24gdXBkYXRlQm9udXMoZHQpewogIGlmKEJPTlVTLm1zZ1Q+MCkgQk9OVVMubXNnVC09ZHQ7CiAgaWYoQk9OVVMua2luZD09PSdwcmltaScpeyB1cGRhdGVQcmltaShkdCk7IHJldHVybjsgfQogIGNvbnN0IG09Qk9OVVMubW90aGVyOyBCT05VUy5wdCs9ZHQ7CiAgaWYoQk9OVVMuYmFubmVyPjApIEJPTlVTLmJhbm5lci09ZHQ7CiAgaWYobS5oaXQ+MCkgbS5oaXQtPWR0OwoKICBpZihCT05VUy5waD09PSdpbicpewogICAgY29uc3Qgaz1NYXRoLm1pbigxLEJPTlVTLnB0LzEuMSk7CiAgICBtLnkgPSAtVyouNDIgKyAoSCouMjYgKyBXKi40MikqKDEtTWF0aC5wb3coMS1rLDMpKTsKICAgIC8qIGlsIGNhbXBvIHJlc3RhIGluIG1vdmltZW50byBmaW5vIGFsbCdpbXB1bHNvOiBuaWVudGUgZmVybW8taW1tYWdpbmUgKi8KICAgIGZvcihsZXQgaT1yb2Nrcy5sZW5ndGgtMTtpPj0wO2ktLSl7CiAgICAgIGNvbnN0IGE9cm9ja3NbaV07IGEueCs9YS52eCpkdDsgYS55Kz1hLnZ5KmR0OyBhLnJvdCs9YS52cm90KmR0OwogICAgICBpZihhLnktYS5yPkgrMjApeyBhLmRlYWQ9dHJ1ZTsgcm9ja3Muc3BsaWNlKGksMSk7IH0KICAgIH0KICAgIGlmKGs+PTEpeyBCT05VUy5waD0ncmVsZWFzZSc7IEJPTlVTLnB0PTA7IGJ1aWxkUG9kcygpOyBib251c0VNUCgpOyB9CgogIH0gZWxzZSBpZihCT05VUy5waD09PSdyZWxlYXNlJyl7CiAgICBtLnkgLT0gNipkdDsKICAgIGNvbnN0IHNob3VsZD1NYXRoLm1pbig5LCBNYXRoLmZsb29yKEJPTlVTLnB0Ly4xOSkpOwogICAgd2hpbGUoQk9OVVMucXVldWU8c2hvdWxkKXsKICAgICAgY29uc3QgcD1CT05VUy5wb2RzW0JPTlVTLnF1ZXVlXTsKICAgICAgcC50dD0wOyBwLnN4PW0ueCtybmQoLW0udyouMyxtLncqLjMpOyBwLnN5PW0ueSttLncqLjE2OyBwLng9cC5zeDsgcC55PXAuc3k7CiAgICAgIGV4cGxvZGUocC5zeCxwLnN5LDEwLCdkYXRhJyk7CiAgICAgIEJPTlVTLnF1ZXVlKys7CiAgICB9CiAgICBpZihCT05VUy5wdD4yLjEpewogICAgICBCT05VUy5waD0ncGxheSc7IEJPTlVTLnB0PTA7IEJPTlVTLmhvbGQ9aG9sZFRpbWUoKTsgYWRkVGltZSgwKTsKICAgICAgQk9OVVMuYmFubmVyPTU7CiAgICAgIGJvbnVzTXNnKFRPVUNIPyAnTUlSQSBUUkFTQ0lOQU5ETyDCtyBUT0NDQSBMQSBOQVZJQ0VMTEEgUEVSIFNQQVJBUkUnCiAgICAgICAgICAgICAgICAgICAgOiAnTUlSQSBDT04g4oaQIOKGkiDCtyBTUEFaSU8gUEVSIFVOIENPTFBPJywgJzcwLDIzMCwyNTUnLCAzLjQpOwogICAgfQoKICB9IGVsc2UgaWYoQk9OVVMucGg9PT0ncGxheScpewogICAgbS55IC09IG0udnkqZHQ7CiAgICBCT05VUy50LT1kdDsKICAgIEJPTlVTLmhvbGQtPWR0OwogICAgaWYoQk9OVVMuaG9sZDw9MCkgcmVzaHVmZmxlUG9kcygpOwogICAgaWYoQk9OVVMudDw9MCl7IEJPTlVTLnBoPSdvdXQnOyBCT05VUy5wdD0wOyBib251c01zZygnTEEgTkFWRSBNQURSRSBFXCcgRlVHR0lUQScsJzI1NSwxNzYsMzInLDEuNik7IH0KCiAgfSBlbHNlIGlmKEJPTlVTLnBoPT09J3dpbicpewogICAgbS55IC09IChtLnZ5KzE4MCkqZHQ7IG0uaGl0PS42OwogICAgY29uc3Qgbj1NYXRoLmZsb29yKEJPTlVTLnB0Ly4wNzUpOwogICAgd2hpbGUoQk9OVVMuZG9uZTxuICYmIEJPTlVTLmRvbmU8Qk9OVVMucG9kcy5sZW5ndGgpewogICAgICBjb25zdCBwPUJPTlVTLnBvZHNbQk9OVVMuZG9uZSsrXTsKICAgICAgaWYoIXAudGFrZW4peyBleHBsb2RlKHAueCxwLnkscC5yKjEuMywnZ29sZCcpOyBwLnRha2VuPXRydWU7IH0KICAgIH0KICAgIGlmKEJPTlVTLnB0PjEuNSkgZmluaXNoQm9udXMoKTsKCiAgfSBlbHNlIGlmKEJPTlVTLnBoPT09J291dCcpewogICAgbS55IC09IChtLnZ5KzI2MCkqZHQ7CiAgICBjb25zdCBuPU1hdGguZmxvb3IoQk9OVVMucHQvLjA1KTsKICAgIHdoaWxlKEJPTlVTLmRvbmU8biAmJiBCT05VUy5kb25lPEJPTlVTLnBvZHMubGVuZ3RoKXsKICAgICAgY29uc3QgcD1CT05VUy5wb2RzW0JPTlVTLmRvbmUrK107CiAgICAgIGlmKCFwLnRha2VuKXsgZXhwbG9kZShwLngscC55LHAuciouOCwnZGF0YScpOyBwLnRha2VuPXRydWU7IH0KICAgIH0KICAgIGlmKEJPTlVTLnB0Pi45KSBmaW5pc2hCb251cygpOwogIH0KCiAgLyogbW90byBkZWkgcG9kOiBmZXJtaSBwZXIgbGEgZmluZXN0cmEgZGkgcmFnaW9uYW1lbnRvLCBwb2kgcmljb2xsb2NhemlvbmUgY2ljbGljYSAqLwogIGNvbnN0IHdhcm4gPSAoQk9OVVMucGg9PT0ncGxheScgJiYgQk9OVVMuaG9sZDwxKSA/ICgxLUJPTlVTLmhvbGQpKjMuMiA6IDA7CiAgZm9yKGxldCBpPTA7aTxCT05VUy5wb2RzLmxlbmd0aDtpKyspewogICAgY29uc3QgcD1CT05VUy5wb2RzW2ldOwogICAgaWYocC50dDwwKSBjb250aW51ZTsKICAgIGlmKHAucHVsc2U+MCkgcC5wdWxzZS09ZHQqMi4yOwogICAgaWYocC50dDwxKXsKICAgICAgcC50dD1NYXRoLm1pbigxLHAudHQrZHQqKEJPTlVTLnBoPT09J3BsYXknPzEuNDoyLjEpKTsKICAgICAgY29uc3Qgaz0xLU1hdGgucG93KDEtcC50dCwzKTsKICAgICAgcC54PXAuc3grKHAuaHgtcC5zeCkqazsgcC55PXAuc3krKHAuaHktcC5zeSkqazsKICAgIH0gZWxzZSB7CiAgICAgIC8qIGZlcm1hIHN1bGwnYXNzZSBYOiDDqCBxdWVsbG8gY2hlIGNvbnRhIHBlciBpbCBwdW50YW1lbnRvICovCiAgICAgIHAucm90ICs9IHAudnJvdCouMypkdDsKICAgICAgcC54ID0gcC5oeCArICh3YXJuPyBybmQoLXdhcm4sd2FybikgOiAwKTsKICAgICAgcC55ID0gcC5oeSArIE1hdGguc2luKHQqMS41ICsgcC5oeCouMDMpKjEuOCArICh3YXJuPyBybmQoLXdhcm4sd2FybikgOiAwKTsKICAgIH0KICAgIC8qIGNvbGxpc2lvbmUgY29uIGkgcHJvaWV0dGlsaSAqLwogICAgaWYocC50YWtlbiB8fCBCT05VUy5waCE9PSdwbGF5JykgY29udGludWU7CiAgICBmb3IobGV0IGo9YnVsbGV0cy5sZW5ndGgtMTtqPj0wO2otLSl7CiAgICAgIGNvbnN0IGI9YnVsbGV0c1tqXSwgZHg9Yi54LXAueCwgZHk9Yi55LXAueTsKICAgICAgaWYoZHgqZHgrZHkqZHkgPCAocC5yKzYpKihwLnIrNikpewogICAgICAgIGJ1bGxldHMuc3BsaWNlKGosMSk7IGhpdFBvZChwKTsKICAgICAgICBpZihCT05VUy5vbiAmJiAhQk9OVVMuc29sdmVkICYmIGRlYWRFbmQoKSkgY2hhaW5CcmVhaygnVklDT0xPIENJRUNPIOKAlCBDQVRFTkEgU0NJT0xUQScpOwogICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgfQp9CmZ1bmN0aW9uIGZpbmlzaEJvbnVzKCl7CiAgaWYoIUJPTlVTLm9uKSByZXR1cm47ICAgICAgICAgICAgICAvLyBndWFyZGlhOiBtYWkgZHVlIGF2YW56YW1lbnRpIGRpIGxpdmVsbG8KICBCT05VUy5vbj1mYWxzZTsgQk9OVVMucG9kcy5sZW5ndGg9MDsgQk9OVVMud3JlY2tzLmxlbmd0aD0wOwogIHNwYXduVD0xNDAwOyAgICAgICAgICAgICAgICAgICAgICAgLy8gcmVzcGlybyBwcmltYSBkZWwgcml0b3JubyBkZWdsaSBhc3Rlcm9pZGkKICBsZXZlbFVwKCk7Cn0KCi8qIC0tLSByZXNhIGdyYWZpY2EgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi8KZnVuY3Rpb24gZHJhd01vdGhlcihtKXsKICBjb25zdCB3PW0udywgaD13Ki40NjsKICAvKiBjb25vIGRpIHJpbGFzY2lvICovCiAgaWYoQk9OVVMucGg9PT0ncmVsZWFzZScpewogICAgY29uc3QgZz1jdHguY3JlYXRlTGluZWFyR3JhZGllbnQoMCxtLnksMCxIKTsKICAgIGcuYWRkQ29sb3JTdG9wKDAsJ3JnYmEoNzAsMjMwLDI1NSwuMTYpJyk7IGcuYWRkQ29sb3JTdG9wKDEsJ3JnYmEoNzAsMjMwLDI1NSwwKScpOwogICAgY3R4LmZpbGxTdHlsZT1nOwogICAgY3R4LmJlZ2luUGF0aCgpOyBjdHgubW92ZVRvKG0ueC13Ki4yMCxtLnkraCouMyk7IGN0eC5saW5lVG8obS54K3cqLjIwLG0ueStoKi4zKTsKICAgIGN0eC5saW5lVG8obS54K3cqLjk1LEgpOyBjdHgubGluZVRvKG0ueC13Ki45NSxIKTsgY3R4LmNsb3NlUGF0aCgpOyBjdHguZmlsbCgpOwogIH0KICBjdHguc2F2ZSgpOyBjdHgudHJhbnNsYXRlKG0ueCxtLnkpOwoKICAvKiBwcm9wdWxzb3JpICovCiAgY3R4LnNhdmUoKTsgY3R4Lmdsb2JhbENvbXBvc2l0ZU9wZXJhdGlvbj0nbGlnaHRlcic7CiAgWy0xLDFdLmZvckVhY2goc3g9PnsKICAgIGNvbnN0IGV4PXN4KncqLjE0LCBleT1oKi40OCwgZmw9MjQrTWF0aC5zaW4odCoyNCtzeCoyKSo4OwogICAgY29uc3QgZz1jdHguY3JlYXRlTGluZWFyR3JhZGllbnQoZXgsZXksZXgsZXkrZmwpOwogICAgZy5hZGRDb2xvclN0b3AoMCwncmdiYSgyNTUsMjU1LDI1NSwuODUpJyk7CiAgICBnLmFkZENvbG9yU3RvcCguNCwncmdiYSgxMzAsMjA2LDI1NSwuNTUpJyk7CiAgICBnLmFkZENvbG9yU3RvcCgxLCdyZ2JhKDcwLDIzMCwyNTUsMCknKTsKICAgIGN0eC5maWxsU3R5bGU9ZzsKICAgIGN0eC5iZWdpblBhdGgoKTsgY3R4Lm1vdmVUbyhleC13Ki4wMzUsZXkpOyBjdHgubGluZVRvKGV4K3cqLjAzNSxleSk7IGN0eC5saW5lVG8oZXgsZXkrZmwpOyBjdHguY2xvc2VQYXRoKCk7IGN0eC5maWxsKCk7CiAgfSk7CiAgY3R4LnJlc3RvcmUoKTsKCiAgLyogc2NhZm86IG1lenpvIHByb2ZpbG8gc3BlY2NoaWF0byAqLwogIGNvbnN0IEhBTEY9W1swLC0uNjBdLFsuMDgsLS40N10sWy4xMSwtLjIwXSxbLjMwLC0uMTJdLFsuNTAsLjAyXSxbLjQ0LC4xN10sWy4yMCwuMjFdLFsuMTYsLjQ1XSxbLjA2LC41Ml1dOwogIGN0eC5iZWdpblBhdGgoKTsKICBmb3IobGV0IGk9MDtpPEhBTEYubGVuZ3RoO2krKyl7IGNvbnN0IHA9SEFMRltpXTsgaT8gY3R4LmxpbmVUbyhwWzBdKncscFsxXSpoKSA6IGN0eC5tb3ZlVG8ocFswXSp3LHBbMV0qaCk7IH0KICBmb3IobGV0IGk9SEFMRi5sZW5ndGgtMTtpPj0wO2ktLSl7IGNvbnN0IHA9SEFMRltpXTsgY3R4LmxpbmVUbygtcFswXSp3LHBbMV0qaCk7IH0KICBjdHguY2xvc2VQYXRoKCk7CiAgY29uc3QgaGc9Y3R4LmNyZWF0ZUxpbmVhckdyYWRpZW50KDAsLWgqLjYsMCxoKi41Mik7CiAgaGcuYWRkQ29sb3JTdG9wKDAsJyM5ZGIzZDknKTsgaGcuYWRkQ29sb3JTdG9wKC4zMiwnIzMzNDU2YycpOyBoZy5hZGRDb2xvclN0b3AoMSwnIzBiMTIyNCcpOwogIGN0eC5maWxsU3R5bGU9aGc7IGN0eC5maWxsKCk7CiAgY3R4LmxpbmVXaWR0aD0xLjc7IGN0eC5zdHJva2VTdHlsZT1gcmdiYSg3MCwyMzAsMjU1LCR7LjUrKG0uaGl0PjA/LjU6MCl9KWA7CiAgY3R4LnNoYWRvd0NvbG9yPSdyZ2JhKDcwLDIzMCwyNTUsLjcpJzsgY3R4LnNoYWRvd0JsdXI9MTY7IGN0eC5zdHJva2UoKTsgY3R4LnNoYWRvd0JsdXI9MDsKCiAgLyogb2Jsw7IgZGkgcGxhbmNpYSAqLwogIGN0eC5maWxsU3R5bGU9J3JnYmEoMTUwLDI0MCwyNTUsLjg1KSc7CiAgZm9yKGxldCBpPS0zO2k8PTM7aSsrKSBjdHguZmlsbFJlY3QoaSp3Ki4wNS13Ki4wMTIsIC1oKi4zMCwgdyouMDI0LCBoKi4wNDUpOwoKICAvKiByZWF0dG9yZSAqLwogIGNvbnN0IHB1PS41NStNYXRoLnNpbih0KjMuMikqLjI1OwogIGNvbnN0IHJnPWN0eC5jcmVhdGVSYWRpYWxHcmFkaWVudCgwLGgqLjA2LDAsMCxoKi4wNix3Ki4xNik7CiAgcmcuYWRkQ29sb3JTdG9wKDAsYHJnYmEoMjU1LDEyMCwxODAsJHtwdX0pYCk7CiAgcmcuYWRkQ29sb3JTdG9wKC41LGByZ2JhKDI1NSw0NiwxMDcsJHtwdSouNDV9KWApOwogIHJnLmFkZENvbG9yU3RvcCgxLCdyZ2JhKDI1NSw0NiwxMDcsMCknKTsKICBjdHguZmlsbFN0eWxlPXJnOyBjdHguYmVnaW5QYXRoKCk7IGN0eC5hcmMoMCxoKi4wNix3Ki4xNiwwLFRBVSk7IGN0eC5maWxsKCk7CgogIC8qIG5lcnZhdHVyZSBkZWkgcGlsb25pICovCiAgY3R4LmxpbmVXaWR0aD0xOyBjdHguc3Ryb2tlU3R5bGU9J3JnYmEoMTQwLDE5MCwyNTUsLjIyKSc7CiAgWy0xLDFdLmZvckVhY2goc3g9PnsKICAgIGN0eC5iZWdpblBhdGgoKTsgY3R4Lm1vdmVUbyhzeCp3Ki4xMiwtaCouMTYpOyBjdHgubGluZVRvKHN4KncqLjQ3LGgqLjAxKTsgY3R4LnN0cm9rZSgpOwogICAgY3R4LmJlZ2luUGF0aCgpOyBjdHgubW92ZVRvKHN4KncqLjE0LGgqLjEwKTsgIGN0eC5saW5lVG8oc3gqdyouNDIsaCouMTUpOyBjdHguc3Ryb2tlKCk7CiAgfSk7CiAgY3R4LnJlc3RvcmUoKTsKfQoKZnVuY3Rpb24gZHJhd1BvZChwKXsKICBpZihwLnRha2VuIHx8IHAudHQ8MCkgcmV0dXJuOwogIGNvbnN0IGdvbGQgPSBjbG9zYWJsZSgpICYmIHAua2luZD09PSdudW0nICYmIHAudmFsPT09Qk9OVVMuYWNjOwogIGNvbnN0IHMgPSBwLnR0PDEgPyAuMzUrLjY1KnAudHQgOiAxICsgKHAucHVsc2U+MD8gcC5wdWxzZSouMjIgOiAwKTsKICBjb25zdCBudW0gPSBwLmtpbmQ9PT0nbnVtJzsKICBjb25zdCBiYXNlID0gZ29sZCA/IFsyNTUsMTk2LDQ0XSA6IG51bSA/IFs3MCwyMzAsMjU1XSA6IFsyNTUsNDYsMTA3XTsKICBjb25zdCBjb2wgPSBiYXNlLmpvaW4oJywnKTsKCiAgaWYoZ29sZCl7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvKiBhbG9uZSBwdWxzYW50ZSBkZWwgYmVyc2FnbGlvICovCiAgICBjb25zdCBrPShNYXRoLnNpbih0KjcpKzEpLzI7CiAgICBjdHguc2F2ZSgpOyBjdHguZ2xvYmFsQ29tcG9zaXRlT3BlcmF0aW9uPSdsaWdodGVyJzsKICAgIGNvbnN0IGc9Y3R4LmNyZWF0ZVJhZGlhbEdyYWRpZW50KHAueCxwLnkscC5yKi42LHAueCxwLnkscC5yKigyK2sqLjcpKTsKICAgIGcuYWRkQ29sb3JTdG9wKDAsYHJnYmEoMjU1LDE5Niw0NCwkey4zK2sqLjI1fSlgKTsKICAgIGcuYWRkQ29sb3JTdG9wKDEsJ3JnYmEoMjU1LDE5Niw0NCwwKScpOwogICAgY3R4LmZpbGxTdHlsZT1nOyBjdHguYmVnaW5QYXRoKCk7IGN0eC5hcmMocC54LHAueSxwLnIqKDIrayouNyksMCxUQVUpOyBjdHguZmlsbCgpOwogICAgY3R4LnJlc3RvcmUoKTsKICB9CgogIGN0eC5zYXZlKCk7IGN0eC50cmFuc2xhdGUocC54LHAueSk7IGN0eC5zY2FsZShzLHMpOyBjdHgucm90YXRlKHAucm90KTsKICBjb25zdCBzaWRlcyA9IG51bT82OjQ7CiAgY3R4LmJlZ2luUGF0aCgpOwogIGZvcihsZXQgaT0wO2k8c2lkZXM7aSsrKXsKICAgIGNvbnN0IGE9KGkvc2lkZXMpKlRBVSAtIE1hdGguUEkvMjsKICAgIGNvbnN0IHB4PU1hdGguY29zKGEpKnAuciwgcHk9TWF0aC5zaW4oYSkqcC5yOwogICAgaT8gY3R4LmxpbmVUbyhweCxweSkgOiBjdHgubW92ZVRvKHB4LHB5KTsKICB9CiAgY3R4LmNsb3NlUGF0aCgpOwogIGNvbnN0IGc9Y3R4LmNyZWF0ZVJhZGlhbEdyYWRpZW50KDAsLXAuciouMzUscC5yKi4xLDAsMCxwLnIpOwogIGcuYWRkQ29sb3JTdG9wKDAsYHJnYmEoJHtjb2x9LC4zMilgKTsKICBnLmFkZENvbG9yU3RvcCgxLCdyZ2JhKDUsOSwyMCwuOSknKTsKICBjdHguZmlsbFN0eWxlPWc7IGN0eC5maWxsKCk7CiAgY3R4LmxpbmVXaWR0aD0yLjE7IGN0eC5zdHJva2VTdHlsZT1gcmdiYSgke2NvbH0sLjk1KWA7CiAgY3R4LnNoYWRvd0NvbG9yPWByZ2JhKCR7Y29sfSwuOSlgOyBjdHguc2hhZG93Qmx1cj1nb2xkPzI0OjEzOyBjdHguc3Ryb2tlKCk7CiAgY3R4LnJlc3RvcmUoKTsKCiAgY3R4LnNhdmUoKTsgY3R4LnRyYW5zbGF0ZShwLngscC55KTsgY3R4LnNjYWxlKHMscyk7CiAgY3R4LmZvbnQ9YDcwMCAke01hdGgucm91bmQocC5yKihudW0/LjkyOjEuMTUpKX1weCAkeyd1aS1tb25vc3BhY2UsU0ZNb25vLVJlZ3VsYXIsTWVubG8sbW9ub3NwYWNlJ31gOwogIGN0eC50ZXh0QWxpZ249J2NlbnRlcic7IGN0eC50ZXh0QmFzZWxpbmU9J21pZGRsZSc7CiAgY3R4LnNoYWRvd0NvbG9yPWByZ2JhKCR7Y29sfSwuOTUpYDsgY3R4LnNoYWRvd0JsdXI9MTQ7CiAgY3R4LmZpbGxTdHlsZSA9IGdvbGQ/JyNmZmY0ZDYnOicjZWFmNmZmJzsKICBjdHguZmlsbFRleHQoU3RyaW5nKHAudmFsKSwgMCwgbnVtPzE6MCk7CiAgY3R4LnJlc3RvcmUoKTsKfQoKLyogLS0tIGFzc2lzdGVuemEgYWwgcHVudGFtZW50byAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovCmZ1bmN0aW9uIGZpcmVSaW5nKCl7IHJldHVybiBNYXRoLm1heCg0OCwgTWF0aC5taW4oODQsIFcqLjExKSk7IH0KLyogTW9kYWxpdMOgIG1pcmE6IG5laSBzZXR0b3JpIGJvbnVzIGUgZGEgcXVhbmRvIGNvbXBhaW9ubyBsZSBjYXJpY2hlLgogICBJbCB0cmFzY2luYW1lbnRvIG5vbiBzcGFyYSBwacO5OiBzZXJ2ZSB1biB0YXAgZGVsaWJlcmF0by4gKi8KZnVuY3Rpb24gYWltaW5nTW9kZSgpeyByZXR1cm4gQk9OVVMub24gfHwgbGV2ZWw+PUNBUkdPX0xWIHx8IEFVVE8ub247IH0KLyogU2VsZXppb25lIHBlciBDT1JTSUEsIG5vbiBwZXIgcmFnZ2lvOiB2aW5jZSBpbCBwb2QgY29uIGlsIGNlbnRybyBwacO5CiAgIHZpY2lubyBzdWxsJ2Fzc2UgWC4gTGUgem9uZSBkaSBjYXR0dXJhIG5vbiBzaSBzb3ZyYXBwb25nb25vIHBpw7kgZSBpbAogICBjb25maW5lIHRyYSBkdWUgYmVyc2FnbGkgw6ggZXNhdHRhbWVudGUgYSBtZXTDoCBzdHJhZGEuICovCmZ1bmN0aW9uIGFpbVBvZCgpewogIGlmKCFzaGlwKSByZXR1cm4gbnVsbDsKICBjb25zdCBsYW5lPUJPTlVTLmxhbmV8fDcwOwogIGxldCBiZXN0PW51bGwsIGJkPTFlOTsKICBmb3IobGV0IGk9MDtpPEJPTlVTLnBvZHMubGVuZ3RoO2krKyl7CiAgICBjb25zdCBwPUJPTlVTLnBvZHNbaV07CiAgICBpZihwLnRha2VuIHx8IHAudHQ8MCB8fCBwLnkgPj0gc2hpcC55LTMwKSBjb250aW51ZTsKICAgIGNvbnN0IGQ9TWF0aC5hYnMocC54LXNoaXAueCk7CiAgICBpZihkPGJkKXsgYmQ9ZDsgYmVzdD1wOyB9CiAgfQogIHJldHVybiAoYmVzdCAmJiBiZCA8PSBiZXN0LnIgKyBsYW5lKi41KSA/IGJlc3QgOiBudWxsOwp9Ci8qIEZyYSBnbGkgYXN0ZXJvaWRpIHZpbmNlIGlsIHBpw7kgYmFzc28gZnJhIHF1ZWxsaSBhbGxpbmVhdGk6IMOoIHF1ZWxsbwogICBjaGUgaWwgY29scG8gaW5jb250cmVyZWJiZSBwZXIgcHJpbW8uICovCmZ1bmN0aW9uIGFpbVJvY2soKXsKICBpZighc2hpcCkgcmV0dXJuIG51bGw7CiAgbGV0IGJlc3Q9bnVsbDsKICBmb3IobGV0IGk9MDtpPHJvY2tzLmxlbmd0aDtpKyspewogICAgY29uc3QgYT1yb2Nrc1tpXTsKICAgIGlmKGEuZGVhZCB8fCBhLnkgPj0gc2hpcC55LTMwKSBjb250aW51ZTsKICAgIGlmKE1hdGguYWJzKGEueC1zaGlwLngpIDw9IGEuciAmJiAoIWJlc3QgfHwgYS55PmJlc3QueSkpIGJlc3Q9YTsKICB9CiAgcmV0dXJuIGJlc3Q7Cn0KZnVuY3Rpb24gYWltVGFyZ2V0KCl7IHJldHVybiBCT05VUy5vbiA/IGFpbVBvZCgpIDogKGxldmVsPj1DQVJHT19MViA/IGFpbVJvY2soKSA6IG51bGwpOyB9Ci8qIGNvbG9yZSBkZWxsYSBwYXJlbnRlc2kgPSBuYXR1cmEgZGVsIGJlcnNhZ2xpbywgbGV0dGEgcHJpbWEgZGkgc3BhcmFyZSAqLwpmdW5jdGlvbiBhaW1Db2xvcih0Zyl7CiAgaWYoIXRnKSByZXR1cm4gJzcwLDIzMCwyNTUnOwogIGNvbnN0IGM9dGcuY2FyZ287CiAgaWYoIWMpIHJldHVybiB0Zy5raW5kPyAnMjU1LDE5Niw0NCcgOiAnMTUwLDIxMCwyNTUnOwogIHJldHVybiBjLnQ9PT0nbXVsdCc/ICcyNTUsMjE0LDgwJyA6IGMudD09PSdudWtlJz8gJzI1NSwyMTQsMTAnCiAgICAgICA6IGMudD09PSdsaWZlJz8gJzExMCwyNDAsMjAwJyA6IGMudD09PSdwbHVzJz8gJzExMCwyNDAsMTYwJyA6ICcyNTUsNDYsMTA3JzsKfQpmdW5jdGlvbiBkcmF3QWltKCl7CiAgaWYoIXNoaXApIHJldHVybjsKICBpZihCT05VUy5vbil7IGlmKEJPTlVTLnBoIT09J3BsYXknKSByZXR1cm47IH0KICBlbHNlIGlmKGxldmVsPENBUkdPX0xWKSByZXR1cm47CgogIGNvbnN0IHRndD1haW1UYXJnZXQoKSwgY29sPWFpbUNvbG9yKHRndCk7CiAgY3R4LnNhdmUoKTsKCiAgLyogcmFnZ2lvIGRpIG1pcmEgKi8KICBjdHguc2V0TGluZURhc2goWzUsMTFdKTsgY3R4LmxpbmVEYXNoT2Zmc2V0PS10KjcwOyBjdHgubGluZVdpZHRoPTEuNTsKICBjdHguc3Ryb2tlU3R5bGUgPSB0Z3Q/IGByZ2JhKCR7Y29sfSwuNTUpYCA6ICdyZ2JhKDcwLDIzMCwyNTUsLjE4KSc7CiAgY3R4LmJlZ2luUGF0aCgpOyBjdHgubW92ZVRvKHNoaXAueCwgc2hpcC55LTI2KTsKICBjdHgubGluZVRvKHNoaXAueCwgdGd0PyB0Z3QueSt0Z3QuciA6IEgqLjE3KTsgY3R4LnN0cm9rZSgpOwogIGN0eC5zZXRMaW5lRGFzaChbXSk7CgogIC8qIHBhcmVudGVzaSBkaSBhY3F1aXNpemlvbmUgKi8KICBpZih0Z3QpewogICAgY29uc3QgUj10Z3Qucis5LCBjPWByZ2JhKCR7Y29sfSwuOTUpYDsKICAgIGN0eC5zdHJva2VTdHlsZT1jOyBjdHgubGluZVdpZHRoPTIuNDsgY3R4LmxpbmVDYXA9J3JvdW5kJzsKICAgIGN0eC5zaGFkb3dDb2xvcj1jOyBjdHguc2hhZG93Qmx1cj0xMjsKICAgIFtbLTEsLTFdLFsxLC0xXSxbLTEsMV0sWzEsMV1dLmZvckVhY2gocT0+ewogICAgICBjb25zdCBzeD1xWzBdLCBzeT1xWzFdOwogICAgICBjdHguYmVnaW5QYXRoKCk7CiAgICAgIGN0eC5tb3ZlVG8odGd0Lngrc3gqUiwgdGd0Lnkrc3kqUiouNDIpOwogICAgICBjdHgubGluZVRvKHRndC54K3N4KlIsIHRndC55K3N5KlIpOwogICAgICBjdHgubGluZVRvKHRndC54K3N4KlIqLjQyLCB0Z3QueStzeSpSKTsKICAgICAgY3R4LnN0cm9rZSgpOwogICAgfSk7CiAgICBjdHguc2hhZG93Qmx1cj0wOwogIH0KCiAgLyogYW5lbGxvIGRpIGZ1b2NvOiBsYSB6b25hIGNoZSByaXNwb25kZSBhbCB0YXAgKG8gYWwgY2xpY2spICovCiAgewogICAgY29uc3Qgaz0oTWF0aC5zaW4odCo0KSsxKS8yLCBSPWZpcmVSaW5nKCk7CiAgICBjdHguc2V0TGluZURhc2goWzQsOF0pOyBjdHgubGluZURhc2hPZmZzZXQ9dCoyNjsgY3R4LmxpbmVXaWR0aD0xLjQ7CiAgICBjdHguc3Ryb2tlU3R5bGU9YHJnYmEoNzAsMjMwLDI1NSwkey4yMCtrKi4yMH0pYDsKICAgIGN0eC5iZWdpblBhdGgoKTsgY3R4LmFyYyhzaGlwLngsIHNoaXAueSwgUiwgMCwgVEFVKTsgY3R4LnN0cm9rZSgpOwogICAgY3R4LnNldExpbmVEYXNoKFtdKTsKICB9CiAgY3R4LnJlc3RvcmUoKTsKfQoKZnVuY3Rpb24gZHJhd0JvbnVzV29ybGQoKXsKICBpZihCT05VUy5raW5kPT09J3ByaW1pJyl7IGRyYXdQcmltaVdvcmxkKCk7IHJldHVybjsgfQogIGNvbnN0IG09Qk9OVVMubW90aGVyOwogIGlmKG0gJiYgbS55Pi1tLncpeyBzaGFkb3dSb2NrKHt4Om0ueCx5Om0ueSxyOm0udyouMzB9KTsgZHJhd01vdGhlcihtKTsgfQogIGZvcihsZXQgaT0wO2k8Qk9OVVMucG9kcy5sZW5ndGg7aSsrKXsKICAgIGNvbnN0IHA9Qk9OVVMucG9kc1tpXTsKICAgIGlmKCFwLnRha2VuICYmIHAudHQ+PTApIHNoYWRvd1JvY2socCk7CiAgfQogIGZvcihsZXQgaT0wO2k8Qk9OVVMucG9kcy5sZW5ndGg7aSsrKSBkcmF3UG9kKEJPTlVTLnBvZHNbaV0pOwogIGRyYXdBaW0oKTsKfQoKLyogcGlhc3RyYSBkZWxsJ2VzcHJlc3Npb25lICsgY3Jvbm9tZXRybyAqLwpmdW5jdGlvbiBycmVjdCh4LHksdyxoLHIpewogIGN0eC5iZWdpblBhdGgoKTsKICBjdHgubW92ZVRvKHgrcix5KTsgY3R4LmxpbmVUbyh4K3ctcix5KTsgY3R4LnF1YWRyYXRpY0N1cnZlVG8oeCt3LHkseCt3LHkrcik7CiAgY3R4LmxpbmVUbyh4K3cseStoLXIpOyBjdHgucXVhZHJhdGljQ3VydmVUbyh4K3cseStoLHgrdy1yLHkraCk7CiAgY3R4LmxpbmVUbyh4K3IseStoKTsgY3R4LnF1YWRyYXRpY0N1cnZlVG8oeCx5K2gseCx5K2gtcik7CiAgY3R4LmxpbmVUbyh4LHkrcik7IGN0eC5xdWFkcmF0aWNDdXJ2ZVRvKHgseSx4K3IseSk7IGN0eC5jbG9zZVBhdGgoKTsKfQpmdW5jdGlvbiBkcmF3Qm9udXNIVUQoKXsKICBpZihCT05VUy5raW5kPT09J3ByaW1pJyl7IGRyYXdQcmltaUhVRCgpOyByZXR1cm47IH0KICBjb25zdCBjeT1NYXRoLm1heCgxMTYsIEgqLjE1NSksIGZzPU1hdGgubWF4KDE3LCBNYXRoLm1pbigyNywgVy8xNSkpOwoKICAvKiAtLS0gZGlzdGludGl2byBwZXJtYW5lbnRlIGRlbGwnb2JpZXR0aXZvIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovCiAgaWYoQk9OVVMudGFyZ2V0IT1udWxsICYmIEJPTlVTLnBoIT09J2luJyl7CiAgICBjdHguc2F2ZSgpOwogICAgY29uc3QgbGY9TWF0aC5tYXgoMTAsZnMqLjUyKSwgbmY9TWF0aC5tYXgoMTcsZnMqLjg2KTsKICAgIGN0eC5mb250PWA3MDAgJHtsZn1weCB1aS1tb25vc3BhY2UsU0ZNb25vLVJlZ3VsYXIsTWVubG8sbW9ub3NwYWNlYDsKICAgIGNvbnN0IGx3PWN0eC5tZWFzdXJlVGV4dCgnT0JJRVRUSVZPICcpLndpZHRoOwogICAgY3R4LmZvbnQ9YDgwMCAke25mfXB4IHVpLW1vbm9zcGFjZSxTRk1vbm8tUmVndWxhcixNZW5sbyxtb25vc3BhY2VgOwogICAgY29uc3Qgbnc9Y3R4Lm1lYXN1cmVUZXh0KFN0cmluZyhCT05VUy50YXJnZXQpKS53aWR0aDsKICAgIGNvbnN0IGJ3PWx3K253KzMwLCBieD0oVy1idykvMiwgYmg9bmYqMS42LCBieT1jeS1mcyoxLjA1LWJoLTg7CiAgICBjdHguZmlsbFN0eWxlPSdyZ2JhKDMwLDE4LDIsLjgwKSc7IHJyZWN0KGJ4LGJ5LGJ3LGJoLGJoKi41KTsgY3R4LmZpbGwoKTsKICAgIGN0eC5saW5lV2lkdGg9MS42OyBjdHguc3Ryb2tlU3R5bGU9J3JnYmEoMjU1LDE5Niw0NCwuODUpJzsKICAgIGN0eC5zaGFkb3dDb2xvcj0ncmdiYSgyNTUsMTk2LDQ0LC44KSc7IGN0eC5zaGFkb3dCbHVyPTE2OyBjdHguc3Ryb2tlKCk7IGN0eC5zaGFkb3dCbHVyPTA7CiAgICBjdHgudGV4dEJhc2VsaW5lPSdtaWRkbGUnOyBjdHgudGV4dEFsaWduPSdsZWZ0JzsKICAgIGN0eC5mb250PWA3MDAgJHtsZn1weCB1aS1tb25vc3BhY2UsU0ZNb25vLVJlZ3VsYXIsTWVubG8sbW9ub3NwYWNlYDsKICAgIGN0eC5maWxsU3R5bGU9J3JnYmEoMjU1LDIyMiwxNTAsLjc1KSc7CiAgICBjdHguZmlsbFRleHQoJ09CSUVUVElWTyAnLCBieCsxNSwgYnkrYmgvMisxKTsKICAgIGN0eC5mb250PWA4MDAgJHtuZn1weCB1aS1tb25vc3BhY2UsU0ZNb25vLVJlZ3VsYXIsTWVubG8sbW9ub3NwYWNlYDsKICAgIGN0eC5maWxsU3R5bGU9JyNmZmQxNjYnOwogICAgY3R4LnNoYWRvd0NvbG9yPSdyZ2JhKDI1NSwxOTYsNDQsLjkpJzsgY3R4LnNoYWRvd0JsdXI9MTQ7CiAgICBjdHguZmlsbFRleHQoU3RyaW5nKEJPTlVTLnRhcmdldCksIGJ4KzE1K2x3LCBieStiaC8yKTsKICAgIGN0eC5yZXN0b3JlKCk7CiAgfQoKICBsZXQgZXhwciwgcmVzOwogIGlmKEJPTlVTLmFjYz09PW51bGwpeyBleHByPSdDT0xQSVNDSSBVTiBOVU1FUk8nOyByZXM9Jyc7IH0KICBlbHNlIHsgZXhwcj1CT05VUy5zdGVwcy5qb2luKCcgJyk7IHJlcyA9IEJPTlVTLnBlbmQhPT1udWxsID8gJz8nIDogKEJPTlVTLnN0ZXBzLmxlbmd0aD49Mz8gU3RyaW5nKEJPTlVTLmFjYykgOiAnJyk7IH0KCiAgY3R4LnNhdmUoKTsKICBjdHguZm9udD1gNzAwICR7ZnN9cHggdWktbW9ub3NwYWNlLFNGTW9uby1SZWd1bGFyLE1lbmxvLG1vbm9zcGFjZWA7CiAgY29uc3QgZnVsbCA9IGV4cHIgKyAocmVzPyAnICA9ICAnK3JlcyA6ICcnKTsKICBjb25zdCB0dyA9IGN0eC5tZWFzdXJlVGV4dChmdWxsKS53aWR0aDsKICBjb25zdCBwdyA9IE1hdGgubWluKFctMjgsIHR3KzQ2KSwgcHg9KFctcHcpLzIsIHBoPWZzKjIuMSwgcHk9Y3ktcGgvMjsKCiAgY3R4LmZpbGxTdHlsZT0ncmdiYSg2LDEwLDIyLC43MiknOyBycmVjdChweCxweSxwdyxwaCxwaCouMjgpOyBjdHguZmlsbCgpOwogIGN0eC5saW5lV2lkdGg9MS40OwogIGN0eC5zdHJva2VTdHlsZSA9IGNsb3NhYmxlKCk/ICdyZ2JhKDI1NSwxOTYsNDQsLjkpJyA6ICdyZ2JhKDcwLDIzMCwyNTUsLjU1KSc7CiAgY3R4LnNoYWRvd0NvbG9yID0gY3R4LnN0cm9rZVN0eWxlOyBjdHguc2hhZG93Qmx1cj0xNDsgY3R4LnN0cm9rZSgpOyBjdHguc2hhZG93Qmx1cj0wOwoKICBjdHgudGV4dEFsaWduPSdjZW50ZXInOyBjdHgudGV4dEJhc2VsaW5lPSdtaWRkbGUnOwogIGN0eC5maWxsU3R5bGUgPSBCT05VUy5hY2M9PT1udWxsPyAncmdiYSgyMzIsMjQwLDI1NSwuNSknIDogJyNlYWY2ZmYnOwogIGlmKHJlcyl7CiAgICBjb25zdCBldz1jdHgubWVhc3VyZVRleHQoZXhwcisnICA9ICAnKS53aWR0aCwgeDA9Vy8yLXR3LzI7CiAgICBjdHgudGV4dEFsaWduPSdsZWZ0JzsgY3R4LmZpbGxUZXh0KGV4cHIrJyAgPSAgJywgeDAsIGN5KTsKICAgIGN0eC5maWxsU3R5bGUgPSBjbG9zYWJsZSgpPyAnI2ZmZDE2NicgOiAncmdiYSgyMzIsMjQwLDI1NSwuNTUpJzsKICAgIGN0eC5zaGFkb3dDb2xvcj0ncmdiYSgyNTUsMTk2LDQ0LC44KSc7IGN0eC5zaGFkb3dCbHVyPWNsb3NhYmxlKCk/MTY6MDsKICAgIGN0eC5maWxsVGV4dChyZXMsIHgwK2V3LCBjeSk7IGN0eC5zaGFkb3dCbHVyPTA7CiAgfSBlbHNlIGN0eC5maWxsVGV4dChleHByLCBXLzIsIGN5KTsKCiAgLyogY3Jvbm9tZXRybyA9IHF1b3RhIHJlc2lkdWEgZGVsbGEgbmF2ZSBtYWRyZSAqLwogIGNvbnN0IGJ3PXB3Ki43MiwgYng9KFctYncpLzIsIGJ5PXB5K3BoKzcsIGs9Y2xhbXAoQk9OVVMudC9CT05VUy50bWF4LDAsMSk7CiAgY3R4LmZpbGxTdHlsZT0ncmdiYSgyNTUsMjU1LDI1NSwuMTApJzsgY3R4LmZpbGxSZWN0KGJ4LGJ5LGJ3LDMpOwogIGN0eC5maWxsU3R5bGUgPSBrPC4yOD8gJyNmZjJlNmInIDogJyM0NmU2ZmYnOwogIGN0eC5zaGFkb3dDb2xvcj1jdHguZmlsbFN0eWxlOyBjdHguc2hhZG93Qmx1cj04OwogIGN0eC5maWxsUmVjdChieCxieSxidyprLDMpOyBjdHguc2hhZG93Qmx1cj0wOwoKICAvKiBtZXNzYWdnaW8gZGkgc3RhdG8gKi8KICBpZihCT05VUy5tc2dUPjApewogICAgY29uc3QgYT1NYXRoLm1pbigxLEJPTlVTLm1zZ1QqMS42KTsKICAgIGN0eC5mb250PWA3MDAgJHtNYXRoLm1heCgxMixmcyouNTgpfXB4IHVpLW1vbm9zcGFjZSxTRk1vbm8tUmVndWxhcixNZW5sbyxtb25vc3BhY2VgOwogICAgY3R4LnRleHRBbGlnbj0nY2VudGVyJzsgY3R4LmZpbGxTdHlsZT1gcmdiYSgke0JPTlVTLm1zZ0NvbH0sJHthfSlgOwogICAgY3R4LnNoYWRvd0NvbG9yPWByZ2JhKCR7Qk9OVVMubXNnQ29sfSwuOClgOyBjdHguc2hhZG93Qmx1cj0xMjsKICAgIGN0eC5maWxsVGV4dChCT05VUy5tc2csIFcvMiwgYnkrMjIpOwogIH0KICBjdHgucmVzdG9yZSgpOwoKICAvKiAtLS0gaW5zZWduYSBncmFuZGUgZSB0ZW1wb3JhbmVhOiBjb3NhIHNlcnZlIGZhcmUsIHNlbnphIGVxdWl2b2NpIC0tLSAqLwogIGlmKEJPTlVTLmJhbm5lcj4wICYmIEJPTlVTLnBoPT09J3BsYXknKXsKICAgIGNvbnN0IGs9TWF0aC5taW4oMSwoNS1CT05VUy5iYW5uZXIpLy4zNSk7ICAgICAgICAgICAgLy8gZW50cmF0YQogICAgY29uc3QgYT1NYXRoLm1pbihrLCBNYXRoLm1pbigxLEJPTlVTLmJhbm5lcioxLjQpKTsgICAvLyB1c2NpdGEKICAgIGNvbnN0IGN5Qj1IKi43NTUsIGJpZz1NYXRoLm1heCg1MiwgTWF0aC5taW4oMTEyLCBXLzMuNikpOwogICAgY3R4LnNhdmUoKTsKICAgIGN0eC50ZXh0QWxpZ249J2NlbnRlcic7CiAgICBjdHguZ2xvYmFsQWxwaGE9YSouOTsKICAgIGNvbnN0IGc9Y3R4LmNyZWF0ZUxpbmVhckdyYWRpZW50KDAsY3lCLWJpZywwLGN5QitiaWcqLjcpOwogICAgZy5hZGRDb2xvclN0b3AoMCwncmdiYSg2LDEwLDIyLDApJyk7CiAgICBnLmFkZENvbG9yU3RvcCguNSwncmdiYSg2LDEwLDIyLC44NiknKTsKICAgIGcuYWRkQ29sb3JTdG9wKDEsJ3JnYmEoNiwxMCwyMiwwKScpOwogICAgY3R4LmZpbGxTdHlsZT1nOyBjdHguZmlsbFJlY3QoMCxjeUItYmlnLFcsYmlnKjEuNzUpOwoKICAgIGN0eC5nbG9iYWxBbHBoYT1hOwogICAgY3R4LnRleHRCYXNlbGluZT0nYWxwaGFiZXRpYyc7CiAgICBjdHguZm9udD1gNzAwICR7TWF0aC5tYXgoMTEsYmlnKi4xNSl9cHggdWktbW9ub3NwYWNlLFNGTW9uby1SZWd1bGFyLE1lbmxvLG1vbm9zcGFjZWA7CiAgICBjdHguZmlsbFN0eWxlPSdyZ2JhKDI1NSwyMjIsMTUwLC44NSknOwogICAgY3R4LmZpbGxUZXh0KCdEIEUgViBJICAgTyBUIFQgRSBOIEUgUiBFJywgVy8yLCBjeUItYmlnKi40NCk7CgogICAgY29uc3Qgc2M9MSsoMS1rKSouNTsKICAgIGN0eC5zYXZlKCk7IGN0eC50cmFuc2xhdGUoVy8yLGN5Qik7IGN0eC5zY2FsZShzYyxzYyk7CiAgICBjdHguZm9udD1gODAwICR7TWF0aC5yb3VuZChiaWcpfXB4IHVpLW1vbm9zcGFjZSxTRk1vbm8tUmVndWxhcixNZW5sbyxtb25vc3BhY2VgOwogICAgY3R4LnRleHRCYXNlbGluZT0nbWlkZGxlJzsKICAgIGN0eC5maWxsU3R5bGU9JyNmZmQxNjYnOwogICAgY3R4LnNoYWRvd0NvbG9yPSdyZ2JhKDI1NSwxOTYsNDQsLjk1KSc7IGN0eC5zaGFkb3dCbHVyPTM0OwogICAgY3R4LmZpbGxUZXh0KFN0cmluZyhCT05VUy50YXJnZXQpLCAwLCAwKTsKICAgIGN0eC5yZXN0b3JlKCk7CgogICAgY3R4LmZvbnQ9YDcwMCAke01hdGgubWF4KDEwLGJpZyouMTI1KX1weCB1aS1tb25vc3BhY2UsU0ZNb25vLVJlZ3VsYXIsTWVubG8sbW9ub3NwYWNlYDsKICAgIGN0eC5maWxsU3R5bGU9J3JnYmEoMTUwLDIyMCwyNTUsLjkpJzsKICAgIGN0eC5zaGFkb3dDb2xvcj0ncmdiYSg3MCwyMzAsMjU1LC42KSc7IGN0eC5zaGFkb3dCbHVyPTEwOwogICAgY3R4LmZpbGxUZXh0KCdDT01CSU5BIEdMSSBBTFRSSSBOVU1FUkkgQ09OIEdMSSBPUEVSQVRPUkknLCBXLzIsIGN5QitiaWcqLjUyKTsKICAgIGN0eC5maWxsVGV4dCgnTlVNRVJPIOKGkiBPUEVSQVRPUkUg4oaSIE5VTUVSTyDihpIgJytCT05VUy50YXJnZXQsIFcvMiwgY3lCK2JpZyouNzApOwogICAgY3R4LnJlc3RvcmUoKTsKICB9Cn0KCi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQogICBTRVRUT1JFIFBSSU1JIOKAlCBjb252b2dsaW8gZGEgYWJiYXR0ZXJlIHBlciBzZWxlemlvbmUKICAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiAgIFVuIHJpbW9yY2hpYXRvcmUgYXR0cmF2ZXJzYSBsbyBzY2hlcm1vIHRyYWluYW5kbyB1bmEgZmlsYSBkaQogICBjb250ZW5pdG9yaSBudW1lcmF0aS4gVmFsZSBzb2xvIGlsIG51bWVybyBwcmltbzogKzMwMDAuCiAgIE9nbmkgY29tcG9zaXRvIGFiYmF0dHV0bzog4oiSMjAwMCwgZSBpbCBwdW50ZWdnaW8gcHXDsiBhbmRhcmUgc290dG8gemVyby4KICAgSWwgcHJpbW8gY29scGl0byBzaSBzdGFjY2EgZSBwcmVjaXBpdGEgZnVtYW5kbyBuZWxsJ2FiaXNzby4KICAgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICovCmNvbnN0IFBSSU1FX1BUUyA9IDMwMDAsIFdST05HX1BUUyA9IC0yMDAwOwoKZnVuY3Rpb24gaXNQcmltZShuKXsKICBpZihuPDIpIHJldHVybiBmYWxzZTsKICBpZihuPDQpIHJldHVybiB0cnVlOwogIGlmKG4lMj09PTApIHJldHVybiBmYWxzZTsKICBmb3IobGV0IGQ9MzsgZCpkPD1uOyBkKz0yKSBpZihuJWQ9PT0wKSByZXR1cm4gZmFsc2U7CiAgcmV0dXJuIHRydWU7Cn0KLyogY29tcG9zaXRpICJjaGUgc2VtYnJhbm8gcHJpbWkiOiBkaXNwYXJpLCBub24gbXVsdGlwbGkgZGkgNSwgcGnDuSBsJzEgKi8KY29uc3QgVFJBUFM9WzEsOSwxNSwyMSwyNSwyNywzMywzNSwzOSw0OSw1MSw1NSw1Nyw2Myw2NSw2OSw3Nyw4MSw4NSw4Nyw5MSw5Myw5NSw5OSwKICAgICAgICAgICAgIDExMSwxMTUsMTE3LDExOSwxMjEsMTIzLDEzMywxNDMsMTYxLDE2OSwxODddOwpjb25zdCBQUklNRVM9WzIsMyw1LDcsMTEsMTMsMTcsMTksMjMsMjksMzEsMzcsNDEsNDMsNDcsNTMsNTksNjEsNjcsNzEsNzMsNzksODMsODksOTcsCiAgICAgICAgICAgICAgMTAxLDEwMywxMDcsMTA5LDExMywxMjcsMTMxLDEzNywxMzksMTQ5XTsKCmZ1bmN0aW9uIG1ha2VDb252b3kobHZsKXsKICBjb25zdCBuID0gTWF0aC5taW4oMTQsIDEwK01hdGguZmxvb3IobHZsLzIpKTsKICBjb25zdCBuUHJpbWUgPSBNYXRoLm1heCg0LCBNYXRoLnJvdW5kKG4qLjQ1KSk7CiAgY29uc3QgaGkgPSBNYXRoLm1pbihQUklNRVMubGVuZ3RoLCAxNStsdmwqMyksIGh0ID0gTWF0aC5taW4oVFJBUFMubGVuZ3RoLCAxNCtsdmwqMyk7CiAgY29uc3Qgb3V0PVtdLCB1c2VkPU9iamVjdC5jcmVhdGUobnVsbCk7CiAgbGV0IGd1YXJkPTA7CiAgd2hpbGUob3V0Lmxlbmd0aDxuUHJpbWUgJiYgZ3VhcmQrKzw0MDApewogICAgY29uc3Qgdj1QUklNRVNbcm5kaSgwLGhpLTEpXTsgaWYoIXVzZWRbdl0peyB1c2VkW3ZdPTE7IG91dC5wdXNoKHYpOyB9CiAgfQogIGd1YXJkPTA7CiAgd2hpbGUob3V0Lmxlbmd0aDxuICYmIGd1YXJkKys8NDAwKXsKICAgIGNvbnN0IHY9VFJBUFNbcm5kaSgwLGh0LTEpXTsgaWYoIXVzZWRbdl0peyB1c2VkW3ZdPTE7IG91dC5wdXNoKHYpOyB9CiAgfQogIGZvcihsZXQgaT1vdXQubGVuZ3RoLTE7aT4wO2ktLSl7IGNvbnN0IGo9cm5kaSgwLGkpLCB0bXA9b3V0W2ldOyBvdXRbaV09b3V0W2pdOyBvdXRbal09dG1wOyB9CiAgcmV0dXJuIG91dDsKfQoKZnVuY3Rpb24gc3RhcnRQcmltaSgpewogIGNvbnN0IHZhbHMgPSBtYWtlQ29udm95KGxldmVsKTsKICBjb25zdCBSID0gTWF0aC5tYXgoMTksIE1hdGgubWluKDI5LCBXLzEzKSk7CiAgQk9OVVMuZ2FwID0gTWF0aC5tYXgoNzIsIE1hdGgubWluKDExMiwgVy81LjQpKTsKICBCT05VUy5sYW5lID0gQk9OVVMuZ2FwOwogIEJPTlVTLmRpciA9IE1hdGgucmFuZG9tKCk8LjUgPyAxIDogLTE7CiAgQk9OVVMudG1heCA9IE1hdGgubWF4KDE2LCAyNi1sZXZlbCk7IEJPTlVTLnQ9Qk9OVVMudG1heDsKICBCT05VUy5oaXRzPTA7IEJPTlVTLm1pc3M9MDsKICBCT05VUy5uUHJpbWUgPSB2YWxzLmZpbHRlcihpc1ByaW1lKS5sZW5ndGg7CiAgQk9OVVMucG9kcyA9IHZhbHMubWFwKCh2LGkpPT4oewogICAga2luZDonbnVtJywgdmFsOnYsIHByaW1lOmlzUHJpbWUodiksIHI6UiwgaWR4OmksCiAgICB4OjAsIHk6MCwgcm90OjAsIHZyb3Q6cm5kKC0uMywuMyksIHR0OjEsIHRha2VuOmZhbHNlLCBwdWxzZTowCiAgfSkpOwogIGNvbnN0IHNwYW4gPSBCT05VUy5nYXAqKHZhbHMubGVuZ3RoKzEpOwogIEJPTlVTLnR1ZyA9IHt4OiBCT05VUy5kaXI+MCA/IC0xMDAgOiBXKzEwMCwgeTogSCouMzAsIHc6TWF0aC5taW4oVyouMzQsMTkwKSwgc3Bhbn07CiAgQk9OVVMudHVnLnYgPSAoVyArIHNwYW4gKyAyMjApIC8gTWF0aC5tYXgoNS41LCAxMC1sZXZlbCouNCk7CiAgYm9udXNNc2coJ1NFVFRPUkUgUFJJTUknLCAnMjU1LDE3NiwzMicsIDIuMik7Cn0KCi8qIC0tLSByZWxpdHRpIGNoZSBwcmVjaXBpdGFubyBuZWxsJ2FiaXNzbyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi8KZnVuY3Rpb24gZHJvcFdyZWNrKHApewogIEJPTlVTLndyZWNrcy5wdXNoKHt4OnAueCwgeTpwLnksIHZhbDpwLnZhbCwgcjpwLnIsCiAgICB2eDpybmQoLTQwLDQwKSwgdnk6cm5kKDQwLDkwKSwgcm90OnAucm90LCB2cm90OnJuZCgtMy40LDMuNCksCiAgICBsaWZlOjAsIG1heDpybmQoMS42LDIuMyksIHB1ZmY6MH0pOwp9CmZ1bmN0aW9uIHVwZGF0ZVdyZWNrcyhkdCl7CiAgZm9yKGxldCBpPUJPTlVTLndyZWNrcy5sZW5ndGgtMTtpPj0wO2ktLSl7CiAgICBjb25zdCB3PUJPTlVTLndyZWNrc1tpXTsgdy5saWZlKz1kdDsKICAgIGlmKHcubGlmZT49dy5tYXgpeyBCT05VUy53cmVja3Muc3BsaWNlKGksMSk7IGNvbnRpbnVlOyB9CiAgICB3LnZ5ICs9IDEyMCpkdDsgdy54ICs9IHcudngqZHQ7IHcueSArPSB3LnZ5KmR0OyB3LnJvdCArPSB3LnZyb3QqZHQ7CiAgICB3LnB1ZmYgLT0gZHQ7CiAgICBpZih3LnB1ZmY8PTApeyAgICAgICAgICAgICAgICAgICAgICAgLy8gc2NpYSBkaSBmdW1vIHZlcnNvIGwnYWJpc3NvCiAgICAgIHcucHVmZj0uMDQ1OwogICAgICBzbW9rZS5wdXNoKHt4OncueCtybmQoLTYsNiksIHk6dy55K3JuZCgtNiw2KSwgcjp3LnIqLjQyLCBncjpybmQoMzAsNjQpLAogICAgICAgICAgICAgICAgICB2eDpybmQoLTE0LDE0KSwgdnk6cm5kKC0zNCwtNiksIGxpZmU6MCwgbWF4OnJuZCguNSwuOTUpfSk7CiAgICB9CiAgfQp9CmZ1bmN0aW9uIGRyYXdXcmVja3MoKXsKICBmb3IobGV0IGk9MDtpPEJPTlVTLndyZWNrcy5sZW5ndGg7aSsrKXsKICAgIGNvbnN0IHc9Qk9OVVMud3JlY2tzW2ldLCBrPXcubGlmZS93Lm1heDsKICAgIGNvbnN0IHM9MS0uNjIqaywgYT1rPC43NT8gMSA6ICgxLWspLy4yNTsgICAvLyByaW1waWNjaW9saXNjZTogc3Byb2ZvbmRhCiAgICBjdHguc2F2ZSgpOwogICAgY3R4Lmdsb2JhbEFscGhhPWE7IGN0eC50cmFuc2xhdGUody54LHcueSk7IGN0eC5zY2FsZShzLHMpOyBjdHgucm90YXRlKHcucm90KTsKICAgIGN0eC5iZWdpblBhdGgoKTsKICAgIGZvcihsZXQgaj0wO2o8ODtqKyspewogICAgICBjb25zdCBhbmc9KGovOCkqVEFVLU1hdGguUEkvOCwgcHgyPU1hdGguY29zKGFuZykqdy5yLCBweTI9TWF0aC5zaW4oYW5nKSp3LnI7CiAgICAgIGo/IGN0eC5saW5lVG8ocHgyLHB5MikgOiBjdHgubW92ZVRvKHB4MixweTIpOwogICAgfQogICAgY3R4LmNsb3NlUGF0aCgpOwogICAgY29uc3QgZz1jdHguY3JlYXRlUmFkaWFsR3JhZGllbnQoMCwwLHcuciouMSwwLDAsdy5yKTsKICAgIGcuYWRkQ29sb3JTdG9wKDAsYHJnYmEoJHsxODAtayoxMjB9LCR7NzAtayo1MH0sMzAsLjkpYCk7CiAgICBnLmFkZENvbG9yU3RvcCgxLCdyZ2JhKDE0LDEyLDE2LC45NSknKTsKICAgIGN0eC5maWxsU3R5bGU9ZzsgY3R4LmZpbGwoKTsKICAgIGN0eC5saW5lV2lkdGg9MS42OyBjdHguc3Ryb2tlU3R5bGU9YHJnYmEoMjU1LCR7MTUwLWsqMTEwfSw2MCwkey44KigxLWspfSlgOwogICAgY3R4LnNoYWRvd0NvbG9yPSdyZ2JhKDI1NSwxMjAsMzAsLjgpJzsgY3R4LnNoYWRvd0JsdXI9MTIqKDEtayk7IGN0eC5zdHJva2UoKTsKICAgIGN0eC5zaGFkb3dCbHVyPTA7CiAgICBjdHgucm90YXRlKC13LnJvdCk7CiAgICBjdHguZm9udD1gNzAwICR7TWF0aC5yb3VuZCh3LnIqLjkpfXB4IHVpLW1vbm9zcGFjZSxTRk1vbm8tUmVndWxhcixNZW5sbyxtb25vc3BhY2VgOwogICAgY3R4LnRleHRBbGlnbj0nY2VudGVyJzsgY3R4LnRleHRCYXNlbGluZT0nbWlkZGxlJzsKICAgIGN0eC5maWxsU3R5bGU9YHJnYmEoMjU1LDIyNSwxOTAsJHsuNzUqKDEtayl9KWA7IGN0eC5maWxsVGV4dChTdHJpbmcody52YWwpLDAsMSk7CiAgICBjdHgucmVzdG9yZSgpOwogIH0KfQoKLyogLS0tIGNvbHBvIHN1bCBjb252b2dsaW8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovCmZ1bmN0aW9uIGhpdENhcmdvKHApewogIHAudGFrZW49dHJ1ZTsKICBpZihwLnByaW1lKXsKICAgIEJPTlVTLmhpdHMrKzsKICAgIGFkZFNjb3JlKFBSSU1FX1BUUyxmYWxzZSk7CiAgICBhZGRGbG9hdChwLngscC55LCcrJytQUklNRV9QVFMsJzI1NSwxOTYsNDQnKTsKICAgIGV4cGxvZGUocC54LHAueSxwLnIqMS41LCdnb2xkJyk7CiAgICBkcm9wV3JlY2socCk7CiAgICBzZnhMb2NrKEJPTlVTLmhpdHMpOwogICAgYm9udXNNc2cocC52YWwrJyDDiCBQUklNTycsJzI1NSwxOTYsNDQnLDEuMCk7CiAgICBhZGRUaW1lKC44KTsKICB9IGVsc2UgewogICAgQk9OVVMubWlzcysrOwogICAgYWRkU2NvcmUoV1JPTkdfUFRTLGZhbHNlKTsKICAgIGFkZEZsb2F0KHAueCxwLnksU3RyaW5nKFdST05HX1BUUyksJzI1NSw0NiwxMDcnKTsKICAgIGV4cGxvZGUocC54LHAueSxwLnIqMS4zLCdzaGlwJyk7CiAgICBjb25zdCBkPXNtYWxsZXN0RmFjdG9yKHAudmFsKTsKICAgIGJvbnVzTXNnKHAudmFsPT09MT8gJzEgTk9OIMOIIFBSSU1PJyA6IHAudmFsKycgPSAnK2QrJyDDlyAnKyhwLnZhbC9kKSwnMjU1LDQ2LDEwNycsMS41KTsKICAgIGlmKCFSRURVQ0VEKSBzaGFrZT1NYXRoLm1pbigyMixzaGFrZSsxMyk7CiAgICBzZnhFcnIoKTsKICB9Cn0KZnVuY3Rpb24gc21hbGxlc3RGYWN0b3Iobil7IGZvcihsZXQgZD0yO2QqZDw9bjtkKyspIGlmKG4lZD09PTApIHJldHVybiBkOyByZXR1cm4gbjsgfQoKLyogLS0tIGFnZ2lvcm5hbWVudG8gZGVsIHNldHRvcmUgcHJpbWkgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovCmZ1bmN0aW9uIHVwZGF0ZVByaW1pKGR0KXsKICBjb25zdCBjPUJPTlVTLnR1ZzsgQk9OVVMucHQrPWR0OwogIHVwZGF0ZVdyZWNrcyhkdCk7CgogIGlmKEJPTlVTLnBoPT09J2luJyl7CiAgICBjLnggKz0gQk9OVVMuZGlyKmMudipkdDsKICAgIGZvcihsZXQgaT1yb2Nrcy5sZW5ndGgtMTtpPj0wO2ktLSl7CiAgICAgIGNvbnN0IGE9cm9ja3NbaV07IGEueCs9YS52eCpkdDsgYS55Kz1hLnZ5KmR0OyBhLnJvdCs9YS52cm90KmR0OwogICAgICBpZihhLnktYS5yPkgrMjApeyBhLmRlYWQ9dHJ1ZTsgcm9ja3Muc3BsaWNlKGksMSk7IH0KICAgIH0KICAgIGlmKEJPTlVTLnB0Pi45KXsKICAgICAgQk9OVVMucGg9J3BsYXknOyBCT05VUy5wdD0wOyBib251c0VNUGF0KGMueCxjLnkpOwogICAgICBib251c01zZyhUT1VDSD8gJ1NPTE8gSSBOVU1FUkkgUFJJTUkgwrcgVE9DQ0EgTEEgTkFWSUNFTExBIFBFUiBTUEFSQVJFJwogICAgICAgICAgICAgICAgICAgIDogJ1NPTE8gSSBOVU1FUkkgUFJJTUkgwrcgU1BBWklPIFBFUiBVTiBDT0xQTycsJzI1NSwxNzYsMzInLDMuNCk7CiAgICB9CiAgfSBlbHNlIGlmKEJPTlVTLnBoPT09J3BsYXknKXsKICAgIGMueCArPSBCT05VUy5kaXIqYy52KmR0OwogICAgQk9OVVMudC09ZHQ7CiAgICAvKiBmaW5lIHBhc3NhZ2dpbzogaWwgY29udm9nbGlvIGludmVydGUgbGEgcm90dGEgZSByaWVudHJhICovCiAgICBjb25zdCB0YWlsID0gYy54IC0gQk9OVVMuZGlyKmMuc3BhbjsKICAgIGlmKChCT05VUy5kaXI+MCAmJiB0YWlsPlcrODApIHx8IChCT05VUy5kaXI8MCAmJiB0YWlsPC04MCkpewogICAgICBpZihCT05VUy50PjMgJiYgQk9OVVMucG9kcy5zb21lKHA9PiFwLnRha2VuKSl7CiAgICAgICAgQk9OVVMuZGlyPS1CT05VUy5kaXI7CiAgICAgICAgYy54ID0gQk9OVVMuZGlyPjAgPyAtMTAwIDogVysxMDA7CiAgICAgICAgYy55ID0gSCooLjI0K01hdGgucmFuZG9tKCkqLjE0KTsKICAgICAgICBib251c01zZygnSUwgQ09OVk9HTElPIFJJRU5UUkEnLCcyNTUsMTc2LDMyJywxLjQpOwogICAgICB9IGVsc2UgeyBCT05VUy5waD0nb3V0JzsgQk9OVVMucHQ9MDsgfQogICAgfQogICAgaWYoIUJPTlVTLnBvZHMuc29tZShwPT4hcC50YWtlbikpewogICAgICBCT05VUy5waD0nb3V0JzsgQk9OVVMucHQ9MDsgQk9OVVMuc29sdmVkPXRydWU7CiAgICAgIGJvbnVzTXNnKCdDT05WT0dMSU8gUklQVUxJVE8nLCcyNTUsMTk2LDQ0JywyLjApOwogICAgfQogICAgaWYoQk9OVVMudDw9MCl7IEJPTlVTLnBoPSdvdXQnOyBCT05VUy5wdD0wOyBib251c01zZygnSUwgQ09OVk9HTElPIMOIIFNGVUdHSVRPJywnMjU1LDE3NiwzMicsMS42KTsgfQoKICB9IGVsc2UgaWYoQk9OVVMucGg9PT0nb3V0Jyl7CiAgICBjLnggKz0gQk9OVVMuZGlyKmMudioxLjkqZHQ7CiAgICBpZihCT05VUy5wdD4xLjEgJiYgIUJPTlVTLndyZWNrcy5sZW5ndGgpIGZpbmlzaEJvbnVzKCk7CiAgICBpZihCT05VUy5wdD4yLjYpIGZpbmlzaEJvbnVzKCk7CiAgfQoKICAvKiBwb3NpemlvbmUgZGVpIGNvbnRlbml0b3JpIGx1bmdvIGlsIGNhdm8gZGkgdHJhaW5vICovCiAgY29uc3QgYW1wPU1hdGgubWluKDI2LEgqLjAzNSk7CiAgZm9yKGxldCBpPTA7aTxCT05VUy5wb2RzLmxlbmd0aDtpKyspewogICAgY29uc3QgcD1CT05VUy5wb2RzW2ldOwogICAgcC54ID0gYy54IC0gQk9OVVMuZGlyKkJPTlVTLmdhcCooaSsxKTsKICAgIHAueSA9IGMueSArIE1hdGguc2luKHQqMS4xNSArIGkqLjU1KSphbXA7CiAgICBwLnJvdCArPSBwLnZyb3QqZHQ7CiAgICBpZihwLnB1bHNlPjApIHAucHVsc2UtPWR0KjIuMjsKICAgIGlmKHAudGFrZW4gfHwgQk9OVVMucGghPT0ncGxheScpIGNvbnRpbnVlOwogICAgZm9yKGxldCBqPWJ1bGxldHMubGVuZ3RoLTE7aj49MDtqLS0pewogICAgICBjb25zdCBiPWJ1bGxldHNbal0sIGR4PWIueC1wLngsIGR5PWIueS1wLnk7CiAgICAgIGlmKGR4KmR4K2R5KmR5IDwgKHAucis2KSoocC5yKzYpKXsgYnVsbGV0cy5zcGxpY2UoaiwxKTsgaGl0Q2FyZ28ocCk7IGJyZWFrOyB9CiAgICB9CiAgfQp9CmZ1bmN0aW9uIGJvbnVzRU1QYXQoeCx5KXsKICBmb3IobGV0IGk9cm9ja3MubGVuZ3RoLTE7aT49MDtpLS0peyBjb25zdCBhPXJvY2tzW2ldOyBleHBsb2RlKGEueCxhLnksYS5yLCdkYXRhJyk7IH0KICByb2Nrcy5sZW5ndGg9MDsgYnVsbGV0cy5sZW5ndGg9MDsKICBmb3IobGV0IGk9MDtpPDI7aSsrKQogICAgd2F2ZXMucHVzaCh7eDpjbGFtcCh4LDAsVyksIHksIHIwOjQwK2kqNzAsIHIxOk1hdGgubWF4KFcsSCkqMS40LCBsaWZlOjAsIG1heDouNytpKi4xMiwgdzozLCB0b25lOidnb2xkJ30pOwogIGlmKCFSRURVQ0VEKXsgc2hha2U9TWF0aC5taW4oMjQsc2hha2UrMTMpOyBmbGFzaD1NYXRoLm1pbiguNixmbGFzaCsuMyk7IH0KfQoKLyogLS0tIHJlc2EgZ3JhZmljYSBkZWwgY29udm9nbGlvIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovCmZ1bmN0aW9uIGRyYXdUdWcoYyl7CiAgY29uc3Qgdz1jLncsIGg9dyouNDQsIGQ9Qk9OVVMuZGlyOwogIGN0eC5zYXZlKCk7IGN0eC50cmFuc2xhdGUoYy54LGMueSk7IGN0eC5zY2FsZShkLDEpOwoKICAvKiBwcm9wdWxzb3JpIHN1bCByZXRybyAqLwogIGN0eC5zYXZlKCk7IGN0eC5nbG9iYWxDb21wb3NpdGVPcGVyYXRpb249J2xpZ2h0ZXInOwogIFstLjM0LC4zNF0uZm9yRWFjaChvPT57CiAgICBjb25zdCBleD0tdyouNDYsIGV5PWgqbywgZmw9MjIrTWF0aC5zaW4odCoyNitvKjkpKjc7CiAgICBjb25zdCBnPWN0eC5jcmVhdGVMaW5lYXJHcmFkaWVudChleCxleSxleC1mbCxleSk7CiAgICBnLmFkZENvbG9yU3RvcCgwLCdyZ2JhKDI1NSwyNTUsMjU1LC44NSknKTsKICAgIGcuYWRkQ29sb3JTdG9wKC40LCdyZ2JhKDI1NSwxOTAsMTEwLC41KScpOwogICAgZy5hZGRDb2xvclN0b3AoMSwncmdiYSgyNTUsMTc2LDMyLDApJyk7CiAgICBjdHguZmlsbFN0eWxlPWc7CiAgICBjdHguYmVnaW5QYXRoKCk7IGN0eC5tb3ZlVG8oZXgsZXktaCouMTEpOyBjdHgubGluZVRvKGV4LGV5K2gqLjExKTsgY3R4LmxpbmVUbyhleC1mbCxleSk7IGN0eC5jbG9zZVBhdGgoKTsgY3R4LmZpbGwoKTsKICB9KTsKICBjdHgucmVzdG9yZSgpOwoKICAvKiBzY2FmbyBkYSByaW1vcmNoaW86IG11c28gYSBjdW5lbywgZG9yc28gYSBjb250YWluZXIgKi8KICBjb25zdCBIQUxGPVtbLjUyLDBdLFsuMzQsLS4yNl0sWy4wNiwtLjM0XSxbLS4yMCwtLjMwXSxbLS40NCwtLjIyXSxbLS40OCwwXV07CiAgY3R4LmJlZ2luUGF0aCgpOwogIGZvcihsZXQgaT0wO2k8SEFMRi5sZW5ndGg7aSsrKXsgY29uc3QgcT1IQUxGW2ldOyBpPyBjdHgubGluZVRvKHFbMF0qdyxxWzFdKmgpIDogY3R4Lm1vdmVUbyhxWzBdKncscVsxXSpoKTsgfQogIGZvcihsZXQgaT1IQUxGLmxlbmd0aC0xO2k+PTA7aS0tKXsgY29uc3QgcT1IQUxGW2ldOyBjdHgubGluZVRvKHFbMF0qdywtcVsxXSpoKTsgfQogIGN0eC5jbG9zZVBhdGgoKTsKICBjb25zdCBoZz1jdHguY3JlYXRlTGluZWFyR3JhZGllbnQoMCwtaCouMzQsMCxoKi4zNCk7CiAgaGcuYWRkQ29sb3JTdG9wKDAsJyNiN2M2ZTInKTsgaGcuYWRkQ29sb3JTdG9wKC40MiwnIzNhNGE2YycpOwogIGhnLmFkZENvbG9yU3RvcCgxLCcjMTExYTJlJyk7CiAgY3R4LmZpbGxTdHlsZT1oZzsgY3R4LmZpbGwoKTsKICBjdHgubGluZVdpZHRoPTEuNzsgY3R4LnN0cm9rZVN0eWxlPSdyZ2JhKDI1NSwxNzYsMzIsLjc1KSc7CiAgY3R4LnNoYWRvd0NvbG9yPSdyZ2JhKDI1NSwxNzYsMzIsLjcpJzsgY3R4LnNoYWRvd0JsdXI9MTU7IGN0eC5zdHJva2UoKTsgY3R4LnNoYWRvd0JsdXI9MDsKCiAgLyogcGxhbmNpYSBlIGx1Y2kgZGkgdmlhICovCiAgY3R4LmZpbGxTdHlsZT0ncmdiYSgxNTAsMjQwLDI1NSwuOSknOwogIGN0eC5maWxsUmVjdCh3Ki4yMCwtaCouMDksdyouMTAsaCouMTgpOwogIGNvbnN0IGJsPShNYXRoLnNpbih0KjYpKzEpLzI7CiAgY3R4LmZpbGxTdHlsZT1gcmdiYSgyNTUsNjAsOTAsJHsuMytibCouN30pYDsKICBjdHguYmVnaW5QYXRoKCk7IGN0eC5hcmMoLXcqLjEwLC1oKi4yOSwyLjYsMCxUQVUpOyBjdHguZmlsbCgpOwogIGN0eC5iZWdpblBhdGgoKTsgY3R4LmFyYygtdyouMTAsIGgqLjI5LDIuNiwwLFRBVSk7IGN0eC5maWxsKCk7CgogIC8qIGdhbmNpbyBkaSB0cmFpbm8gKi8KICBjdHguc3Ryb2tlU3R5bGU9J3JnYmEoMTgwLDIwMCwyMzUsLjYpJzsgY3R4LmxpbmVXaWR0aD0yOwogIGN0eC5iZWdpblBhdGgoKTsgY3R4Lm1vdmVUbygtdyouNDgsMCk7IGN0eC5saW5lVG8oLXcqLjU2LDApOyBjdHguc3Ryb2tlKCk7CiAgY3R4LnJlc3RvcmUoKTsKfQpmdW5jdGlvbiBkcmF3Q2FyZ28ocCl7CiAgaWYocC50YWtlbikgcmV0dXJuOwogIGNvbnN0IHMgPSAxKyhwLnB1bHNlPjA/IHAucHVsc2UqLjIgOiAwKTsKICBjdHguc2F2ZSgpOyBjdHgudHJhbnNsYXRlKHAueCxwLnkpOyBjdHguc2NhbGUocyxzKTsKICBjdHgucm90YXRlKE1hdGguc2luKHQqMS40K3AuaWR4KSouMDkpOwogIC8qIGNvbnRlbml0b3JlIG90dGFnb25hbGU6IG5lc3N1biBpbmRpemlvIGNyb21hdGljbyBzdWxsYSBwcmltYWxpdMOgICovCiAgY3R4LmJlZ2luUGF0aCgpOwogIGZvcihsZXQgaj0wO2o8ODtqKyspewogICAgY29uc3QgYT0oai84KSpUQVUtTWF0aC5QSS84LCBxeD1NYXRoLmNvcyhhKSpwLnIsIHF5PU1hdGguc2luKGEpKnAucjsKICAgIGo/IGN0eC5saW5lVG8ocXgscXkpIDogY3R4Lm1vdmVUbyhxeCxxeSk7CiAgfQogIGN0eC5jbG9zZVBhdGgoKTsKICBjb25zdCBnPWN0eC5jcmVhdGVMaW5lYXJHcmFkaWVudCgwLC1wLnIsMCxwLnIpOwogIGcuYWRkQ29sb3JTdG9wKDAsJ3JnYmEoMjI2LDIzNiwyNTUsLjMwKScpOwogIGcuYWRkQ29sb3JTdG9wKC40NSwncmdiYSgyMCwzMCw1MiwuOTApJyk7CiAgZy5hZGRDb2xvclN0b3AoMSwncmdiYSg2LDEwLDIwLC45NSknKTsKICBjdHguZmlsbFN0eWxlPWc7IGN0eC5maWxsKCk7CiAgY3R4LmxpbmVXaWR0aD0yLjE7IGN0eC5zdHJva2VTdHlsZT0ncmdiYSgyNTUsMTk2LDkwLC45MiknOwogIGN0eC5zaGFkb3dDb2xvcj0ncmdiYSgyNTUsMTc2LDMyLC43NSknOyBjdHguc2hhZG93Qmx1cj0xMzsgY3R4LnN0cm9rZSgpOyBjdHguc2hhZG93Qmx1cj0wOwogIC8qIGZhc2NpYSBkaSBjYXJpY28gKi8KICBjdHguc3Ryb2tlU3R5bGU9J3JnYmEoMjU1LDE5Niw5MCwuMjgpJzsgY3R4LmxpbmVXaWR0aD0xOwogIGN0eC5iZWdpblBhdGgoKTsgY3R4Lm1vdmVUbygtcC5yKi43MiwwKTsgY3R4LmxpbmVUbyhwLnIqLjcyLDApOyBjdHguc3Ryb2tlKCk7CiAgY3R4LnJlc3RvcmUoKTsKCiAgY3R4LnNhdmUoKTsgY3R4LnRyYW5zbGF0ZShwLngscC55KTsKICBjdHguZm9udD1gNzAwICR7TWF0aC5yb3VuZChwLnIqLjkyKX1weCB1aS1tb25vc3BhY2UsU0ZNb25vLVJlZ3VsYXIsTWVubG8sbW9ub3NwYWNlYDsKICBjdHgudGV4dEFsaWduPSdjZW50ZXInOyBjdHgudGV4dEJhc2VsaW5lPSdtaWRkbGUnOwogIGN0eC5zaGFkb3dDb2xvcj0ncmdiYSgyNTUsMTk2LDkwLC45KSc7IGN0eC5zaGFkb3dCbHVyPTEzOwogIGN0eC5maWxsU3R5bGU9JyNmZmYyZGMnOyBjdHguZmlsbFRleHQoU3RyaW5nKHAudmFsKSwwLDEpOwogIGN0eC5yZXN0b3JlKCk7Cn0KZnVuY3Rpb24gZHJhd1ByaW1pV29ybGQoKXsKICBjb25zdCBjPUJPTlVTLnR1ZzsKICAvKiBjYXZvIGRpIHRyYWlubyB0cmEgZ2xpIGVsZW1lbnRpIGFuY29yYSBhZ2dhbmNpYXRpICovCiAgY3R4LnNhdmUoKTsKICBjdHguc3Ryb2tlU3R5bGU9J3JnYmEoMjU1LDE5Niw5MCwuMjQpJzsgY3R4LmxpbmVXaWR0aD0xLjY7CiAgY3R4LmJlZ2luUGF0aCgpOwogIGxldCBseD1jLngtQk9OVVMuZGlyKmMudyouNTYsIGx5PWMueSwgc3RhcnRlZD10cnVlOwogIGN0eC5tb3ZlVG8obHgsbHkpOwogIGZvcihsZXQgaT0wO2k8Qk9OVVMucG9kcy5sZW5ndGg7aSsrKXsKICAgIGNvbnN0IHA9Qk9OVVMucG9kc1tpXTsKICAgIGlmKHAudGFrZW4peyBzdGFydGVkPWZhbHNlOyBjb250aW51ZTsgfQogICAgaWYoIXN0YXJ0ZWQpeyBjdHgubW92ZVRvKHAueCxwLnkpOyBzdGFydGVkPXRydWU7IH0KICAgIGVsc2UgY3R4LmxpbmVUbyhwLngscC55KTsKICB9CiAgY3R4LnN0cm9rZSgpOyBjdHgucmVzdG9yZSgpOwoKICBkcmF3V3JlY2tzKCk7CiAgc2hhZG93Um9jayh7eDpjLngseTpjLnkscjpjLncqLjI2fSk7CiAgZm9yKGxldCBpPTA7aTxCT05VUy5wb2RzLmxlbmd0aDtpKyspeyBjb25zdCBwPUJPTlVTLnBvZHNbaV07IGlmKCFwLnRha2VuKSBzaGFkb3dSb2NrKHApOyB9CiAgZHJhd1R1ZyhjKTsKICBmb3IobGV0IGk9MDtpPEJPTlVTLnBvZHMubGVuZ3RoO2krKykgZHJhd0NhcmdvKEJPTlVTLnBvZHNbaV0pOwogIGRyYXdBaW0oKTsKfQpmdW5jdGlvbiBkcmF3UHJpbWlIVUQoKXsKICBjb25zdCBjeT1NYXRoLm1heCgxMTYsSCouMTU1KSwgZnM9TWF0aC5tYXgoMTUsTWF0aC5taW4oMjQsVy8xNykpOwogIGN0eC5zYXZlKCk7CiAgY3R4LmZvbnQ9YDcwMCAke2ZzfXB4IHVpLW1vbm9zcGFjZSxTRk1vbm8tUmVndWxhcixNZW5sbyxtb25vc3BhY2VgOwogIGNvbnN0IHR4dD1gUFJJTUkgJHtCT05VUy5oaXRzfS8ke0JPTlVTLm5QcmltZX0gICBFUlJPUkkgJHtCT05VUy5taXNzfWA7CiAgY29uc3QgdHc9Y3R4Lm1lYXN1cmVUZXh0KHR4dCkud2lkdGgsIHB3PU1hdGgubWluKFctMjgsdHcrNDQpLCBweHg9KFctcHcpLzIsIHBoPWZzKjIuMSwgcHkyPWN5LXBoLzI7CiAgY3R4LmZpbGxTdHlsZT0ncmdiYSg2LDEwLDIyLC43MiknOyBycmVjdChweHgscHkyLHB3LHBoLHBoKi4yOCk7IGN0eC5maWxsKCk7CiAgY3R4LmxpbmVXaWR0aD0xLjQ7IGN0eC5zdHJva2VTdHlsZT0ncmdiYSgyNTUsMTc2LDMyLC42KSc7CiAgY3R4LnNoYWRvd0NvbG9yPWN0eC5zdHJva2VTdHlsZTsgY3R4LnNoYWRvd0JsdXI9MTQ7IGN0eC5zdHJva2UoKTsgY3R4LnNoYWRvd0JsdXI9MDsKICBjdHgudGV4dEFsaWduPSdjZW50ZXInOyBjdHgudGV4dEJhc2VsaW5lPSdtaWRkbGUnOwogIGN0eC5maWxsU3R5bGU9JyNmZmU2YjgnOyBjdHguZmlsbFRleHQodHh0LFcvMixjeSk7CgogIGNvbnN0IGJ3PXB3Ki43MiwgYng9KFctYncpLzIsIGJ5PXB5MitwaCs3LCBrPWNsYW1wKEJPTlVTLnQvQk9OVVMudG1heCwwLDEpOwogIGN0eC5maWxsU3R5bGU9J3JnYmEoMjU1LDI1NSwyNTUsLjEwKSc7IGN0eC5maWxsUmVjdChieCxieSxidywzKTsKICBjdHguZmlsbFN0eWxlPWs8LjI4PycjZmYyZTZiJzonI2ZmYjAyMCc7CiAgY3R4LnNoYWRvd0NvbG9yPWN0eC5maWxsU3R5bGU7IGN0eC5zaGFkb3dCbHVyPTg7IGN0eC5maWxsUmVjdChieCxieSxidyprLDMpOyBjdHguc2hhZG93Qmx1cj0wOwoKICBpZihCT05VUy5tc2dUPjApewogICAgY29uc3QgYT1NYXRoLm1pbigxLEJPTlVTLm1zZ1QqMS42KTsKICAgIGN0eC5mb250PWA3MDAgJHtNYXRoLm1heCgxMixmcyouNjIpfXB4IHVpLW1vbm9zcGFjZSxTRk1vbm8tUmVndWxhcixNZW5sbyxtb25vc3BhY2VgOwogICAgY3R4LmZpbGxTdHlsZT1gcmdiYSgke0JPTlVTLm1zZ0NvbH0sJHthfSlgOwogICAgY3R4LnNoYWRvd0NvbG9yPWByZ2JhKCR7Qk9OVVMubXNnQ29sfSwuOClgOyBjdHguc2hhZG93Qmx1cj0xMjsKICAgIGN0eC5maWxsVGV4dChCT05VUy5tc2csVy8yLGJ5KzIyKTsKICB9CiAgY3R4LnJlc3RvcmUoKTsKfQoKLyogbnVtZXJpIHZvbGFudGkgc3VsIHB1bnRvIGQnaW1wYXR0byAqLwpmdW5jdGlvbiBhZGRGbG9hdCh4LHksdHh0LGNvbCl7IGZsb2F0cy5wdXNoKHt4LHksdHh0LGNvbCxsaWZlOjAsbWF4OjEuMTV9KTsgfQpmdW5jdGlvbiBzaG93Tm90aWNlKHR4dCxzdWIsZHVyKXsgbm90aWNlPXR4dDsgbm90aWNlU3ViPXN1Ynx8Jyc7IG5vdGljZVQ9ZHVyfHw0LjU7IH0KZnVuY3Rpb24gZHJhd05vdGljZShkdCl7CiAgaWYobm90aWNlVDw9MCkgcmV0dXJuOwogIG5vdGljZVQtPWR0OwogIGNvbnN0IGE9TWF0aC5taW4oMSwgTWF0aC5taW4obm90aWNlVCoxLjMsICg0LjUtbm90aWNlVCkqNCkpOwogIGlmKGE8PTApIHJldHVybjsKICBjb25zdCBjeT1IKi43NCwgZnM9TWF0aC5tYXgoMTUsIE1hdGgubWluKDI2LCBXLzE1KSk7CiAgY3R4LnNhdmUoKTsKICBjdHgudGV4dEFsaWduPSdjZW50ZXInOyBjdHgudGV4dEJhc2VsaW5lPSdtaWRkbGUnOwogIGNvbnN0IGc9Y3R4LmNyZWF0ZUxpbmVhckdyYWRpZW50KDAsY3ktZnMqMi40LDAsY3krZnMqMi40KTsKICBnLmFkZENvbG9yU3RvcCgwLCdyZ2JhKDYsMTAsMjIsMCknKTsKICBnLmFkZENvbG9yU3RvcCguNSxgcmdiYSg2LDEwLDIyLCR7Ljg0KmF9KWApOwogIGcuYWRkQ29sb3JTdG9wKDEsJ3JnYmEoNiwxMCwyMiwwKScpOwogIGN0eC5maWxsU3R5bGU9ZzsgY3R4LmZpbGxSZWN0KDAsY3ktZnMqMi40LFcsZnMqNC44KTsKICBjdHguZm9udD1gODAwICR7TWF0aC5yb3VuZChmcyl9cHggdWktbW9ub3NwYWNlLFNGTW9uby1SZWd1bGFyLE1lbmxvLG1vbm9zcGFjZWA7CiAgY3R4LmZpbGxTdHlsZT1gcmdiYSgyNTUsMTk2LDQ0LCR7YX0pYDsKICBjdHguc2hhZG93Q29sb3I9J3JnYmEoMjU1LDE5Niw0NCwuOSknOyBjdHguc2hhZG93Qmx1cj0xODsKICBjdHguZmlsbFRleHQobm90aWNlLCBXLzIsIGN5LWZzKi42NSk7CiAgaWYobm90aWNlU3ViKXsKICAgIGN0eC5mb250PWA3MDAgJHtNYXRoLnJvdW5kKGZzKi42Mil9cHggdWktbW9ub3NwYWNlLFNGTW9uby1SZWd1bGFyLE1lbmxvLG1vbm9zcGFjZWA7CiAgICBjdHguZmlsbFN0eWxlPWByZ2JhKDE1MCwyMjAsMjU1LCR7YX0pYDsKICAgIGN0eC5zaGFkb3dDb2xvcj0ncmdiYSg3MCwyMzAsMjU1LC43KSc7IGN0eC5zaGFkb3dCbHVyPTEwOwogICAgY3R4LmZpbGxUZXh0KG5vdGljZVN1YiwgVy8yLCBjeStmcyouNjUpOwogIH0KICBjdHgucmVzdG9yZSgpOwp9CmZ1bmN0aW9uIGRyYXdGbG9hdHMoZHQpewogIGlmKCFmbG9hdHMubGVuZ3RoKSByZXR1cm47CiAgY3R4LnNhdmUoKTsKICBjdHgudGV4dEFsaWduPSdjZW50ZXInOyBjdHgudGV4dEJhc2VsaW5lPSdtaWRkbGUnOwogIGZvcihsZXQgaT1mbG9hdHMubGVuZ3RoLTE7aT49MDtpLS0pewogICAgY29uc3QgZj1mbG9hdHNbaV07IGYubGlmZSs9ZHQ7CiAgICBpZihmLmxpZmU+PWYubWF4KXsgZmxvYXRzLnNwbGljZShpLDEpOyBjb250aW51ZTsgfQogICAgY29uc3Qgaz1mLmxpZmUvZi5tYXgsIGE9azwuMTU/IGsvLjE1IDogKDEtaykvLjg1OwogICAgY29uc3Qgc3o9TWF0aC5tYXgoMTgsIE1hdGgubWluKDM0LCBXLzEyKSkgKiAoMSsoazwuMTg/ICgxLWsvLjE4KSouMzUgOiAwKSk7CiAgICBjdHguZm9udD1gODAwICR7TWF0aC5yb3VuZChzeil9cHggdWktbW9ub3NwYWNlLFNGTW9uby1SZWd1bGFyLE1lbmxvLG1vbm9zcGFjZWA7CiAgICBjdHguZmlsbFN0eWxlPWByZ2JhKCR7Zi5jb2x9LCR7YX0pYDsKICAgIGN0eC5zaGFkb3dDb2xvcj1gcmdiYSgke2YuY29sfSwuOSlgOyBjdHguc2hhZG93Qmx1cj0xNjsKICAgIGN0eC5maWxsVGV4dChmLnR4dCwgZi54LCBmLnkgLSA1OCprKTsKICB9CiAgY3R4LnJlc3RvcmUoKTsKfQoKLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiAgIFJJU09MVVpJT05FIERFTExFIENBUklDSEUKICAgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICovCmZ1bmN0aW9uIHNldFNjb3JlKHYpewogIHNjb3JlPU1hdGgucm91bmQodik7CiAgZWxTY29yZS50ZXh0Q29udGVudD1zY29yZTsKICBlbFNjb3JlLnN0eWxlLmNvbG9yID0gc2NvcmU8MCA/ICcjZmYyZTZiJyA6ICcnOwogIGVsU2NvcmUuc3R5bGUudGV4dFNoYWRvdyA9IHNjb3JlPDAgPyAnMCAwIDE4cHggcmdiYSgyNTUsNDYsMTA3LC42KScgOiAnJzsKICBlbFNjb3JlLmNsYXNzTGlzdC5yZW1vdmUoJ3BvcCcpOyB2b2lkIGVsU2NvcmUub2Zmc2V0V2lkdGg7IGVsU2NvcmUuY2xhc3NMaXN0LmFkZCgncG9wJyk7Cn0KZnVuY3Rpb24gZ2FpbkxpZmUobil7CiAgY29uc3QgcHJpbWE9bGl2ZXM7CiAgbGl2ZXM9TWF0aC5taW4oTUFYTCwgbGl2ZXMrbik7CiAgcGFpbnRIdWxscygpOwogIGNvbnN0IGRhdGk9bGl2ZXMtcHJpbWE7CiAgdG9hc3QoZGF0aT4wID8gKGRhdGk+MT8gJysnK2RhdGkrJyBTQ0FGSScgOiAnKzEgU0NBRk8nKSA6ICdTVElWQSBQSUVOQScpOwp9CmZ1bmN0aW9uIGxvc2VMaWZlKHgseSl7CiAgZXhwbG9kZSh4LHksNTIsJ3NoaXAnKTsKICBmb3IobGV0IGk9MDtpPDM7aSsrKQogICAgd2F2ZXMucHVzaCh7eCx5LHIwOjMwK2kqNDUscjE6TWF0aC5tYXgoVyxIKSoxLjEsbGlmZTowLG1heDouNStpKi4xLHc6Mi42LHRvbmU6J3NoaXAnfSk7CiAgbGl2ZXMtLTsgcGFpbnRIdWxscygpOwogIGlmKCFSRURVQ0VEKXsgc2hha2U9TWF0aC5taW4oMjgsc2hha2UrMTgpOyBmbGFzaD1NYXRoLm1pbiguNyxmbGFzaCsuNCk7IH0KICBpZihsaXZlczw9MCkgZ2FtZU92ZXIoKTsKICBlbHNlIHsgaWYoc2hpcCkgc2hpcC5pbnY9Mi4yOyB0b2FzdCgnQ09OVEFNSU5BWklPTkUnKTsgfQp9CmZ1bmN0aW9uIGFwcGx5Q2FyZ28oYSl7CiAgY29uc3QgYz1hLmNhcmdvOyBpZighYykgcmV0dXJuOwogIGlmKGMudD09PSdwbHVzJyl7CiAgICBhZGRTY29yZShjLnZhbCxmYWxzZSk7CiAgICBhZGRGbG9hdChhLngsYS55LCcrJytjLnZhbCwnMTEwLDI0MCwxNjAnKTsgc2Z4TG9jayg0KTsKICB9IGVsc2UgaWYoYy50PT09J21pbnVzJyl7CiAgICBhZGRTY29yZShjLnZhbCxmYWxzZSk7CiAgICBhZGRGbG9hdChhLngsYS55LCfiiJInK01hdGguYWJzKGMudmFsKSwnMjU1LDQ2LDEwNycpOwogICAgaWYoIVJFRFVDRUQpIHNoYWtlPU1hdGgubWluKDIwLHNoYWtlKzEwKTsKICAgIHNmeEVycigpOwogIH0gZWxzZSBpZihjLnQ9PT0nbGlmZScpewogICAgZ2FpbkxpZmUoYy5uKTsKICAgIGFkZEZsb2F0KGEueCxhLnksIGMubj4xPyAnKycrYy5uKycgU0NBRkknIDogJysxIFNDQUZPJywnMTEwLDI0MCwyMDAnKTsKICAgIGZvcihsZXQgaT0wO2k8MztpKyspCiAgICAgIHdhdmVzLnB1c2goe3g6YS54LHk6YS55LHIwOjI2K2kqNDAscjE6TWF0aC5tYXgoVyxIKSouOSxsaWZlOjAsbWF4Oi41K2kqLjA5LHc6Mi40LHRvbmU6J2RhdGEnfSk7CiAgICBzZnhMZXZlbCgpOwogIH0gZWxzZSBpZihjLnQ9PT0nbXVsdCcpewogICAgLyogaW4gcm9zc28gaWwgZG9yYXRvIGF6emVyYSBpbCBkZWJpdG8gcHJpbWEgZGkgbW9sdGlwbGljYXJlICovCiAgICBjb25zdCBwcmltYT1NYXRoLm1heCgwLHNjb3JlKTsKICAgIHNldFNjb3JlKHByaW1hKmMubSk7CiAgICBhZGRGbG9hdChhLngsYS55LCfDlycrYy5tLCcyNTUsMjE0LDgwJyk7CiAgICBmb3IobGV0IGk9MDtpPDU7aSsrKQogICAgICB3YXZlcy5wdXNoKHt4OmEueCx5OmEueSxyMDoyNCtpKjQ2LHIxOk1hdGgubWF4KFcsSCkqMS41LGxpZmU6MCxtYXg6LjYraSouMSx3OjMuMix0b25lOidnb2xkJ30pOwogICAgaWYoIVJFRFVDRUQpeyBzaGFrZT1NYXRoLm1pbigyNixzaGFrZSsxNik7IGZsYXNoPU1hdGgubWluKC43LGZsYXNoKy40Mik7IH0KICAgIHRvYXN0KCdQVU5URUdHSU8gw5cnK2MubSk7CiAgICBzZnhKYWNrcG90KCk7CiAgfSBlbHNlIGlmKGMudD09PSdudWtlJyl7CiAgICBsb3NlTGlmZShhLngsYS55KTsKICAgIGFkZEZsb2F0KGEueCxhLnksJ+KIkjEgU0NBRk8nLCcyNTUsMjE0LDEwJyk7CiAgICBzZnhBbGFybSgpOwogIH0KfQoKLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiAgIENPTE9OTkEgU09OT1JBIOKAlCAuL2F1ZGlvLzAwMS5tcDMg4oCmIDAyMC5tcDMKICAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiAgIEkgYnJhbmkgc2kgc29uZGFubyBjb24gbCdlbGVtZW50byBBdWRpbyBzdGVzc28sIG5vbiBjb24gZmV0Y2gvSEVBRDoKICAgcXVlbGxhIHZpYSBmYWxsaXNjZSBzdSBmaWxlOi8vIGUgc2VuemEgQ09SUy4gQ2hpIHJpc3BvbmRlIGVudHJhIGluCiAgIHNjYWxldHRhLiBMYSByaXByb2R1emlvbmUgw6ggY2lyY29sYXJlIGUsIHNlIHVuIGJyYW5vIHNpIHJpdmVsYQogICBpbGxlZ2dpYmlsZSBpbiBjb3JzYSwgdmllbmUgdG9sdG8gZSBzaSBwYXNzYSBhbCBzdWNjZXNzaXZvLgogICBDb24gbGEgc2NhbGV0dGEgdnVvdGEgbCdpY29uYSByZXN0YSB2aXNpYmlsZSBtYSBzcGVudGEuCiAgID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqLwpjb25zdCBNVVNJQyA9IHsKICBiYXNlOicuL2F1ZGlvLycsIHRvdGFsOjIwLCBsaXN0OltdLCBpZHg6MCwgZWw6bnVsbCwKICByZWFkeTpmYWxzZSwgb246dHJ1ZSwgc2Nhbm5pbmc6dHJ1ZSwgZGVhZDpmYWxzZSwgZmFpbHM6MCwgc3RhcnRlZDpmYWxzZSwgdm9sOi41Cn07CmNvbnN0IHBhZDMgPSBuID0+IFN0cmluZyhuKS5wYWRTdGFydCgzLCcwJyk7CmNvbnN0IHRyYWNrVVJMID0gbiA9PiBNVVNJQy5iYXNlICsgcGFkMyhuKSArICcubXAzJzsKCmNvbnN0IFNWR19PTiA9CiAgJzxzdmcgdmlld0JveD0iMCAwIDI0IDI0IiBhcmlhLWhpZGRlbj0idHJ1ZSI+JysKICAnPHBhdGggZD0iTTQgOS40aDMuM0wxMiA1LjV2MTNMNy4zIDE0LjZINHoiIGZpbGw9ImN1cnJlbnRDb2xvciIvPicrCiAgJzxwYXRoIGQ9Ik0xNS4zIDkuNGE0LjIgNC4yIDAgMDEwIDUuMiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMS44IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4nKwogICc8cGF0aCBkPSJNMTcuOSA3LjFhNy42IDcuNiAwIDAxMCA5LjgiIGZpbGw9Im5vbmUiIHN0cm9rZT0iY3VycmVudENvbG9yIiBzdHJva2Utd2lkdGg9IjEuOCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+PC9zdmc+JzsKY29uc3QgU1ZHX09GRiA9CiAgJzxzdmcgdmlld0JveD0iMCAwIDI0IDI0IiBhcmlhLWhpZGRlbj0idHJ1ZSI+JysKICAnPHBhdGggZD0iTTQgOS40aDMuM0wxMiA1LjV2MTNMNy4zIDE0LjZINHoiIGZpbGw9ImN1cnJlbnRDb2xvciIvPicrCiAgJzxwYXRoIGQ9Ik0xNS42IDkuNmw1IDQuOE0yMC42IDkuNmwtNSA0LjgiIGZpbGw9Im5vbmUiIHN0cm9rZT0iY3VycmVudENvbG9yIiBzdHJva2Utd2lkdGg9IjEuOCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+PC9zdmc+JzsKCmZ1bmN0aW9uIHBhaW50TXVzaWMoKXsKICBpZighZWxNYnRuKSByZXR1cm47CiAgY29uc3QgZGVhZCA9IE1VU0lDLmRlYWQgfHwgKCFNVVNJQy5zY2FubmluZyAmJiAhTVVTSUMubGlzdC5sZW5ndGgpOwogIGVsTWJ0bi5jbGFzc05hbWUgPSAnbWJ0biAnICsgKE1VU0lDLnNjYW5uaW5nID8gJ3NjYW4nIDogZGVhZCA/ICdkZWFkJyA6IE1VU0lDLm9uID8gJ29uJyA6ICdvZmYnKTsKICBlbE1idG4uaW5uZXJIVE1MID0gKCFNVVNJQy5zY2FubmluZyAmJiAhZGVhZCAmJiBNVVNJQy5vbikgPyBTVkdfT04gOiBTVkdfT0ZGOwogIGVsTWJ0bi5kaXNhYmxlZCA9IE1VU0lDLnNjYW5uaW5nIHx8IGRlYWQ7CiAgZWxNYnRuLnNldEF0dHJpYnV0ZSgnYXJpYS1wcmVzc2VkJywgU3RyaW5nKCEhTVVTSUMub24gJiYgIWRlYWQpKTsKICBlbE1idG4uc2V0QXR0cmlidXRlKCdhcmlhLWxhYmVsJywKICAgIE1VU0lDLnNjYW5uaW5nID8gJ1JpY2VyY2EgYnJhbmkgaW4gY29yc28nIDoKICAgIGRlYWQgPyAnTmVzc3VuIGJyYW5vIGRpc3BvbmliaWxlJyA6CiAgICBNVVNJQy5vbiA/ICdNdXNpY2EgYXR0aXZhOiB0b2NjYSBwZXIgZGlzYXR0aXZhcmUnIDogJ011c2ljYSBkaXNhdHRpdmF0YTogdG9jY2EgcGVyIGF0dGl2YXJlJyk7CiAgZWxNdHJrLnRleHRDb250ZW50ID0gKCFNVVNJQy5zY2FubmluZyAmJiAhZGVhZCAmJiBNVVNJQy5vbiAmJiBNVVNJQy5saXN0Lmxlbmd0aCkKICAgID8gJ+KZqiAnK3BhZDMoTVVTSUMubGlzdFtNVVNJQy5pZHhdKSA6ICcnOwp9CgovKiBzb25kYSB1biBzaW5nb2xvIGJyYW5vOiByaXNwb25kZSBhaSBtZXRhZGF0aSBvcHB1cmUgbm9uIGVzaXN0ZSAqLwpmdW5jdGlvbiBwcm9iZVRyYWNrKG4pewogIHJldHVybiBuZXcgUHJvbWlzZShyZXM9PnsKICAgIGNvbnN0IGE9bmV3IEF1ZGlvKCk7CiAgICBhLnByZWxvYWQ9J21ldGFkYXRhJzsgYS5tdXRlZD10cnVlOwogICAgbGV0IGRvbmU9ZmFsc2UsIHRtPTA7CiAgICBjb25zdCBlbmQ9dj0+ewogICAgICBpZihkb25lKSByZXR1cm47IGRvbmU9dHJ1ZTsgY2xlYXJUaW1lb3V0KHRtKTsKICAgICAgYS5yZW1vdmVFdmVudExpc3RlbmVyKCdsb2FkZWRtZXRhZGF0YScsb2spOwogICAgICBhLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NhbnBsYXl0aHJvdWdoJyxvayk7CiAgICAgIGEucmVtb3ZlRXZlbnRMaXN0ZW5lcignZXJyb3InLGtvKTsKICAgICAgYS5yZW1vdmVBdHRyaWJ1dGUoJ3NyYycpOwogICAgICByZXModik7CiAgICB9OwogICAgY29uc3Qgb2s9KCk9PmVuZCh0cnVlKSwga289KCk9PmVuZChmYWxzZSk7CiAgICBhLmFkZEV2ZW50TGlzdGVuZXIoJ2xvYWRlZG1ldGFkYXRhJyxvayk7CiAgICBhLmFkZEV2ZW50TGlzdGVuZXIoJ2NhbnBsYXl0aHJvdWdoJyxvayk7CiAgICBhLmFkZEV2ZW50TGlzdGVuZXIoJ2Vycm9yJyxrbyk7CiAgICB0bT1zZXRUaW1lb3V0KGtvLCA3MDAwKTsgICAgICAgICAgLy8gcmV0ZSBsZW50YSBvIHNlcnZlciBtdXRvOiBub24gc2kgcmVzdGEgYXBwZXNpCiAgICB0cnl7IGEuc3JjPXRyYWNrVVJMKG4pOyBhLmxvYWQoKTsgfWNhdGNoKGUpeyBrbygpOyB9CiAgfSk7Cn0KCi8qIHNjYW5zaW9uZSBjb24gY29uY29ycmVuemEgbGltaXRhdGE6IDIwIHJpY2hpZXN0ZSBpbiBwYXJhbGxlbG8gc2FyZWJiZXJvCiAgIHVubyBzcHJlY28gcHJvcHJpbyBtZW50cmUgaWwgZ2lvY28gc3RhIHBhcnRlbmRvICovCmZ1bmN0aW9uIHNjYW5NdXNpYygpewogIGNvbnN0IG51bXM9W107IGZvcihsZXQgaT0xO2k8PU1VU0lDLnRvdGFsO2krKykgbnVtcy5wdXNoKGkpOwogIGNvbnN0IGZvdW5kPVtdOyBsZXQgY3Vyc29yPTA7CiAgY29uc3Qgd29ya2VyPSgpPT4gY3Vyc29yPj1udW1zLmxlbmd0aCA/IFByb21pc2UucmVzb2x2ZSgpCiAgICA6IChuPT5wcm9iZVRyYWNrKG4pLnRoZW4ob2s9PnsgaWYob2spIGZvdW5kLnB1c2gobik7IHJldHVybiB3b3JrZXIoKTsgfSkpKG51bXNbY3Vyc29yKytdKTsKICByZXR1cm4gUHJvbWlzZS5hbGwoW3dvcmtlcigpLHdvcmtlcigpLHdvcmtlcigpLHdvcmtlcigpXSkudGhlbigoKT0+ewogICAgZm91bmQuc29ydCgoYSxiKT0+YS1iKTsKICAgIE1VU0lDLmxpc3Q9Zm91bmQ7CiAgICBNVVNJQy5zY2FubmluZz1mYWxzZTsKICAgIE1VU0lDLnJlYWR5PWZvdW5kLmxlbmd0aD4wOwogICAgaWYoIU1VU0lDLnJlYWR5KXsgbXVzaWNLaWxsKCk7IHJldHVybjsgfSAgIC8vIHN0YXRvIGludGVybm8gY29lcmVudGUgY29uIGwnaWNvbmEgc3BlbnRhCiAgICBwYWludE11c2ljKCk7CiAgICBpZihNVVNJQy5zdGFydGVkICYmIE1VU0lDLm9uKSBtdXNpY0xvYWQoKTsKICB9KTsKfQoKZnVuY3Rpb24gbXVzaWNLaWxsKCl7CiAgTVVTSUMuZGVhZD10cnVlOyBNVVNJQy5yZWFkeT1mYWxzZTsgTVVTSUMub249ZmFsc2U7CiAgaWYoTVVTSUMuZWwpeyB0cnl7IE1VU0lDLmVsLnBhdXNlKCk7IE1VU0lDLmVsLnJlbW92ZUF0dHJpYnV0ZSgnc3JjJyk7IH1jYXRjaChlKXt9IH0KICBwYWludE11c2ljKCk7Cn0KZnVuY3Rpb24gbXVzaWNMb2FkKCl7CiAgaWYoIU1VU0lDLmxpc3QubGVuZ3RoKXsgbXVzaWNLaWxsKCk7IHJldHVybjsgfQogIGNvbnN0IGVsPU1VU0lDLmVsOwogIGVsLnNyYz10cmFja1VSTChNVVNJQy5saXN0W01VU0lDLmlkeF0pOwogIGVsLmxvYWQoKTsKICBpZihNVVNJQy5vbikgZWwucGxheSgpLmNhdGNoKCgpPT57fSk7ICAgLy8gaWwgY29uc2Vuc28gYXJyaXZhIGNvbCBwcmltbyB0b2NjbwogIHBhaW50TXVzaWMoKTsKfQpmdW5jdGlvbiBtdXNpY05leHQoKXsKICBpZighTVVTSUMubGlzdC5sZW5ndGgpeyBtdXNpY0tpbGwoKTsgcmV0dXJuOyB9CiAgTVVTSUMuaWR4PShNVVNJQy5pZHgrMSklTVVTSUMubGlzdC5sZW5ndGg7ICAgLy8gcmlwcm9kdXppb25lIGNpcmNvbGFyZQogIG11c2ljTG9hZCgpOwp9CmZ1bmN0aW9uIG11c2ljRHJvcCgpewogIC8qIGJyYW5vIGlsbGVnZ2liaWxlIGluIGNvcnNhOiBsbyB0b2xnbyBkYWxsYSBzY2FsZXR0YSBlIHByb3NlZ3VvLgogICAgIEwnaW5kaWNlIHB1bnRhIGdpw6AgYWwgc3VjY2Vzc2l2byBkb3BvIGxhIHJpbW96aW9uZS4gKi8KICBpZihNVVNJQy5saXN0Lmxlbmd0aCkgTVVTSUMubGlzdC5zcGxpY2UoTVVTSUMuaWR4LDEpOwogIGlmKCFNVVNJQy5saXN0Lmxlbmd0aCl7IG11c2ljS2lsbCgpOyByZXR1cm47IH0KICBpZihNVVNJQy5pZHg+PU1VU0lDLmxpc3QubGVuZ3RoKSBNVVNJQy5pZHg9MDsKICBpZigrK01VU0lDLmZhaWxzID4gTVVTSUMudG90YWwpeyBtdXNpY0tpbGwoKTsgcmV0dXJuOyB9CiAgbXVzaWNMb2FkKCk7Cn0KZnVuY3Rpb24gbXVzaWNUb2dnbGUoKXsKICBpZihNVVNJQy5zY2FubmluZyB8fCBNVVNJQy5kZWFkKSByZXR1cm47CiAgTVVTSUMub249IU1VU0lDLm9uOwogIGlmKE1VU0lDLm9uKXsKICAgIE1VU0lDLnN0YXJ0ZWQ9dHJ1ZTsKICAgIGlmKCFNVVNJQy5lbC5nZXRBdHRyaWJ1dGUoJ3NyYycpKSBtdXNpY0xvYWQoKTsKICAgIGVsc2UgTVVTSUMuZWwucGxheSgpLmNhdGNoKCgpPT57fSk7CiAgfSBlbHNlIE1VU0lDLmVsLnBhdXNlKCk7CiAgcGFpbnRNdXNpYygpOwp9Ci8qIGxhIHJpcHJvZHV6aW9uZSBwdcOyIHBhcnRpcmUgc29sbyBkb3BvIHVuIGdlc3RvIGRlbGwndXRlbnRlOiBpbCBwdWxzYW50ZQogICBkaSBhdnZpbyBkZWxsYSBwYXJ0aXRhIMOoIHF1ZWwgZ2VzdG8gKi8KZnVuY3Rpb24gbXVzaWNLaWNrKCl7CiAgTVVTSUMuc3RhcnRlZD10cnVlOwogIGlmKE1VU0lDLnNjYW5uaW5nIHx8IE1VU0lDLmRlYWQgfHwgIU1VU0lDLm9uKSByZXR1cm47CiAgaWYoIU1VU0lDLmVsLmdldEF0dHJpYnV0ZSgnc3JjJykpIG11c2ljTG9hZCgpOwogIGVsc2UgTVVTSUMuZWwucGxheSgpLmNhdGNoKCgpPT57fSk7Cn0KCmZ1bmN0aW9uIG11c2ljSW5pdCgpewogIGlmKHR5cGVvZiBBdWRpbyE9PSdmdW5jdGlvbicpeyBtdXNpY0tpbGwoKTsgcmV0dXJuOyB9CiAgY29uc3QgZWw9bmV3IEF1ZGlvKCk7CiAgZWwudm9sdW1lPU1VU0lDLnZvbDsgZWwucHJlbG9hZD0nbm9uZSc7CiAgZWwuYWRkRXZlbnRMaXN0ZW5lcignZW5kZWQnLCBtdXNpY05leHQpOwogIGVsLmFkZEV2ZW50TGlzdGVuZXIoJ2Vycm9yJywgKCk9PnsgaWYoZWwuZ2V0QXR0cmlidXRlKCdzcmMnKSkgbXVzaWNEcm9wKCk7IH0pOwogIGVsLmFkZEV2ZW50TGlzdGVuZXIoJ3BsYXlpbmcnLCAoKT0+eyBNVVNJQy5mYWlscz0wOyBwYWludE11c2ljKCk7IH0pOwogIE1VU0lDLmVsPWVsOwogIGVsTWJ0bi5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIG11c2ljVG9nZ2xlKTsKICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCd2aXNpYmlsaXR5Y2hhbmdlJywgKCk9PnsKICAgIGlmKCFNVVNJQy5lbCkgcmV0dXJuOwogICAgaWYoZG9jdW1lbnQuaGlkZGVuKSBNVVNJQy5lbC5wYXVzZSgpOwogICAgZWxzZSBpZihNVVNJQy5vbiAmJiAhTVVTSUMuZGVhZCAmJiBNVVNJQy5zdGFydGVkKSBNVVNJQy5lbC5wbGF5KCkuY2F0Y2goKCk9Pnt9KTsKICB9KTsKICBwYWludE11c2ljKCk7CiAgc2Nhbk11c2ljKCk7Cn0KCi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQogICBBUEVSVFVSQSDigJQgcG9zYSBkaSAyIHMsIHBvaSBkaXNzb2x2ZW56YSBpbiBiaWFuY28gZSBnYXVzc2lhbmEKICAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiAgIEwnaW1tYWdpbmUgw6ggdW4gYWNjZXNzb3Jpbzogc2UgbWFuY2EgbyB0YXJkYSwgaWwgZ2lvY28gbm9uIGRldmUKICAgcmVzdGFyZSBkaWV0cm8gdW4gdmVsby4gVHJlIHZpZSBkJ3VzY2l0YSBpbmRpcGVuZGVudGkuCiAgID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqLwpmdW5jdGlvbiBzcGxhc2hJbml0KCl7CiAgY29uc3Qgc3A9ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3NwbGFzaCcpLCBpbT1kb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnc3BsYXNoaW1nJyk7CiAgaWYoIXNwKSByZXR1cm47CiAgbGV0IGNoaXVzbz1mYWxzZSwgdGltZXI9MDsKCiAgY29uc3QgdmlhPSgpPT57IGlmKGNoaXVzbykgcmV0dXJuOyBjaGl1c289dHJ1ZTsgY2xlYXJUaW1lb3V0KHRpbWVyKTsgc3AuY2xhc3NMaXN0LmFkZCgnZ29uZScpOyB9OwogIGNvbnN0IGRpc3NvbHZpPSgpPT57CiAgICBpZihjaGl1c28pIHJldHVybjsKICAgIGNsZWFyVGltZW91dCh0aW1lcik7CiAgICBpZihSRURVQ0VEKXsgdmlhKCk7IHJldHVybjsgfQogICAgc3AuY2xhc3NMaXN0LmFkZCgnb3V0Jyk7CiAgICB0aW1lcj1zZXRUaW1lb3V0KHZpYSwgODgwKTsgICAgICAgICAgLy8gYSBmaW5lIGFuaW1hemlvbmUgZXNjZSBkYWwgZmx1c3NvCiAgfTsKICBjb25zdCBwb3NhPSgpPT57IGNsZWFyVGltZW91dCh0aW1lcik7IHRpbWVyPXNldFRpbWVvdXQoZGlzc29sdmksIDIwMDApOyB9OwoKICBpZighaW0peyB2aWEoKTsgcmV0dXJuOyB9CiAgaWYoaW0uY29tcGxldGUpewogICAgaW0ubmF0dXJhbFdpZHRoID8gcG9zYSgpIDogdmlhKCk7ICAgIC8vIGdpw6AgaW4gY2FjaGUsIG9wcHVyZSBnacOgIGZhbGxpdGEKICB9IGVsc2UgewogICAgaW0uYWRkRXZlbnRMaXN0ZW5lcignbG9hZCcsIHBvc2EpOwogICAgaW0uYWRkRXZlbnRMaXN0ZW5lcignZXJyb3InLCB2aWEpOyAgIC8vIGltbWFnaW5lIGFzc2VudGU6IHNpIHBhcnRlIHN1Yml0bwogICAgdGltZXI9c2V0VGltZW91dChkaXNzb2x2aSwgNDUwMCk7ICAgIC8vIHJldGUgbGVudGE6IG5vbiBzaSByZXN0YSBhcHBlc2kKICB9Cn0KCi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQogICBNT0RBTElUw4AgU0VMRVpJT05BIEUgU1BBUkEKICAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiAgIFNpIHRvY2NhIGwnZWxlbWVudG8gZGEgY29scGlyZTogbGEgbmF2aWNlbGxhIHNpIGFsbGluZWEgZGEgc29sYSBlCiAgIGZhIGZ1b2NvLiBJbCBwdW50YW1lbnRvIHNtZXR0ZSBkaSBlc3NlcmUgdW5hIHByb3ZhIGRpIGRlc3RyZXp6YSBlCiAgIGRpdmVudGEgdW5hIHNjZWx0YSB0YXR0aWNhIOKAlCB1dGlsZSBzb3ByYXR0dXR0byBuZWkgc2V0dG9yaSBib251cywKICAgZG92ZSBzYmFnbGlhcmUgYmVyc2FnbGlvIGNvc3RhIHB1bnRpIG8gc3BlenphIGxhIGNhdGVuYS4KICAgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICovCmNvbnN0IEFVVE8gPSB7b246ZmFsc2UsIHRhcmdldDpudWxsfTsKCmNvbnN0IFNWR19WSVNPUiA9CiAgJzxzdmcgdmlld0JveD0iMCAwIDI0IDI0IiBhcmlhLWhpZGRlbj0idHJ1ZSI+JysKICAnPGNpcmNsZSBjeD0iMTIiIGN5PSIxMiIgcj0iOS4xIiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIxLjciLz4nKwogICc8cGF0aCBkPSJNNC45IDkuMWg1LjZ2Mi4xYzAgMS41LTEuMiAyLjYtMi44IDIuNnMtMi44LTEuMS0yLjgtMi42eiIgZmlsbD0iY3VycmVudENvbG9yIi8+JysKICAnPHBhdGggZD0iTTEzLjUgOS4xaDUuNnYyLjFjMCAxLjUtMS4yIDIuNi0yLjggMi42cy0yLjgtMS4xLTIuOC0yLjZ6IiBmaWxsPSJjdXJyZW50Q29sb3IiLz4nKwogICc8cGF0aCBkPSJNMTAuNSA5LjloMyIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4nKwogICc8cGF0aCBkPSJNOC41IDE2LjRjMS4yIDEuMiA1LjggMS4yIDcgMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMS42IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz48L3N2Zz4nOwoKZnVuY3Rpb24gcGFpbnRWaXNvcigpewogIGlmKCFlbFZidG4pIHJldHVybjsKICBlbFZidG4uY2xhc3NOYW1lPSdtYnRuIHZpcyAnKyhBVVRPLm9uPydvbic6J29mZicpOwogIGVsVmJ0bi5pbm5lckhUTUw9U1ZHX1ZJU09SOwogIGVsVmJ0bi5zZXRBdHRyaWJ1dGUoJ2FyaWEtcHJlc3NlZCcsIFN0cmluZyhBVVRPLm9uKSk7Cn0KLyogbGFtcG8gZGkgY29tbXV0YXppb25lOiBzZm9jYXR1cmEgZ2F1c3NpYW5hLCB2aXJhdGEgYWwgYmlhbmNvLCByaWVudHJvICovCmZ1bmN0aW9uIHZpc29yRmxhc2goKXsKICBpZihSRURVQ0VEKSByZXR1cm47CiAgW2VsU3RhZ2UsIGVsSHVkLCBlbEJsb29tXS5mb3JFYWNoKGVsPT57CiAgICBpZighZWwpIHJldHVybjsKICAgIGVsLmNsYXNzTGlzdC5yZW1vdmUoJ3Zpc29yJyk7IHZvaWQgZWwub2Zmc2V0V2lkdGg7IGVsLmNsYXNzTGlzdC5hZGQoJ3Zpc29yJyk7CiAgfSk7Cn0KZnVuY3Rpb24gc2Z4Vmlzb3Iob24pewogIGNvbnN0IGE9YXVkaW8oKTsgaWYoIWEpIHJldHVybjsKICBjb25zdCBub3RlcyA9IG9uID8gWzM5Miw1ODcsODgwXSA6IFs4ODAsNTg3LDM5Ml07CiAgbm90ZXMuZm9yRWFjaCgoaHosaSk9PnsKICAgIGNvbnN0IG89YS5jcmVhdGVPc2NpbGxhdG9yKCksIGc9YS5jcmVhdGVHYWluKCksIGY9YS5jcmVhdGVCaXF1YWRGaWx0ZXIoKSwgdDA9YS5jdXJyZW50VGltZStpKi4wNTU7CiAgICBmLnR5cGU9J2JhbmRwYXNzJzsgZi5mcmVxdWVuY3kudmFsdWU9aHoqMS40OyBmLlEudmFsdWU9MS4yOwogICAgby50eXBlID0gb24gPyAndHJpYW5nbGUnIDogJ3NpbmUnOwogICAgby5mcmVxdWVuY3kuc2V0VmFsdWVBdFRpbWUoaHoqKG9uPy44OjEuMiksIHQwKTsKICAgIG8uZnJlcXVlbmN5LmV4cG9uZW50aWFsUmFtcFRvVmFsdWVBdFRpbWUoaHosIHQwKy4wNSk7CiAgICBnLmdhaW4uc2V0VmFsdWVBdFRpbWUoLjAwMSx0MCk7IGcuZ2Fpbi5leHBvbmVudGlhbFJhbXBUb1ZhbHVlQXRUaW1lKC4xMCx0MCsuMDE1KTsKICAgIGcuZ2Fpbi5leHBvbmVudGlhbFJhbXBUb1ZhbHVlQXRUaW1lKC4wMDAxLHQwKy4yNCk7CiAgICBvLmNvbm5lY3QoZik7IGYuY29ubmVjdChnKTsgZy5jb25uZWN0KGEuZGVzdGluYXRpb24pOyBvLnN0YXJ0KHQwKTsgby5zdG9wKHQwKy4yNik7CiAgfSk7CiAgaWYob24peyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gZnJ1c2NpYXRhIGRpIGluc2VyaW1lbnRvCiAgICBjb25zdCBkdXI9LjI4LCBuPWEuc2FtcGxlUmF0ZSpkdXIsIGJ1Zj1hLmNyZWF0ZUJ1ZmZlcigxLG4sYS5zYW1wbGVSYXRlKSwgZD1idWYuZ2V0Q2hhbm5lbERhdGEoMCk7CiAgICBmb3IobGV0IGk9MDtpPG47aSsrKSBkW2ldPShNYXRoLnJhbmRvbSgpKjItMSkqKDEtaS9uKTsKICAgIGNvbnN0IHNyYz1hLmNyZWF0ZUJ1ZmZlclNvdXJjZSgpOyBzcmMuYnVmZmVyPWJ1ZjsKICAgIGNvbnN0IGJwPWEuY3JlYXRlQmlxdWFkRmlsdGVyKCk7IGJwLnR5cGU9J2JhbmRwYXNzJzsKICAgIGJwLmZyZXF1ZW5jeS5zZXRWYWx1ZUF0VGltZSg2MDAsYS5jdXJyZW50VGltZSk7CiAgICBicC5mcmVxdWVuY3kuZXhwb25lbnRpYWxSYW1wVG9WYWx1ZUF0VGltZSg1MjAwLGEuY3VycmVudFRpbWUrZHVyKTsKICAgIGNvbnN0IGc9YS5jcmVhdGVHYWluKCk7IGcuZ2Fpbi5zZXRWYWx1ZUF0VGltZSguMDcsYS5jdXJyZW50VGltZSk7CiAgICBnLmdhaW4uZXhwb25lbnRpYWxSYW1wVG9WYWx1ZUF0VGltZSguMDAwMSxhLmN1cnJlbnRUaW1lK2R1cik7CiAgICBzcmMuY29ubmVjdChicCk7IGJwLmNvbm5lY3QoZyk7IGcuY29ubmVjdChhLmRlc3RpbmF0aW9uKTsgc3JjLnN0YXJ0KCk7CiAgfQp9CmZ1bmN0aW9uIHZpc29yVG9nZ2xlKCl7CiAgQVVUTy5vbj0hQVVUTy5vbjsKICBBVVRPLnRhcmdldD1udWxsOwogIHBhaW50Vmlzb3IoKTsKICBhdWRpbygpOwogIHNmeFZpc29yKEFVVE8ub24pOwogIGlmKEFVVE8ub24pIHZpc29yRmxhc2goKTsgICAgICAgICAgICAgICAgIC8vIGlsIGxhbXBvIHNlZ25hIGwnaW5zZXJpbWVudG8KfQoKLyogc2VsZXppb25lOiBjb3NhIHNpIHRyb3ZhIHNvdHRvIGlsIGRpdG8sIGNvbiB0b2xsZXJhbnphIGdlbmVyb3NhICovCmZ1bmN0aW9uIHBpY2tBdCh4LHkpewogIGNvbnN0IHRvbD1NYXRoLm1heCgxNSwgVyouMDQ1KTsKICBsZXQgYmVzdD1udWxsLCBiZD0xZTk7CiAgZm9yKGxldCBpPTA7aTxCT05VUy5wb2RzLmxlbmd0aDtpKyspewogICAgY29uc3QgcD1CT05VUy5wb2RzW2ldOwogICAgaWYocC50YWtlbiB8fCBwLnR0PDApIGNvbnRpbnVlOwogICAgY29uc3QgZD1NYXRoLmh5cG90KHAueC14LCBwLnkteSk7CiAgICBpZihkPD1wLnIrdG9sICYmIGQ8YmQpeyBiZD1kOyBiZXN0PXA7IH0KICB9CiAgZm9yKGxldCBpPTA7aTxyb2Nrcy5sZW5ndGg7aSsrKXsKICAgIGNvbnN0IGE9cm9ja3NbaV07CiAgICBpZihhLmRlYWQpIGNvbnRpbnVlOwogICAgY29uc3QgZD1NYXRoLmh5cG90KGEueC14LCBhLnkteSk7CiAgICBpZihkPD1hLnIrdG9sICYmIGQ8YmQpeyBiZD1kOyBiZXN0PWE7IH0KICB9CiAgcmV0dXJuIGJlc3Q7Cn0KZnVuY3Rpb24gdGFyZ2V0QWxpdmUodGcpewogIGlmKCF0ZyB8fCB0Zy50YWtlbiB8fCB0Zy5kZWFkIHx8ICFzaGlwKSByZXR1cm4gZmFsc2U7CiAgaWYoIU51bWJlci5pc0Zpbml0ZSh0Zy54KSB8fCAhTnVtYmVyLmlzRmluaXRlKHRnLnkpKSByZXR1cm4gZmFsc2U7CiAgcmV0dXJuIHRnLnkgPCBzaGlwLnktMzQ7ICAgICAgICAgICAgICAgICAgLy8gc290dG8gbGEgbmF2aWNlbGxhIGlsIGNvbHBvIG5vbiBhcnJpdmVyZWJiZQp9Ci8qIGFsbGluZWFtZW50byBlIGZ1b2NvOiBsYSBuYXZpY2VsbGEgaW5zZWd1ZSBsYSBYIGRlbCBiZXJzYWdsaW8sIGNoZSBuZWwKICAgZnJhdHRlbXBvIGNvbnRpbnVhIGEgbXVvdmVyc2kgKi8KZnVuY3Rpb24gYXV0b1N0ZXAoZHQsIG5vdyl7CiAgaWYoIUFVVE8udGFyZ2V0KSByZXR1cm4gZmFsc2U7CiAgaWYoIXRhcmdldEFsaXZlKEFVVE8udGFyZ2V0KSl7IEFVVE8udGFyZ2V0PW51bGw7IHJldHVybiBmYWxzZTsgfQogIGNvbnN0IHdhbnQ9Y2xhbXAoQVVUTy50YXJnZXQueCwgMjAsIFctMjApOwogIGNvbnN0IGQ9d2FudC1zaGlwLngsIHN0ZXA9U0hJUF9WKjEuNCpkdDsKICBpZihNYXRoLmFicyhkKTw9TWF0aC5tYXgoNCxzdGVwKSl7CiAgICBzaGlwLng9d2FudDsKICAgIGlmKGZpcmUobm93LCBBVVRPLnRhcmdldCkpIEFVVE8udGFyZ2V0PW51bGw7ICAgLy8gc2UgaWwgY2Fubm9uZSDDqCBjYWxkbywgcmlwcm92YQogIH0gZWxzZSB7CiAgICBzaGlwLnggKz0gKGQ+MD8xOi0xKSpzdGVwOwogIH0KICBzaGlwLnRpbHQgKz0gKGNsYW1wKGQvNzAsLTEsMSkqLjM0IC0gc2hpcC50aWx0KSpNYXRoLm1pbigxLGR0KjEyKTsKICByZXR1cm4gdHJ1ZTsKfQpmdW5jdGlvbiBkcmF3QXV0b0xvY2soKXsKICBpZighQVVUTy5vbiB8fCAhQVVUTy50YXJnZXQgfHwgIXRhcmdldEFsaXZlKEFVVE8udGFyZ2V0KSkgcmV0dXJuOwogIGNvbnN0IHRnPUFVVE8udGFyZ2V0LCBjb2w9YWltQ29sb3IodGcpLCBSPXRnLnIrMTMsIGs9KE1hdGguc2luKHQqOSkrMSkvMjsKICBjdHguc2F2ZSgpOwogIC8qIGZpbG8gZGkgY29sbGVnYW1lbnRvIGNvbiBsYSBuYXZpY2VsbGEgKi8KICBjdHguc2V0TGluZURhc2goWzMsN10pOyBjdHgubGluZURhc2hPZmZzZXQ9LXQqOTA7IGN0eC5saW5lV2lkdGg9MS4zOwogIGN0eC5zdHJva2VTdHlsZT1gcmdiYSgke2NvbH0sLjQyKWA7CiAgY3R4LmJlZ2luUGF0aCgpOyBjdHgubW92ZVRvKHNoaXAueCwgc2hpcC55LTI0KTsgY3R4LmxpbmVUbyh0Zy54LCB0Zy55KTsgY3R4LnN0cm9rZSgpOwogIGN0eC5zZXRMaW5lRGFzaChbXSk7CiAgLyogZ2hpZXJhIGluIHJvdGF6aW9uZSAqLwogIGN0eC50cmFuc2xhdGUodGcueCwgdGcueSk7IGN0eC5yb3RhdGUodCoyLjIpOwogIGN0eC5zdHJva2VTdHlsZT1gcmdiYSgke2NvbH0sJHsuNjUrayouMzV9KWA7IGN0eC5saW5lV2lkdGg9Mi40OwogIGN0eC5zaGFkb3dDb2xvcj1gcmdiYSgke2NvbH0sLjkpYDsgY3R4LnNoYWRvd0JsdXI9MTQ7CiAgZm9yKGxldCBpPTA7aTw0O2krKyl7CiAgICBjdHguYmVnaW5QYXRoKCk7CiAgICBjdHguYXJjKDAsMCxSK2sqMywgaSpUQVUvNCsuMTYsIGkqVEFVLzQrVEFVLzQtLjE2KTsKICAgIGN0eC5zdHJva2UoKTsKICB9CiAgLyogY3VuZW8gZGkgY29udmVyZ2VuemEgKi8KICBjdHgucm90YXRlKC10KjIuMik7CiAgY3R4LmZpbGxTdHlsZT1gcmdiYSgke2NvbH0sJHsuNStrKi40fSlgOwogIGZvcihsZXQgaT0wO2k8NDtpKyspewogICAgY29uc3QgYTA9aSpUQVUvNCtNYXRoLlBJLzQsIGR4PU1hdGguY29zKGEwKSwgZHk9TWF0aC5zaW4oYTApLCBvPVIrOStrKjQ7CiAgICBjdHguYmVnaW5QYXRoKCk7CiAgICBjdHgubW92ZVRvKGR4Km8sIGR5Km8pOwogICAgY3R4LmxpbmVUbyhkeCoobys3KS1keSo0LCBkeSoobys3KStkeCo0KTsKICAgIGN0eC5saW5lVG8oZHgqKG8rNykrZHkqNCwgZHkqKG8rNyktZHgqNCk7CiAgICBjdHguY2xvc2VQYXRoKCk7IGN0eC5maWxsKCk7CiAgfQogIGN0eC5yZXN0b3JlKCk7Cn0KCi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQogICBIVUQKICAgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICovCmZ1bmN0aW9uIHNwZWVkTXVsKCl7IHJldHVybiAxICsgbGV2ZWwqMC4yMjsgfQoKZnVuY3Rpb24gcGFpbnRIdWxscygpewogIGVsSHVsbHMuaW5uZXJIVE1MPScnOwogIGNvbnN0IG49TWF0aC5taW4oTUFYTCwgTWF0aC5tYXgoTElWRVMsIGxpdmVzKSk7CiAgZm9yKGxldCBpPTA7aTxuO2krKyl7CiAgICBjb25zdCBkPWRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpOwogICAgZC5jbGFzc05hbWU9J2h1bGwnKyhpPGxpdmVzPycnOicgb2ZmJyk7CiAgICBlbEh1bGxzLmFwcGVuZENoaWxkKGQpOwogIH0KfQpmdW5jdGlvbiBhZGRTY29yZShuLCBnYXRlKXsKICBzY29yZSs9bjsKICBlbFNjb3JlLnRleHRDb250ZW50PXNjb3JlOwogIGVsU2NvcmUuc3R5bGUuY29sb3IgPSBzY29yZTwwID8gJyNmZjJlNmInIDogJyc7CiAgZWxTY29yZS5zdHlsZS50ZXh0U2hhZG93ID0gc2NvcmU8MCA/ICcwIDAgMThweCByZ2JhKDI1NSw0NiwxMDcsLjYpJyA6ICcnOwogIGVsU2NvcmUuY2xhc3NMaXN0LnJlbW92ZSgncG9wJyk7IHZvaWQgZWxTY29yZS5vZmZzZXRXaWR0aDsgZWxTY29yZS5jbGFzc0xpc3QuYWRkKCdwb3AnKTsKICBpZihnYXRlKXsKICAgIGdhdGVQcm9nPU1hdGgubWF4KDAsZ2F0ZVByb2crbik7CiAgICBpZihnYXRlUHJvZz49UFRTX1BFUl9MRVZFTCAmJiAhQk9OVVMub24peyBnYXRlUHJvZy09UFRTX1BFUl9MRVZFTDsgc3RhcnRCb251cygpOyB9CiAgfQogIGVsR2F1Z2Uuc3R5bGUud2lkdGg9KGNsYW1wKGdhdGVQcm9nL1BUU19QRVJfTEVWRUwsMCwxKSoxMDApKyclJzsKfQpmdW5jdGlvbiBsZXZlbFVwKCl7CiAgbGV2ZWwrKzsKICBlbExldmVsLnRleHRDb250ZW50PWxldmVsKzE7CiAgZWxHYXVnZS5zdHlsZS53aWR0aD0oY2xhbXAoZ2F0ZVByb2cvUFRTX1BFUl9MRVZFTCwwLDEpKjEwMCkrJyUnOwogIHRvYXN0KCdMSVZFTExPICcrKGxldmVsKzEpKTsKICBpZihsZXZlbD09PUNBUkdPX0xWKQogICAgc2hvd05vdGljZSgnQ0FSSUNIRSBJTiBDQU1QTycsIFRPVUNIPyAnRlVPQ08gQSBDT0xQTyBTSU5HT0xPIMK3IFRPQ0NBIExBIE5BVklDRUxMQScKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogJ0lMIE1JUklOTyBNT1NUUkEgQ09TQSBTVEFJIFBFUiBDT0xQSVJFJywgNS41KTsKICBjb25zdCBzaz1za2luRm9yKGxldmVsKTsKICBlbFRpY2tlci5pbm5lckhUTUw9J1NFVFRPUkUgPGI+Jytzay5ub21lKyc8L2I+IMK3ICcrCiAgICAobGV2ZWw+PUNBUkdPX0xWPyAnQ0FSSUNIRSBBVFRJVkUgPGI+U8OMPC9iPiDCtyBBVFRFTlpJT05FIEFJIE1FVEVPUklUSSBSQURJT0FUVElWSScKICAgICAgICAgICAgICAgICAgICA6ICdDQVJJQ0hFIEFUVElWRSA8Yj5OTzwvYj4gwrcgMTUwIFBUIC8gSU1QQVRUTycpOwogIHNmeExldmVsKCk7CiAgZm9yKGxldCBpPTA7aTwzO2krKykgd2F2ZXMucHVzaCh7eDpXLzIseTpILzIscjA6NDAraSo2MCxyMTpNYXRoLm1heChXLEgpKjEuMSxsaWZlOjAsbWF4Oi41NStpKi4xLHc6Mix0b25lOidyb2NrJ30pOwp9CmZ1bmN0aW9uIHRvYXN0KHR4dCl7CiAgZWxUb2FzdC50ZXh0Q29udGVudD10eHQ7CiAgZWxUb2FzdC5jbGFzc0xpc3QucmVtb3ZlKCdvbicpOyB2b2lkIGVsVG9hc3Qub2Zmc2V0V2lkdGg7IGVsVG9hc3QuY2xhc3NMaXN0LmFkZCgnb24nKTsKfQoKLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiAgIElOUFVUIOKAlCB0YXN0aWVyYSArIHB1bnRhdG9yZSwgaWwgdG9jY28gbXVvdmUgZSBzcGFyYSBpbnNpZW1lCiAgID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqLwpjb25zdCBrZXlzPU9iamVjdC5jcmVhdGUobnVsbCk7CmNvbnN0IFRPVUNIID0gbWF0Y2hNZWRpYSgnKHBvaW50ZXI6Y29hcnNlKScpLm1hdGNoZXM7CmxldCBwdHI9e2FjdGl2ZTpmYWxzZSwgeDowLCB5OjAsIGx4OjAsIHgwOjAsIHkwOjAsIHQwOjAsIG1vdmVkOmZhbHNlLCB0YXA6bnVsbCwgdGFwS2V5OmZhbHNlfTsKCmFkZEV2ZW50TGlzdGVuZXIoJ2tleWRvd24nLGU9PnsKICBpZihbJ0Fycm93TGVmdCcsJ0Fycm93UmlnaHQnLCdTcGFjZScsJ0tleUEnLCdLZXlEJ10uaW5jbHVkZXMoZS5jb2RlKSkgZS5wcmV2ZW50RGVmYXVsdCgpOwogIGlmKGUuY29kZT09PSdTcGFjZScgJiYgIWUucmVwZWF0KSBwdHIudGFwS2V5PXRydWU7ICAgICAgLy8gZnJvbnRlIGRpIHNhbGl0YTogY29scG8gc2luZ29sbwogIGtleXNbZS5jb2RlXT10cnVlOwogIGlmKChlLmNvZGU9PT0nU3BhY2UnfHxlLmNvZGU9PT0nRW50ZXInKSAmJiAhcnVubmluZykgc3RhcnQoKTsKfSx7cGFzc2l2ZTpmYWxzZX0pOwphZGRFdmVudExpc3RlbmVyKCdrZXl1cCcsZT0+eyBrZXlzW2UuY29kZV09ZmFsc2U7IH0pOwoKY29uc3QgcHg9ZT0+ZS50b3VjaGVzJiZlLnRvdWNoZXNbMF0/ZS50b3VjaGVzWzBdLmNsaWVudFg6ZS5jbGllbnRYOwpjb25zdCBweT1lPT5lLnRvdWNoZXMmJmUudG91Y2hlc1swXT9lLnRvdWNoZXNbMF0uY2xpZW50WTplLmNsaWVudFk7CgpmdW5jdGlvbiBwZG93bihlKXsKICBwdHIuYWN0aXZlPXRydWU7IHB0ci5tb3ZlZD1mYWxzZTsgcHRyLnQwPXBlcmZvcm1hbmNlLm5vdygpOwogIHB0ci54PXB0ci54MD1wdHIubHg9cHgoZSk7IHB0ci55PXB0ci55MD1weShlKTsKfQpmdW5jdGlvbiBwbW92ZShlKXsKICBpZighcHRyLmFjdGl2ZSkgcmV0dXJuOwogIHB0ci54PXB4KGUpOyBwdHIueT1weShlKTsKICBpZihNYXRoLmFicyhwdHIueC1wdHIueDApPjExIHx8IE1hdGguYWJzKHB0ci55LXB0ci55MCk+MTEpIHB0ci5tb3ZlZD10cnVlOwp9CmZ1bmN0aW9uIHB1cCgpewogIC8qIHRhcCA9IHByZXNzaW9uZSBicmV2ZSBlIGZlcm1hIOKGkiBjb2xwbyBzaW5nb2xvLCBkaXN0aW50byBkYWwgdHJhc2NpbmFtZW50byAqLwogIGlmKHB0ci5hY3RpdmUgJiYgIXB0ci5tb3ZlZCAmJiBwZXJmb3JtYW5jZS5ub3coKS1wdHIudDAgPCA0MjApCiAgICBwdHIudGFwPXt4OnB0ci54LCB5OnB0ci55fTsKICBwdHIuYWN0aXZlPWZhbHNlOwp9CmN2LmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoc3RhcnQnLHBkb3duLHtwYXNzaXZlOnRydWV9KTsKY3YuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgcG1vdmUse3Bhc3NpdmU6dHJ1ZX0pOwpjdi5hZGRFdmVudExpc3RlbmVyKCd0b3VjaGVuZCcsICBwdXAsICB7cGFzc2l2ZTp0cnVlfSk7CmN2LmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoY2FuY2VsJyxwdXAsIHtwYXNzaXZlOnRydWV9KTsKY3YuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgcGRvd24pOwphZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCBwbW92ZSk7CmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCAgIHB1cCk7CgovKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KICAgTE9HSUNBCiAgID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqLwpmdW5jdGlvbiBmaXJlKG5vdywgbG9jayl7CiAgaWYobm93LWxhc3RGaXJlIDwgRklSRV9NUykgcmV0dXJuIGZhbHNlOwogIGxhc3RGaXJlPW5vdzsKICAvKiBpbCBjb2xwbyBzaSBhZ2dhbmNpYSBhIGNpw7IgY2hlIGlsIG1pcmlubyBpbnF1YWRyYXZhIGFsbCdpc3RhbnRlIGRlbGxvCiAgICAgc3Bhcm86IHF1ZWxsbyBjaGUgdmVkaSBpbmNvcm5pY2lhdG8gw6ggcXVlbGxvIGNoZSBjb2xwaXNjaSAqLwogIGJ1bGxldHMucHVzaCh7eDpzaGlwLngsIHk6c2hpcC55LTIyLCB2eTotQlVMTEVUX1YsIGxvY2s6bG9ja3x8bnVsbH0pOwogIHNmeFNob3QoKTsKICBzaGlwLnRocj0xOwogIHJldHVybiB0cnVlOwp9CgpmdW5jdGlvbiBoaXRTaGlwKCl7CiAgaWYoc2hpcC5pbnY+MCkgcmV0dXJuOwogIGV4cGxvZGUoc2hpcC54LCBzaGlwLnksIDQwLCAnc2hpcCcpOwogIGxpdmVzLS07IHBhaW50SHVsbHMoKTsKICBpZihsaXZlczw9MCl7IGdhbWVPdmVyKCk7IH0KICBlbHNlIHsgc2hpcC54PVcvMjsgc2hpcC5pbnY9Mi40OyB0b2FzdCgnU0NBRk8gUEVSU08nKTsgfQp9CgpmdW5jdGlvbiB1cGRhdGUoZHQsIG5vdyl7CiAgdCs9ZHQ7CgogIC8qIC0tLSBuYXZlIC0tLSAqLwogIGxldCBkaXI9MDsKICBpZihrZXlzLkFycm93TGVmdHx8a2V5cy5LZXlBKSAgZGlyLT0xOwogIGlmKGtleXMuQXJyb3dSaWdodHx8a2V5cy5LZXlEKSBkaXIrPTE7CgogIGNvbnN0IGFpbWluZyA9IGFpbWluZ01vZGUoKTsgICAvLyBkYWxsZSBjYXJpY2hlIGluIHBvaTogbmllbnRlIHJhZmZpY2Egc3VsIHRyYXNjaW5hbWVudG8KCiAgLyogbGEgbWFyY2lhIGQnYWxsaW5lYW1lbnRvIGhhIGxhIHByZWNlZGVuemEsIG1hIGlsIHRyYXNjaW5hbWVudG8KICAgICBtYW51YWxlIGxhIGFubnVsbGE6IHNjaGl2YXJlIGRldmUgcmVzdGFyZSBzZW1wcmUgcG9zc2liaWxlICovCiAgaWYocHRyLmFjdGl2ZSAmJiBwdHIubW92ZWQpIEFVVE8udGFyZ2V0PW51bGw7CiAgY29uc3QgYXV0b0J1c3kgPSBBVVRPLm9uICYmIGF1dG9TdGVwKGR0LCBub3cpOwoKICBpZihhdXRvQnVzeSl7CiAgICAvKiBsYSBuYXZpY2VsbGEgw6ggZ292ZXJuYXRhIGRhIGF1dG9TdGVwOiBuZXNzdW4gYWx0cm8gY29tYW5kbyBkaSByb3R0YSAqLwogIH0gZWxzZSBpZihhaW1pbmcpewogICAgaWYoYWltTG9jaz4wKSBhaW1Mb2NrLT1kdDsKICAgIC8qIFRyYXNjaW5hbWVudG8gUkVMQVRJVk8gZSBzb2xvIGRvcG8gY2hlIGlsIGdlc3RvIMOoIHN0YXRvIHJpY29ub3NjaXV0bwogICAgICAgY29tZSB0YWxlOiBpbCBkaXRvIGNoZSBzaSByaWFwcG9nZ2lhIHBlciBzcGFyYXJlIG5vbiBzcG9zdGEgbGEgbWlyYS4KICAgICAgIERvcG8gaWwgY29scG8gaWwgbW92aW1lbnRvIGxhdGVyYWxlIHJlc3RhIGNvbmdlbGF0byBwZXIgdW4gaXN0YW50ZSwKICAgICAgIHBlcmNow6kgw6ggbMOsIGNoZSBuYXNjb25vIGdsaSBzcG9zdGFtZW50aSBpbnZvbG9udGFyaS4gKi8KICAgIGNvbnN0IGRkeCA9IChwdHIuYWN0aXZlICYmIE51bWJlci5pc0Zpbml0ZShwdHIubHgpKSA/IChwdHIueCAtIHB0ci5seCkgOiAwOwogICAgaWYocHRyLmFjdGl2ZSAmJiBwdHIubW92ZWQgJiYgYWltTG9jazw9MCAmJiBOdW1iZXIuaXNGaW5pdGUoZGR4KSl7CiAgICAgIHNoaXAueCArPSBkZHg7CiAgICAgIHNoaXAudGlsdCArPSAoY2xhbXAoZGR4Ki4wNywtMSwxKSouMzAgLSBzaGlwLnRpbHQpKk1hdGgubWluKDEsZHQqMTIpOwogICAgfSBlbHNlIHsKICAgICAgc2hpcC54ICs9IGRpcipTSElQX1YqZHQ7CiAgICAgIHNoaXAudGlsdCArPSAoZGlyKi4zMCAtIHNoaXAudGlsdCkqTWF0aC5taW4oMSxkdCoxMik7CiAgICB9CiAgfSBlbHNlIGlmKHB0ci5hY3RpdmUpewogICAgY29uc3QgZD1wdHIueC1zaGlwLng7CiAgICBzaGlwLnggKz0gY2xhbXAoZCwgLVNISVBfVipkdCwgU0hJUF9WKmR0KTsKICAgIHNoaXAudGlsdCArPSAoY2xhbXAoZC85MCwtMSwxKSouMzIgLSBzaGlwLnRpbHQpKk1hdGgubWluKDEsZHQqMTIpOwogICAgZmlyZShub3cpOwogIH0gZWxzZSB7CiAgICBzaGlwLnggKz0gZGlyKlNISVBfVipkdDsKICAgIHNoaXAudGlsdCArPSAoZGlyKi4zMCAtIHNoaXAudGlsdCkqTWF0aC5taW4oMSxkdCoxMik7CiAgfQoKICBpZihhaW1pbmcpewogICAgaWYocHRyLnRhcCl7CiAgICAgIGNvbnN0IFI9ZmlyZVJpbmcoKSwgdGR4PXB0ci50YXAueC1zaGlwLngsIHRkeT1wdHIudGFwLnktc2hpcC55OwogICAgICBjb25zdCBzdU5hdmUgPSB0ZHgqdGR4K3RkeSp0ZHkgPD0gUipSOwogICAgICBsZXQgcHJlc289bnVsbDsKICAgICAgLyogaW4gbW9kYWxpdMOgIHZpc29yZSBpbCB0b2NjbyBkZXNpZ25hOiBzaSBzY2VnbGllIGNvc2EgY29scGlyZSwKICAgICAgICAgbm9uIGRhIGRvdmUgc3BhcmFyZS4gSWwgdG9jY28gc3VsbGEgbmF2aWNlbGxhIHJlc3RhIGlsIGNvbHBvIGRpcml0dG8uICovCiAgICAgIGlmKEFVVE8ub24gJiYgIXN1TmF2ZSkgcHJlc289cGlja0F0KHB0ci50YXAueCwgcHRyLnRhcC55KTsKICAgICAgaWYocHJlc28gJiYgdGFyZ2V0QWxpdmUocHJlc28pKXsKICAgICAgICBBVVRPLnRhcmdldD1wcmVzbzsgYWltTG9jaz0wOyBzZnhMb2NrKDIpOwogICAgICB9IGVsc2UgaWYoc3VOYXZlKXsKICAgICAgICBmaXJlKG5vdywgYWltVGFyZ2V0KCkpOyBhaW1Mb2NrPS4zNDsKICAgICAgfSBlbHNlIGlmKCFBVVRPLm9uICYmIEJPTlVTLm9uICYmIEJPTlVTLnBoPT09J3BsYXknKXsKICAgICAgICBib251c01zZygnVE9DQ0EgTEEgTkFWSUNFTExBIFBFUiBTUEFSQVJFJywnNzAsMjMwLDI1NScsMS4yKTsKICAgICAgfQogICAgICBwdHIudGFwPW51bGw7CiAgICB9CiAgICAvKiBsYSB0YXN0aWVyYSBub24gc29mZnJlIGRlbCBwcm9ibGVtYTogbMOsIGlsIGZ1b2NvIMOoIGRlbGliZXJhdG8uCiAgICAgICBOZWkgc2V0dG9yaSBib251cyByZXN0YSBjb211bnF1ZSBhIGNvbHBvIHNpbmdvbG8uICovCiAgICBpZihCT05VUy5vbil7IGlmKHB0ci50YXBLZXkpIGZpcmUobm93LCBhaW1UYXJnZXQoKSk7IH0KICAgIGVsc2UgaWYoa2V5cy5TcGFjZSkgZmlyZShub3csIGFpbVRhcmdldCgpKTsKICB9IGVsc2UgewogICAgaWYoa2V5cy5TcGFjZSkgZmlyZShub3cpOwogICAgcHRyLnRhcD1udWxsOwogIH0KICBwdHIudGFwS2V5PWZhbHNlOwoKICBwdHIubHggPSBwdHIueDsgICAgICAgICAgICAgICAgICAgICAgIC8vIGJhc2VsaW5lIHNlbXByZSBhbGxpbmVhdGEsIGluIG9nbmkgbW9kYWxpdMOgCiAgaWYoIU51bWJlci5pc0Zpbml0ZShzaGlwLngpKSBzaGlwLnggPSBXLzI7ICAgLy8gcmV0ZSBkaSBzaWN1cmV6emEgY29udHJvIGkgTmFOCiAgc2hpcC54ID0gY2xhbXAoc2hpcC54LCAyMCwgVy0yMCk7CiAgc2hpcC50aHIgPSBNYXRoLm1heCgwLCBzaGlwLnRoci1kdCo0KTsKICBpZihzaGlwLmludj4wKSBzaGlwLmludi09ZHQ7CgogIC8qIC0tLSBwcm9pZXR0aWxpIC0tLSAqLwogIGZvcihsZXQgaT1idWxsZXRzLmxlbmd0aC0xO2k+PTA7aS0tKXsKICAgIGNvbnN0IGI9YnVsbGV0c1tpXTsgYi55Kz1iLnZ5KmR0OwogICAgaWYoYi5sb2NrKXsKICAgICAgLyogaWwgYmVyc2FnbGlvIHB1w7IgZXNzZXJlIHN0YXRvIGRpc3RydXR0byBvIHVzY2l0byBkaSBjYW1wbzoKICAgICAgICAgbCdvZ2dldHRvIHJlc3RhIGluIG1lbW9yaWEgbWEgw6ggbWFyY2F0bywgYWx0cmltZW50aSBpbCBjb2xwbwogICAgICAgICBpbnNlZ3VpcmViYmUgdW4gZmFudGFzbWEgKi8KICAgICAgaWYoYi5sb2NrLnRha2VuIHx8IGIubG9jay5kZWFkKSBiLmxvY2s9bnVsbDsKICAgICAgZWxzZSBiLnggKz0gY2xhbXAoYi5sb2NrLngtYi54LCAtNTYwKmR0LCA1NjAqZHQpOwogICAgfQogICAgaWYoYi55PC0yNCkgYnVsbGV0cy5zcGxpY2UoaSwxKTsKICB9CgogIC8qIC0tLSBzZXR0b3JlIG1hdGVtYXRpY286IG9uZGEgb3JkaW5hcmlhIHNvc3Blc2EgLS0tICovCiAgaWYoQk9OVVMub24peyB1cGRhdGVCb251cyhkdCk7IHJldHVybjsgfQoKICAvKiAtLS0gc3Bhd24gLS0tICovCiAgc3Bhd25ULT1kdCoxMDAwOwogIGlmKHNwYXduVDw9MCl7CiAgICBzcGF3blJvY2soKTsKICAgIGlmKGxldmVsPj0zICYmIE1hdGgucmFuZG9tKCk8LjI4KSBzcGF3blJvY2soKTsKICAgIHNwYXduVCA9IE1hdGgubWF4KDIzMCwgODgwIC0gbGV2ZWwqNzIpICogcm5kKC43NSwxLjI1KTsKICB9CgogIC8qIC0tLSBhc3Rlcm9pZGkgLS0tICovCiAgZm9yKGxldCBpPXJvY2tzLmxlbmd0aC0xO2k+PTA7aS0tKXsKICAgIGNvbnN0IGE9cm9ja3NbaV07CiAgICBhLngrPWEudngqZHQ7IGEueSs9YS52eSpkdDsgYS5yb3QrPWEudnJvdCpkdDsKICAgIGlmKGEueDxhLnJ8fGEueD5XLWEucil7IGEudngqPS0xOyBhLng9Y2xhbXAoYS54LGEucixXLWEucik7IH0KICAgIGlmKGEueS1hLnI+SCsyMCl7IGEuZGVhZD10cnVlOyByb2Nrcy5zcGxpY2UoaSwxKTsgY29udGludWU7IH0KCiAgICAvKiBjb2xwaXRvIGRhIHByb2lldHRpbGUgKi8KICAgIGxldCBkZWFkPWZhbHNlOwogICAgZm9yKGxldCBqPWJ1bGxldHMubGVuZ3RoLTE7aj49MDtqLS0pewogICAgICBjb25zdCBiPWJ1bGxldHNbal0sIGR4PWIueC1hLngsIGR5PWIueS1hLnk7CiAgICAgIGlmKGR4KmR4K2R5KmR5IDwgKGEucis0KSooYS5yKzQpKXsKICAgICAgICBidWxsZXRzLnNwbGljZShqLDEpOwogICAgICAgIGNvbnN0IGNnPWEuY2FyZ287CiAgICAgICAgY29uc3QgdG9ubyA9ICFjZz8gJ3JvY2snIDogKGNnLnQ9PT0nbXVsdCc/ICdnb2xkJyA6IGNnLnQ9PT0nbGlmZSc/ICdkYXRhJwogICAgICAgICAgICAgICAgICAgIDogY2cudD09PSdudWtlJz8gJ3NoaXAnIDogY2cudD09PSdwbHVzJz8gJ2RhdGEnIDogJ3NoaXAnKTsKICAgICAgICBleHBsb2RlKGEueCxhLnksIGNnPyBhLnIqMS4yNSA6IGEuciwgdG9ubyk7CiAgICAgICAga2lsbHMrKzsgYWRkU2NvcmUoUFRTX1BFUl9ST0NLLCB0cnVlKTsKICAgICAgICBhcHBseUNhcmdvKGEpOwogICAgICAgIGRlYWQ9dHJ1ZTsgYnJlYWs7CiAgICAgIH0KICAgIH0KICAgIGlmKGRlYWQpeyBhLmRlYWQ9dHJ1ZTsgcm9ja3Muc3BsaWNlKGksMSk7IGNvbnRpbnVlOyB9CgogICAgLyogaW1wYXR0byBzdWxsYSBuYXZlICovCiAgICBjb25zdCBkeD1zaGlwLngtYS54LCBkeT1zaGlwLnktYS55LCBycj1hLnIrc2hpcC5yOwogICAgaWYoc2hpcC5pbnY8PTAgJiYgZHgqZHgrZHkqZHkgPCBycipycil7CiAgICAgIGV4cGxvZGUoYS54LGEueSxhLnIsJ3JvY2snKTsKICAgICAgYS5kZWFkPXRydWU7IHJvY2tzLnNwbGljZShpLDEpOwogICAgICBoaXRTaGlwKCk7CiAgICB9CiAgfQp9CgpmdW5jdGlvbiByZW5kZXIoZHQpewogIC8qIElsIGNvcnBvIMOoIHJhY2NoaXVzbyBpbiB0cnkvZmluYWxseTogc2UgdW4gZnJhbWUgc29sbGV2YSB1bidlY2NlemlvbmUsCiAgICAgbG8gc3RhY2sgZGVsIGNhbnZhcyBkZXZlIGNvbXVucXVlIHRvcm5hcmUgaW4gcGFyaS4gU2VuemEgcXVlc3RhIHJldGUgdW4KICAgICBzaW5nb2xvIGVycm9yZSBmYSBhY2N1bXVsYXJlIHRyYXNsYXppb25pIGEgb2duaSBmcmFtZSBlIGwnaW1tYWdpbmUKICAgICBkZWdlbmVyYSBpbnZlY2UgZGkgbGltaXRhcnNpIGEgc2FsdGFyZSB1biBmb3RvZ3JhbW1hLiAqLwogIGN0eC5zYXZlKCk7CiAgdHJ5eyByZW5kZXJTY2VuZShkdCk7IH0KICBmaW5hbGx5eyBjdHgucmVzdG9yZSgpOyBjdHguc2V0VHJhbnNmb3JtKERQUiwwLDAsRFBSLDAsMCk7IH0KCiAgaWYoZmxhc2g+MCl7CiAgICBjdHguZmlsbFN0eWxlPWByZ2JhKDI1NSwyMzgsMjA2LCR7Zmxhc2gqLjU1fSlgOwogICAgY3R4LmZpbGxSZWN0KDAsMCxXLEgpOwogICAgZmxhc2g9TWF0aC5tYXgoMCxmbGFzaC1kdCo0LjIpOwogICAgaWYoIU51bWJlci5pc0Zpbml0ZShmbGFzaCkpIGZsYXNoPTA7CiAgfQp9CgpmdW5jdGlvbiByZW5kZXJTY2VuZShkdCl7CiAgLyogc2ZvbmRvICovCiAgaWYoc2hha2U+MCl7CiAgICBjdHgudHJhbnNsYXRlKHJuZCgtc2hha2Usc2hha2UpKi41LCBybmQoLXNoYWtlLHNoYWtlKSouNSk7CiAgICBzaGFrZSA9IE1hdGgubWF4KDAsIHNoYWtlIC0gZHQqNzApOwogIH0KICBjdHguZmlsbFN0eWxlPScjMDUwNjBkJzsgY3R4LmZpbGxSZWN0KC00MCwtNDAsVys4MCxIKzgwKTsKICBjb25zdCBnPWN0eC5jcmVhdGVSYWRpYWxHcmFkaWVudChXLzIsLUgqLjIsMTAsVy8yLEgqLjM1LE1hdGgubWF4KFcsSCkpOwogIGcuYWRkQ29sb3JTdG9wKDAsJ3JnYmEoMzAsNTIsMTIwLC40MiknKTsgZy5hZGRDb2xvclN0b3AoMSwncmdiYSg0LDUsMTIsMCknKTsKICBjdHguZmlsbFN0eWxlPWc7IGN0eC5maWxsUmVjdCgtNDAsLTQwLFcrODAsSCs4MCk7CgogIGNvbnN0IG11bCA9IHNwZWVkTXVsKCk7CiAgZHJhd0FieXNzKGR0LCBtdWwpOwoKICAvKiBwaWFubyBkZWxsZSBvbWJyZTogc290dG8gYWdsaSBvZ2dldHRpLCBzb3ByYSBhbGwnYWJpc3NvICovCiAgZm9yKGxldCBpPTA7aTxyb2Nrcy5sZW5ndGg7aSsrKSBzaGFkb3dSb2NrKHJvY2tzW2ldKTsKICBpZihzaGlwICYmIHNoaXAuYWxpdmUpIHNoYWRvd1NoaXAoc2hpcCk7CgogIGZvcihsZXQgaT0wO2k8cm9ja3MubGVuZ3RoO2krKykgZHJhd1JvY2socm9ja3NbaV0pOwogIGlmKEJPTlVTLm9uKSBkcmF3Qm9udXNXb3JsZCgpOwogIGVsc2UgaWYoYWltaW5nTW9kZSgpKSBkcmF3QWltKCk7CiAgZHJhd0F1dG9Mb2NrKCk7CgogIC8qIHByb2lldHRpbGkgKi8KICBjdHguc2F2ZSgpOyBjdHguZ2xvYmFsQ29tcG9zaXRlT3BlcmF0aW9uPSdsaWdodGVyJzsKICBmb3IobGV0IGk9MDtpPGJ1bGxldHMubGVuZ3RoO2krKyl7CiAgICBjb25zdCBiPWJ1bGxldHNbaV07CiAgICBjb25zdCBiZz1jdHguY3JlYXRlTGluZWFyR3JhZGllbnQoYi54LGIueS0xNixiLngsYi55KzgpOwogICAgYmcuYWRkQ29sb3JTdG9wKDAsJ3JnYmEoNzAsMjMwLDI1NSwwKScpOwogICAgYmcuYWRkQ29sb3JTdG9wKC42LCdyZ2JhKDE2MCwyNDYsMjU1LC45NSknKTsKICAgIGJnLmFkZENvbG9yU3RvcCgxLCdyZ2JhKDI1NSwyNTUsMjU1LDEpJyk7CiAgICBjdHguZmlsbFN0eWxlPWJnOyBjdHguZmlsbFJlY3QoYi54LTEuNiwgYi55LTE2LCAzLjIsIDI0KTsKICAgIGN0eC5maWxsU3R5bGU9J3JnYmEoNzAsMjMwLDI1NSwuMzIpJzsgY3R4LmJlZ2luUGF0aCgpOyBjdHguYXJjKGIueCxiLnksNywwLFRBVSk7IGN0eC5maWxsKCk7CiAgfQogIGN0eC5yZXN0b3JlKCk7CgogIGlmKHNoaXAgJiYgc2hpcC5hbGl2ZSkgZHJhd1NoaXAoc2hpcCk7CiAgZHJhd0ZYKGR0KTsKICBkcmF3RmxvYXRzKGR0KTsKICBkcmF3Tm90aWNlKGR0KTsKICBpZihCT05VUy5vbikgZHJhd0JvbnVzSFVEKCk7CiAgZHJhd01vdGVzKGR0LCBtdWwpOwp9CgovKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KICAgTE9PUAogICA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gKi8KbGV0IHByZXY9MDsKZnVuY3Rpb24gbG9vcCh0cyl7CiAgcmVxdWVzdEFuaW1hdGlvbkZyYW1lKGxvb3ApOwogIGlmKCFwcmV2KSBwcmV2PXRzOwogIGxldCBkdD0odHMtcHJldikvMTAwMDsgcHJldj10czsKICBpZihkdD4uMDUpIGR0PS4wNTsgICAgICAgICAgICAgICAgICAgIC8vIG5pZW50ZSBzYWx0aSBkb3BvIHVuIHRhYiBpbiBiYWNrZ3JvdW5kCiAgaWYocnVubmluZykgdXBkYXRlKGR0LCB0cyk7CiAgcmVuZGVyKGR0KTsKfQpyZXF1ZXN0QW5pbWF0aW9uRnJhbWUobG9vcCk7CgovKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KICAgRkxVU1NPIFBBUlRJVEEKICAgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICovCmZ1bmN0aW9uIHN0YXJ0KCl7CiAgc2NvcmU9MDsgZ2F0ZVByb2c9MDsga2lsbHM9MDsgbGV2ZWw9MDsgbGl2ZXM9TElWRVM7IG92ZXI9ZmFsc2U7CiAgYnVsbGV0cy5sZW5ndGg9cm9ja3MubGVuZ3RoPXNwYXJrcy5sZW5ndGg9ZGVicmlzLmxlbmd0aD1zbW9rZS5sZW5ndGg9YmFsbHMubGVuZ3RoPXdhdmVzLmxlbmd0aD1mbG9hdHMubGVuZ3RoPTA7CiAgQk9OVVMub249ZmFsc2U7IEJPTlVTLnBvZHMubGVuZ3RoPTA7IEJPTlVTLndyZWNrcy5sZW5ndGg9MDsgQk9OVVMubXNnVD0wOwogIHB0ci50YXA9bnVsbDsgcHRyLnRhcEtleT1mYWxzZTsgcHRyLmFjdGl2ZT1mYWxzZTsgYWltTG9jaz0wOyBub3RpY2VUPTA7IEFVVE8udGFyZ2V0PW51bGw7CiAgc2hha2U9MDsgZmxhc2g9MDsgc3Bhd25UPTQwMDsgbGFzdEZpcmU9MDsKICBzaGlwPW1ha2VTaGlwKCk7CiAgZWxTY29yZS50ZXh0Q29udGVudD0nMCc7IGVsU2NvcmUuc3R5bGUuY29sb3I9Jyc7IGVsU2NvcmUuc3R5bGUudGV4dFNoYWRvdz0nJzsgZWxMZXZlbC50ZXh0Q29udGVudD0nMSc7CiAgZWxUaWNrZXIuaW5uZXJIVE1MPSdTRVRUT1JFIDxiPicrc2tpbkZvcigwKS5ub21lKyc8L2I+IMK3IENBUklDSEUgQVRUSVZFIDxiPkRBTCBMSVZFTExPICcrKENBUkdPX0xWKzEpKyc8L2I+IMK3IDE1MCBQVCAvIElNUEFUVE8nOyBlbEdhdWdlLnN0eWxlLndpZHRoPScwJSc7CiAgcGFpbnRIdWxscygpOwogIGVsVmVpbC5jbGFzc0xpc3QuYWRkKCdoaWRlJyk7CiAgcnVubmluZz10cnVlOwogIGF1ZGlvKCk7CiAgbXVzaWNLaWNrKCk7Cn0KZnVuY3Rpb24gZ2FtZU92ZXIoKXsKICBydW5uaW5nPWZhbHNlOyBvdmVyPXRydWU7CiAgQk9OVVMub249ZmFsc2U7IEJPTlVTLnBvZHMubGVuZ3RoPTA7IEJPTlVTLndyZWNrcy5sZW5ndGg9MDsgQk9OVVMubXNnVD0wOwogIGNvbnN0IGx2bD1sZXZlbCsxOwogIGVsSDEuaW5uZXJIVE1MPSc8c3Bhbj5NaXNzaW9uZTwvc3Bhbj5DT05DTFVTQSc7CiAgZWxGaW5hbC5zdHlsZS5kaXNwbGF5PSdibG9jayc7CiAgZWxGaW5hbC50ZXh0Q29udGVudD1zY29yZTsKICBlbEZpbmFsLnN0eWxlLmNvbG9yID0gc2NvcmU8MCA/ICcjZmYyZTZiJyA6ICcnOwogIGVsSGludC5pbm5lckhUTUw9J0xpdmVsbG8gcmFnZ2l1bnRvIDxlbT4nK2x2bCsnPC9lbT4gwrcgYXN0ZXJvaWRpIGRpc3RydXR0aSA8ZW0+JytraWxscysnPC9lbT48YnI+JysKICAgICAgICAgICAgICAgICAgICc8ZW0+U3BhemlvPC9lbT4gbyBpbCBwdWxzYW50ZSBwZXIgcmlwYXJ0aXJlJzsKICBlbEJ0bi50ZXh0Q29udGVudD0nUmlwcm92YSc7CiAgZWxWZWlsLmNsYXNzTGlzdC5yZW1vdmUoJ2hpZGUnKTsKfQplbEJ0bi5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHN0YXJ0KTsKCnBhaW50SHVsbHMoKTsKcmVzaXplKCk7Ci8qIGxhIGNvbG9ubmEgc29ub3JhIMOoIHVuIGFjY2Vzc29yaW86IHVuIHN1byBndWFzdG8gbm9uIGRldmUKICAgaW1wZWRpcmUgbCdhdnZpbyBkZWwgZ2lvY28gKi8KdHJ5eyBtdXNpY0luaXQoKTsgfWNhdGNoKGUpeyB0cnl7IG11c2ljS2lsbCgpOyB9Y2F0Y2goXyl7fSB9Ci8qIGFuY2hlIGkgY29tYW5kaSBhY2Nlc3Nvcmkgbm9uIGRldm9ubyBwb3RlciBpbXBlZGlyZSBsJ2F2dmlvICovCnRyeXsgcGFpbnRWaXNvcigpOyBpZihlbFZidG4pIGVsVmJ0bi5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHZpc29yVG9nZ2xlKTsgfWNhdGNoKGUpe30KdHJ5eyBzcGxhc2hJbml0KCk7IH1jYXRjaChlKXsgY29uc3Qgc3A9ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3NwbGFzaCcpOyBpZihzcCkgc3AuY2xhc3NMaXN0LmFkZCgnZ29uZScpOyB9Cn0pKCk7Cjwvc2NyaXB0Pgo8L2JvZHk+CjwvaHRtbD4K"))));</script>
26 visite

Commenti

Nessun commento, per ora.

Per commentare serve un accesso. Qui siamo tutti tecnici e colleghi!

Accedi per commentare

Continua

Altri strumentidello stesso genere

Tutto il codice

BASH MIT

Syskiller

Report FULL SYSTEM single bash

Vi raccoglie in un unico report load, cpu, ram, swap, dischi, inode, processi pesanti, porte in ascolto, connessioni, servizi falliti, errori kernel, OOM killer, ultimi login, file grossi e directory che vi stanno esplodendo. Utile per poi spararlo via alla AI preferita che in tempo zero fà in 1 minuto quello che facevamo noi prima in 2 ore... :-)) ** Sempre prestando occhio anche a cosa fà la AI, ovviamente **

18 visite

BASH MIT

Monitor integrità directory

Monitor files nuovi/eliminati/modificati

Vi è mai capitato di dovervi scansionare un sacco di directory e files per poi accorgervi che ad essere broken era un symlink o maree di inodes? Questo potrebbe essere lo strumento che fà per voi. Facile da usare, veloce e sopratutto và diritto al punto.

16 visite

BASH MIT

Backup incrementale con rotazione (bash)

Un solo file, nessuna dipendenza.

Vi serve un bash veloce per un backup incrementale rapido, sicuro e senza troppe pretese? Questo bash l'ho usato varie volte a chiusura lavoro per il backup di folder sulle quali ci ritornavo sporadicamente, ma dove era necessario sapere sempre dove ci si era fermati. Un bash senza fronzoli ma che fà il suo lavoro.

24 visite

Scarica