From d6f5f613fbaf5aa0afdab6acc00056451310f9d7 Mon Sep 17 00:00:00 2001 From: serkanozer Date: Fri, 7 Jul 2017 02:03:00 +0300 Subject: [PATCH 1/2] Trim search text from beginning and the end. (fixes #1861) --- examples/dist/app.js | 13537 +++++++------- examples/dist/bundle.js | 3618 ++-- examples/dist/common.js | 27246 ++++++++++++++-------------- examples/dist/standalone.js | 3253 ++-- src/Select.js | 3 + src/utils/defaultFilterOptions.js | 7 + src/utils/trim.js | 10 + test/Select-test.js | 36 + 8 files changed, 24238 insertions(+), 23472 deletions(-) create mode 100644 src/utils/trim.js diff --git a/examples/dist/app.js b/examples/dist/app.js index 276ddb6683..673e9674e9 100644 --- a/examples/dist/app.js +++ b/examples/dist/app.js @@ -522,7 +522,7 @@ function arrowRenderer() { module.exports = UsersField; -},{"../data/users":15,"create-react-class":undefined,"prop-types":undefined,"react":undefined,"react-gravatar":31,"react-select":undefined}],6:[function(require,module,exports){ +},{"../data/users":15,"create-react-class":undefined,"prop-types":undefined,"react":undefined,"react-gravatar":21,"react-select":undefined}],6:[function(require,module,exports){ 'use strict'; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } @@ -613,7 +613,7 @@ var DisabledUpsellOptions = (0, _createReactClass2['default'])({ }); module.exports = DisabledUpsellOptions; -},{"create-react-class":undefined,"prop-types":undefined,"react":undefined,"react-highlight-words":32,"react-select":undefined}],7:[function(require,module,exports){ +},{"create-react-class":undefined,"prop-types":undefined,"react":undefined,"react-highlight-words":30,"react-select":undefined}],7:[function(require,module,exports){ 'use strict'; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } @@ -761,7 +761,7 @@ var GithubUsers = (0, _createReactClass2['default'])({ module.exports = GithubUsers; -},{"create-react-class":undefined,"isomorphic-fetch":23,"prop-types":undefined,"react":undefined,"react-select":undefined}],8:[function(require,module,exports){ +},{"create-react-class":undefined,"isomorphic-fetch":16,"prop-types":undefined,"react":undefined,"react-select":undefined}],8:[function(require,module,exports){ 'use strict'; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } @@ -1212,7 +1212,7 @@ var CitiesField = (0, _createReactClass2['default'])({ module.exports = CitiesField; -},{"../data/cities":12,"create-react-class":undefined,"react":undefined,"react-virtualized-select":35}],12:[function(require,module,exports){ +},{"../data/cities":12,"create-react-class":undefined,"react":undefined,"react-virtualized-select":33}],12:[function(require,module,exports){ 'use strict'; exports.CITIES = [{ name: 'Abilene' }, { name: 'Addison' }, { name: 'Akron' }, { name: 'Alameda' }, { name: 'Albany' }, { name: 'Albany' }, { name: 'Albany' }, { name: 'Albuquerque' }, { name: 'Alexandria' }, { name: 'Alexandria' }, { name: 'Alhambra' }, { name: 'Aliso Viejo' }, { name: 'Allen' }, { name: 'Allentown' }, { name: 'Alpharetta' }, { name: 'Altamonte Springs' }, { name: 'Altoona' }, { name: 'Amarillo' }, { name: 'Ames' }, { name: 'Anaheim' }, { name: 'Anchorage' }, { name: 'Anderson' }, { name: 'Ankeny' }, { name: 'Ann Arbor' }, { name: 'Annapolis' }, { name: 'Antioch' }, { name: 'Apache Junction' }, { name: 'Apex' }, { name: 'Apopka' }, { name: 'Apple Valley' }, { name: 'Apple Valley' }, { name: 'Appleton' }, { name: 'Arcadia' }, { name: 'Arlington' }, { name: 'Arlington Heights' }, { name: 'Arvada' }, { name: 'Asheville' }, { name: 'Athens-Clarke County' }, { name: 'Atlanta' }, { name: 'Atlantic City' }, { name: 'Attleboro' }, { name: 'Auburn' }, { name: 'Auburn' }, { name: 'Augusta-Richmond County' }, { name: 'Aurora' }, { name: 'Aurora' }, { name: 'Austin' }, { name: 'Aventura' }, { name: 'Avondale' }, { name: 'Azusa' }, { name: 'Bakersfield' }, { name: 'Baldwin Park' }, { name: 'Baltimore' }, { name: 'Barnstable Town' }, { name: 'Bartlett' }, { name: 'Bartlett' }, { name: 'Baton Rouge' }, { name: 'Battle Creek' }, { name: 'Bayonne' }, { name: 'Baytown' }, { name: 'Beaumont' }, { name: 'Beaumont' }, { name: 'Beavercreek' }, { name: 'Beaverton' }, { name: 'Bedford' }, { name: 'Bell Gardens' }, { name: 'Belleville' }, { name: 'Bellevue' }, { name: 'Bellevue' }, { name: 'Bellflower' }, { name: 'Bellingham' }, { name: 'Beloit' }, { name: 'Bend' }, { name: 'Bentonville' }, { name: 'Berkeley' }, { name: 'Berwyn' }, { name: 'Bethlehem' }, { name: 'Beverly' }, { name: 'Billings' }, { name: 'Biloxi' }, { name: 'Binghamton' }, { name: 'Birmingham' }, { name: 'Bismarck' }, { name: 'Blacksburg' }, { name: 'Blaine' }, { name: 'Bloomington' }, { name: 'Bloomington' }, { name: 'Bloomington' }, { name: 'Blue Springs' }, { name: 'Boca Raton' }, { name: 'Boise City' }, { name: 'Bolingbrook' }, { name: 'Bonita Springs' }, { name: 'Bossier City' }, { name: 'Boston' }, { name: 'Boulder' }, { name: 'Bountiful' }, { name: 'Bowie' }, { name: 'Bowling Green' }, { name: 'Boynton Beach' }, { name: 'Bozeman' }, { name: 'Bradenton' }, { name: 'Brea' }, { name: 'Bremerton' }, { name: 'Brentwood' }, { name: 'Brentwood' }, { name: 'Bridgeport' }, { name: 'Bristol' }, { name: 'Brockton' }, { name: 'Broken Arrow' }, { name: 'Brookfield' }, { name: 'Brookhaven' }, { name: 'Brooklyn Park' }, { name: 'Broomfield' }, { name: 'Brownsville' }, { name: 'Bryan' }, { name: 'Buckeye' }, { name: 'Buena Park' }, { name: 'Buffalo' }, { name: 'Buffalo Grove' }, { name: 'Bullhead City' }, { name: 'Burbank' }, { name: 'Burien' }, { name: 'Burleson' }, { name: 'Burlington' }, { name: 'Burlington' }, { name: 'Burnsville' }, { name: 'Caldwell' }, { name: 'Calexico' }, { name: 'Calumet City' }, { name: 'Camarillo' }, { name: 'Cambridge' }, { name: 'Camden' }, { name: 'Campbell' }, { name: 'Canton' }, { name: 'Cape Coral' }, { name: 'Cape Girardeau' }, { name: 'Carlsbad' }, { name: 'Carmel' }, { name: 'Carol Stream' }, { name: 'Carpentersville' }, { name: 'Carrollton' }, { name: 'Carson' }, { name: 'Carson City' }, { name: 'Cary' }, { name: 'Casa Grande' }, { name: 'Casper' }, { name: 'Castle Rock' }, { name: 'Cathedral City' }, { name: 'Cedar Falls' }, { name: 'Cedar Hill' }, { name: 'Cedar Park' }, { name: 'Cedar Rapids' }, { name: 'Centennial' }, { name: 'Ceres' }, { name: 'Cerritos' }, { name: 'Champaign' }, { name: 'Chandler' }, { name: 'Chapel Hill' }, { name: 'Charleston' }, { name: 'Charleston' }, { name: 'Charlotte' }, { name: 'Charlottesville' }, { name: 'Chattanooga' }, { name: 'Chelsea' }, { name: 'Chesapeake' }, { name: 'Chesterfield' }, { name: 'Cheyenne' }, { name: 'Chicago' }, { name: 'Chico' }, { name: 'Chicopee' }, { name: 'Chino' }, { name: 'Chino Hills' }, { name: 'Chula Vista' }, { name: 'Cicero' }, { name: 'Cincinnati' }, { name: 'Citrus Heights' }, { name: 'Clarksville' }, { name: 'Clearwater' }, { name: 'Cleveland' }, { name: 'Cleveland' }, { name: 'Cleveland Heights' }, { name: 'Clifton' }, { name: 'Clovis' }, { name: 'Clovis' }, { name: 'Coachella' }, { name: 'Coconut Creek' }, { name: 'Coeur d\'Alene' }, { name: 'College Station' }, { name: 'Collierville' }, { name: 'Colorado Springs' }, { name: 'Colton' }, { name: 'Columbia' }, { name: 'Columbia' }, { name: 'Columbus' }, { name: 'Columbus' }, { name: 'Columbus' }, { name: 'Commerce City' }, { name: 'Compton' }, { name: 'Concord' }, { name: 'Concord' }, { name: 'Concord' }, { name: 'Conroe' }, { name: 'Conway' }, { name: 'Coon Rapids' }, { name: 'Coppell' }, { name: 'Coral Gables' }, { name: 'Coral Springs' }, { name: 'Corona' }, { name: 'Corpus Christi' }, { name: 'Corvallis' }, { name: 'Costa Mesa' }, { name: 'Council Bluffs' }, { name: 'Covina' }, { name: 'Covington' }, { name: 'Cranston' }, { name: 'Crystal Lake' }, { name: 'Culver City' }, { name: 'Cupertino' }, { name: 'Cutler Bay' }, { name: 'Cuyahoga Falls' }, { name: 'Cypress' }, { name: 'Dallas' }, { name: 'Daly City' }, { name: 'Danbury' }, { name: 'Danville' }, { name: 'Danville' }, { name: 'Davenport' }, { name: 'Davie' }, { name: 'Davis' }, { name: 'Dayton' }, { name: 'Daytona Beach' }, { name: 'DeKalb' }, { name: 'DeSoto' }, { name: 'Dearborn' }, { name: 'Dearborn Heights' }, { name: 'Decatur' }, { name: 'Decatur' }, { name: 'Deerfield Beach' }, { name: 'Delano' }, { name: 'Delray Beach' }, { name: 'Deltona' }, { name: 'Denton' }, { name: 'Denver' }, { name: 'Des Moines' }, { name: 'Des Plaines' }, { name: 'Detroit' }, { name: 'Diamond Bar' }, { name: 'Doral' }, { name: 'Dothan' }, { name: 'Dover' }, { name: 'Downers Grove' }, { name: 'Downey' }, { name: 'Draper' }, { name: 'Dublin' }, { name: 'Dublin' }, { name: 'Dubuque' }, { name: 'Duluth' }, { name: 'Duncanville' }, { name: 'Dunwoody' }, { name: 'Durham' }, { name: 'Eagan' }, { name: 'East Lansing' }, { name: 'East Orange' }, { name: 'East Providence' }, { name: 'Eastvale' }, { name: 'Eau Claire' }, { name: 'Eden Prairie' }, { name: 'Edina' }, { name: 'Edinburg' }, { name: 'Edmond' }, { name: 'Edmonds' }, { name: 'El Cajon' }, { name: 'El Centro' }, { name: 'El Monte' }, { name: 'El Paso' }, { name: 'Elgin' }, { name: 'Elizabeth' }, { name: 'Elk Grove' }, { name: 'Elkhart' }, { name: 'Elmhurst' }, { name: 'Elyria' }, { name: 'Encinitas' }, { name: 'Enid' }, { name: 'Erie' }, { name: 'Escondido' }, { name: 'Euclid' }, { name: 'Eugene' }, { name: 'Euless' }, { name: 'Evanston' }, { name: 'Evansville' }, { name: 'Everett' }, { name: 'Everett' }, { name: 'Fairfield' }, { name: 'Fairfield' }, { name: 'Fall River' }, { name: 'Fargo' }, { name: 'Farmington' }, { name: 'Farmington Hills' }, { name: 'Fayetteville' }, { name: 'Fayetteville' }, { name: 'Federal Way' }, { name: 'Findlay' }, { name: 'Fishers' }, { name: 'Fitchburg' }, { name: 'Flagstaff' }, { name: 'Flint' }, { name: 'Florence' }, { name: 'Florence' }, { name: 'Florissant' }, { name: 'Flower Mound' }, { name: 'Folsom' }, { name: 'Fond du Lac' }, { name: 'Fontana' }, { name: 'Fort Collins' }, { name: 'Fort Lauderdale' }, { name: 'Fort Myers' }, { name: 'Fort Pierce' }, { name: 'Fort Smith' }, { name: 'Fort Wayne' }, { name: 'Fort Worth' }, { name: 'Fountain Valley' }, { name: 'Franklin' }, { name: 'Frederick' }, { name: 'Freeport' }, { name: 'Fremont' }, { name: 'Fresno' }, { name: 'Friendswood' }, { name: 'Frisco' }, { name: 'Fullerton' }, { name: 'Gainesville' }, { name: 'Gaithersburg' }, { name: 'Galveston' }, { name: 'Garden Grove' }, { name: 'Gardena' }, { name: 'Garland' }, { name: 'Gary' }, { name: 'Gastonia' }, { name: 'Georgetown' }, { name: 'Germantown' }, { name: 'Gilbert' }, { name: 'Gilroy' }, { name: 'Glendale' }, { name: 'Glendale' }, { name: 'Glendora' }, { name: 'Glenview' }, { name: 'Goodyear' }, { name: 'Goose Creek' }, { name: 'Grand Forks' }, { name: 'Grand Island' }, { name: 'Grand Junction' }, { name: 'Grand Prairie' }, { name: 'Grand Rapids' }, { name: 'Grapevine' }, { name: 'Great Falls' }, { name: 'Greeley' }, { name: 'Green Bay' }, { name: 'Greenacres' }, { name: 'Greenfield' }, { name: 'Greensboro' }, { name: 'Greenville' }, { name: 'Greenville' }, { name: 'Greenwood' }, { name: 'Gresham' }, { name: 'Grove City' }, { name: 'Gulfport' }, { name: 'Hackensack' }, { name: 'Hagerstown' }, { name: 'Hallandale Beach' }, { name: 'Haltom City' }, { name: 'Hamilton' }, { name: 'Hammond' }, { name: 'Hampton' }, { name: 'Hanford' }, { name: 'Hanover Park' }, { name: 'Harlingen' }, { name: 'Harrisburg' }, { name: 'Harrisonburg' }, { name: 'Hartford' }, { name: 'Hattiesburg' }, { name: 'Haverhill' }, { name: 'Hawthorne' }, { name: 'Hayward' }, { name: 'Hemet' }, { name: 'Hempstead' }, { name: 'Henderson' }, { name: 'Hendersonville' }, { name: 'Hesperia' }, { name: 'Hialeah' }, { name: 'Hickory' }, { name: 'High Point' }, { name: 'Highland' }, { name: 'Hillsboro' }, { name: 'Hilton Head Island' }, { name: 'Hoboken' }, { name: 'Hoffman Estates' }, { name: 'Hollywood' }, { name: 'Holyoke' }, { name: 'Homestead' }, { name: 'Honolulu' }, { name: 'Hoover' }, { name: 'Houston' }, { name: 'Huber Heights' }, { name: 'Huntersville' }, { name: 'Huntington' }, { name: 'Huntington Beach' }, { name: 'Huntington Park' }, { name: 'Huntsville' }, { name: 'Huntsville' }, { name: 'Hurst' }, { name: 'Hutchinson' }, { name: 'Idaho Falls' }, { name: 'Independence' }, { name: 'Indianapolis' }, { name: 'Indio' }, { name: 'Inglewood' }, { name: 'Iowa City' }, { name: 'Irvine' }, { name: 'Irving' }, { name: 'Jackson' }, { name: 'Jackson' }, { name: 'Jacksonville' }, { name: 'Jacksonville' }, { name: 'Janesville' }, { name: 'Jefferson City' }, { name: 'Jeffersonville' }, { name: 'Jersey City' }, { name: 'Johns Creek' }, { name: 'Johnson City' }, { name: 'Joliet' }, { name: 'Jonesboro' }, { name: 'Joplin' }, { name: 'Jupiter' }, { name: 'Jurupa Valley' }, { name: 'Kalamazoo' }, { name: 'Kannapolis' }, { name: 'Kansas City' }, { name: 'Kansas City' }, { name: 'Kearny' }, { name: 'Keizer' }, { name: 'Keller' }, { name: 'Kenner' }, { name: 'Kennewick' }, { name: 'Kenosha' }, { name: 'Kent' }, { name: 'Kentwood' }, { name: 'Kettering' }, { name: 'Killeen' }, { name: 'Kingsport' }, { name: 'Kirkland' }, { name: 'Kissimmee' }, { name: 'Knoxville' }, { name: 'Kokomo' }, { name: 'La Crosse' }, { name: 'La Habra' }, { name: 'La Mesa' }, { name: 'La Mirada' }, { name: 'La Puente' }, { name: 'La Quinta' }, { name: 'Lacey' }, { name: 'Lafayette' }, { name: 'Lafayette' }, { name: 'Laguna Niguel' }, { name: 'Lake Charles' }, { name: 'Lake Elsinore' }, { name: 'Lake Forest' }, { name: 'Lake Havasu City' }, { name: 'Lake Oswego' }, { name: 'Lakeland' }, { name: 'Lakeville' }, { name: 'Lakewood' }, { name: 'Lakewood' }, { name: 'Lakewood' }, { name: 'Lakewood' }, { name: 'Lancaster' }, { name: 'Lancaster' }, { name: 'Lancaster' }, { name: 'Lancaster' }, { name: 'Lansing' }, { name: 'Laredo' }, { name: 'Largo' }, { name: 'Las Cruces' }, { name: 'Las Vegas' }, { name: 'Lauderhill' }, { name: 'Lawrence' }, { name: 'Lawrence' }, { name: 'Lawrence' }, { name: 'Lawton' }, { name: 'Layton' }, { name: 'League City' }, { name: 'Lee\'s Summit' }, { name: 'Leesburg' }, { name: 'Lehi' }, { name: 'Lenexa' }, { name: 'Leominster' }, { name: 'Lewisville' }, { name: 'Lexington-Fayette' }, { name: 'Lima' }, { name: 'Lincoln' }, { name: 'Lincoln' }, { name: 'Lincoln Park' }, { name: 'Linden' }, { name: 'Little Rock' }, { name: 'Littleton' }, { name: 'Livermore' }, { name: 'Livonia' }, { name: 'Lodi' }, { name: 'Logan' }, { name: 'Lombard' }, { name: 'Lompoc' }, { name: 'Long Beach' }, { name: 'Longmont' }, { name: 'Longview' }, { name: 'Lorain' }, { name: 'Los Angeles' }, { name: 'Louisville/Jefferson County' }, { name: 'Loveland' }, { name: 'Lowell' }, { name: 'Lubbock' }, { name: 'Lynchburg' }, { name: 'Lynn' }, { name: 'Lynwood' }, { name: 'Macon' }, { name: 'Madera' }, { name: 'Madison' }, { name: 'Madison' }, { name: 'Malden' }, { name: 'Manassas' }, { name: 'Manchester' }, { name: 'Manhattan' }, { name: 'Mankato' }, { name: 'Mansfield' }, { name: 'Mansfield' }, { name: 'Manteca' }, { name: 'Maple Grove' }, { name: 'Maplewood' }, { name: 'Marana' }, { name: 'Margate' }, { name: 'Maricopa' }, { name: 'Marietta' }, { name: 'Marlborough' }, { name: 'Martinez' }, { name: 'Marysville' }, { name: 'McAllen' }, { name: 'McKinney' }, { name: 'Medford' }, { name: 'Medford' }, { name: 'Melbourne' }, { name: 'Memphis' }, { name: 'Menifee' }, { name: 'Mentor' }, { name: 'Merced' }, { name: 'Meriden' }, { name: 'Meridian' }, { name: 'Meridian' }, { name: 'Mesa' }, { name: 'Mesquite' }, { name: 'Methuen' }, { name: 'Miami' }, { name: 'Miami Beach' }, { name: 'Miami Gardens' }, { name: 'Middletown' }, { name: 'Middletown' }, { name: 'Midland' }, { name: 'Midland' }, { name: 'Midwest City' }, { name: 'Milford' }, { name: 'Milpitas' }, { name: 'Milwaukee' }, { name: 'Minneapolis' }, { name: 'Minnetonka' }, { name: 'Minot' }, { name: 'Miramar' }, { name: 'Mishawaka' }, { name: 'Mission' }, { name: 'Mission Viejo' }, { name: 'Missoula' }, { name: 'Missouri City' }, { name: 'Mobile' }, { name: 'Modesto' }, { name: 'Moline' }, { name: 'Monroe' }, { name: 'Monrovia' }, { name: 'Montclair' }, { name: 'Montebello' }, { name: 'Monterey Park' }, { name: 'Montgomery' }, { name: 'Moore' }, { name: 'Moorhead' }, { name: 'Moreno Valley' }, { name: 'Morgan Hill' }, { name: 'Mount Pleasant' }, { name: 'Mount Prospect' }, { name: 'Mount Vernon' }, { name: 'Mountain View' }, { name: 'Muncie' }, { name: 'Murfreesboro' }, { name: 'Murray' }, { name: 'Murrieta' }, { name: 'Muskegon' }, { name: 'Muskogee' }, { name: 'Nampa' }, { name: 'Napa' }, { name: 'Naperville' }, { name: 'Nashua' }, { name: 'Nashville-Davidson' }, { name: 'National City' }, { name: 'New Bedford' }, { name: 'New Berlin' }, { name: 'New Braunfels' }, { name: 'New Britain' }, { name: 'New Brunswick' }, { name: 'New Haven' }, { name: 'New Orleans' }, { name: 'New Rochelle' }, { name: 'New York' }, { name: 'Newark' }, { name: 'Newark' }, { name: 'Newark' }, { name: 'Newport Beach' }, { name: 'Newport News' }, { name: 'Newton' }, { name: 'Niagara Falls' }, { name: 'Noblesville' }, { name: 'Norfolk' }, { name: 'Normal' }, { name: 'Norman' }, { name: 'North Charleston' }, { name: 'North Las Vegas' }, { name: 'North Lauderdale' }, { name: 'North Little Rock' }, { name: 'North Miami' }, { name: 'North Miami Beach' }, { name: 'North Port' }, { name: 'North Richland Hills' }, { name: 'Northglenn' }, { name: 'Norwalk' }, { name: 'Norwalk' }, { name: 'Norwich' }, { name: 'Novato' }, { name: 'Novi' }, { name: 'O\'Fallon' }, { name: 'Oak Lawn' }, { name: 'Oak Park' }, { name: 'Oakland' }, { name: 'Oakland Park' }, { name: 'Oakley' }, { name: 'Ocala' }, { name: 'Oceanside' }, { name: 'Ocoee' }, { name: 'Odessa' }, { name: 'Ogden' }, { name: 'Oklahoma City' }, { name: 'Olathe' }, { name: 'Olympia' }, { name: 'Omaha' }, { name: 'Ontario' }, { name: 'Orange' }, { name: 'Orem' }, { name: 'Orland Park' }, { name: 'Orlando' }, { name: 'Ormond Beach' }, { name: 'Oro Valley' }, { name: 'Oshkosh' }, { name: 'Overland Park' }, { name: 'Owensboro' }, { name: 'Oxnard' }, { name: 'Pacifica' }, { name: 'Palatine' }, { name: 'Palm Bay' }, { name: 'Palm Beach Gardens' }, { name: 'Palm Coast' }, { name: 'Palm Desert' }, { name: 'Palm Springs' }, { name: 'Palmdale' }, { name: 'Palo Alto' }, { name: 'Panama City' }, { name: 'Paramount' }, { name: 'Park Ridge' }, { name: 'Parker' }, { name: 'Parma' }, { name: 'Pasadena' }, { name: 'Pasadena' }, { name: 'Pasco' }, { name: 'Passaic' }, { name: 'Paterson' }, { name: 'Pawtucket' }, { name: 'Peabody' }, { name: 'Peachtree Corners' }, { name: 'Pearland' }, { name: 'Pembroke Pines' }, { name: 'Pensacola' }, { name: 'Peoria' }, { name: 'Peoria' }, { name: 'Perris' }, { name: 'Perth Amboy' }, { name: 'Petaluma' }, { name: 'Pflugerville' }, { name: 'Pharr' }, { name: 'Phenix City' }, { name: 'Philadelphia' }, { name: 'Phoenix' }, { name: 'Pico Rivera' }, { name: 'Pine Bluff' }, { name: 'Pinellas Park' }, { name: 'Pittsburg' }, { name: 'Pittsburgh' }, { name: 'Pittsfield' }, { name: 'Placentia' }, { name: 'Plainfield' }, { name: 'Plainfield' }, { name: 'Plano' }, { name: 'Plantation' }, { name: 'Pleasanton' }, { name: 'Plymouth' }, { name: 'Pocatello' }, { name: 'Pomona' }, { name: 'Pompano Beach' }, { name: 'Pontiac' }, { name: 'Port Arthur' }, { name: 'Port Orange' }, { name: 'Port St. Lucie' }, { name: 'Portage' }, { name: 'Porterville' }, { name: 'Portland' }, { name: 'Portland' }, { name: 'Portsmouth' }, { name: 'Poway' }, { name: 'Prescott' }, { name: 'Prescott Valley' }, { name: 'Providence' }, { name: 'Provo' }, { name: 'Pueblo' }, { name: 'Puyallup' }, { name: 'Quincy' }, { name: 'Quincy' }, { name: 'Racine' }, { name: 'Raleigh' }, { name: 'Rancho Cordova' }, { name: 'Rancho Cucamonga' }, { name: 'Rancho Palos Verdes' }, { name: 'Rancho Santa Margarita' }, { name: 'Rapid City' }, { name: 'Reading' }, { name: 'Redding' }, { name: 'Redlands' }, { name: 'Redmond' }, { name: 'Redondo Beach' }, { name: 'Redwood City' }, { name: 'Reno' }, { name: 'Renton' }, { name: 'Revere' }, { name: 'Rialto' }, { name: 'Richardson' }, { name: 'Richland' }, { name: 'Richmond' }, { name: 'Richmond' }, { name: 'Rio Rancho' }, { name: 'Riverside' }, { name: 'Riverton' }, { name: 'Roanoke' }, { name: 'Rochester' }, { name: 'Rochester' }, { name: 'Rochester Hills' }, { name: 'Rock Hill' }, { name: 'Rock Island' }, { name: 'Rockford' }, { name: 'Rocklin' }, { name: 'Rockville' }, { name: 'Rockwall' }, { name: 'Rocky Mount' }, { name: 'Rogers' }, { name: 'Rohnert Park' }, { name: 'Romeoville' }, { name: 'Rosemead' }, { name: 'Roseville' }, { name: 'Roseville' }, { name: 'Roswell' }, { name: 'Roswell' }, { name: 'Round Rock' }, { name: 'Rowlett' }, { name: 'Roy' }, { name: 'Royal Oak' }, { name: 'Sacramento' }, { name: 'Saginaw' }, { name: 'Salem' }, { name: 'Salem' }, { name: 'Salina' }, { name: 'Salinas' }, { name: 'Salt Lake City' }, { name: 'Sammamish' }, { name: 'San Angelo' }, { name: 'San Antonio' }, { name: 'San Bernardino' }, { name: 'San Bruno' }, { name: 'San Buenaventura (Ventura)' }, { name: 'San Clemente' }, { name: 'San Diego' }, { name: 'San Francisco' }, { name: 'San Gabriel' }, { name: 'San Jacinto' }, { name: 'San Jose' }, { name: 'San Leandro' }, { name: 'San Luis Obispo' }, { name: 'San Marcos' }, { name: 'San Marcos' }, { name: 'San Mateo' }, { name: 'San Rafael' }, { name: 'San Ramon' }, { name: 'Sandy' }, { name: 'Sandy Springs' }, { name: 'Sanford' }, { name: 'Santa Ana' }, { name: 'Santa Barbara' }, { name: 'Santa Clara' }, { name: 'Santa Clarita' }, { name: 'Santa Cruz' }, { name: 'Santa Fe' }, { name: 'Santa Maria' }, { name: 'Santa Monica' }, { name: 'Santa Rosa' }, { name: 'Santee' }, { name: 'Sarasota' }, { name: 'Savannah' }, { name: 'Sayreville' }, { name: 'Schaumburg' }, { name: 'Schenectady' }, { name: 'Scottsdale' }, { name: 'Scranton' }, { name: 'Seattle' }, { name: 'Shakopee' }, { name: 'Shawnee' }, { name: 'Sheboygan' }, { name: 'Shelton' }, { name: 'Sherman' }, { name: 'Shoreline' }, { name: 'Shreveport' }, { name: 'Sierra Vista' }, { name: 'Simi Valley' }, { name: 'Sioux City' }, { name: 'Sioux Falls' }, { name: 'Skokie' }, { name: 'Smyrna' }, { name: 'Smyrna' }, { name: 'Somerville' }, { name: 'South Bend' }, { name: 'South Gate' }, { name: 'South Jordan' }, { name: 'South San Francisco' }, { name: 'Southaven' }, { name: 'Southfield' }, { name: 'Spanish Fork' }, { name: 'Sparks' }, { name: 'Spartanburg' }, { name: 'Spokane' }, { name: 'Spokane Valley' }, { name: 'Springdale' }, { name: 'Springfield' }, { name: 'Springfield' }, { name: 'Springfield' }, { name: 'Springfield' }, { name: 'Springfield' }, { name: 'St. Charles' }, { name: 'St. Clair Shores' }, { name: 'St. Cloud' }, { name: 'St. Cloud' }, { name: 'St. George' }, { name: 'St. Joseph' }, { name: 'St. Louis' }, { name: 'St. Louis Park' }, { name: 'St. Paul' }, { name: 'St. Peters' }, { name: 'St. Petersburg' }, { name: 'Stamford' }, { name: 'Stanton' }, { name: 'State College' }, { name: 'Sterling Heights' }, { name: 'Stillwater' }, { name: 'Stockton' }, { name: 'Streamwood' }, { name: 'Strongsville' }, { name: 'Suffolk' }, { name: 'Sugar Land' }, { name: 'Summerville' }, { name: 'Sumter' }, { name: 'Sunnyvale' }, { name: 'Sunrise' }, { name: 'Surprise' }, { name: 'Syracuse' }, { name: 'Tacoma' }, { name: 'Tallahassee' }, { name: 'Tamarac' }, { name: 'Tampa' }, { name: 'Taunton' }, { name: 'Taylor' }, { name: 'Taylorsville' }, { name: 'Temecula' }, { name: 'Tempe' }, { name: 'Temple' }, { name: 'Terre Haute' }, { name: 'Texarkana' }, { name: 'Texas City' }, { name: 'The Colony' }, { name: 'Thornton' }, { name: 'Thousand Oaks' }, { name: 'Tigard' }, { name: 'Tinley Park' }, { name: 'Titusville' }, { name: 'Toledo' }, { name: 'Topeka' }, { name: 'Torrance' }, { name: 'Tracy' }, { name: 'Trenton' }, { name: 'Troy' }, { name: 'Troy' }, { name: 'Tucson' }, { name: 'Tulare' }, { name: 'Tulsa' }, { name: 'Turlock' }, { name: 'Tuscaloosa' }, { name: 'Tustin' }, { name: 'Twin Falls' }, { name: 'Tyler' }, { name: 'Union City' }, { name: 'Union City' }, { name: 'Upland' }, { name: 'Urbana' }, { name: 'Urbandale' }, { name: 'Utica' }, { name: 'Vacaville' }, { name: 'Valdosta' }, { name: 'Vallejo' }, { name: 'Valley Stream' }, { name: 'Vancouver' }, { name: 'Victoria' }, { name: 'Victorville' }, { name: 'Vineland' }, { name: 'Virginia Beach' }, { name: 'Visalia' }, { name: 'Vista' }, { name: 'Waco' }, { name: 'Walnut Creek' }, { name: 'Waltham' }, { name: 'Warner Robins' }, { name: 'Warren' }, { name: 'Warren' }, { name: 'Warwick' }, { name: 'Washington' }, { name: 'Waterbury' }, { name: 'Waterloo' }, { name: 'Watsonville' }, { name: 'Waukegan' }, { name: 'Waukesha' }, { name: 'Wausau' }, { name: 'Wauwatosa' }, { name: 'Wellington' }, { name: 'Weslaco' }, { name: 'West Allis' }, { name: 'West Covina' }, { name: 'West Des Moines' }, { name: 'West Haven' }, { name: 'West Jordan' }, { name: 'West New York' }, { name: 'West Palm Beach' }, { name: 'West Sacramento' }, { name: 'West Valley City' }, { name: 'Westerville' }, { name: 'Westfield' }, { name: 'Westland' }, { name: 'Westminster' }, { name: 'Westminster' }, { name: 'Weston' }, { name: 'Weymouth Town' }, { name: 'Wheaton' }, { name: 'Wheeling' }, { name: 'White Plains' }, { name: 'Whittier' }, { name: 'Wichita' }, { name: 'Wichita Falls' }, { name: 'Wilkes-Barre' }, { name: 'Wilmington' }, { name: 'Wilmington' }, { name: 'Wilson' }, { name: 'Winston-Salem' }, { name: 'Winter Garden' }, { name: 'Woburn' }, { name: 'Woodbury' }, { name: 'Woodland' }, { name: 'Woonsocket' }, { name: 'Worcester' }, { name: 'Wylie' }, { name: 'Wyoming' }, { name: 'Yakima' }, { name: 'Yonkers' }, { name: 'Yorba Linda' }, { name: 'York' }, { name: 'Youngstown' }, { name: 'Yuba City' }, { name: 'Yucaipa' }, { name: 'Yuma' }]; @@ -1235,572 +1235,575 @@ exports.US = [{ value: 'AL', label: 'Alabama', disabled: true }, { value: 'AK', module.exports = [{ value: 'John Smith', label: 'John Smith', email: 'john@smith.com' }, { value: 'Merry Jane', label: 'Merry Jane', email: 'merry@jane.com' }, { value: 'Stan Hoper', label: 'Stan Hoper', email: 'stan@hoper.com' }]; },{}],16:[function(require,module,exports){ -var charenc = { - // UTF-8 encoding - utf8: { - // Convert a string to a byte array - stringToBytes: function(str) { - return charenc.bin.stringToBytes(unescape(encodeURIComponent(str))); - }, +// the whatwg-fetch polyfill installs the fetch() function +// on the global object (window or self) +// +// Return that as the export for use in Webpack, Browserify etc. +require('whatwg-fetch'); +module.exports = self.fetch.bind(self); - // Convert a byte array to a string - bytesToString: function(bytes) { - return decodeURIComponent(escape(charenc.bin.bytesToString(bytes))); - } - }, +},{"whatwg-fetch":17}],17:[function(require,module,exports){ +(function(self) { + 'use strict'; - // Binary encoding - bin: { - // Convert a string to a byte array - stringToBytes: function(str) { - for (var bytes = [], i = 0; i < str.length; i++) - bytes.push(str.charCodeAt(i) & 0xFF); - return bytes; - }, + if (self.fetch) { + return + } - // Convert a byte array to a string - bytesToString: function(bytes) { - for (var str = [], i = 0; i < bytes.length; i++) - str.push(String.fromCharCode(bytes[i])); - return str.join(''); - } + var support = { + searchParams: 'URLSearchParams' in self, + iterable: 'Symbol' in self && 'iterator' in Symbol, + blob: 'FileReader' in self && 'Blob' in self && (function() { + try { + new Blob() + return true + } catch(e) { + return false + } + })(), + formData: 'FormData' in self, + arrayBuffer: 'ArrayBuffer' in self } -}; -module.exports = charenc; + if (support.arrayBuffer) { + var viewClasses = [ + '[object Int8Array]', + '[object Uint8Array]', + '[object Uint8ClampedArray]', + '[object Int16Array]', + '[object Uint16Array]', + '[object Int32Array]', + '[object Uint32Array]', + '[object Float32Array]', + '[object Float64Array]' + ] -},{}],17:[function(require,module,exports){ -(function() { - var base64map - = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', + var isDataView = function(obj) { + return obj && DataView.prototype.isPrototypeOf(obj) + } - crypt = { - // Bit-wise rotation left - rotl: function(n, b) { - return (n << b) | (n >>> (32 - b)); - }, + var isArrayBufferView = ArrayBuffer.isView || function(obj) { + return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1 + } + } - // Bit-wise rotation right - rotr: function(n, b) { - return (n << (32 - b)) | (n >>> b); - }, + function normalizeName(name) { + if (typeof name !== 'string') { + name = String(name) + } + if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) { + throw new TypeError('Invalid character in header field name') + } + return name.toLowerCase() + } - // Swap big-endian to little-endian and vice versa - endian: function(n) { - // If number given, swap endian - if (n.constructor == Number) { - return crypt.rotl(n, 8) & 0x00FF00FF | crypt.rotl(n, 24) & 0xFF00FF00; + function normalizeValue(value) { + if (typeof value !== 'string') { + value = String(value) + } + return value + } + + // Build a destructive iterator for the value list + function iteratorFor(items) { + var iterator = { + next: function() { + var value = items.shift() + return {done: value === undefined, value: value} } + } - // Else, assume array and swap all items - for (var i = 0; i < n.length; i++) - n[i] = crypt.endian(n[i]); - return n; - }, + if (support.iterable) { + iterator[Symbol.iterator] = function() { + return iterator + } + } - // Generate an array of any length of random bytes - randomBytes: function(n) { - for (var bytes = []; n > 0; n--) - bytes.push(Math.floor(Math.random() * 256)); - return bytes; - }, + return iterator + } - // Convert a byte array to big-endian 32-bit words - bytesToWords: function(bytes) { - for (var words = [], i = 0, b = 0; i < bytes.length; i++, b += 8) - words[b >>> 5] |= bytes[i] << (24 - b % 32); - return words; - }, + function Headers(headers) { + this.map = {} - // Convert big-endian 32-bit words to a byte array - wordsToBytes: function(words) { - for (var bytes = [], b = 0; b < words.length * 32; b += 8) - bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF); - return bytes; - }, + if (headers instanceof Headers) { + headers.forEach(function(value, name) { + this.append(name, value) + }, this) + } else if (Array.isArray(headers)) { + headers.forEach(function(header) { + this.append(header[0], header[1]) + }, this) + } else if (headers) { + Object.getOwnPropertyNames(headers).forEach(function(name) { + this.append(name, headers[name]) + }, this) + } + } - // Convert a byte array to a hex string - bytesToHex: function(bytes) { - for (var hex = [], i = 0; i < bytes.length; i++) { - hex.push((bytes[i] >>> 4).toString(16)); - hex.push((bytes[i] & 0xF).toString(16)); - } - return hex.join(''); - }, + Headers.prototype.append = function(name, value) { + name = normalizeName(name) + value = normalizeValue(value) + var oldValue = this.map[name] + this.map[name] = oldValue ? oldValue+','+value : value + } - // Convert a hex string to a byte array - hexToBytes: function(hex) { - for (var bytes = [], c = 0; c < hex.length; c += 2) - bytes.push(parseInt(hex.substr(c, 2), 16)); - return bytes; - }, + Headers.prototype['delete'] = function(name) { + delete this.map[normalizeName(name)] + } - // Convert a byte array to a base-64 string - bytesToBase64: function(bytes) { - for (var base64 = [], i = 0; i < bytes.length; i += 3) { - var triplet = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]; - for (var j = 0; j < 4; j++) - if (i * 8 + j * 6 <= bytes.length * 8) - base64.push(base64map.charAt((triplet >>> 6 * (3 - j)) & 0x3F)); - else - base64.push('='); - } - return base64.join(''); - }, + Headers.prototype.get = function(name) { + name = normalizeName(name) + return this.has(name) ? this.map[name] : null + } - // Convert a base-64 string to a byte array - base64ToBytes: function(base64) { - // Remove non-base-64 characters - base64 = base64.replace(/[^A-Z0-9+\/]/ig, ''); + Headers.prototype.has = function(name) { + return this.map.hasOwnProperty(normalizeName(name)) + } - for (var bytes = [], i = 0, imod4 = 0; i < base64.length; - imod4 = ++i % 4) { - if (imod4 == 0) continue; - bytes.push(((base64map.indexOf(base64.charAt(i - 1)) - & (Math.pow(2, -2 * imod4 + 8) - 1)) << (imod4 * 2)) - | (base64map.indexOf(base64.charAt(i)) >>> (6 - imod4 * 2))); + Headers.prototype.set = function(name, value) { + this.map[normalizeName(name)] = normalizeValue(value) + } + + Headers.prototype.forEach = function(callback, thisArg) { + for (var name in this.map) { + if (this.map.hasOwnProperty(name)) { + callback.call(thisArg, this.map[name], name, this) } - return bytes; } - }; + } - module.exports = crypt; -})(); + Headers.prototype.keys = function() { + var items = [] + this.forEach(function(value, name) { items.push(name) }) + return iteratorFor(items) + } -},{}],18:[function(require,module,exports){ -'use strict'; -module.exports = !!(typeof window !== 'undefined' && window.document && window.document.createElement); -},{}],19:[function(require,module,exports){ -'use strict'; + Headers.prototype.values = function() { + var items = [] + this.forEach(function(value) { items.push(value) }) + return iteratorFor(items) + } -var canUseDOM = require('./inDOM'); + Headers.prototype.entries = function() { + var items = [] + this.forEach(function(value, name) { items.push([name, value]) }) + return iteratorFor(items) + } -var size; + if (support.iterable) { + Headers.prototype[Symbol.iterator] = Headers.prototype.entries + } -module.exports = function (recalc) { - if (!size || recalc) { - if (canUseDOM) { - var scrollDiv = document.createElement('div'); + function consumed(body) { + if (body.bodyUsed) { + return Promise.reject(new TypeError('Already read')) + } + body.bodyUsed = true + } - scrollDiv.style.position = 'absolute'; - scrollDiv.style.top = '-9999px'; - scrollDiv.style.width = '50px'; - scrollDiv.style.height = '50px'; - scrollDiv.style.overflow = 'scroll'; + function fileReaderReady(reader) { + return new Promise(function(resolve, reject) { + reader.onload = function() { + resolve(reader.result) + } + reader.onerror = function() { + reject(reader.error) + } + }) + } - document.body.appendChild(scrollDiv); - size = scrollDiv.offsetWidth - scrollDiv.clientWidth; - document.body.removeChild(scrollDiv); + function readBlobAsArrayBuffer(blob) { + var reader = new FileReader() + var promise = fileReaderReady(reader) + reader.readAsArrayBuffer(blob) + return promise + } + + function readBlobAsText(blob) { + var reader = new FileReader() + var promise = fileReaderReady(reader) + reader.readAsText(blob) + return promise + } + + function readArrayBufferAsText(buf) { + var view = new Uint8Array(buf) + var chars = new Array(view.length) + + for (var i = 0; i < view.length; i++) { + chars[i] = String.fromCharCode(view[i]) } + return chars.join('') } - return size; -}; -},{"./inDOM":18}],20:[function(require,module,exports){ -/** - * Copyright (c) 2013-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @typechecks - * - */ + function bufferClone(buf) { + if (buf.slice) { + return buf.slice(0) + } else { + var view = new Uint8Array(buf.byteLength) + view.set(new Uint8Array(buf)) + return view.buffer + } + } -/*eslint-disable no-self-compare */ + function Body() { + this.bodyUsed = false -'use strict'; + this._initBody = function(body) { + this._bodyInit = body + if (!body) { + this._bodyText = '' + } else if (typeof body === 'string') { + this._bodyText = body + } else if (support.blob && Blob.prototype.isPrototypeOf(body)) { + this._bodyBlob = body + } else if (support.formData && FormData.prototype.isPrototypeOf(body)) { + this._bodyFormData = body + } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) { + this._bodyText = body.toString() + } else if (support.arrayBuffer && support.blob && isDataView(body)) { + this._bodyArrayBuffer = bufferClone(body.buffer) + // IE 10-11 can't handle a DataView body. + this._bodyInit = new Blob([this._bodyArrayBuffer]) + } else if (support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) { + this._bodyArrayBuffer = bufferClone(body) + } else { + throw new Error('unsupported BodyInit type') + } -var hasOwnProperty = Object.prototype.hasOwnProperty; + if (!this.headers.get('content-type')) { + if (typeof body === 'string') { + this.headers.set('content-type', 'text/plain;charset=UTF-8') + } else if (this._bodyBlob && this._bodyBlob.type) { + this.headers.set('content-type', this._bodyBlob.type) + } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) { + this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8') + } + } + } -/** - * inlined Object.is polyfill to avoid requiring consumers ship their own - * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is - */ -function is(x, y) { - // SameValue algorithm - if (x === y) { - // Steps 1-5, 7-10 - // Steps 6.b-6.e: +0 != -0 - // Added the nonzero y check to make Flow happy, but it is redundant - return x !== 0 || y !== 0 || 1 / x === 1 / y; - } else { - // Step 6.a: NaN == NaN - return x !== x && y !== y; - } -} + if (support.blob) { + this.blob = function() { + var rejected = consumed(this) + if (rejected) { + return rejected + } -/** - * Performs equality by iterating through keys on an object and returning false - * when any key has values which are not strictly equal between the arguments. - * Returns true when the values of all keys are strictly equal. - */ -function shallowEqual(objA, objB) { - if (is(objA, objB)) { - return true; - } + if (this._bodyBlob) { + return Promise.resolve(this._bodyBlob) + } else if (this._bodyArrayBuffer) { + return Promise.resolve(new Blob([this._bodyArrayBuffer])) + } else if (this._bodyFormData) { + throw new Error('could not read FormData body as blob') + } else { + return Promise.resolve(new Blob([this._bodyText])) + } + } - if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) { - return false; - } + this.arrayBuffer = function() { + if (this._bodyArrayBuffer) { + return consumed(this) || Promise.resolve(this._bodyArrayBuffer) + } else { + return this.blob().then(readBlobAsArrayBuffer) + } + } + } - var keysA = Object.keys(objA); - var keysB = Object.keys(objB); + this.text = function() { + var rejected = consumed(this) + if (rejected) { + return rejected + } - if (keysA.length !== keysB.length) { - return false; - } + if (this._bodyBlob) { + return readBlobAsText(this._bodyBlob) + } else if (this._bodyArrayBuffer) { + return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer)) + } else if (this._bodyFormData) { + throw new Error('could not read FormData body as text') + } else { + return Promise.resolve(this._bodyText) + } + } - // Test for A's keys different from B. - for (var i = 0; i < keysA.length; i++) { - if (!hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) { - return false; + if (support.formData) { + this.formData = function() { + return this.text().then(decode) + } } - } - return true; -} + this.json = function() { + return this.text().then(JSON.parse) + } -module.exports = shallowEqual; -},{}],21:[function(require,module,exports){ -/*! - * Determine if an object is a Buffer - * - * @author Feross Aboukhadijeh - * @license MIT - */ + return this + } -// The _isBuffer check is for Safari 5-7 support, because it's missing -// Object.prototype.constructor. Remove this eventually -module.exports = function (obj) { - return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer) -} + // HTTP methods whose capitalization should be normalized + var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT'] -function isBuffer (obj) { - return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj) -} + function normalizeMethod(method) { + var upcased = method.toUpperCase() + return (methods.indexOf(upcased) > -1) ? upcased : method + } -// For Node v0.10 support. Remove this eventually. -function isSlowBuffer (obj) { - return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0)) -} + function Request(input, options) { + options = options || {} + var body = options.body -},{}],22:[function(require,module,exports){ -module.exports = function() { - var mediaQuery; - if (typeof window !== "undefined" && window !== null) { - mediaQuery = "(-webkit-min-device-pixel-ratio: 1.25), (min--moz-device-pixel-ratio: 1.25), (-o-min-device-pixel-ratio: 5/4), (min-resolution: 1.25dppx)"; - if (window.devicePixelRatio > 1.25) { - return true; + if (input instanceof Request) { + if (input.bodyUsed) { + throw new TypeError('Already read') + } + this.url = input.url + this.credentials = input.credentials + if (!options.headers) { + this.headers = new Headers(input.headers) + } + this.method = input.method + this.mode = input.mode + if (!body && input._bodyInit != null) { + body = input._bodyInit + input.bodyUsed = true + } + } else { + this.url = String(input) } - if (window.matchMedia && window.matchMedia(mediaQuery).matches) { - return true; + + this.credentials = options.credentials || this.credentials || 'omit' + if (options.headers || !this.headers) { + this.headers = new Headers(options.headers) } + this.method = normalizeMethod(options.method || this.method || 'GET') + this.mode = options.mode || this.mode || null + this.referrer = null + + if ((this.method === 'GET' || this.method === 'HEAD') && body) { + throw new TypeError('Body not allowed for GET or HEAD requests') + } + this._initBody(body) } - return false; -}; -},{}],23:[function(require,module,exports){ -// the whatwg-fetch polyfill installs the fetch() function -// on the global object (window or self) -// -// Return that as the export for use in Webpack, Browserify etc. -require('whatwg-fetch'); -module.exports = self.fetch.bind(self); + Request.prototype.clone = function() { + return new Request(this, { body: this._bodyInit }) + } -},{"whatwg-fetch":83}],24:[function(require,module,exports){ -(function(){ - var crypt = require('crypt'), - utf8 = require('charenc').utf8, - isBuffer = require('is-buffer'), - bin = require('charenc').bin, - - // The core - md5 = function (message, options) { - // Convert to byte array - if (message.constructor == String) - if (options && options.encoding === 'binary') - message = bin.stringToBytes(message); - else - message = utf8.stringToBytes(message); - else if (isBuffer(message)) - message = Array.prototype.slice.call(message, 0); - else if (!Array.isArray(message)) - message = message.toString(); - // else, assume byte array already - - var m = crypt.bytesToWords(message), - l = message.length * 8, - a = 1732584193, - b = -271733879, - c = -1732584194, - d = 271733878; - - // Swap endian - for (var i = 0; i < m.length; i++) { - m[i] = ((m[i] << 8) | (m[i] >>> 24)) & 0x00FF00FF | - ((m[i] << 24) | (m[i] >>> 8)) & 0xFF00FF00; - } - - // Padding - m[l >>> 5] |= 0x80 << (l % 32); - m[(((l + 64) >>> 9) << 4) + 14] = l; - - // Method shortcuts - var FF = md5._ff, - GG = md5._gg, - HH = md5._hh, - II = md5._ii; - - for (var i = 0; i < m.length; i += 16) { - - var aa = a, - bb = b, - cc = c, - dd = d; - - a = FF(a, b, c, d, m[i+ 0], 7, -680876936); - d = FF(d, a, b, c, m[i+ 1], 12, -389564586); - c = FF(c, d, a, b, m[i+ 2], 17, 606105819); - b = FF(b, c, d, a, m[i+ 3], 22, -1044525330); - a = FF(a, b, c, d, m[i+ 4], 7, -176418897); - d = FF(d, a, b, c, m[i+ 5], 12, 1200080426); - c = FF(c, d, a, b, m[i+ 6], 17, -1473231341); - b = FF(b, c, d, a, m[i+ 7], 22, -45705983); - a = FF(a, b, c, d, m[i+ 8], 7, 1770035416); - d = FF(d, a, b, c, m[i+ 9], 12, -1958414417); - c = FF(c, d, a, b, m[i+10], 17, -42063); - b = FF(b, c, d, a, m[i+11], 22, -1990404162); - a = FF(a, b, c, d, m[i+12], 7, 1804603682); - d = FF(d, a, b, c, m[i+13], 12, -40341101); - c = FF(c, d, a, b, m[i+14], 17, -1502002290); - b = FF(b, c, d, a, m[i+15], 22, 1236535329); - - a = GG(a, b, c, d, m[i+ 1], 5, -165796510); - d = GG(d, a, b, c, m[i+ 6], 9, -1069501632); - c = GG(c, d, a, b, m[i+11], 14, 643717713); - b = GG(b, c, d, a, m[i+ 0], 20, -373897302); - a = GG(a, b, c, d, m[i+ 5], 5, -701558691); - d = GG(d, a, b, c, m[i+10], 9, 38016083); - c = GG(c, d, a, b, m[i+15], 14, -660478335); - b = GG(b, c, d, a, m[i+ 4], 20, -405537848); - a = GG(a, b, c, d, m[i+ 9], 5, 568446438); - d = GG(d, a, b, c, m[i+14], 9, -1019803690); - c = GG(c, d, a, b, m[i+ 3], 14, -187363961); - b = GG(b, c, d, a, m[i+ 8], 20, 1163531501); - a = GG(a, b, c, d, m[i+13], 5, -1444681467); - d = GG(d, a, b, c, m[i+ 2], 9, -51403784); - c = GG(c, d, a, b, m[i+ 7], 14, 1735328473); - b = GG(b, c, d, a, m[i+12], 20, -1926607734); - - a = HH(a, b, c, d, m[i+ 5], 4, -378558); - d = HH(d, a, b, c, m[i+ 8], 11, -2022574463); - c = HH(c, d, a, b, m[i+11], 16, 1839030562); - b = HH(b, c, d, a, m[i+14], 23, -35309556); - a = HH(a, b, c, d, m[i+ 1], 4, -1530992060); - d = HH(d, a, b, c, m[i+ 4], 11, 1272893353); - c = HH(c, d, a, b, m[i+ 7], 16, -155497632); - b = HH(b, c, d, a, m[i+10], 23, -1094730640); - a = HH(a, b, c, d, m[i+13], 4, 681279174); - d = HH(d, a, b, c, m[i+ 0], 11, -358537222); - c = HH(c, d, a, b, m[i+ 3], 16, -722521979); - b = HH(b, c, d, a, m[i+ 6], 23, 76029189); - a = HH(a, b, c, d, m[i+ 9], 4, -640364487); - d = HH(d, a, b, c, m[i+12], 11, -421815835); - c = HH(c, d, a, b, m[i+15], 16, 530742520); - b = HH(b, c, d, a, m[i+ 2], 23, -995338651); - - a = II(a, b, c, d, m[i+ 0], 6, -198630844); - d = II(d, a, b, c, m[i+ 7], 10, 1126891415); - c = II(c, d, a, b, m[i+14], 15, -1416354905); - b = II(b, c, d, a, m[i+ 5], 21, -57434055); - a = II(a, b, c, d, m[i+12], 6, 1700485571); - d = II(d, a, b, c, m[i+ 3], 10, -1894986606); - c = II(c, d, a, b, m[i+10], 15, -1051523); - b = II(b, c, d, a, m[i+ 1], 21, -2054922799); - a = II(a, b, c, d, m[i+ 8], 6, 1873313359); - d = II(d, a, b, c, m[i+15], 10, -30611744); - c = II(c, d, a, b, m[i+ 6], 15, -1560198380); - b = II(b, c, d, a, m[i+13], 21, 1309151649); - a = II(a, b, c, d, m[i+ 4], 6, -145523070); - d = II(d, a, b, c, m[i+11], 10, -1120210379); - c = II(c, d, a, b, m[i+ 2], 15, 718787259); - b = II(b, c, d, a, m[i+ 9], 21, -343485551); - - a = (a + aa) >>> 0; - b = (b + bb) >>> 0; - c = (c + cc) >>> 0; - d = (d + dd) >>> 0; - } - - return crypt.endian([a, b, c, d]); - }; - - // Auxiliary functions - md5._ff = function (a, b, c, d, x, s, t) { - var n = a + (b & c | ~b & d) + (x >>> 0) + t; - return ((n << s) | (n >>> (32 - s))) + b; - }; - md5._gg = function (a, b, c, d, x, s, t) { - var n = a + (b & d | c & ~d) + (x >>> 0) + t; - return ((n << s) | (n >>> (32 - s))) + b; - }; - md5._hh = function (a, b, c, d, x, s, t) { - var n = a + (b ^ c ^ d) + (x >>> 0) + t; - return ((n << s) | (n >>> (32 - s))) + b; - }; - md5._ii = function (a, b, c, d, x, s, t) { - var n = a + (c ^ (b | ~d)) + (x >>> 0) + t; - return ((n << s) | (n >>> (32 - s))) + b; - }; - - // Package private blocksize - md5._blocksize = 16; - md5._digestsize = 16; - - module.exports = function (message, options) { - if (message === undefined || message === null) - throw new Error('Illegal argument ' + message); - - var digestbytes = crypt.wordsToBytes(md5(message, options)); - return options && options.asBytes ? digestbytes : - options && options.asString ? bin.bytesToString(digestbytes) : - crypt.bytesToHex(digestbytes); - }; - -})(); + function decode(body) { + var form = new FormData() + body.trim().split('&').forEach(function(bytes) { + if (bytes) { + var split = bytes.split('=') + var name = split.shift().replace(/\+/g, ' ') + var value = split.join('=').replace(/\+/g, ' ') + form.append(decodeURIComponent(name), decodeURIComponent(value)) + } + }) + return form + } -},{"charenc":16,"crypt":17,"is-buffer":21}],25:[function(require,module,exports){ -/* -object-assign -(c) Sindre Sorhus -@license MIT -*/ + function parseHeaders(rawHeaders) { + var headers = new Headers() + rawHeaders.split(/\r?\n/).forEach(function(line) { + var parts = line.split(':') + var key = parts.shift().trim() + if (key) { + var value = parts.join(':').trim() + headers.append(key, value) + } + }) + return headers + } -'use strict'; -/* eslint-disable no-unused-vars */ -var getOwnPropertySymbols = Object.getOwnPropertySymbols; -var hasOwnProperty = Object.prototype.hasOwnProperty; -var propIsEnumerable = Object.prototype.propertyIsEnumerable; + Body.call(Request.prototype) -function toObject(val) { - if (val === null || val === undefined) { - throw new TypeError('Object.assign cannot be called with null or undefined'); - } + function Response(bodyInit, options) { + if (!options) { + options = {} + } - return Object(val); -} + this.type = 'default' + this.status = 'status' in options ? options.status : 200 + this.ok = this.status >= 200 && this.status < 300 + this.statusText = 'statusText' in options ? options.statusText : 'OK' + this.headers = new Headers(options.headers) + this.url = options.url || '' + this._initBody(bodyInit) + } -function shouldUseNative() { - try { - if (!Object.assign) { - return false; - } + Body.call(Response.prototype) - // Detect buggy property enumeration order in older V8 versions. + Response.prototype.clone = function() { + return new Response(this._bodyInit, { + status: this.status, + statusText: this.statusText, + headers: new Headers(this.headers), + url: this.url + }) + } - // https://bugs.chromium.org/p/v8/issues/detail?id=4118 - var test1 = new String('abc'); // eslint-disable-line no-new-wrappers - test1[5] = 'de'; - if (Object.getOwnPropertyNames(test1)[0] === '5') { - return false; - } + Response.error = function() { + var response = new Response(null, {status: 0, statusText: ''}) + response.type = 'error' + return response + } - // https://bugs.chromium.org/p/v8/issues/detail?id=3056 - var test2 = {}; - for (var i = 0; i < 10; i++) { - test2['_' + String.fromCharCode(i)] = i; - } - var order2 = Object.getOwnPropertyNames(test2).map(function (n) { - return test2[n]; - }); - if (order2.join('') !== '0123456789') { - return false; - } + var redirectStatuses = [301, 302, 303, 307, 308] - // https://bugs.chromium.org/p/v8/issues/detail?id=3056 - var test3 = {}; - 'abcdefghijklmnopqrst'.split('').forEach(function (letter) { - test3[letter] = letter; - }); - if (Object.keys(Object.assign({}, test3)).join('') !== - 'abcdefghijklmnopqrst') { - return false; - } + Response.redirect = function(url, status) { + if (redirectStatuses.indexOf(status) === -1) { + throw new RangeError('Invalid status code') + } - return true; - } catch (err) { - // We don't expect any of the above to throw, but better to be safe. - return false; - } -} + return new Response(null, {status: status, headers: {location: url}}) + } -module.exports = shouldUseNative() ? Object.assign : function (target, source) { - var from; - var to = toObject(target); - var symbols; + self.Headers = Headers + self.Request = Request + self.Response = Response - for (var s = 1; s < arguments.length; s++) { - from = Object(arguments[s]); + self.fetch = function(input, init) { + return new Promise(function(resolve, reject) { + var request = new Request(input, init) + var xhr = new XMLHttpRequest() - for (var key in from) { - if (hasOwnProperty.call(from, key)) { - to[key] = from[key]; - } - } + xhr.onload = function() { + var options = { + status: xhr.status, + statusText: xhr.statusText, + headers: parseHeaders(xhr.getAllResponseHeaders() || '') + } + options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL') + var body = 'response' in xhr ? xhr.response : xhr.responseText + resolve(new Response(body, options)) + } - if (getOwnPropertySymbols) { - symbols = getOwnPropertySymbols(from); - for (var i = 0; i < symbols.length; i++) { - if (propIsEnumerable.call(from, symbols[i])) { - to[symbols[i]] = from[symbols[i]]; - } - } - } - } + xhr.onerror = function() { + reject(new TypeError('Network request failed')) + } - return to; -}; + xhr.ontimeout = function() { + reject(new TypeError('Network request failed')) + } -},{}],26:[function(require,module,exports){ -(function (process){ -// Generated by CoffeeScript 1.7.1 -(function() { - var getNanoSeconds, hrtime, loadTime; + xhr.open(request.method, request.url, true) - if ((typeof performance !== "undefined" && performance !== null) && performance.now) { - module.exports = function() { - return performance.now(); - }; - } else if ((typeof process !== "undefined" && process !== null) && process.hrtime) { - module.exports = function() { - return (getNanoSeconds() - loadTime) / 1e6; - }; - hrtime = process.hrtime; - getNanoSeconds = function() { - var hr; - hr = hrtime(); - return hr[0] * 1e9 + hr[1]; - }; - loadTime = getNanoSeconds(); - } else if (Date.now) { - module.exports = function() { - return Date.now() - loadTime; - }; - loadTime = Date.now(); + if (request.credentials === 'include') { + xhr.withCredentials = true + } + + if ('responseType' in xhr && support.blob) { + xhr.responseType = 'blob' + } + + request.headers.forEach(function(value, name) { + xhr.setRequestHeader(name, value) + }) + + xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit) + }) + } + self.fetch.polyfill = true +})(typeof self !== 'undefined' ? self : this); + +},{}],18:[function(require,module,exports){ +/** + * Copyright 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule shallowCompare + */ + +'use strict'; + +var shallowEqual = require('fbjs/lib/shallowEqual'); + +/** + * Does a shallow comparison for props and state. + * See ReactComponentWithPureRenderMixin + * See also https://facebook.github.io/react/docs/shallow-compare.html + */ +function shallowCompare(instance, nextProps, nextState) { + return ( + !shallowEqual(instance.props, nextProps) || + !shallowEqual(instance.state, nextState) + ); +} + +module.exports = shallowCompare; + +},{"fbjs/lib/shallowEqual":19}],19:[function(require,module,exports){ +/** + * Copyright (c) 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @typechecks + * + */ + +/*eslint-disable no-self-compare */ + +'use strict'; + +var hasOwnProperty = Object.prototype.hasOwnProperty; + +/** + * inlined Object.is polyfill to avoid requiring consumers ship their own + * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is + */ +function is(x, y) { + // SameValue algorithm + if (x === y) { + // Steps 1-5, 7-10 + // Steps 6.b-6.e: +0 != -0 + // Added the nonzero y check to make Flow happy, but it is redundant + return x !== 0 || y !== 0 || 1 / x === 1 / y; } else { - module.exports = function() { - return new Date().getTime() - loadTime; - }; - loadTime = new Date().getTime(); + // Step 6.a: NaN == NaN + return x !== x && y !== y; } +} -}).call(this); +/** + * Performs equality by iterating through keys on an object and returning false + * when any key has values which are not strictly equal between the arguments. + * Returns true when the values of all keys are strictly equal. + */ +function shallowEqual(objA, objB) { + if (is(objA, objB)) { + return true; + } -}).call(this,require('_process')) -},{"_process":27}],27:[function(require,module,exports){ + if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) { + return false; + } + + var keysA = Object.keys(objA); + var keysB = Object.keys(objB); + + if (keysA.length !== keysB.length) { + return false; + } + + // Test for A's keys different from B. + for (var i = 0; i < keysA.length; i++) { + if (!hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) { + return false; + } + } + + return true; +} + +module.exports = shallowEqual; +},{}],20:[function(require,module,exports){ // shim for using process in browser var process = module.exports = {}; @@ -1971,6 +1974,10 @@ process.off = noop; process.removeListener = noop; process.removeAllListeners = noop; process.emit = noop; +process.prependListener = noop; +process.prependOnceListener = noop; + +process.listeners = function (name) { return [] } process.binding = function (name) { throw new Error('process.binding is not supported'); @@ -1982,305 +1989,22 @@ process.chdir = function (dir) { }; process.umask = function() { return 0; }; -},{}],28:[function(require,module,exports){ +},{}],21:[function(require,module,exports){ 'use strict'; -var strictUriEncode = require('strict-uri-encode'); -var objectAssign = require('object-assign'); -function encoderForArrayFormat(opts) { - switch (opts.arrayFormat) { - case 'index': - return function (key, value, index) { - return value === null ? [ - encode(key, opts), - '[', - index, - ']' - ].join('') : [ - encode(key, opts), - '[', - encode(index, opts), - ']=', - encode(value, opts) - ].join(''); - }; +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - case 'bracket': - return function (key, value) { - return value === null ? encode(key, opts) : [ - encode(key, opts), - '[]=', - encode(value, opts) - ].join(''); - }; +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - default: - return function (key, value) { - return value === null ? encode(key, opts) : [ - encode(key, opts), - '=', - encode(value, opts) - ].join(''); - }; - } -} +var _react = require('react'); -function parserForArrayFormat(opts) { - var result; +var _react2 = _interopRequireDefault(_react); - switch (opts.arrayFormat) { - case 'index': - return function (key, value, accumulator) { - result = /\[(\d*)]$/.exec(key); +var _md = require('md5'); - key = key.replace(/\[\d*]$/, ''); +var _md2 = _interopRequireDefault(_md); - if (!result) { - accumulator[key] = value; - return; - } - - if (accumulator[key] === undefined) { - accumulator[key] = {}; - } - - accumulator[key][result[1]] = value; - }; - - case 'bracket': - return function (key, value, accumulator) { - result = /(\[])$/.exec(key); - - key = key.replace(/\[]$/, ''); - - if (!result || accumulator[key] === undefined) { - accumulator[key] = value; - return; - } - - accumulator[key] = [].concat(accumulator[key], value); - }; - - default: - return function (key, value, accumulator) { - if (accumulator[key] === undefined) { - accumulator[key] = value; - return; - } - - accumulator[key] = [].concat(accumulator[key], value); - }; - } -} - -function encode(value, opts) { - if (opts.encode) { - return opts.strict ? strictUriEncode(value) : encodeURIComponent(value); - } - - return value; -} - -function keysSorter(input) { - if (Array.isArray(input)) { - return input.sort(); - } else if (typeof input === 'object') { - return keysSorter(Object.keys(input)).sort(function (a, b) { - return Number(a) - Number(b); - }).map(function (key) { - return input[key]; - }); - } - - return input; -} - -exports.extract = function (str) { - return str.split('?')[1] || ''; -}; - -exports.parse = function (str, opts) { - opts = objectAssign({arrayFormat: 'none'}, opts); - - var formatter = parserForArrayFormat(opts); - - // Create an object with no prototype - // https://github.com/sindresorhus/query-string/issues/47 - var ret = Object.create(null); - - if (typeof str !== 'string') { - return ret; - } - - str = str.trim().replace(/^(\?|#|&)/, ''); - - if (!str) { - return ret; - } - - str.split('&').forEach(function (param) { - var parts = param.replace(/\+/g, ' ').split('='); - // Firefox (pre 40) decodes `%3D` to `=` - // https://github.com/sindresorhus/query-string/pull/37 - var key = parts.shift(); - var val = parts.length > 0 ? parts.join('=') : undefined; - - // missing `=` should be `null`: - // http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters - val = val === undefined ? null : decodeURIComponent(val); - - formatter(decodeURIComponent(key), val, ret); - }); - - return Object.keys(ret).sort().reduce(function (result, key) { - var val = ret[key]; - if (Boolean(val) && typeof val === 'object' && !Array.isArray(val)) { - // Sort object keys, not values - result[key] = keysSorter(val); - } else { - result[key] = val; - } - - return result; - }, Object.create(null)); -}; - -exports.stringify = function (obj, opts) { - var defaults = { - encode: true, - strict: true, - arrayFormat: 'none' - }; - - opts = objectAssign(defaults, opts); - - var formatter = encoderForArrayFormat(opts); - - return obj ? Object.keys(obj).sort().map(function (key) { - var val = obj[key]; - - if (val === undefined) { - return ''; - } - - if (val === null) { - return encode(key, opts); - } - - if (Array.isArray(val)) { - var result = []; - - val.slice().forEach(function (val2) { - if (val2 === undefined) { - return; - } - - result.push(formatter(key, val2, result.length)); - }); - - return result.join('&'); - } - - return encode(key, opts) + '=' + encode(val, opts); - }).filter(function (x) { - return x.length > 0; - }).join('&') : ''; -}; - -},{"object-assign":25,"strict-uri-encode":82}],29:[function(require,module,exports){ -(function (global){ -var now = require('performance-now') - , root = typeof window === 'undefined' ? global : window - , vendors = ['moz', 'webkit'] - , suffix = 'AnimationFrame' - , raf = root['request' + suffix] - , caf = root['cancel' + suffix] || root['cancelRequest' + suffix] - -for(var i = 0; !raf && i < vendors.length; i++) { - raf = root[vendors[i] + 'Request' + suffix] - caf = root[vendors[i] + 'Cancel' + suffix] - || root[vendors[i] + 'CancelRequest' + suffix] -} - -// Some versions of FF have rAF but not cAF -if(!raf || !caf) { - var last = 0 - , id = 0 - , queue = [] - , frameDuration = 1000 / 60 - - raf = function(callback) { - if(queue.length === 0) { - var _now = now() - , next = Math.max(0, frameDuration - (_now - last)) - last = next + _now - setTimeout(function() { - var cp = queue.slice(0) - // Clear queue here to prevent - // callbacks from appending listeners - // to the current frame's queue - queue.length = 0 - for(var i = 0; i < cp.length; i++) { - if(!cp[i].cancelled) { - try{ - cp[i].callback(last) - } catch(e) { - setTimeout(function() { throw e }, 0) - } - } - } - }, Math.round(next)) - } - queue.push({ - handle: ++id, - callback: callback, - cancelled: false - }) - return id - } - - caf = function(handle) { - for(var i = 0; i < queue.length; i++) { - if(queue[i].handle === handle) { - queue[i].cancelled = true - } - } - } -} - -module.exports = function(fn) { - // Wrap in a new function to prevent - // `cancel` potentially being assigned - // to the native rAF function - return raf.call(root, fn) -} -module.exports.cancel = function() { - caf.apply(root, arguments) -} -module.exports.polyfill = function() { - root.requestAnimationFrame = raf - root.cancelAnimationFrame = caf -} - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"performance-now":26}],30:[function(require,module,exports){ -module.exports = require('react/lib/shallowCompare'); -},{"react/lib/shallowCompare":81}],31:[function(require,module,exports){ -'use strict'; - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _react = require('react'); - -var _react2 = _interopRequireDefault(_react); - -var _md = require('md5'); - -var _md2 = _interopRequireDefault(_md); - -var _queryString = require('query-string'); +var _queryString = require('query-string'); var _queryString2 = _interopRequireDefault(_queryString); @@ -2288,6 +2012,10 @@ var _isRetina = require('is-retina'); var _isRetina2 = _interopRequireDefault(_isRetina); +var _propTypes = require('prop-types'); + +var _propTypes2 = _interopRequireDefault(_propTypes); + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } @@ -2304,7 +2032,7 @@ var Gravatar = function (_React$Component) { function Gravatar() { _classCallCheck(this, Gravatar); - return _possibleConstructorReturn(this, Object.getPrototypeOf(Gravatar).apply(this, arguments)); + return _possibleConstructorReturn(this, (Gravatar.__proto__ || Object.getPrototypeOf(Gravatar)).apply(this, arguments)); } _createClass(Gravatar, [{ @@ -2331,7 +2059,7 @@ var Gravatar = function (_React$Component) { if (this.props.md5) { hash = this.props.md5; } else if (typeof this.props.email === 'string') { - hash = (0, _md2.default)(formattedEmail); + hash = (0, _md2.default)(formattedEmail, { encoding: "binary" }); } else { console.warn('Gravatar image can not be fetched. Either the "email" or "md5" prop must be specified.'); return _react2.default.createElement('script', null); @@ -2394,14 +2122,14 @@ var Gravatar = function (_React$Component) { Gravatar.displayName = 'Gravatar'; Gravatar.propTypes = { - email: _react2.default.PropTypes.string, - md5: _react2.default.PropTypes.string, - size: _react2.default.PropTypes.number, - rating: _react2.default.PropTypes.string, - default: _react2.default.PropTypes.string, - className: _react2.default.PropTypes.string, - protocol: _react2.default.PropTypes.string, - style: _react2.default.PropTypes.object + email: _propTypes2.default.string, + md5: _propTypes2.default.string, + size: _propTypes2.default.number, + rating: _propTypes2.default.string, + default: _propTypes2.default.string, + className: _propTypes2.default.string, + protocol: _propTypes2.default.string, + style: _propTypes2.default.object }; Gravatar.defaultProps = { size: 50, @@ -2412,690 +2140,927 @@ Gravatar.defaultProps = { module.exports = Gravatar; -},{"is-retina":22,"md5":24,"query-string":28,"react":undefined}],32:[function(require,module,exports){ -module.exports = -/******/ (function(modules) { // webpackBootstrap -/******/ // The module cache -/******/ var installedModules = {}; -/******/ -/******/ // The require function -/******/ function __webpack_require__(moduleId) { -/******/ -/******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) -/******/ return installedModules[moduleId].exports; -/******/ -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ exports: {}, -/******/ id: moduleId, -/******/ loaded: false -/******/ }; -/******/ -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); -/******/ -/******/ // Flag the module as loaded -/******/ module.loaded = true; -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/******/ -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; -/******/ -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; -/******/ -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = ""; -/******/ -/******/ // Load entry module and return exports -/******/ return __webpack_require__(0); -/******/ }) -/************************************************************************/ -/******/ ([ -/* 0 */ -/***/ function(module, exports, __webpack_require__) { - - module.exports = __webpack_require__(1); - - -/***/ }, -/* 1 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, '__esModule', { - value: true - }); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - - var _Highlighter = __webpack_require__(2); - - var _Highlighter2 = _interopRequireDefault(_Highlighter); - - var _utils = __webpack_require__(4); - - exports['default'] = _Highlighter2['default']; - exports.combineChunks = _utils.combineChunks; - exports.fillInChunks = _utils.fillInChunks; - exports.findAll = _utils.findAll; - exports.findChunks = _utils.findChunks; - -/***/ }, -/* 2 */ -/***/ function(module, exports, __webpack_require__) { +},{"is-retina":22,"md5":23,"prop-types":undefined,"query-string":27,"react":undefined}],22:[function(require,module,exports){ +module.exports = function() { + var mediaQuery; + if (typeof window !== "undefined" && window !== null) { + mediaQuery = "(-webkit-min-device-pixel-ratio: 1.25), (min--moz-device-pixel-ratio: 1.25), (-o-min-device-pixel-ratio: 5/4), (min-resolution: 1.25dppx)"; + if (window.devicePixelRatio > 1.25) { + return true; + } + if (window.matchMedia && window.matchMedia(mediaQuery).matches) { + return true; + } + } + return false; +}; - 'use strict'; - - Object.defineProperty(exports, '__esModule', { - value: true - }); - exports['default'] = Highlighter; - - function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } } - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - - var _react = __webpack_require__(3); - - var _react2 = _interopRequireDefault(_react); - - var _utilsJs = __webpack_require__(4); - - var Chunks = _interopRequireWildcard(_utilsJs); - - Highlighter.propTypes = { - highlightClassName: _react.PropTypes.string, - highlightStyle: _react.PropTypes.object, - searchWords: _react.PropTypes.arrayOf(_react.PropTypes.string).isRequired, - textToHighlight: _react.PropTypes.string.isRequired, - sanitize: _react.PropTypes.func - }; - - /** - * Highlights all occurrences of search terms (searchText) within a string (textToHighlight). - * This function returns an array of strings and s (wrapping highlighted words). - */ - - function Highlighter(_ref) { - var _ref$highlightClassName = _ref.highlightClassName; - var highlightClassName = _ref$highlightClassName === undefined ? '' : _ref$highlightClassName; - var _ref$highlightStyle = _ref.highlightStyle; - var highlightStyle = _ref$highlightStyle === undefined ? {} : _ref$highlightStyle; - var searchWords = _ref.searchWords; - var textToHighlight = _ref.textToHighlight; - var sanitize = _ref.sanitize; - - var chunks = Chunks.findAll(textToHighlight, searchWords, sanitize); - - return _react2['default'].createElement( - 'span', - null, - chunks.map(function (chunk, index) { - var text = textToHighlight.substr(chunk.start, chunk.end - chunk.start); - - if (chunk.highlight) { - return _react2['default'].createElement( - 'mark', - { - className: highlightClassName, - key: index, - style: highlightStyle - }, - text - ); - } else { - return _react2['default'].createElement( - 'span', - { key: index }, - text - ); - } - }) - ); - } - - module.exports = exports['default']; +},{}],23:[function(require,module,exports){ +(function(){ + var crypt = require('crypt'), + utf8 = require('charenc').utf8, + isBuffer = require('is-buffer'), + bin = require('charenc').bin, + + // The core + md5 = function (message, options) { + // Convert to byte array + if (message.constructor == String) + if (options && options.encoding === 'binary') + message = bin.stringToBytes(message); + else + message = utf8.stringToBytes(message); + else if (isBuffer(message)) + message = Array.prototype.slice.call(message, 0); + else if (!Array.isArray(message)) + message = message.toString(); + // else, assume byte array already + + var m = crypt.bytesToWords(message), + l = message.length * 8, + a = 1732584193, + b = -271733879, + c = -1732584194, + d = 271733878; + + // Swap endian + for (var i = 0; i < m.length; i++) { + m[i] = ((m[i] << 8) | (m[i] >>> 24)) & 0x00FF00FF | + ((m[i] << 24) | (m[i] >>> 8)) & 0xFF00FF00; + } + + // Padding + m[l >>> 5] |= 0x80 << (l % 32); + m[(((l + 64) >>> 9) << 4) + 14] = l; + + // Method shortcuts + var FF = md5._ff, + GG = md5._gg, + HH = md5._hh, + II = md5._ii; + + for (var i = 0; i < m.length; i += 16) { + + var aa = a, + bb = b, + cc = c, + dd = d; + + a = FF(a, b, c, d, m[i+ 0], 7, -680876936); + d = FF(d, a, b, c, m[i+ 1], 12, -389564586); + c = FF(c, d, a, b, m[i+ 2], 17, 606105819); + b = FF(b, c, d, a, m[i+ 3], 22, -1044525330); + a = FF(a, b, c, d, m[i+ 4], 7, -176418897); + d = FF(d, a, b, c, m[i+ 5], 12, 1200080426); + c = FF(c, d, a, b, m[i+ 6], 17, -1473231341); + b = FF(b, c, d, a, m[i+ 7], 22, -45705983); + a = FF(a, b, c, d, m[i+ 8], 7, 1770035416); + d = FF(d, a, b, c, m[i+ 9], 12, -1958414417); + c = FF(c, d, a, b, m[i+10], 17, -42063); + b = FF(b, c, d, a, m[i+11], 22, -1990404162); + a = FF(a, b, c, d, m[i+12], 7, 1804603682); + d = FF(d, a, b, c, m[i+13], 12, -40341101); + c = FF(c, d, a, b, m[i+14], 17, -1502002290); + b = FF(b, c, d, a, m[i+15], 22, 1236535329); + + a = GG(a, b, c, d, m[i+ 1], 5, -165796510); + d = GG(d, a, b, c, m[i+ 6], 9, -1069501632); + c = GG(c, d, a, b, m[i+11], 14, 643717713); + b = GG(b, c, d, a, m[i+ 0], 20, -373897302); + a = GG(a, b, c, d, m[i+ 5], 5, -701558691); + d = GG(d, a, b, c, m[i+10], 9, 38016083); + c = GG(c, d, a, b, m[i+15], 14, -660478335); + b = GG(b, c, d, a, m[i+ 4], 20, -405537848); + a = GG(a, b, c, d, m[i+ 9], 5, 568446438); + d = GG(d, a, b, c, m[i+14], 9, -1019803690); + c = GG(c, d, a, b, m[i+ 3], 14, -187363961); + b = GG(b, c, d, a, m[i+ 8], 20, 1163531501); + a = GG(a, b, c, d, m[i+13], 5, -1444681467); + d = GG(d, a, b, c, m[i+ 2], 9, -51403784); + c = GG(c, d, a, b, m[i+ 7], 14, 1735328473); + b = GG(b, c, d, a, m[i+12], 20, -1926607734); + + a = HH(a, b, c, d, m[i+ 5], 4, -378558); + d = HH(d, a, b, c, m[i+ 8], 11, -2022574463); + c = HH(c, d, a, b, m[i+11], 16, 1839030562); + b = HH(b, c, d, a, m[i+14], 23, -35309556); + a = HH(a, b, c, d, m[i+ 1], 4, -1530992060); + d = HH(d, a, b, c, m[i+ 4], 11, 1272893353); + c = HH(c, d, a, b, m[i+ 7], 16, -155497632); + b = HH(b, c, d, a, m[i+10], 23, -1094730640); + a = HH(a, b, c, d, m[i+13], 4, 681279174); + d = HH(d, a, b, c, m[i+ 0], 11, -358537222); + c = HH(c, d, a, b, m[i+ 3], 16, -722521979); + b = HH(b, c, d, a, m[i+ 6], 23, 76029189); + a = HH(a, b, c, d, m[i+ 9], 4, -640364487); + d = HH(d, a, b, c, m[i+12], 11, -421815835); + c = HH(c, d, a, b, m[i+15], 16, 530742520); + b = HH(b, c, d, a, m[i+ 2], 23, -995338651); + + a = II(a, b, c, d, m[i+ 0], 6, -198630844); + d = II(d, a, b, c, m[i+ 7], 10, 1126891415); + c = II(c, d, a, b, m[i+14], 15, -1416354905); + b = II(b, c, d, a, m[i+ 5], 21, -57434055); + a = II(a, b, c, d, m[i+12], 6, 1700485571); + d = II(d, a, b, c, m[i+ 3], 10, -1894986606); + c = II(c, d, a, b, m[i+10], 15, -1051523); + b = II(b, c, d, a, m[i+ 1], 21, -2054922799); + a = II(a, b, c, d, m[i+ 8], 6, 1873313359); + d = II(d, a, b, c, m[i+15], 10, -30611744); + c = II(c, d, a, b, m[i+ 6], 15, -1560198380); + b = II(b, c, d, a, m[i+13], 21, 1309151649); + a = II(a, b, c, d, m[i+ 4], 6, -145523070); + d = II(d, a, b, c, m[i+11], 10, -1120210379); + c = II(c, d, a, b, m[i+ 2], 15, 718787259); + b = II(b, c, d, a, m[i+ 9], 21, -343485551); + + a = (a + aa) >>> 0; + b = (b + bb) >>> 0; + c = (c + cc) >>> 0; + d = (d + dd) >>> 0; + } + + return crypt.endian([a, b, c, d]); + }; + + // Auxiliary functions + md5._ff = function (a, b, c, d, x, s, t) { + var n = a + (b & c | ~b & d) + (x >>> 0) + t; + return ((n << s) | (n >>> (32 - s))) + b; + }; + md5._gg = function (a, b, c, d, x, s, t) { + var n = a + (b & d | c & ~d) + (x >>> 0) + t; + return ((n << s) | (n >>> (32 - s))) + b; + }; + md5._hh = function (a, b, c, d, x, s, t) { + var n = a + (b ^ c ^ d) + (x >>> 0) + t; + return ((n << s) | (n >>> (32 - s))) + b; + }; + md5._ii = function (a, b, c, d, x, s, t) { + var n = a + (c ^ (b | ~d)) + (x >>> 0) + t; + return ((n << s) | (n >>> (32 - s))) + b; + }; + + // Package private blocksize + md5._blocksize = 16; + md5._digestsize = 16; + + module.exports = function (message, options) { + if (message === undefined || message === null) + throw new Error('Illegal argument ' + message); + + var digestbytes = crypt.wordsToBytes(md5(message, options)); + return options && options.asBytes ? digestbytes : + options && options.asString ? bin.bytesToString(digestbytes) : + crypt.bytesToHex(digestbytes); + }; + +})(); -/***/ }, -/* 3 */ -/***/ function(module, exports) { +},{"charenc":24,"crypt":25,"is-buffer":26}],24:[function(require,module,exports){ +var charenc = { + // UTF-8 encoding + utf8: { + // Convert a string to a byte array + stringToBytes: function(str) { + return charenc.bin.stringToBytes(unescape(encodeURIComponent(str))); + }, - module.exports = require("react"); + // Convert a byte array to a string + bytesToString: function(bytes) { + return decodeURIComponent(escape(charenc.bin.bytesToString(bytes))); + } + }, -/***/ }, -/* 4 */ -/***/ function(module, exports) { + // Binary encoding + bin: { + // Convert a string to a byte array + stringToBytes: function(str) { + for (var bytes = [], i = 0; i < str.length; i++) + bytes.push(str.charCodeAt(i) & 0xFF); + return bytes; + }, - /** - * Creates an array of chunk objects representing both higlightable and non highlightable pieces of text that match each search word. - * @param searchWords string[] - * @param textToSearch string - * @return {start:number, end:number, highlight:boolean}[] - */ - 'use strict'; - - Object.defineProperty(exports, '__esModule', { - value: true - }); - var findAll = function findAll(textToSearch, wordsToFind, sanitize) { - return fillInChunks(combineChunks(findChunks(textToSearch, wordsToFind, sanitize)), textToSearch.length); - }; - - exports.findAll = findAll; - /** - * Takes an array of {start:number, end:number} objects and combines chunks that overlap into single chunks. - * @param chunks {start:number, end:number}[] - * @return {start:number, end:number}[] - */ - var combineChunks = function combineChunks(chunks) { - chunks = chunks.sort(function (first, second) { - return first.start - second.start; - }).reduce(function (processedChunks, nextChunk) { - // First chunk just goes straight in the array... - if (processedChunks.length === 0) { - return [nextChunk]; - } else { - // ... subsequent chunks get checked to see if they overlap... - var prevChunk = processedChunks.pop(); - if (nextChunk.start <= prevChunk.end) { - // It may be the case that prevChunk completely surrounds nextChunk, so take the - // largest of the end indeces. - var endIndex = Math.max(prevChunk.end, nextChunk.end); - processedChunks.push({ start: prevChunk.start, end: endIndex }); - } else { - processedChunks.push(prevChunk, nextChunk); - } - return processedChunks; - } - }, []); - - return chunks; - }; - - exports.combineChunks = combineChunks; - /** - * Examine textToSearch for any matches. - * If we find matches, add them to the returned array as a "chunk" object ({start:number, end:number}). - * @param textToSearch string - * @param wordsToFind string[] - * @param sanitize Process and optionally modify textToSearch and wordsToFind before comparison; this can be used to eg. remove accents - * @return {start:number, end:number}[] - */ - var findChunks = function findChunks(textToSearch, wordsToFind) { - var sanitize = arguments.length <= 2 || arguments[2] === undefined ? identity : arguments[2]; - return wordsToFind.filter(function (searchWord) { - return searchWord; - }) // Remove empty words - .reduce(function (chunks, searchWord) { - var normalizedWord = sanitize(searchWord); - var normalizedText = sanitize(textToSearch); - var regex = new RegExp(normalizedWord, 'gi'); - var match = undefined; - while ((match = regex.exec(normalizedText)) != null) { - chunks.push({ start: match.index, end: regex.lastIndex }); - } - return chunks; - }, []); - }; - - exports.findChunks = findChunks; - /** - * Given a set of chunks to highlight, create an additional set of chunks - * to represent the bits of text between the highlighted text. - * @param chunksToHighlight {start:number, end:number}[] - * @param totalLength number - * @return {start:number, end:number, highlight:boolean}[] - */ - var fillInChunks = function fillInChunks(chunksToHighlight, totalLength) { - var allChunks = []; - var append = function append(start, end, highlight) { - if (end - start > 0) { - allChunks.push({ start: start, end: end, highlight: highlight }); - } - }; - - if (chunksToHighlight.length === 0) { - append(0, totalLength, false); - } else { - (function () { - var lastIndex = 0; - chunksToHighlight.forEach(function (chunk) { - append(lastIndex, chunk.start, false); - append(chunk.start, chunk.end, true); - lastIndex = chunk.end; - }); - append(lastIndex, totalLength, false); - })(); - } - return allChunks; - }; - - exports.fillInChunks = fillInChunks; - function identity(value) { - return value; - } + // Convert a byte array to a string + bytesToString: function(bytes) { + for (var str = [], i = 0; i < bytes.length; i++) + str.push(String.fromCharCode(bytes[i])); + return str.join(''); + } + } +}; -/***/ } -/******/ ]); +module.exports = charenc; -},{"react":undefined}],33:[function(require,module,exports){ -'use strict'; +},{}],25:[function(require,module,exports){ +(function() { + var base64map + = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', -Object.defineProperty(exports, "__esModule", { - value: true -}); + crypt = { + // Bit-wise rotation left + rotl: function(n, b) { + return (n << b) | (n >>> (32 - b)); + }, -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + // Bit-wise rotation right + rotr: function(n, b) { + return (n << (32 - b)) | (n >>> b); + }, -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + // Swap big-endian to little-endian and vice versa + endian: function(n) { + // If number given, swap endian + if (n.constructor == Number) { + return crypt.rotl(n, 8) & 0x00FF00FF | crypt.rotl(n, 24) & 0xFF00FF00; + } -var _react = require('react'); + // Else, assume array and swap all items + for (var i = 0; i < n.length; i++) + n[i] = crypt.endian(n[i]); + return n; + }, + + // Generate an array of any length of random bytes + randomBytes: function(n) { + for (var bytes = []; n > 0; n--) + bytes.push(Math.floor(Math.random() * 256)); + return bytes; + }, + + // Convert a byte array to big-endian 32-bit words + bytesToWords: function(bytes) { + for (var words = [], i = 0, b = 0; i < bytes.length; i++, b += 8) + words[b >>> 5] |= bytes[i] << (24 - b % 32); + return words; + }, + + // Convert big-endian 32-bit words to a byte array + wordsToBytes: function(words) { + for (var bytes = [], b = 0; b < words.length * 32; b += 8) + bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF); + return bytes; + }, + + // Convert a byte array to a hex string + bytesToHex: function(bytes) { + for (var hex = [], i = 0; i < bytes.length; i++) { + hex.push((bytes[i] >>> 4).toString(16)); + hex.push((bytes[i] & 0xF).toString(16)); + } + return hex.join(''); + }, + + // Convert a hex string to a byte array + hexToBytes: function(hex) { + for (var bytes = [], c = 0; c < hex.length; c += 2) + bytes.push(parseInt(hex.substr(c, 2), 16)); + return bytes; + }, + + // Convert a byte array to a base-64 string + bytesToBase64: function(bytes) { + for (var base64 = [], i = 0; i < bytes.length; i += 3) { + var triplet = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]; + for (var j = 0; j < 4; j++) + if (i * 8 + j * 6 <= bytes.length * 8) + base64.push(base64map.charAt((triplet >>> 6 * (3 - j)) & 0x3F)); + else + base64.push('='); + } + return base64.join(''); + }, + + // Convert a base-64 string to a byte array + base64ToBytes: function(base64) { + // Remove non-base-64 characters + base64 = base64.replace(/[^A-Z0-9+\/]/ig, ''); + + for (var bytes = [], i = 0, imod4 = 0; i < base64.length; + imod4 = ++i % 4) { + if (imod4 == 0) continue; + bytes.push(((base64map.indexOf(base64.charAt(i - 1)) + & (Math.pow(2, -2 * imod4 + 8) - 1)) << (imod4 * 2)) + | (base64map.indexOf(base64.charAt(i)) >>> (6 - imod4 * 2))); + } + return bytes; + } + }; + + module.exports = crypt; +})(); + +},{}],26:[function(require,module,exports){ +/*! + * Determine if an object is a Buffer + * + * @author Feross Aboukhadijeh + * @license MIT + */ + +// The _isBuffer check is for Safari 5-7 support, because it's missing +// Object.prototype.constructor. Remove this eventually +module.exports = function (obj) { + return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer) +} -var _react2 = _interopRequireDefault(_react); +function isBuffer (obj) { + return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj) +} -var _reactSelect = require('react-select'); +// For Node v0.10 support. Remove this eventually. +function isSlowBuffer (obj) { + return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0)) +} -var _reactSelect2 = _interopRequireDefault(_reactSelect); +},{}],27:[function(require,module,exports){ +'use strict'; +var strictUriEncode = require('strict-uri-encode'); +var objectAssign = require('object-assign'); -var _reactVirtualized = require('react-virtualized'); +function encoderForArrayFormat(opts) { + switch (opts.arrayFormat) { + case 'index': + return function (key, value, index) { + return value === null ? [ + encode(key, opts), + '[', + index, + ']' + ].join('') : [ + encode(key, opts), + '[', + encode(index, opts), + ']=', + encode(value, opts) + ].join(''); + }; -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + case 'bracket': + return function (key, value) { + return value === null ? encode(key, opts) : [ + encode(key, opts), + '[]=', + encode(value, opts) + ].join(''); + }; -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + default: + return function (key, value) { + return value === null ? encode(key, opts) : [ + encode(key, opts), + '=', + encode(value, opts) + ].join(''); + }; + } +} -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } +function parserForArrayFormat(opts) { + var result; -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + switch (opts.arrayFormat) { + case 'index': + return function (key, value, accumulator) { + result = /\[(\d*)\]$/.exec(key); -var VirtualizedSelect = function (_Component) { - _inherits(VirtualizedSelect, _Component); + key = key.replace(/\[\d*\]$/, ''); - function VirtualizedSelect(props, context) { - _classCallCheck(this, VirtualizedSelect); + if (!result) { + accumulator[key] = value; + return; + } - var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(VirtualizedSelect).call(this, props, context)); + if (accumulator[key] === undefined) { + accumulator[key] = {}; + } - _this._renderMenu = _this._renderMenu.bind(_this); - _this._optionRenderer = _this._optionRenderer.bind(_this); - return _this; - } + accumulator[key][result[1]] = value; + }; - /** See VirtualScroll#recomputeRowHeights */ + case 'bracket': + return function (key, value, accumulator) { + result = /(\[\])$/.exec(key); + key = key.replace(/\[\]$/, ''); + if (!result) { + accumulator[key] = value; + return; + } else if (accumulator[key] === undefined) { + accumulator[key] = [value]; + return; + } - _createClass(VirtualizedSelect, [{ - key: 'recomputeOptionHeights', - value: function recomputeOptionHeights() { - var index = arguments.length <= 0 || arguments[0] === undefined ? 0 : arguments[0]; + accumulator[key] = [].concat(accumulator[key], value); + }; - if (this._virtualScroll) { - this._virtualScroll.recomputeRowHeights(index); - } - } - }, { - key: 'render', - value: function render() { - var SelectComponent = this._getSelectComponent(); + default: + return function (key, value, accumulator) { + if (accumulator[key] === undefined) { + accumulator[key] = value; + return; + } - return _react2.default.createElement(SelectComponent, _extends({}, this.props, { - menuRenderer: this._renderMenu, - menuStyle: { overflow: 'hidden' } - })); - } + accumulator[key] = [].concat(accumulator[key], value); + }; + } +} - // See https://github.com/JedWatson/react-select/#effeciently-rendering-large-lists-with-windowing +function encode(value, opts) { + if (opts.encode) { + return opts.strict ? strictUriEncode(value) : encodeURIComponent(value); + } - }, { - key: '_renderMenu', - value: function _renderMenu(_ref) { - var _this2 = this; + return value; +} - var focusedOption = _ref.focusedOption; - var focusOption = _ref.focusOption; - var labelKey = _ref.labelKey; - var options = _ref.options; - var selectValue = _ref.selectValue; - var valueArray = _ref.valueArray; - var optionRenderer = this.props.optionRenderer; +function keysSorter(input) { + if (Array.isArray(input)) { + return input.sort(); + } else if (typeof input === 'object') { + return keysSorter(Object.keys(input)).sort(function (a, b) { + return Number(a) - Number(b); + }).map(function (key) { + return input[key]; + }); + } - var focusedOptionIndex = options.indexOf(focusedOption); - var height = this._calculateVirtualScrollHeight({ options: options }); - var innerRowRenderer = optionRenderer || this._optionRenderer; + return input; +} - function wrappedRowRenderer(_ref2) { - var index = _ref2.index; +exports.extract = function (str) { + return str.split('?')[1] || ''; +}; - var option = options[index]; +exports.parse = function (str, opts) { + opts = objectAssign({arrayFormat: 'none'}, opts); - return innerRowRenderer({ - focusedOption: focusedOption, - focusedOptionIndex: focusedOptionIndex, - focusOption: focusOption, - labelKey: labelKey, - option: option, - optionIndex: index, - options: options, - selectValue: selectValue, - valueArray: valueArray - }); - } + var formatter = parserForArrayFormat(opts); - return _react2.default.createElement( - _reactVirtualized.AutoSizer, - { disableHeight: true }, - function (_ref3) { - var width = _ref3.width; - return _react2.default.createElement(_reactVirtualized.VirtualScroll, { - className: 'VirtualSelectGrid', - height: height, - ref: function ref(_ref5) { - return _this2._virtualScroll = _ref5; - }, - rowCount: options.length, - rowHeight: function rowHeight(_ref4) { - var index = _ref4.index; - return _this2._getOptionHeight({ - option: options[index] - }); - }, - rowRenderer: wrappedRowRenderer, - scrollToIndex: focusedOptionIndex, - width: width - }); - } - ); - } - }, { - key: '_calculateVirtualScrollHeight', - value: function _calculateVirtualScrollHeight(_ref6) { - var options = _ref6.options; - var maxHeight = this.props.maxHeight; + // Create an object with no prototype + // https://github.com/sindresorhus/query-string/issues/47 + var ret = Object.create(null); + if (typeof str !== 'string') { + return ret; + } - var height = 0; + str = str.trim().replace(/^(\?|#|&)/, ''); - for (var optionIndex = 0; optionIndex < options.length; optionIndex++) { - var option = options[optionIndex]; + if (!str) { + return ret; + } - height += this._getOptionHeight({ option: option }); + str.split('&').forEach(function (param) { + var parts = param.replace(/\+/g, ' ').split('='); + // Firefox (pre 40) decodes `%3D` to `=` + // https://github.com/sindresorhus/query-string/pull/37 + var key = parts.shift(); + var val = parts.length > 0 ? parts.join('=') : undefined; - if (height > maxHeight) { - return maxHeight; - } - } + // missing `=` should be `null`: + // http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters + val = val === undefined ? null : decodeURIComponent(val); - return height; - } - }, { - key: '_getOptionHeight', - value: function _getOptionHeight(_ref7) { - var option = _ref7.option; - var optionHeight = this.props.optionHeight; + formatter(decodeURIComponent(key), val, ret); + }); + return Object.keys(ret).sort().reduce(function (result, key) { + var val = ret[key]; + if (Boolean(val) && typeof val === 'object' && !Array.isArray(val)) { + // Sort object keys, not values + result[key] = keysSorter(val); + } else { + result[key] = val; + } - return optionHeight instanceof Function ? optionHeight({ option: option }) : optionHeight; - } - }, { - key: '_getSelectComponent', - value: function _getSelectComponent() { - var _props = this.props; - var async = _props.async; - var selectComponent = _props.selectComponent; + return result; + }, Object.create(null)); +}; +exports.stringify = function (obj, opts) { + var defaults = { + encode: true, + strict: true, + arrayFormat: 'none' + }; - if (selectComponent) { - return selectComponent; - } else if (async) { - return _reactSelect2.default.Async; - } else { - return _reactSelect2.default; - } - } - }, { - key: '_optionRenderer', - value: function _optionRenderer(_ref8) { - var focusedOption = _ref8.focusedOption; - var focusOption = _ref8.focusOption; - var labelKey = _ref8.labelKey; - var option = _ref8.option; - var selectValue = _ref8.selectValue; + opts = objectAssign(defaults, opts); - var height = this._getOptionHeight({ option: option }); + var formatter = encoderForArrayFormat(opts); - var className = ['VirtualizedSelectOption']; + return obj ? Object.keys(obj).sort().map(function (key) { + var val = obj[key]; - if (option === focusedOption) { - className.push('VirtualizedSelectFocusedOption'); - } + if (val === undefined) { + return ''; + } - if (option.disabled) { - className.push('VirtualizedSelectDisabledOption'); - } + if (val === null) { + return encode(key, opts); + } - var events = option.disabled ? {} : { - onClick: function onClick() { - return selectValue(option); - }, - onMouseOver: function onMouseOver() { - return focusOption(option); - } - }; + if (Array.isArray(val)) { + var result = []; - return _react2.default.createElement( - 'div', - _extends({ - className: className.join(' '), - style: { height: height } - }, events), - option[labelKey] - ); - } - }]); + val.slice().forEach(function (val2) { + if (val2 === undefined) { + return; + } - return VirtualizedSelect; -}(_react.Component); + result.push(formatter(key, val2, result.length)); + }); -VirtualizedSelect.propTypes = { - async: _react.PropTypes.bool, - maxHeight: _react.PropTypes.number.isRequired, - optionHeight: _react.PropTypes.oneOfType([_react.PropTypes.number, _react.PropTypes.func]).isRequired, - optionRenderer: _react.PropTypes.func, - selectComponent: _react.PropTypes.func -}; -VirtualizedSelect.defaultProps = { - async: false, - maxHeight: 200, - optionHeight: 35 -}; -exports.default = VirtualizedSelect; -},{"react":undefined,"react-select":undefined,"react-virtualized":77}],34:[function(require,module,exports){ -'use strict'; + return result.join('&'); + } -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.default = undefined; + return encode(key, opts) + '=' + encode(val, opts); + }).filter(function (x) { + return x.length > 0; + }).join('&') : ''; +}; -var _VirtualizedSelect = require('./VirtualizedSelect'); +},{"object-assign":28,"strict-uri-encode":29}],28:[function(require,module,exports){ +/* +object-assign +(c) Sindre Sorhus +@license MIT +*/ -var _VirtualizedSelect2 = _interopRequireDefault(_VirtualizedSelect); +'use strict'; +/* eslint-disable no-unused-vars */ +var getOwnPropertySymbols = Object.getOwnPropertySymbols; +var hasOwnProperty = Object.prototype.hasOwnProperty; +var propIsEnumerable = Object.prototype.propertyIsEnumerable; -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +function toObject(val) { + if (val === null || val === undefined) { + throw new TypeError('Object.assign cannot be called with null or undefined'); + } -exports.default = _VirtualizedSelect2.default; -},{"./VirtualizedSelect":33}],35:[function(require,module,exports){ -arguments[4][34][0].apply(exports,arguments) -},{"./VirtualizedSelect":34,"dup":34}],36:[function(require,module,exports){ -'use strict'; + return Object(val); +} -Object.defineProperty(exports, "__esModule", { - value: true -}); +function shouldUseNative() { + try { + if (!Object.assign) { + return false; + } -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + // Detect buggy property enumeration order in older V8 versions. -var _react = require('react'); + // https://bugs.chromium.org/p/v8/issues/detail?id=4118 + var test1 = new String('abc'); // eslint-disable-line no-new-wrappers + test1[5] = 'de'; + if (Object.getOwnPropertyNames(test1)[0] === '5') { + return false; + } -var _react2 = _interopRequireDefault(_react); + // https://bugs.chromium.org/p/v8/issues/detail?id=3056 + var test2 = {}; + for (var i = 0; i < 10; i++) { + test2['_' + String.fromCharCode(i)] = i; + } + var order2 = Object.getOwnPropertyNames(test2).map(function (n) { + return test2[n]; + }); + if (order2.join('') !== '0123456789') { + return false; + } -var _reactAddonsShallowCompare = require('react-addons-shallow-compare'); + // https://bugs.chromium.org/p/v8/issues/detail?id=3056 + var test3 = {}; + 'abcdefghijklmnopqrst'.split('').forEach(function (letter) { + test3[letter] = letter; + }); + if (Object.keys(Object.assign({}, test3)).join('') !== + 'abcdefghijklmnopqrst') { + return false; + } -var _reactAddonsShallowCompare2 = _interopRequireDefault(_reactAddonsShallowCompare); + return true; + } catch (err) { + // We don't expect any of the above to throw, but better to be safe. + return false; + } +} -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +module.exports = shouldUseNative() ? Object.assign : function (target, source) { + var from; + var to = toObject(target); + var symbols; -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + for (var s = 1; s < arguments.length; s++) { + from = Object(arguments[s]); -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + for (var key in from) { + if (hasOwnProperty.call(from, key)) { + to[key] = from[key]; + } + } -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + if (getOwnPropertySymbols) { + symbols = getOwnPropertySymbols(from); + for (var i = 0; i < symbols.length; i++) { + if (propIsEnumerable.call(from, symbols[i])) { + to[symbols[i]] = from[symbols[i]]; + } + } + } + } -/** - * This HOC decorates a virtualized component and responds to arrow-key events by scrolling one row or column at a time. - */ -var ArrowKeyStepper = function (_Component) { - _inherits(ArrowKeyStepper, _Component); + return to; +}; - function ArrowKeyStepper(props, context) { - _classCallCheck(this, ArrowKeyStepper); +},{}],29:[function(require,module,exports){ +'use strict'; +module.exports = function (str) { + return encodeURIComponent(str).replace(/[!'()*]/g, function (c) { + return '%' + c.charCodeAt(0).toString(16).toUpperCase(); + }); +}; - var _this = _possibleConstructorReturn(this, (ArrowKeyStepper.__proto__ || Object.getPrototypeOf(ArrowKeyStepper)).call(this, props, context)); +},{}],30:[function(require,module,exports){ +module.exports = +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; +/******/ +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.loaded = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ function(module, exports, __webpack_require__) { - _this.state = { - scrollToColumn: 0, - scrollToRow: 0 - }; + module.exports = __webpack_require__(1); - _this._columnStartIndex = 0; - _this._columnStopIndex = 0; - _this._rowStartIndex = 0; - _this._rowStopIndex = 0; - _this._onKeyDown = _this._onKeyDown.bind(_this); - _this._onSectionRendered = _this._onSectionRendered.bind(_this); - return _this; - } +/***/ }, +/* 1 */ +/***/ function(module, exports, __webpack_require__) { - _createClass(ArrowKeyStepper, [{ - key: 'render', - value: function render() { - var _props = this.props; - var className = _props.className; - var children = _props.children; - var _state = this.state; - var scrollToColumn = _state.scrollToColumn; - var scrollToRow = _state.scrollToRow; + 'use strict'; + + Object.defineProperty(exports, '__esModule', { + value: true + }); + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _Highlighter = __webpack_require__(2); + + var _Highlighter2 = _interopRequireDefault(_Highlighter); + + var _utils = __webpack_require__(4); + + exports['default'] = _Highlighter2['default']; + exports.combineChunks = _utils.combineChunks; + exports.fillInChunks = _utils.fillInChunks; + exports.findAll = _utils.findAll; + exports.findChunks = _utils.findChunks; +/***/ }, +/* 2 */ +/***/ function(module, exports, __webpack_require__) { - return _react2.default.createElement( - 'div', - { - className: className, - onKeyDown: this._onKeyDown - }, - children({ - onSectionRendered: this._onSectionRendered, - scrollToColumn: scrollToColumn, - scrollToRow: scrollToRow - }) - ); - } - }, { - key: 'shouldComponentUpdate', - value: function shouldComponentUpdate(nextProps, nextState) { - return (0, _reactAddonsShallowCompare2.default)(this, nextProps, nextState); - } - }, { - key: '_onKeyDown', - value: function _onKeyDown(event) { - var _props2 = this.props; - var columnCount = _props2.columnCount; - var rowCount = _props2.rowCount; + 'use strict'; + + Object.defineProperty(exports, '__esModule', { + value: true + }); + exports['default'] = Highlighter; + + function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } } + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _react = __webpack_require__(3); + + var _react2 = _interopRequireDefault(_react); + + var _utilsJs = __webpack_require__(4); + + var Chunks = _interopRequireWildcard(_utilsJs); + + Highlighter.propTypes = { + highlightClassName: _react.PropTypes.string, + highlightStyle: _react.PropTypes.object, + searchWords: _react.PropTypes.arrayOf(_react.PropTypes.string).isRequired, + textToHighlight: _react.PropTypes.string.isRequired, + sanitize: _react.PropTypes.func + }; + + /** + * Highlights all occurrences of search terms (searchText) within a string (textToHighlight). + * This function returns an array of strings and s (wrapping highlighted words). + */ + + function Highlighter(_ref) { + var _ref$highlightClassName = _ref.highlightClassName; + var highlightClassName = _ref$highlightClassName === undefined ? '' : _ref$highlightClassName; + var _ref$highlightStyle = _ref.highlightStyle; + var highlightStyle = _ref$highlightStyle === undefined ? {} : _ref$highlightStyle; + var searchWords = _ref.searchWords; + var textToHighlight = _ref.textToHighlight; + var sanitize = _ref.sanitize; + + var chunks = Chunks.findAll(textToHighlight, searchWords, sanitize); + + return _react2['default'].createElement( + 'span', + null, + chunks.map(function (chunk, index) { + var text = textToHighlight.substr(chunk.start, chunk.end - chunk.start); + + if (chunk.highlight) { + return _react2['default'].createElement( + 'mark', + { + className: highlightClassName, + key: index, + style: highlightStyle + }, + text + ); + } else { + return _react2['default'].createElement( + 'span', + { key: index }, + text + ); + } + }) + ); + } + + module.exports = exports['default']; - // The above cases all prevent default event event behavior. - // This is to keep the grid from scrolling after the snap-to update. +/***/ }, +/* 3 */ +/***/ function(module, exports) { - switch (event.key) { - case 'ArrowDown': - event.preventDefault(); - this.setState({ - scrollToRow: Math.min(this._rowStopIndex + 1, rowCount - 1) - }); - break; - case 'ArrowLeft': - event.preventDefault(); - this.setState({ - scrollToColumn: Math.max(this._columnStartIndex - 1, 0) - }); - break; - case 'ArrowRight': - event.preventDefault(); - this.setState({ - scrollToColumn: Math.min(this._columnStopIndex + 1, columnCount - 1) - }); - break; - case 'ArrowUp': - event.preventDefault(); - this.setState({ - scrollToRow: Math.max(this._rowStartIndex - 1, 0) - }); - break; - } - } - }, { - key: '_onSectionRendered', - value: function _onSectionRendered(_ref) { - var columnStartIndex = _ref.columnStartIndex; - var columnStopIndex = _ref.columnStopIndex; - var rowStartIndex = _ref.rowStartIndex; - var rowStopIndex = _ref.rowStopIndex; + module.exports = require("react"); - this._columnStartIndex = columnStartIndex; - this._columnStopIndex = columnStopIndex; - this._rowStartIndex = rowStartIndex; - this._rowStopIndex = rowStopIndex; - } - }]); +/***/ }, +/* 4 */ +/***/ function(module, exports) { + + /** + * Creates an array of chunk objects representing both higlightable and non highlightable pieces of text that match each search word. + * @param searchWords string[] + * @param textToSearch string + * @return {start:number, end:number, highlight:boolean}[] + */ + 'use strict'; + + Object.defineProperty(exports, '__esModule', { + value: true + }); + var findAll = function findAll(textToSearch, wordsToFind, sanitize) { + return fillInChunks(combineChunks(findChunks(textToSearch, wordsToFind, sanitize)), textToSearch.length); + }; + + exports.findAll = findAll; + /** + * Takes an array of {start:number, end:number} objects and combines chunks that overlap into single chunks. + * @param chunks {start:number, end:number}[] + * @return {start:number, end:number}[] + */ + var combineChunks = function combineChunks(chunks) { + chunks = chunks.sort(function (first, second) { + return first.start - second.start; + }).reduce(function (processedChunks, nextChunk) { + // First chunk just goes straight in the array... + if (processedChunks.length === 0) { + return [nextChunk]; + } else { + // ... subsequent chunks get checked to see if they overlap... + var prevChunk = processedChunks.pop(); + if (nextChunk.start <= prevChunk.end) { + // It may be the case that prevChunk completely surrounds nextChunk, so take the + // largest of the end indeces. + var endIndex = Math.max(prevChunk.end, nextChunk.end); + processedChunks.push({ start: prevChunk.start, end: endIndex }); + } else { + processedChunks.push(prevChunk, nextChunk); + } + return processedChunks; + } + }, []); + + return chunks; + }; + + exports.combineChunks = combineChunks; + /** + * Examine textToSearch for any matches. + * If we find matches, add them to the returned array as a "chunk" object ({start:number, end:number}). + * @param textToSearch string + * @param wordsToFind string[] + * @param sanitize Process and optionally modify textToSearch and wordsToFind before comparison; this can be used to eg. remove accents + * @return {start:number, end:number}[] + */ + var findChunks = function findChunks(textToSearch, wordsToFind) { + var sanitize = arguments.length <= 2 || arguments[2] === undefined ? identity : arguments[2]; + return wordsToFind.filter(function (searchWord) { + return searchWord; + }) // Remove empty words + .reduce(function (chunks, searchWord) { + var normalizedWord = sanitize(searchWord); + var normalizedText = sanitize(textToSearch); + var regex = new RegExp(normalizedWord, 'gi'); + var match = undefined; + while ((match = regex.exec(normalizedText)) != null) { + chunks.push({ start: match.index, end: regex.lastIndex }); + } + return chunks; + }, []); + }; + + exports.findChunks = findChunks; + /** + * Given a set of chunks to highlight, create an additional set of chunks + * to represent the bits of text between the highlighted text. + * @param chunksToHighlight {start:number, end:number}[] + * @param totalLength number + * @return {start:number, end:number, highlight:boolean}[] + */ + var fillInChunks = function fillInChunks(chunksToHighlight, totalLength) { + var allChunks = []; + var append = function append(start, end, highlight) { + if (end - start > 0) { + allChunks.push({ start: start, end: end, highlight: highlight }); + } + }; + + if (chunksToHighlight.length === 0) { + append(0, totalLength, false); + } else { + (function () { + var lastIndex = 0; + chunksToHighlight.forEach(function (chunk) { + append(lastIndex, chunk.start, false); + append(chunk.start, chunk.end, true); + lastIndex = chunk.end; + }); + append(lastIndex, totalLength, false); + })(); + } + return allChunks; + }; + + exports.fillInChunks = fillInChunks; + function identity(value) { + return value; + } - return ArrowKeyStepper; -}(_react.Component); +/***/ } +/******/ ]); -ArrowKeyStepper.propTypes = { - children: _react.PropTypes.func.isRequired, - className: _react.PropTypes.string, - columnCount: _react.PropTypes.number.isRequired, - rowCount: _react.PropTypes.number.isRequired -}; -exports.default = ArrowKeyStepper; -},{"react":undefined,"react-addons-shallow-compare":30}],37:[function(require,module,exports){ +},{"react":undefined}],31:[function(require,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); -exports.ArrowKeyStepper = exports.default = undefined; - -var _ArrowKeyStepper2 = require('./ArrowKeyStepper'); - -var _ArrowKeyStepper3 = _interopRequireDefault(_ArrowKeyStepper2); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -exports.default = _ArrowKeyStepper3.default; -exports.ArrowKeyStepper = _ArrowKeyStepper3.default; -},{"./ArrowKeyStepper":36}],38:[function(require,module,exports){ -'use strict'; -Object.defineProperty(exports, "__esModule", { - value: true -}); +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); @@ -3103,9 +3068,11 @@ var _react = require('react'); var _react2 = _interopRequireDefault(_react); -var _reactAddonsShallowCompare = require('react-addons-shallow-compare'); +var _reactSelect = require('react-select'); -var _reactAddonsShallowCompare2 = _interopRequireDefault(_reactAddonsShallowCompare); +var _reactSelect2 = _interopRequireDefault(_reactSelect); + +var _reactVirtualized = require('react-virtualized'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -3115,172 +3082,225 @@ function _possibleConstructorReturn(self, call) { if (!self) { throw new Referen function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } -/** - * Decorator component that automatically adjusts the width and height of a single child. - * Child component should not be declared as a child but should rather be specified by a `ChildComponent` property. - * All other properties will be passed through to the child component. - */ -var AutoSizer = function (_Component) { - _inherits(AutoSizer, _Component); - - function AutoSizer(props) { - _classCallCheck(this, AutoSizer); +var VirtualizedSelect = function (_Component) { + _inherits(VirtualizedSelect, _Component); - var _this = _possibleConstructorReturn(this, (AutoSizer.__proto__ || Object.getPrototypeOf(AutoSizer)).call(this, props)); + function VirtualizedSelect(props, context) { + _classCallCheck(this, VirtualizedSelect); - _this.state = { - height: 0, - width: 0 - }; + var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(VirtualizedSelect).call(this, props, context)); - _this._onResize = _this._onResize.bind(_this); - _this._onScroll = _this._onScroll.bind(_this); - _this._setRef = _this._setRef.bind(_this); + _this._renderMenu = _this._renderMenu.bind(_this); + _this._optionRenderer = _this._optionRenderer.bind(_this); return _this; } - _createClass(AutoSizer, [{ - key: 'componentDidMount', - value: function componentDidMount() { - // Delay access of parentNode until mount. - // This handles edge-cases where the component has already been unmounted before its ref has been set, - // As well as libraries like react-lite which have a slightly different lifecycle. - this._parentNode = this._autoSizer.parentNode; + /** See VirtualScroll#recomputeRowHeights */ - // Defer requiring resize handler in order to support server-side rendering. - // See issue #41 - this._detectElementResize = require('../vendor/detectElementResize'); - this._detectElementResize.addResizeListener(this._parentNode, this._onResize); - this._onResize(); - } - }, { - key: 'componentWillUnmount', - value: function componentWillUnmount() { - if (this._detectElementResize) { - this._detectElementResize.removeResizeListener(this._parentNode, this._onResize); + _createClass(VirtualizedSelect, [{ + key: 'recomputeOptionHeights', + value: function recomputeOptionHeights() { + var index = arguments.length <= 0 || arguments[0] === undefined ? 0 : arguments[0]; + + if (this._virtualScroll) { + this._virtualScroll.recomputeRowHeights(index); } } }, { key: 'render', value: function render() { - var _props = this.props; - var children = _props.children; - var disableHeight = _props.disableHeight; - var disableWidth = _props.disableWidth; - var _state = this.state; - var height = _state.height; - var width = _state.width; + var SelectComponent = this._getSelectComponent(); - // Outer div should not force width/height since that may prevent containers from shrinking. - // Inner component should overflow and use calculated width/height. - // See issue #68 for more information. + return _react2.default.createElement(SelectComponent, _extends({}, this.props, { + menuRenderer: this._renderMenu, + menuStyle: { overflow: 'hidden' } + })); + } - var outerStyle = { overflow: 'visible' }; + // See https://github.com/JedWatson/react-select/#effeciently-rendering-large-lists-with-windowing - if (!disableHeight) { - outerStyle.height = 0; - } + }, { + key: '_renderMenu', + value: function _renderMenu(_ref) { + var _this2 = this; - if (!disableWidth) { - outerStyle.width = 0; + var focusedOption = _ref.focusedOption; + var focusOption = _ref.focusOption; + var labelKey = _ref.labelKey; + var options = _ref.options; + var selectValue = _ref.selectValue; + var valueArray = _ref.valueArray; + var optionRenderer = this.props.optionRenderer; + + var focusedOptionIndex = options.indexOf(focusedOption); + var height = this._calculateVirtualScrollHeight({ options: options }); + var innerRowRenderer = optionRenderer || this._optionRenderer; + + function wrappedRowRenderer(_ref2) { + var index = _ref2.index; + + var option = options[index]; + + return innerRowRenderer({ + focusedOption: focusedOption, + focusedOptionIndex: focusedOptionIndex, + focusOption: focusOption, + labelKey: labelKey, + option: option, + optionIndex: index, + options: options, + selectValue: selectValue, + valueArray: valueArray + }); } return _react2.default.createElement( - 'div', - { - ref: this._setRef, - onScroll: this._onScroll, - style: outerStyle - }, - children({ height: height, width: width }) + _reactVirtualized.AutoSizer, + { disableHeight: true }, + function (_ref3) { + var width = _ref3.width; + return _react2.default.createElement(_reactVirtualized.VirtualScroll, { + className: 'VirtualSelectGrid', + height: height, + ref: function ref(_ref5) { + return _this2._virtualScroll = _ref5; + }, + rowCount: options.length, + rowHeight: function rowHeight(_ref4) { + var index = _ref4.index; + return _this2._getOptionHeight({ + option: options[index] + }); + }, + rowRenderer: wrappedRowRenderer, + scrollToIndex: focusedOptionIndex, + width: width + }); + } ); } }, { - key: 'shouldComponentUpdate', - value: function shouldComponentUpdate(nextProps, nextState) { - return (0, _reactAddonsShallowCompare2.default)(this, nextProps, nextState); + key: '_calculateVirtualScrollHeight', + value: function _calculateVirtualScrollHeight(_ref6) { + var options = _ref6.options; + var maxHeight = this.props.maxHeight; + + + var height = 0; + + for (var optionIndex = 0; optionIndex < options.length; optionIndex++) { + var option = options[optionIndex]; + + height += this._getOptionHeight({ option: option }); + + if (height > maxHeight) { + return maxHeight; + } + } + + return height; } }, { - key: '_onResize', - value: function _onResize() { - var onResize = this.props.onResize; + key: '_getOptionHeight', + value: function _getOptionHeight(_ref7) { + var option = _ref7.option; + var optionHeight = this.props.optionHeight; + + + return optionHeight instanceof Function ? optionHeight({ option: option }) : optionHeight; + } + }, { + key: '_getSelectComponent', + value: function _getSelectComponent() { + var _props = this.props; + var async = _props.async; + var selectComponent = _props.selectComponent; + + + if (selectComponent) { + return selectComponent; + } else if (async) { + return _reactSelect2.default.Async; + } else { + return _reactSelect2.default; + } + } + }, { + key: '_optionRenderer', + value: function _optionRenderer(_ref8) { + var focusedOption = _ref8.focusedOption; + var focusOption = _ref8.focusOption; + var labelKey = _ref8.labelKey; + var option = _ref8.option; + var selectValue = _ref8.selectValue; - // Gaurd against AutoSizer component being removed from the DOM immediately after being added. - // This can result in invalid style values which can result in NaN values if we don't handle them. - // See issue #150 for more context. + var height = this._getOptionHeight({ option: option }); - var boundingRect = this._parentNode.getBoundingClientRect(); - var height = boundingRect.height || 0; - var width = boundingRect.width || 0; + var className = ['VirtualizedSelectOption']; - var style = getComputedStyle(this._parentNode); - var paddingLeft = parseInt(style.paddingLeft, 10) || 0; - var paddingRight = parseInt(style.paddingRight, 10) || 0; - var paddingTop = parseInt(style.paddingTop, 10) || 0; - var paddingBottom = parseInt(style.paddingBottom, 10) || 0; + if (option === focusedOption) { + className.push('VirtualizedSelectFocusedOption'); + } - this.setState({ - height: height - paddingTop - paddingBottom, - width: width - paddingLeft - paddingRight - }); + if (option.disabled) { + className.push('VirtualizedSelectDisabledOption'); + } - onResize({ height: height, width: width }); - } - }, { - key: '_onScroll', - value: function _onScroll(event) { - // Prevent detectElementResize library from being triggered by this scroll event. - event.stopPropagation(); - } - }, { - key: '_setRef', - value: function _setRef(autoSizer) { - this._autoSizer = autoSizer; + var events = option.disabled ? {} : { + onClick: function onClick() { + return selectValue(option); + }, + onMouseOver: function onMouseOver() { + return focusOption(option); + } + }; + + return _react2.default.createElement( + 'div', + _extends({ + className: className.join(' '), + style: { height: height } + }, events), + option[labelKey] + ); } }]); - return AutoSizer; + return VirtualizedSelect; }(_react.Component); -AutoSizer.propTypes = { - /** - * Function respondible for rendering children. - * This function should implement the following signature: - * ({ height, width }) => PropTypes.element - */ - children: _react.PropTypes.func.isRequired, - - /** Disable dynamic :height property */ - disableHeight: _react.PropTypes.bool, - - /** Disable dynamic :width property */ - disableWidth: _react.PropTypes.bool, - - /** Callback to be invoked on-resize: ({ height, width }) */ - onResize: _react.PropTypes.func.isRequired +VirtualizedSelect.propTypes = { + async: _react.PropTypes.bool, + maxHeight: _react.PropTypes.number.isRequired, + optionHeight: _react.PropTypes.oneOfType([_react.PropTypes.number, _react.PropTypes.func]).isRequired, + optionRenderer: _react.PropTypes.func, + selectComponent: _react.PropTypes.func }; -AutoSizer.defaultProps = { - onResize: function onResize() {} +VirtualizedSelect.defaultProps = { + async: false, + maxHeight: 200, + optionHeight: 35 }; -exports.default = AutoSizer; -},{"../vendor/detectElementResize":80,"react":undefined,"react-addons-shallow-compare":30}],39:[function(require,module,exports){ +exports.default = VirtualizedSelect; +},{"react":undefined,"react-select":undefined,"react-virtualized":75}],32:[function(require,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); -exports.AutoSizer = exports.default = undefined; +exports.default = undefined; -var _AutoSizer2 = require('./AutoSizer'); +var _VirtualizedSelect = require('./VirtualizedSelect'); -var _AutoSizer3 = _interopRequireDefault(_AutoSizer2); +var _VirtualizedSelect2 = _interopRequireDefault(_VirtualizedSelect); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -exports.default = _AutoSizer3.default; -exports.AutoSizer = _AutoSizer3.default; -},{"./AutoSizer":38}],40:[function(require,module,exports){ +exports.default = _VirtualizedSelect2.default; +},{"./VirtualizedSelect":31}],33:[function(require,module,exports){ +arguments[4][32][0].apply(exports,arguments) +},{"./VirtualizedSelect":32,"dup":32}],34:[function(require,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { @@ -3297,305 +3317,149 @@ var _reactAddonsShallowCompare = require('react-addons-shallow-compare'); var _reactAddonsShallowCompare2 = _interopRequireDefault(_reactAddonsShallowCompare); -var _reactDom = require('react-dom'); - -var _reactDom2 = _interopRequireDefault(_reactDom); - -var _defaultCellSizeCache = require('./defaultCellSizeCache'); - -var _defaultCellSizeCache2 = _interopRequireDefault(_defaultCellSizeCache); - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - -/** - * Measures a Grid cell's contents by rendering them in a way that is not visible to the user. - * Either a fixed width or height may be provided if it is desirable to measure only in one direction. - */ -var CellMeasurer = function (_Component) { - _inherits(CellMeasurer, _Component); - - function CellMeasurer(props, state) { - _classCallCheck(this, CellMeasurer); - - var _this = _possibleConstructorReturn(this, (CellMeasurer.__proto__ || Object.getPrototypeOf(CellMeasurer)).call(this, props, state)); - - _this._cellSizeCache = props.cellSizeCache || new _defaultCellSizeCache2.default(); - - _this.getColumnWidth = _this.getColumnWidth.bind(_this); - _this.getRowHeight = _this.getRowHeight.bind(_this); - _this.resetMeasurements = _this.resetMeasurements.bind(_this); - _this.resetMeasurementForColumn = _this.resetMeasurementForColumn.bind(_this); - _this.resetMeasurementForRow = _this.resetMeasurementForRow.bind(_this); - return _this; - } - - _createClass(CellMeasurer, [{ - key: 'getColumnWidth', - value: function getColumnWidth(_ref) { - var index = _ref.index; - - if (this._cellSizeCache.hasColumnWidth(index)) { - return this._cellSizeCache.getColumnWidth(index); - } - - var rowCount = this.props.rowCount; - - - var maxWidth = 0; - - for (var rowIndex = 0; rowIndex < rowCount; rowIndex++) { - var _measureCell2 = this._measureCell({ - clientWidth: true, - columnIndex: index, - rowIndex: rowIndex - }); - - var width = _measureCell2.width; - - - maxWidth = Math.max(maxWidth, width); - } - - this._cellSizeCache.setColumnWidth(index, maxWidth); - - return maxWidth; - } - }, { - key: 'getRowHeight', - value: function getRowHeight(_ref2) { - var index = _ref2.index; - - if (this._cellSizeCache.hasRowHeight(index)) { - return this._cellSizeCache.getRowHeight(index); - } - - var columnCount = this.props.columnCount; - - - var maxHeight = 0; - - for (var columnIndex = 0; columnIndex < columnCount; columnIndex++) { - var _measureCell3 = this._measureCell({ - clientHeight: true, - columnIndex: columnIndex, - rowIndex: index - }); - - var height = _measureCell3.height; - - - maxHeight = Math.max(maxHeight, height); - } - - this._cellSizeCache.setRowHeight(index, maxHeight); - - return maxHeight; - } - }, { - key: 'resetMeasurementForColumn', - value: function resetMeasurementForColumn(columnIndex) { - this._cellSizeCache.clearColumnWidth(columnIndex); - } - }, { - key: 'resetMeasurementForRow', - value: function resetMeasurementForRow(rowIndex) { - this._cellSizeCache.clearRowHeight(rowIndex); - } - }, { - key: 'resetMeasurements', - value: function resetMeasurements() { - this._cellSizeCache.clearAllColumnWidths(); - this._cellSizeCache.clearAllRowHeights(); - } - }, { - key: 'componentDidMount', - value: function componentDidMount() { - this._renderAndMount(); - } - }, { - key: 'componentWillReceiveProps', - value: function componentWillReceiveProps(nextProps) { - var cellSizeCache = this.props.cellSizeCache; - - - if (cellSizeCache !== nextProps.cellSizeCache) { - this._cellSizeCache = nextProps.cellSizeCache; - } - - this._updateDivDimensions(nextProps); - } - }, { - key: 'componentWillUnmount', - value: function componentWillUnmount() { - this._unmountContainer(); - } - }, { - key: 'render', - value: function render() { - var children = this.props.children; - - - return children({ - getColumnWidth: this.getColumnWidth, - getRowHeight: this.getRowHeight, - resetMeasurements: this.resetMeasurements, - resetMeasurementForColumn: this.resetMeasurementForColumn, - resetMeasurementForRow: this.resetMeasurementForRow - }); - } - }, { - key: 'shouldComponentUpdate', - value: function shouldComponentUpdate(nextProps, nextState) { - return (0, _reactAddonsShallowCompare2.default)(this, nextProps, nextState); - } - }, { - key: '_getContainerNode', - value: function _getContainerNode(props) { - var container = props.container; - +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - if (container) { - return _reactDom2.default.findDOMNode(typeof container === 'function' ? container() : container); - } else { - return document.body; - } - } - }, { - key: '_measureCell', - value: function _measureCell(_ref3) { - var _ref3$clientHeight = _ref3.clientHeight; - var clientHeight = _ref3$clientHeight === undefined ? false : _ref3$clientHeight; - var _ref3$clientWidth = _ref3.clientWidth; - var clientWidth = _ref3$clientWidth === undefined ? true : _ref3$clientWidth; - var columnIndex = _ref3.columnIndex; - var rowIndex = _ref3.rowIndex; - var cellRenderer = this.props.cellRenderer; +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - var rendered = cellRenderer({ - columnIndex: columnIndex, - rowIndex: rowIndex - }); +/** + * This HOC decorates a virtualized component and responds to arrow-key events by scrolling one row or column at a time. + */ +var ArrowKeyStepper = function (_Component) { + _inherits(ArrowKeyStepper, _Component); - // Handle edge case where this method is called before the CellMeasurer has completed its initial render (and mounted). - this._renderAndMount(); + function ArrowKeyStepper(props, context) { + _classCallCheck(this, ArrowKeyStepper); - // @TODO Keep an eye on this for future React updates as the interface may change: - // https://twitter.com/soprano/status/737316379712331776 - _reactDom2.default.unstable_renderSubtreeIntoContainer(this, rendered, this._div); + var _this = _possibleConstructorReturn(this, (ArrowKeyStepper.__proto__ || Object.getPrototypeOf(ArrowKeyStepper)).call(this, props, context)); - var measurements = { - height: clientHeight && this._div.clientHeight, - width: clientWidth && this._div.clientWidth - }; + _this.state = { + scrollToColumn: 0, + scrollToRow: 0 + }; - _reactDom2.default.unmountComponentAtNode(this._div); + _this._columnStartIndex = 0; + _this._columnStopIndex = 0; + _this._rowStartIndex = 0; + _this._rowStopIndex = 0; - return measurements; - } - }, { - key: '_renderAndMount', - value: function _renderAndMount() { - if (!this._div) { - this._div = document.createElement('div'); - this._div.style.display = 'inline-block'; - this._div.style.position = 'absolute'; - this._div.style.visibility = 'hidden'; - this._div.style.zIndex = -1; + _this._onKeyDown = _this._onKeyDown.bind(_this); + _this._onSectionRendered = _this._onSectionRendered.bind(_this); + return _this; + } - this._updateDivDimensions(this.props); + _createClass(ArrowKeyStepper, [{ + key: 'render', + value: function render() { + var _props = this.props; + var className = _props.className; + var children = _props.children; + var _state = this.state; + var scrollToColumn = _state.scrollToColumn; + var scrollToRow = _state.scrollToRow; - this._containerNode = this._getContainerNode(this.props); - this._containerNode.appendChild(this._div); - } + + return _react2.default.createElement( + 'div', + { + className: className, + onKeyDown: this._onKeyDown + }, + children({ + onSectionRendered: this._onSectionRendered, + scrollToColumn: scrollToColumn, + scrollToRow: scrollToRow + }) + ); } }, { - key: '_unmountContainer', - value: function _unmountContainer() { - if (this._div) { - this._containerNode.removeChild(this._div); - - this._div = null; - } - - this._containerNode = null; + key: 'shouldComponentUpdate', + value: function shouldComponentUpdate(nextProps, nextState) { + return (0, _reactAddonsShallowCompare2.default)(this, nextProps, nextState); } }, { - key: '_updateDivDimensions', - value: function _updateDivDimensions(props) { - var height = props.height; - var width = props.width; + key: '_onKeyDown', + value: function _onKeyDown(event) { + var _props2 = this.props; + var columnCount = _props2.columnCount; + var rowCount = _props2.rowCount; + // The above cases all prevent default event event behavior. + // This is to keep the grid from scrolling after the snap-to update. - if (height && height !== this._divHeight) { - this._divHeight = height; - this._div.style.height = height + 'px'; + switch (event.key) { + case 'ArrowDown': + event.preventDefault(); + this.setState({ + scrollToRow: Math.min(this._rowStopIndex + 1, rowCount - 1) + }); + break; + case 'ArrowLeft': + event.preventDefault(); + this.setState({ + scrollToColumn: Math.max(this._columnStartIndex - 1, 0) + }); + break; + case 'ArrowRight': + event.preventDefault(); + this.setState({ + scrollToColumn: Math.min(this._columnStopIndex + 1, columnCount - 1) + }); + break; + case 'ArrowUp': + event.preventDefault(); + this.setState({ + scrollToRow: Math.max(this._rowStartIndex - 1, 0) + }); + break; } + } + }, { + key: '_onSectionRendered', + value: function _onSectionRendered(_ref) { + var columnStartIndex = _ref.columnStartIndex; + var columnStopIndex = _ref.columnStopIndex; + var rowStartIndex = _ref.rowStartIndex; + var rowStopIndex = _ref.rowStopIndex; - if (width && width !== this._divWidth) { - this._divWidth = width; - this._div.style.width = width + 'px'; - } + this._columnStartIndex = columnStartIndex; + this._columnStopIndex = columnStopIndex; + this._rowStartIndex = rowStartIndex; + this._rowStopIndex = rowStopIndex; } }]); - return CellMeasurer; + return ArrowKeyStepper; }(_react.Component); -CellMeasurer.propTypes = { - /** - * Renders a cell given its indices. - * Should implement the following interface: ({ columnIndex: number, rowIndex: number }): PropTypes.node - */ - cellRenderer: _react.PropTypes.func.isRequired, - - /** - * Optional, custom caching strategy for cell sizes. - */ - cellSizeCache: _react.PropTypes.object, - - /** - * Function respondible for rendering a virtualized component. - * This function should implement the following signature: - * ({ getColumnWidth, getRowHeight, resetMeasurements }) => PropTypes.element - */ +ArrowKeyStepper.propTypes = { children: _react.PropTypes.func.isRequired, - - /** - * Number of columns in grid. - */ + className: _react.PropTypes.string, columnCount: _react.PropTypes.number.isRequired, + rowCount: _react.PropTypes.number.isRequired +}; +exports.default = ArrowKeyStepper; +},{"react":undefined,"react-addons-shallow-compare":18}],35:[function(require,module,exports){ +'use strict'; - /** - * A Node, Component instance, or function that returns either. - * If this property is not specified the document body will be used. - */ - container: _react2.default.PropTypes.oneOfType([_react2.default.PropTypes.func, _react2.default.PropTypes.node]), +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ArrowKeyStepper = exports.default = undefined; - /** - * Assign a fixed :height in order to measure dynamic text :width only. - */ - height: _react.PropTypes.number, +var _ArrowKeyStepper2 = require('./ArrowKeyStepper'); - /** - * Number of rows in grid. - */ - rowCount: _react.PropTypes.number.isRequired, +var _ArrowKeyStepper3 = _interopRequireDefault(_ArrowKeyStepper2); - /** - * Assign a fixed :width in order to measure dynamic text :height only. - */ - width: _react.PropTypes.number -}; -exports.default = CellMeasurer; -},{"./defaultCellSizeCache":41,"react":undefined,"react-addons-shallow-compare":30,"react-dom":undefined}],41:[function(require,module,exports){ -"use strict"; +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = _ArrowKeyStepper3.default; +exports.ArrowKeyStepper = _ArrowKeyStepper3.default; +},{"./ArrowKeyStepper":34}],36:[function(require,module,exports){ +'use strict'; Object.defineProperty(exports, "__esModule", { value: true @@ -3603,773 +3467,709 @@ Object.defineProperty(exports, "__esModule", { var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactAddonsShallowCompare = require('react-addons-shallow-compare'); + +var _reactAddonsShallowCompare2 = _interopRequireDefault(_reactAddonsShallowCompare); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + /** - * Default CellMeasurer `cellSizeCache` implementation. - * Permanently caches all cell sizes (identified by column and row index) unless explicitly cleared. - * Can be configured to handle uniform cell widths and/or heights as a way of optimizing certain use cases. + * Decorator component that automatically adjusts the width and height of a single child. + * Child component should not be declared as a child but should rather be specified by a `ChildComponent` property. + * All other properties will be passed through to the child component. */ -var CellSizeCache = function () { - function CellSizeCache() { - var _ref = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; +var AutoSizer = function (_Component) { + _inherits(AutoSizer, _Component); - var _ref$uniformRowHeight = _ref.uniformRowHeight; - var uniformRowHeight = _ref$uniformRowHeight === undefined ? false : _ref$uniformRowHeight; - var _ref$uniformColumnWid = _ref.uniformColumnWidth; - var uniformColumnWidth = _ref$uniformColumnWid === undefined ? false : _ref$uniformColumnWid; + function AutoSizer(props) { + _classCallCheck(this, AutoSizer); - _classCallCheck(this, CellSizeCache); + var _this = _possibleConstructorReturn(this, (AutoSizer.__proto__ || Object.getPrototypeOf(AutoSizer)).call(this, props)); - this._uniformRowHeight = uniformRowHeight; - this._uniformColumnWidth = uniformColumnWidth; + _this.state = { + height: 0, + width: 0 + }; - this._cachedColumnWidths = {}; - this._cachedRowHeights = {}; + _this._onResize = _this._onResize.bind(_this); + _this._onScroll = _this._onScroll.bind(_this); + _this._setRef = _this._setRef.bind(_this); + return _this; } - _createClass(CellSizeCache, [{ - key: "clearAllColumnWidths", - value: function clearAllColumnWidths() { - this._cachedColumnWidth = undefined; - this._cachedColumnWidths = {}; - } - }, { - key: "clearAllRowHeights", - value: function clearAllRowHeights() { - this._cachedRowHeight = undefined; - this._cachedRowHeights = {}; - } - }, { - key: "clearColumnWidth", - value: function clearColumnWidth(index) { - this._cachedColumnWidth = undefined; + _createClass(AutoSizer, [{ + key: 'componentDidMount', + value: function componentDidMount() { + // Delay access of parentNode until mount. + // This handles edge-cases where the component has already been unmounted before its ref has been set, + // As well as libraries like react-lite which have a slightly different lifecycle. + this._parentNode = this._autoSizer.parentNode; - delete this._cachedColumnWidths[index]; - } - }, { - key: "clearRowHeight", - value: function clearRowHeight(index) { - this._cachedRowHeight = undefined; + // Defer requiring resize handler in order to support server-side rendering. + // See issue #41 + this._detectElementResize = require('../vendor/detectElementResize'); + this._detectElementResize.addResizeListener(this._parentNode, this._onResize); - delete this._cachedRowHeights[index]; + this._onResize(); } }, { - key: "getColumnWidth", - value: function getColumnWidth(index) { - return this._uniformColumnWidth ? this._cachedColumnWidth : this._cachedColumnWidths[index]; + key: 'componentWillUnmount', + value: function componentWillUnmount() { + if (this._detectElementResize) { + this._detectElementResize.removeResizeListener(this._parentNode, this._onResize); + } } }, { - key: "getRowHeight", - value: function getRowHeight(index) { - return this._uniformRowHeight ? this._cachedRowHeight : this._cachedRowHeights[index]; + key: 'render', + value: function render() { + var _props = this.props; + var children = _props.children; + var disableHeight = _props.disableHeight; + var disableWidth = _props.disableWidth; + var _state = this.state; + var height = _state.height; + var width = _state.width; + + // Outer div should not force width/height since that may prevent containers from shrinking. + // Inner component should overflow and use calculated width/height. + // See issue #68 for more information. + + var outerStyle = { overflow: 'visible' }; + + if (!disableHeight) { + outerStyle.height = 0; + } + + if (!disableWidth) { + outerStyle.width = 0; + } + + return _react2.default.createElement( + 'div', + { + ref: this._setRef, + onScroll: this._onScroll, + style: outerStyle + }, + children({ height: height, width: width }) + ); } }, { - key: "hasColumnWidth", - value: function hasColumnWidth(index) { - return this._uniformColumnWidth ? !!this._cachedColumnWidth : !!this._cachedColumnWidths[index]; + key: 'shouldComponentUpdate', + value: function shouldComponentUpdate(nextProps, nextState) { + return (0, _reactAddonsShallowCompare2.default)(this, nextProps, nextState); } }, { - key: "hasRowHeight", - value: function hasRowHeight(index) { - return this._uniformRowHeight ? !!this._cachedRowHeight : !!this._cachedRowHeights[index]; + key: '_onResize', + value: function _onResize() { + var onResize = this.props.onResize; + + // Gaurd against AutoSizer component being removed from the DOM immediately after being added. + // This can result in invalid style values which can result in NaN values if we don't handle them. + // See issue #150 for more context. + + var boundingRect = this._parentNode.getBoundingClientRect(); + var height = boundingRect.height || 0; + var width = boundingRect.width || 0; + + var style = getComputedStyle(this._parentNode); + var paddingLeft = parseInt(style.paddingLeft, 10) || 0; + var paddingRight = parseInt(style.paddingRight, 10) || 0; + var paddingTop = parseInt(style.paddingTop, 10) || 0; + var paddingBottom = parseInt(style.paddingBottom, 10) || 0; + + this.setState({ + height: height - paddingTop - paddingBottom, + width: width - paddingLeft - paddingRight + }); + + onResize({ height: height, width: width }); } }, { - key: "setColumnWidth", - value: function setColumnWidth(index, width) { - this._cachedColumnWidth = width; - this._cachedColumnWidths[index] = width; + key: '_onScroll', + value: function _onScroll(event) { + // Prevent detectElementResize library from being triggered by this scroll event. + event.stopPropagation(); } }, { - key: "setRowHeight", - value: function setRowHeight(index, height) { - this._cachedRowHeight = height; - this._cachedRowHeights[index] = height; + key: '_setRef', + value: function _setRef(autoSizer) { + this._autoSizer = autoSizer; } }]); - return CellSizeCache; -}(); + return AutoSizer; +}(_react.Component); -exports.default = CellSizeCache; -},{}],42:[function(require,module,exports){ +AutoSizer.propTypes = { + /** + * Function respondible for rendering children. + * This function should implement the following signature: + * ({ height, width }) => PropTypes.element + */ + children: _react.PropTypes.func.isRequired, + + /** Disable dynamic :height property */ + disableHeight: _react.PropTypes.bool, + + /** Disable dynamic :width property */ + disableWidth: _react.PropTypes.bool, + + /** Callback to be invoked on-resize: ({ height, width }) */ + onResize: _react.PropTypes.func.isRequired +}; +AutoSizer.defaultProps = { + onResize: function onResize() {} +}; +exports.default = AutoSizer; +},{"../vendor/detectElementResize":78,"react":undefined,"react-addons-shallow-compare":18}],37:[function(require,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); -exports.defaultCellSizeCache = exports.CellMeasurer = exports.default = undefined; - -var _CellMeasurer2 = require('./CellMeasurer'); - -var _CellMeasurer3 = _interopRequireDefault(_CellMeasurer2); +exports.AutoSizer = exports.default = undefined; -var _defaultCellSizeCache2 = require('./defaultCellSizeCache'); +var _AutoSizer2 = require('./AutoSizer'); -var _defaultCellSizeCache3 = _interopRequireDefault(_defaultCellSizeCache2); +var _AutoSizer3 = _interopRequireDefault(_AutoSizer2); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -exports.default = _CellMeasurer3.default; -exports.CellMeasurer = _CellMeasurer3.default; -exports.defaultCellSizeCache = _defaultCellSizeCache3.default; -},{"./CellMeasurer":40,"./defaultCellSizeCache":41}],43:[function(require,module,exports){ +exports.default = _AutoSizer3.default; +exports.AutoSizer = _AutoSizer3.default; +},{"./AutoSizer":36}],38:[function(require,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _react = require('react'); var _react2 = _interopRequireDefault(_react); -var _CollectionView = require('./CollectionView'); - -var _CollectionView2 = _interopRequireDefault(_CollectionView); - -var _calculateSizeAndPositionData2 = require('./utils/calculateSizeAndPositionData'); +var _reactAddonsShallowCompare = require('react-addons-shallow-compare'); -var _calculateSizeAndPositionData3 = _interopRequireDefault(_calculateSizeAndPositionData2); +var _reactAddonsShallowCompare2 = _interopRequireDefault(_reactAddonsShallowCompare); -var _getUpdatedOffsetForIndex = require('../utils/getUpdatedOffsetForIndex'); +var _reactDom = require('react-dom'); -var _getUpdatedOffsetForIndex2 = _interopRequireDefault(_getUpdatedOffsetForIndex); +var _reactDom2 = _interopRequireDefault(_reactDom); -var _reactAddonsShallowCompare = require('react-addons-shallow-compare'); +var _defaultCellSizeCache = require('./defaultCellSizeCache'); -var _reactAddonsShallowCompare2 = _interopRequireDefault(_reactAddonsShallowCompare); +var _defaultCellSizeCache2 = _interopRequireDefault(_defaultCellSizeCache); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } -/** - * Renders scattered or non-linear data. - * Unlike Grid, which renders checkerboard data, Collection can render arbitrarily positioned- even overlapping- data. - */ -var Collection = function (_Component) { - _inherits(Collection, _Component); +/** + * Measures a Grid cell's contents by rendering them in a way that is not visible to the user. + * Either a fixed width or height may be provided if it is desirable to measure only in one direction. + */ +var CellMeasurer = function (_Component) { + _inherits(CellMeasurer, _Component); + + function CellMeasurer(props, state) { + _classCallCheck(this, CellMeasurer); + + var _this = _possibleConstructorReturn(this, (CellMeasurer.__proto__ || Object.getPrototypeOf(CellMeasurer)).call(this, props, state)); + + _this._cellSizeCache = props.cellSizeCache || new _defaultCellSizeCache2.default(); + + _this.getColumnWidth = _this.getColumnWidth.bind(_this); + _this.getRowHeight = _this.getRowHeight.bind(_this); + _this.resetMeasurements = _this.resetMeasurements.bind(_this); + _this.resetMeasurementForColumn = _this.resetMeasurementForColumn.bind(_this); + _this.resetMeasurementForRow = _this.resetMeasurementForRow.bind(_this); + return _this; + } + + _createClass(CellMeasurer, [{ + key: 'getColumnWidth', + value: function getColumnWidth(_ref) { + var index = _ref.index; + + if (this._cellSizeCache.hasColumnWidth(index)) { + return this._cellSizeCache.getColumnWidth(index); + } + + var rowCount = this.props.rowCount; + + + var maxWidth = 0; + + for (var rowIndex = 0; rowIndex < rowCount; rowIndex++) { + var _measureCell2 = this._measureCell({ + clientWidth: true, + columnIndex: index, + rowIndex: rowIndex + }); + + var width = _measureCell2.width; + + + maxWidth = Math.max(maxWidth, width); + } + + this._cellSizeCache.setColumnWidth(index, maxWidth); + + return maxWidth; + } + }, { + key: 'getRowHeight', + value: function getRowHeight(_ref2) { + var index = _ref2.index; + + if (this._cellSizeCache.hasRowHeight(index)) { + return this._cellSizeCache.getRowHeight(index); + } + + var columnCount = this.props.columnCount; - function Collection(props, context) { - _classCallCheck(this, Collection); - var _this = _possibleConstructorReturn(this, (Collection.__proto__ || Object.getPrototypeOf(Collection)).call(this, props, context)); + var maxHeight = 0; - _this._cellMetadata = []; - _this._lastRenderedCellIndices = []; + for (var columnIndex = 0; columnIndex < columnCount; columnIndex++) { + var _measureCell3 = this._measureCell({ + clientHeight: true, + columnIndex: columnIndex, + rowIndex: index + }); - // Cell cache during scroll (for perforamnce) - _this._cellCache = []; + var height = _measureCell3.height; - _this._isScrollingChange = _this._isScrollingChange.bind(_this); - return _this; - } - /** See Collection#recomputeCellSizesAndPositions */ + maxHeight = Math.max(maxHeight, height); + } + this._cellSizeCache.setRowHeight(index, maxHeight); - _createClass(Collection, [{ - key: 'recomputeCellSizesAndPositions', - value: function recomputeCellSizesAndPositions() { - this._cellCache = []; - this._collectionView.recomputeCellSizesAndPositions(); + return maxHeight; + } + }, { + key: 'resetMeasurementForColumn', + value: function resetMeasurementForColumn(columnIndex) { + this._cellSizeCache.clearColumnWidth(columnIndex); + } + }, { + key: 'resetMeasurementForRow', + value: function resetMeasurementForRow(rowIndex) { + this._cellSizeCache.clearRowHeight(rowIndex); + } + }, { + key: 'resetMeasurements', + value: function resetMeasurements() { + this._cellSizeCache.clearAllColumnWidths(); + this._cellSizeCache.clearAllRowHeights(); + } + }, { + key: 'componentDidMount', + value: function componentDidMount() { + this._renderAndMount(); } + }, { + key: 'componentWillReceiveProps', + value: function componentWillReceiveProps(nextProps) { + var cellSizeCache = this.props.cellSizeCache; - /** React lifecycle methods */ + if (cellSizeCache !== nextProps.cellSizeCache) { + this._cellSizeCache = nextProps.cellSizeCache; + } + + this._updateDivDimensions(nextProps); + } + }, { + key: 'componentWillUnmount', + value: function componentWillUnmount() { + this._unmountContainer(); + } }, { key: 'render', value: function render() { - var _this2 = this; + var children = this.props.children; - var props = _objectWithoutProperties(this.props, []); - return _react2.default.createElement(_CollectionView2.default, _extends({ - cellLayoutManager: this, - isScrollingChange: this._isScrollingChange, - ref: function ref(_ref) { - _this2._collectionView = _ref; - } - }, props)); + return children({ + getColumnWidth: this.getColumnWidth, + getRowHeight: this.getRowHeight, + resetMeasurements: this.resetMeasurements, + resetMeasurementForColumn: this.resetMeasurementForColumn, + resetMeasurementForRow: this.resetMeasurementForRow + }); } }, { key: 'shouldComponentUpdate', value: function shouldComponentUpdate(nextProps, nextState) { return (0, _reactAddonsShallowCompare2.default)(this, nextProps, nextState); } + }, { + key: '_getContainerNode', + value: function _getContainerNode(props) { + var container = props.container; - /** CellLayoutManager interface */ + if (container) { + return _reactDom2.default.findDOMNode(typeof container === 'function' ? container() : container); + } else { + return document.body; + } + } }, { - key: 'calculateSizeAndPositionData', - value: function calculateSizeAndPositionData() { - var _props = this.props; - var cellCount = _props.cellCount; - var cellSizeAndPositionGetter = _props.cellSizeAndPositionGetter; - var sectionSize = _props.sectionSize; + key: '_measureCell', + value: function _measureCell(_ref3) { + var _ref3$clientHeight = _ref3.clientHeight; + var clientHeight = _ref3$clientHeight === undefined ? false : _ref3$clientHeight; + var _ref3$clientWidth = _ref3.clientWidth; + var clientWidth = _ref3$clientWidth === undefined ? true : _ref3$clientWidth; + var columnIndex = _ref3.columnIndex; + var rowIndex = _ref3.rowIndex; + var cellRenderer = this.props.cellRenderer; - var data = (0, _calculateSizeAndPositionData3.default)({ - cellCount: cellCount, - cellSizeAndPositionGetter: cellSizeAndPositionGetter, - sectionSize: sectionSize + var rendered = cellRenderer({ + columnIndex: columnIndex, + rowIndex: rowIndex }); - this._cellMetadata = data.cellMetadata; - this._sectionManager = data.sectionManager; - this._height = data.height; - this._width = data.width; - } + // Handle edge case where this method is called before the CellMeasurer has completed its initial render (and mounted). + this._renderAndMount(); - /** - * Returns the most recently rendered set of cell indices. - */ + // @TODO Keep an eye on this for future React updates as the interface may change: + // https://twitter.com/soprano/status/737316379712331776 + _reactDom2.default.unstable_renderSubtreeIntoContainer(this, rendered, this._div); - }, { - key: 'getLastRenderedIndices', - value: function getLastRenderedIndices() { - return this._lastRenderedCellIndices; - } + var measurements = { + height: clientHeight && this._div.clientHeight, + width: clientWidth && this._div.clientWidth + }; - /** - * Calculates the minimum amount of change from the current scroll position to ensure the specified cell is (fully) visible. - */ + _reactDom2.default.unmountComponentAtNode(this._div); + return measurements; + } }, { - key: 'getScrollPositionForCell', - value: function getScrollPositionForCell(_ref2) { - var align = _ref2.align; - var cellIndex = _ref2.cellIndex; - var height = _ref2.height; - var scrollLeft = _ref2.scrollLeft; - var scrollTop = _ref2.scrollTop; - var width = _ref2.width; - var cellCount = this.props.cellCount; - - - if (cellIndex >= 0 && cellIndex < cellCount) { - var cellMetadata = this._cellMetadata[cellIndex]; + key: '_renderAndMount', + value: function _renderAndMount() { + if (!this._div) { + this._div = document.createElement('div'); + this._div.style.display = 'inline-block'; + this._div.style.position = 'absolute'; + this._div.style.visibility = 'hidden'; + this._div.style.zIndex = -1; - scrollLeft = (0, _getUpdatedOffsetForIndex2.default)({ - align: align, - cellOffset: cellMetadata.x, - cellSize: cellMetadata.width, - containerSize: width, - currentOffset: scrollLeft, - targetIndex: cellIndex - }); + this._updateDivDimensions(this.props); - scrollTop = (0, _getUpdatedOffsetForIndex2.default)({ - align: align, - cellOffset: cellMetadata.y, - cellSize: cellMetadata.height, - containerSize: height, - currentOffset: scrollTop, - targetIndex: cellIndex - }); + this._containerNode = this._getContainerNode(this.props); + this._containerNode.appendChild(this._div); } - - return { - scrollLeft: scrollLeft, - scrollTop: scrollTop - }; } }, { - key: 'getTotalSize', - value: function getTotalSize() { - return { - height: this._height, - width: this._width - }; + key: '_unmountContainer', + value: function _unmountContainer() { + if (this._div) { + this._containerNode.removeChild(this._div); + + this._div = null; + } + + this._containerNode = null; } }, { - key: 'cellRenderers', - value: function cellRenderers(_ref3) { - var _this3 = this; - - var height = _ref3.height; - var isScrolling = _ref3.isScrolling; - var width = _ref3.width; - var x = _ref3.x; - var y = _ref3.y; - var _props2 = this.props; - var cellGroupRenderer = _props2.cellGroupRenderer; - var cellRenderer = _props2.cellRenderer; + key: '_updateDivDimensions', + value: function _updateDivDimensions(props) { + var height = props.height; + var width = props.width; - // Store for later calls to getLastRenderedIndices() - this._lastRenderedCellIndices = this._sectionManager.getCellIndices({ - height: height, - width: width, - x: x, - y: y - }); + if (height && height !== this._divHeight) { + this._divHeight = height; + this._div.style.height = height + 'px'; + } - return cellGroupRenderer({ - cellCache: this._cellCache, - cellRenderer: cellRenderer, - cellSizeAndPositionGetter: function cellSizeAndPositionGetter(_ref4) { - var index = _ref4.index; - return _this3._sectionManager.getCellMetadata({ index: index }); - }, - indices: this._lastRenderedCellIndices, - isScrolling: isScrolling - }); - } - }, { - key: '_isScrollingChange', - value: function _isScrollingChange(isScrolling) { - if (!isScrolling) { - this._cellCache = []; + if (width && width !== this._divWidth) { + this._divWidth = width; + this._div.style.width = width + 'px'; } } }]); - return Collection; + return CellMeasurer; }(_react.Component); -Collection.propTypes = { - 'aria-label': _react.PropTypes.string, - +CellMeasurer.propTypes = { /** - * Number of cells in Collection. + * Renders a cell given its indices. + * Should implement the following interface: ({ columnIndex: number, rowIndex: number }): PropTypes.node */ - cellCount: _react.PropTypes.number.isRequired, + cellRenderer: _react.PropTypes.func.isRequired, /** - * Responsible for rendering a group of cells given their indices. - * Should implement the following interface: ({ - * cellSizeAndPositionGetter:Function, - * indices: Array, - * cellRenderer: Function - * }): Array + * Optional, custom caching strategy for cell sizes. */ - cellGroupRenderer: _react.PropTypes.func.isRequired, + cellSizeCache: _react.PropTypes.object, /** - * Responsible for rendering a cell given an row and column index. - * Should implement the following interface: ({ index: number }): PropTypes.element + * Function respondible for rendering a virtualized component. + * This function should implement the following signature: + * ({ getColumnWidth, getRowHeight, resetMeasurements }) => PropTypes.element */ - cellRenderer: _react.PropTypes.func.isRequired, + children: _react.PropTypes.func.isRequired, /** - * Callback responsible for returning size and offset/position information for a given cell (index). - * ({ index: number }): { height: number, width: number, x: number, y: number } + * Number of columns in grid. */ - cellSizeAndPositionGetter: _react.PropTypes.func.isRequired, + columnCount: _react.PropTypes.number.isRequired, /** - * Optionally override the size of the sections a Collection's cells are split into. + * A Node, Component instance, or function that returns either. + * If this property is not specified the document body will be used. */ - sectionSize: _react.PropTypes.number -}; -Collection.defaultProps = { - 'aria-label': 'grid', - cellGroupRenderer: defaultCellGroupRenderer -}; -exports.default = Collection; - - -function defaultCellGroupRenderer(_ref5) { - var cellCache = _ref5.cellCache; - var cellRenderer = _ref5.cellRenderer; - var cellSizeAndPositionGetter = _ref5.cellSizeAndPositionGetter; - var indices = _ref5.indices; - var isScrolling = _ref5.isScrolling; - - return indices.map(function (index) { - var cellMetadata = cellSizeAndPositionGetter({ index: index }); - - // Avoid re-creating cells while scrolling. - // This can lead to the same cell being created many times and can cause performance issues for "heavy" cells. - // If a scroll is in progress- cache and reuse cells. - // This cache will be thrown away once scrolling complets. - var renderedCell = void 0; - - if (isScrolling) { - if (!(index in cellCache)) { - cellCache[index] = cellRenderer({ - index: index, - isScrolling: isScrolling - }); - } + container: _react2.default.PropTypes.oneOfType([_react2.default.PropTypes.func, _react2.default.PropTypes.node]), - renderedCell = cellCache[index]; - } else { - renderedCell = cellRenderer({ - index: index, - isScrolling: isScrolling - }); - } + /** + * Assign a fixed :height in order to measure dynamic text :width only. + */ + height: _react.PropTypes.number, - if (renderedCell == null || renderedCell === false) { - return null; - } + /** + * Number of rows in grid. + */ + rowCount: _react.PropTypes.number.isRequired, - return _react2.default.createElement( - 'div', - { - className: 'Collection__cell', - key: index, - style: { - height: cellMetadata.height, - left: cellMetadata.x, - top: cellMetadata.y, - width: cellMetadata.width - } - }, - renderedCell - ); - }).filter(function (renderedCell) { - return !!renderedCell; - }); -} -},{"../utils/getUpdatedOffsetForIndex":79,"./CollectionView":44,"./utils/calculateSizeAndPositionData":48,"react":undefined,"react-addons-shallow-compare":30}],44:[function(require,module,exports){ -'use strict'; + /** + * Assign a fixed :width in order to measure dynamic text :height only. + */ + width: _react.PropTypes.number +}; +exports.default = CellMeasurer; +},{"./defaultCellSizeCache":39,"react":undefined,"react-addons-shallow-compare":18,"react-dom":undefined}],39:[function(require,module,exports){ +"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); -var _react = require('react'); - -var _react2 = _interopRequireDefault(_react); - -var _classnames = require('classnames'); - -var _classnames2 = _interopRequireDefault(_classnames); - -var _createCallbackMemoizer = require('../utils/createCallbackMemoizer'); - -var _createCallbackMemoizer2 = _interopRequireDefault(_createCallbackMemoizer); - -var _scrollbarSize = require('dom-helpers/util/scrollbarSize'); - -var _scrollbarSize2 = _interopRequireDefault(_scrollbarSize); - -var _raf = require('raf'); - -var _raf2 = _interopRequireDefault(_raf); - -var _reactAddonsShallowCompare = require('react-addons-shallow-compare'); - -var _reactAddonsShallowCompare2 = _interopRequireDefault(_reactAddonsShallowCompare); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - -// @TODO It would be nice to refactor Grid to use this code as well. - -/** - * Specifies the number of miliseconds during which to disable pointer events while a scroll is in progress. - * This improves performance and makes scrolling smoother. - */ -var IS_SCROLLING_TIMEOUT = 150; - -/** - * Controls whether the Grid updates the DOM element's scrollLeft/scrollTop based on the current state or just observes it. - * This prevents Grid from interrupting mouse-wheel animations (see issue #2). - */ -var SCROLL_POSITION_CHANGE_REASONS = { - OBSERVED: 'observed', - REQUESTED: 'requested' -}; - /** - * Monitors changes in properties (eg. cellCount) and state (eg. scroll offsets) to determine when rendering needs to occur. - * This component does not render any visible content itself; it defers to the specified :cellLayoutManager. + * Default CellMeasurer `cellSizeCache` implementation. + * Permanently caches all cell sizes (identified by column and row index) unless explicitly cleared. + * Can be configured to handle uniform cell widths and/or heights as a way of optimizing certain use cases. */ +var CellSizeCache = function () { + function CellSizeCache() { + var _ref = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; -var CollectionView = function (_Component) { - _inherits(CollectionView, _Component); - - function CollectionView(props, context) { - _classCallCheck(this, CollectionView); - - var _this = _possibleConstructorReturn(this, (CollectionView.__proto__ || Object.getPrototypeOf(CollectionView)).call(this, props, context)); + var _ref$uniformRowHeight = _ref.uniformRowHeight; + var uniformRowHeight = _ref$uniformRowHeight === undefined ? false : _ref$uniformRowHeight; + var _ref$uniformColumnWid = _ref.uniformColumnWidth; + var uniformColumnWidth = _ref$uniformColumnWid === undefined ? false : _ref$uniformColumnWid; - _this.state = { - calculateSizeAndPositionDataOnNextUpdate: false, - isScrolling: false, - scrollLeft: 0, - scrollTop: 0 - }; + _classCallCheck(this, CellSizeCache); - // Invokes callbacks only when their values have changed. - _this._onSectionRenderedMemoizer = (0, _createCallbackMemoizer2.default)(); - _this._onScrollMemoizer = (0, _createCallbackMemoizer2.default)(false); + this._uniformRowHeight = uniformRowHeight; + this._uniformColumnWidth = uniformColumnWidth; - // Bind functions to instance so they don't lose context when passed around. - _this._invokeOnSectionRenderedHelper = _this._invokeOnSectionRenderedHelper.bind(_this); - _this._onScroll = _this._onScroll.bind(_this); - _this._updateScrollPositionForScrollToCell = _this._updateScrollPositionForScrollToCell.bind(_this); - return _this; + this._cachedColumnWidths = {}; + this._cachedRowHeights = {}; } - /** - * Forced recompute of cell sizes and positions. - * This function should be called if cell sizes have changed but nothing else has. - * Since cell positions are calculated by callbacks, the collection view has no way of detecting when the underlying data has changed. - */ + _createClass(CellSizeCache, [{ + key: "clearAllColumnWidths", + value: function clearAllColumnWidths() { + this._cachedColumnWidth = undefined; + this._cachedColumnWidths = {}; + } + }, { + key: "clearAllRowHeights", + value: function clearAllRowHeights() { + this._cachedRowHeight = undefined; + this._cachedRowHeights = {}; + } + }, { + key: "clearColumnWidth", + value: function clearColumnWidth(index) { + this._cachedColumnWidth = undefined; + delete this._cachedColumnWidths[index]; + } + }, { + key: "clearRowHeight", + value: function clearRowHeight(index) { + this._cachedRowHeight = undefined; - _createClass(CollectionView, [{ - key: 'recomputeCellSizesAndPositions', - value: function recomputeCellSizesAndPositions() { - this.setState({ - calculateSizeAndPositionDataOnNextUpdate: true - }); + delete this._cachedRowHeights[index]; + } + }, { + key: "getColumnWidth", + value: function getColumnWidth(index) { + return this._uniformColumnWidth ? this._cachedColumnWidth : this._cachedColumnWidths[index]; + } + }, { + key: "getRowHeight", + value: function getRowHeight(index) { + return this._uniformRowHeight ? this._cachedRowHeight : this._cachedRowHeights[index]; + } + }, { + key: "hasColumnWidth", + value: function hasColumnWidth(index) { + return this._uniformColumnWidth ? !!this._cachedColumnWidth : !!this._cachedColumnWidths[index]; + } + }, { + key: "hasRowHeight", + value: function hasRowHeight(index) { + return this._uniformRowHeight ? !!this._cachedRowHeight : !!this._cachedRowHeights[index]; + } + }, { + key: "setColumnWidth", + value: function setColumnWidth(index, width) { + this._cachedColumnWidth = width; + this._cachedColumnWidths[index] = width; + } + }, { + key: "setRowHeight", + value: function setRowHeight(index, height) { + this._cachedRowHeight = height; + this._cachedRowHeights[index] = height; } + }]); - /* ---------------------------- Component lifecycle methods ---------------------------- */ + return CellSizeCache; +}(); - }, { - key: 'componentDidMount', - value: function componentDidMount() { - var _props = this.props; - var cellLayoutManager = _props.cellLayoutManager; - var scrollLeft = _props.scrollLeft; - var scrollToCell = _props.scrollToCell; - var scrollTop = _props.scrollTop; +exports.default = CellSizeCache; +},{}],40:[function(require,module,exports){ +'use strict'; - // If this component was first rendered server-side, scrollbar size will be undefined. - // In that event we need to remeasure. +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.defaultCellSizeCache = exports.CellMeasurer = exports.default = undefined; - if (!this._scrollbarSizeMeasured) { - this._scrollbarSize = (0, _scrollbarSize2.default)(); - this._scrollbarSizeMeasured = true; - this.setState({}); - } +var _CellMeasurer2 = require('./CellMeasurer'); - if (scrollToCell >= 0) { - this._updateScrollPositionForScrollToCell(); - } else if (scrollLeft >= 0 || scrollTop >= 0) { - this._setScrollPosition({ scrollLeft: scrollLeft, scrollTop: scrollTop }); - } +var _CellMeasurer3 = _interopRequireDefault(_CellMeasurer2); - // Update onSectionRendered callback. - this._invokeOnSectionRenderedHelper(); +var _defaultCellSizeCache2 = require('./defaultCellSizeCache'); - var _cellLayoutManager$ge = cellLayoutManager.getTotalSize(); +var _defaultCellSizeCache3 = _interopRequireDefault(_defaultCellSizeCache2); - var totalHeight = _cellLayoutManager$ge.height; - var totalWidth = _cellLayoutManager$ge.width; +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - // Initialize onScroll callback. +exports.default = _CellMeasurer3.default; +exports.CellMeasurer = _CellMeasurer3.default; +exports.defaultCellSizeCache = _defaultCellSizeCache3.default; +},{"./CellMeasurer":38,"./defaultCellSizeCache":39}],41:[function(require,module,exports){ +'use strict'; - this._invokeOnScrollMemoizer({ - scrollLeft: scrollLeft || 0, - scrollTop: scrollTop || 0, - totalHeight: totalHeight, - totalWidth: totalWidth - }); - } - }, { - key: 'componentDidUpdate', - value: function componentDidUpdate(prevProps, prevState) { - var _props2 = this.props; - var height = _props2.height; - var scrollToCell = _props2.scrollToCell; - var width = _props2.width; - var _state = this.state; - var scrollLeft = _state.scrollLeft; - var scrollPositionChangeReason = _state.scrollPositionChangeReason; - var scrollToAlignment = _state.scrollToAlignment; - var scrollTop = _state.scrollTop; +Object.defineProperty(exports, "__esModule", { + value: true +}); - // Make sure requested changes to :scrollLeft or :scrollTop get applied. - // Assigning to scrollLeft/scrollTop tells the browser to interrupt any running scroll animations, - // And to discard any pending async changes to the scroll position that may have happened in the meantime (e.g. on a separate scrolling thread). - // So we only set these when we require an adjustment of the scroll position. - // See issue #2 for more information. +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - if (scrollPositionChangeReason === SCROLL_POSITION_CHANGE_REASONS.REQUESTED) { - if (scrollLeft >= 0 && scrollLeft !== prevState.scrollLeft && scrollLeft !== this._scrollingContainer.scrollLeft) { - this._scrollingContainer.scrollLeft = scrollLeft; - } - if (scrollTop >= 0 && scrollTop !== prevState.scrollTop && scrollTop !== this._scrollingContainer.scrollTop) { - this._scrollingContainer.scrollTop = scrollTop; - } - } +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - // Update scroll offsets if the current :scrollToCell values requires it - if (height !== prevProps.height || scrollToAlignment !== prevProps.scrollToAlignment || scrollToCell !== prevProps.scrollToCell || width !== prevProps.width) { - this._updateScrollPositionForScrollToCell(); - } +var _react = require('react'); - // Update onRowsRendered callback if start/stop indices have changed - this._invokeOnSectionRenderedHelper(); - } - }, { - key: 'componentWillMount', - value: function componentWillMount() { - var cellLayoutManager = this.props.cellLayoutManager; +var _react2 = _interopRequireDefault(_react); +var _CollectionView = require('./CollectionView'); - cellLayoutManager.calculateSizeAndPositionData(); +var _CollectionView2 = _interopRequireDefault(_CollectionView); - // If this component is being rendered server-side, getScrollbarSize() will return undefined. - // We handle this case in componentDidMount() - this._scrollbarSize = (0, _scrollbarSize2.default)(); - if (this._scrollbarSize === undefined) { - this._scrollbarSizeMeasured = false; - this._scrollbarSize = 0; - } else { - this._scrollbarSizeMeasured = true; - } - } - }, { - key: 'componentWillUnmount', - value: function componentWillUnmount() { - if (this._disablePointerEventsTimeoutId) { - clearTimeout(this._disablePointerEventsTimeoutId); - } +var _calculateSizeAndPositionData2 = require('./utils/calculateSizeAndPositionData'); - if (this._setNextStateAnimationFrameId) { - _raf2.default.cancel(this._setNextStateAnimationFrameId); - } - } +var _calculateSizeAndPositionData3 = _interopRequireDefault(_calculateSizeAndPositionData2); - /** - * @private - * This method updates scrollLeft/scrollTop in state for the following conditions: - * 1) Empty content (0 rows or columns) - * 2) New scroll props overriding the current state - * 3) Cells-count or cells-size has changed, making previous scroll offsets invalid - */ +var _getUpdatedOffsetForIndex = require('../utils/getUpdatedOffsetForIndex'); - }, { - key: 'componentWillUpdate', - value: function componentWillUpdate(nextProps, nextState) { - if (nextProps.cellCount === 0 && (nextState.scrollLeft !== 0 || nextState.scrollTop !== 0)) { - this._setScrollPosition({ - scrollLeft: 0, - scrollTop: 0 - }); - } else if (nextProps.scrollLeft !== this.props.scrollLeft || nextProps.scrollTop !== this.props.scrollTop) { - this._setScrollPosition({ - scrollLeft: nextProps.scrollLeft, - scrollTop: nextProps.scrollTop - }); - } +var _getUpdatedOffsetForIndex2 = _interopRequireDefault(_getUpdatedOffsetForIndex); - if (nextProps.cellCount !== this.props.cellCount || nextProps.cellLayoutManager !== this.props.cellLayoutManager || nextState.calculateSizeAndPositionDataOnNextUpdate) { - nextProps.cellLayoutManager.calculateSizeAndPositionData(); - } +var _reactAddonsShallowCompare = require('react-addons-shallow-compare'); - if (nextState.calculateSizeAndPositionDataOnNextUpdate) { - this.setState({ - calculateSizeAndPositionDataOnNextUpdate: false - }); - } - } - }, { - key: 'render', - value: function render() { - var _this2 = this; +var _reactAddonsShallowCompare2 = _interopRequireDefault(_reactAddonsShallowCompare); - var _props3 = this.props; - var autoHeight = _props3.autoHeight; - var cellCount = _props3.cellCount; - var cellLayoutManager = _props3.cellLayoutManager; - var className = _props3.className; - var height = _props3.height; - var horizontalOverscanSize = _props3.horizontalOverscanSize; - var noContentRenderer = _props3.noContentRenderer; - var style = _props3.style; - var verticalOverscanSize = _props3.verticalOverscanSize; - var width = _props3.width; - var _state2 = this.state; - var isScrolling = _state2.isScrolling; - var scrollLeft = _state2.scrollLeft; - var scrollTop = _state2.scrollTop; +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - var _cellLayoutManager$ge2 = cellLayoutManager.getTotalSize(); +function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } - var totalHeight = _cellLayoutManager$ge2.height; - var totalWidth = _cellLayoutManager$ge2.width; +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - // Safely expand the rendered area by the specified overscan amount +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - var left = Math.max(0, scrollLeft - horizontalOverscanSize); - var top = Math.max(0, scrollTop - verticalOverscanSize); - var right = Math.min(totalWidth, scrollLeft + width + horizontalOverscanSize); - var bottom = Math.min(totalHeight, scrollTop + height + verticalOverscanSize); +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - var childrenToDisplay = height > 0 && width > 0 ? cellLayoutManager.cellRenderers({ - height: bottom - top, - isScrolling: isScrolling, - width: right - left, - x: left, - y: top - }) : []; +/** + * Renders scattered or non-linear data. + * Unlike Grid, which renders checkerboard data, Collection can render arbitrarily positioned- even overlapping- data. + */ +var Collection = function (_Component) { + _inherits(Collection, _Component); - var collectionStyle = { - height: autoHeight ? 'auto' : height, - width: width - }; + function Collection(props, context) { + _classCallCheck(this, Collection); - // Force browser to hide scrollbars when we know they aren't necessary. - // Otherwise once scrollbars appear they may not disappear again. - // For more info see issue #116 - var verticalScrollBarSize = totalHeight > height ? this._scrollbarSize : 0; - var horizontalScrollBarSize = totalWidth > width ? this._scrollbarSize : 0; - if (totalWidth + verticalScrollBarSize <= width) { - collectionStyle.overflowX = 'hidden'; - } - if (totalHeight + horizontalScrollBarSize <= height) { - collectionStyle.overflowY = 'hidden'; - } + var _this = _possibleConstructorReturn(this, (Collection.__proto__ || Object.getPrototypeOf(Collection)).call(this, props, context)); - return _react2.default.createElement( - 'div', - { - ref: function ref(_ref) { - _this2._scrollingContainer = _ref; - }, - 'aria-label': this.props['aria-label'], - className: (0, _classnames2.default)('Collection', className), - onScroll: this._onScroll, - role: 'grid', - style: _extends({}, collectionStyle, style), - tabIndex: 0 - }, - cellCount > 0 && _react2.default.createElement( - 'div', - { - className: 'Collection__innerScrollContainer', - style: { - height: totalHeight, - maxHeight: totalHeight, - maxWidth: totalWidth, - pointerEvents: isScrolling ? 'none' : '', - width: totalWidth - } - }, - childrenToDisplay - ), - cellCount === 0 && noContentRenderer() - ); + _this._cellMetadata = []; + _this._lastRenderedCellIndices = []; + + // Cell cache during scroll (for perforamnce) + _this._cellCache = []; + + _this._isScrollingChange = _this._isScrollingChange.bind(_this); + return _this; + } + + /** See Collection#recomputeCellSizesAndPositions */ + + + _createClass(Collection, [{ + key: 'recomputeCellSizesAndPositions', + value: function recomputeCellSizesAndPositions() { + this._cellCache = []; + this._collectionView.recomputeCellSizesAndPositions(); + } + + /** React lifecycle methods */ + + }, { + key: 'render', + value: function render() { + var _this2 = this; + + var props = _objectWithoutProperties(this.props, []); + + return _react2.default.createElement(_CollectionView2.default, _extends({ + cellLayoutManager: this, + isScrollingChange: this._isScrollingChange, + ref: function ref(_ref) { + _this2._collectionView = _ref; + } + }, props)); } }, { key: 'shouldComponentUpdate', @@ -4377,632 +4177,909 @@ var CollectionView = function (_Component) { return (0, _reactAddonsShallowCompare2.default)(this, nextProps, nextState); } - /* ---------------------------- Helper methods ---------------------------- */ + /** CellLayoutManager interface */ + + }, { + key: 'calculateSizeAndPositionData', + value: function calculateSizeAndPositionData() { + var _props = this.props; + var cellCount = _props.cellCount; + var cellSizeAndPositionGetter = _props.cellSizeAndPositionGetter; + var sectionSize = _props.sectionSize; + + + var data = (0, _calculateSizeAndPositionData3.default)({ + cellCount: cellCount, + cellSizeAndPositionGetter: cellSizeAndPositionGetter, + sectionSize: sectionSize + }); + + this._cellMetadata = data.cellMetadata; + this._sectionManager = data.sectionManager; + this._height = data.height; + this._width = data.width; + } /** - * Sets an :isScrolling flag for a small window of time. - * This flag is used to disable pointer events on the scrollable portion of the Collection. - * This prevents jerky/stuttery mouse-wheel scrolling. + * Returns the most recently rendered set of cell indices. */ }, { - key: '_enablePointerEventsAfterDelay', - value: function _enablePointerEventsAfterDelay() { - var _this3 = this; + key: 'getLastRenderedIndices', + value: function getLastRenderedIndices() { + return this._lastRenderedCellIndices; + } - if (this._disablePointerEventsTimeoutId) { - clearTimeout(this._disablePointerEventsTimeoutId); - } + /** + * Calculates the minimum amount of change from the current scroll position to ensure the specified cell is (fully) visible. + */ - this._disablePointerEventsTimeoutId = setTimeout(function () { - var isScrollingChange = _this3.props.isScrollingChange; + }, { + key: 'getScrollPositionForCell', + value: function getScrollPositionForCell(_ref2) { + var align = _ref2.align; + var cellIndex = _ref2.cellIndex; + var height = _ref2.height; + var scrollLeft = _ref2.scrollLeft; + var scrollTop = _ref2.scrollTop; + var width = _ref2.width; + var cellCount = this.props.cellCount; - isScrollingChange(false); + if (cellIndex >= 0 && cellIndex < cellCount) { + var cellMetadata = this._cellMetadata[cellIndex]; - _this3._disablePointerEventsTimeoutId = null; - _this3.setState({ - isScrolling: false + scrollLeft = (0, _getUpdatedOffsetForIndex2.default)({ + align: align, + cellOffset: cellMetadata.x, + cellSize: cellMetadata.width, + containerSize: width, + currentOffset: scrollLeft, + targetIndex: cellIndex }); - }, IS_SCROLLING_TIMEOUT); - } - }, { - key: '_invokeOnSectionRenderedHelper', - value: function _invokeOnSectionRenderedHelper() { - var _props4 = this.props; - var cellLayoutManager = _props4.cellLayoutManager; - var onSectionRendered = _props4.onSectionRendered; + scrollTop = (0, _getUpdatedOffsetForIndex2.default)({ + align: align, + cellOffset: cellMetadata.y, + cellSize: cellMetadata.height, + containerSize: height, + currentOffset: scrollTop, + targetIndex: cellIndex + }); + } - this._onSectionRenderedMemoizer({ - callback: onSectionRendered, - indices: { - indices: cellLayoutManager.getLastRenderedIndices() - } - }); + return { + scrollLeft: scrollLeft, + scrollTop: scrollTop + }; } }, { - key: '_invokeOnScrollMemoizer', - value: function _invokeOnScrollMemoizer(_ref2) { - var _this4 = this; + key: 'getTotalSize', + value: function getTotalSize() { + return { + height: this._height, + width: this._width + }; + } + }, { + key: 'cellRenderers', + value: function cellRenderers(_ref3) { + var _this3 = this; - var scrollLeft = _ref2.scrollLeft; - var scrollTop = _ref2.scrollTop; - var totalHeight = _ref2.totalHeight; - var totalWidth = _ref2.totalWidth; + var height = _ref3.height; + var isScrolling = _ref3.isScrolling; + var width = _ref3.width; + var x = _ref3.x; + var y = _ref3.y; + var _props2 = this.props; + var cellGroupRenderer = _props2.cellGroupRenderer; + var cellRenderer = _props2.cellRenderer; - this._onScrollMemoizer({ - callback: function callback(_ref3) { - var scrollLeft = _ref3.scrollLeft; - var scrollTop = _ref3.scrollTop; - var _props5 = _this4.props; - var height = _props5.height; - var onScroll = _props5.onScroll; - var width = _props5.width; + // Store for later calls to getLastRenderedIndices() + this._lastRenderedCellIndices = this._sectionManager.getCellIndices({ + height: height, + width: width, + x: x, + y: y + }); - onScroll({ - clientHeight: height, - clientWidth: width, - scrollHeight: totalHeight, - scrollLeft: scrollLeft, - scrollTop: scrollTop, - scrollWidth: totalWidth - }); + return cellGroupRenderer({ + cellCache: this._cellCache, + cellRenderer: cellRenderer, + cellSizeAndPositionGetter: function cellSizeAndPositionGetter(_ref4) { + var index = _ref4.index; + return _this3._sectionManager.getCellMetadata({ index: index }); }, - indices: { - scrollLeft: scrollLeft, - scrollTop: scrollTop - } + indices: this._lastRenderedCellIndices, + isScrolling: isScrolling }); } + }, { + key: '_isScrollingChange', + value: function _isScrollingChange(isScrolling) { + if (!isScrolling) { + this._cellCache = []; + } + } + }]); - /** - * Updates the state during the next animation frame. - * Use this method to avoid multiple renders in a small span of time. - * This helps performance for bursty events (like onScroll). - */ + return Collection; +}(_react.Component); - }, { - key: '_setNextState', - value: function _setNextState(state) { - var _this5 = this; +Collection.propTypes = { + 'aria-label': _react.PropTypes.string, - if (this._setNextStateAnimationFrameId) { - _raf2.default.cancel(this._setNextStateAnimationFrameId); - } + /** + * Number of cells in Collection. + */ + cellCount: _react.PropTypes.number.isRequired, + + /** + * Responsible for rendering a group of cells given their indices. + * Should implement the following interface: ({ + * cellSizeAndPositionGetter:Function, + * indices: Array, + * cellRenderer: Function + * }): Array + */ + cellGroupRenderer: _react.PropTypes.func.isRequired, + + /** + * Responsible for rendering a cell given an row and column index. + * Should implement the following interface: ({ index: number }): PropTypes.element + */ + cellRenderer: _react.PropTypes.func.isRequired, + + /** + * Callback responsible for returning size and offset/position information for a given cell (index). + * ({ index: number }): { height: number, width: number, x: number, y: number } + */ + cellSizeAndPositionGetter: _react.PropTypes.func.isRequired, + + /** + * Optionally override the size of the sections a Collection's cells are split into. + */ + sectionSize: _react.PropTypes.number +}; +Collection.defaultProps = { + 'aria-label': 'grid', + cellGroupRenderer: defaultCellGroupRenderer +}; +exports.default = Collection; + + +function defaultCellGroupRenderer(_ref5) { + var cellCache = _ref5.cellCache; + var cellRenderer = _ref5.cellRenderer; + var cellSizeAndPositionGetter = _ref5.cellSizeAndPositionGetter; + var indices = _ref5.indices; + var isScrolling = _ref5.isScrolling; - this._setNextStateAnimationFrameId = (0, _raf2.default)(function () { - _this5._setNextStateAnimationFrameId = null; - _this5.setState(state); - }); - } - }, { - key: '_setScrollPosition', - value: function _setScrollPosition(_ref4) { - var scrollLeft = _ref4.scrollLeft; - var scrollTop = _ref4.scrollTop; + return indices.map(function (index) { + var cellMetadata = cellSizeAndPositionGetter({ index: index }); - var newState = { - scrollPositionChangeReason: SCROLL_POSITION_CHANGE_REASONS.REQUESTED - }; + // Avoid re-creating cells while scrolling. + // This can lead to the same cell being created many times and can cause performance issues for "heavy" cells. + // If a scroll is in progress- cache and reuse cells. + // This cache will be thrown away once scrolling complets. + var renderedCell = void 0; - if (scrollLeft >= 0) { - newState.scrollLeft = scrollLeft; + if (isScrolling) { + if (!(index in cellCache)) { + cellCache[index] = cellRenderer({ + index: index, + isScrolling: isScrolling + }); } - if (scrollTop >= 0) { - newState.scrollTop = scrollTop; - } + renderedCell = cellCache[index]; + } else { + renderedCell = cellRenderer({ + index: index, + isScrolling: isScrolling + }); + } - if (scrollLeft >= 0 && scrollLeft !== this.state.scrollLeft || scrollTop >= 0 && scrollTop !== this.state.scrollTop) { - this.setState(newState); - } + if (renderedCell == null || renderedCell === false) { + return null; } - }, { - key: '_updateScrollPositionForScrollToCell', - value: function _updateScrollPositionForScrollToCell() { - var _props6 = this.props; - var cellLayoutManager = _props6.cellLayoutManager; - var height = _props6.height; - var scrollToAlignment = _props6.scrollToAlignment; - var scrollToCell = _props6.scrollToCell; - var width = _props6.width; - var _state3 = this.state; - var scrollLeft = _state3.scrollLeft; - var scrollTop = _state3.scrollTop; + return _react2.default.createElement( + 'div', + { + className: 'Collection__cell', + key: index, + style: { + height: cellMetadata.height, + left: cellMetadata.x, + top: cellMetadata.y, + width: cellMetadata.width + } + }, + renderedCell + ); + }).filter(function (renderedCell) { + return !!renderedCell; + }); +} +},{"../utils/getUpdatedOffsetForIndex":77,"./CollectionView":42,"./utils/calculateSizeAndPositionData":46,"react":undefined,"react-addons-shallow-compare":18}],42:[function(require,module,exports){ +'use strict'; - if (scrollToCell >= 0) { - var scrollPosition = cellLayoutManager.getScrollPositionForCell({ - align: scrollToAlignment, - cellIndex: scrollToCell, - height: height, - scrollLeft: scrollLeft, - scrollTop: scrollTop, - width: width - }); +Object.defineProperty(exports, "__esModule", { + value: true +}); - if (scrollPosition.scrollLeft !== scrollLeft || scrollPosition.scrollTop !== scrollTop) { - this._setScrollPosition(scrollPosition); - } - } - } - }, { - key: '_onScroll', - value: function _onScroll(event) { - // In certain edge-cases React dispatches an onScroll event with an invalid target.scrollLeft / target.scrollTop. - // This invalid event can be detected by comparing event.target to this component's scrollable DOM element. - // See issue #404 for more information. - if (event.target !== this._scrollingContainer) { - return; - } +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - // Prevent pointer events from interrupting a smooth scroll - this._enablePointerEventsAfterDelay(); +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - // When this component is shrunk drastically, React dispatches a series of back-to-back scroll events, - // Gradually converging on a scrollTop that is within the bounds of the new, smaller height. - // This causes a series of rapid renders that is slow for long lists. - // We can avoid that by doing some simple bounds checking to ensure that scrollTop never exceeds the total height. - var _props7 = this.props; - var cellLayoutManager = _props7.cellLayoutManager; - var height = _props7.height; - var isScrollingChange = _props7.isScrollingChange; - var width = _props7.width; +var _react = require('react'); - var scrollbarSize = this._scrollbarSize; +var _react2 = _interopRequireDefault(_react); - var _cellLayoutManager$ge3 = cellLayoutManager.getTotalSize(); +var _classnames = require('classnames'); - var totalHeight = _cellLayoutManager$ge3.height; - var totalWidth = _cellLayoutManager$ge3.width; +var _classnames2 = _interopRequireDefault(_classnames); - var scrollLeft = Math.max(0, Math.min(totalWidth - width + scrollbarSize, event.target.scrollLeft)); - var scrollTop = Math.max(0, Math.min(totalHeight - height + scrollbarSize, event.target.scrollTop)); +var _createCallbackMemoizer = require('../utils/createCallbackMemoizer'); - // Certain devices (like Apple touchpad) rapid-fire duplicate events. - // Don't force a re-render if this is the case. - // The mouse may move faster then the animation frame does. - // Use requestAnimationFrame to avoid over-updating. - if (this.state.scrollLeft !== scrollLeft || this.state.scrollTop !== scrollTop) { - // Browsers with cancelable scroll events (eg. Firefox) interrupt scrolling animations if scrollTop/scrollLeft is set. - // Other browsers (eg. Safari) don't scroll as well without the help under certain conditions (DOM or style changes during scrolling). - // All things considered, this seems to be the best current work around that I'm aware of. - // For more information see https://github.com/bvaughn/react-virtualized/pull/124 - var scrollPositionChangeReason = event.cancelable ? SCROLL_POSITION_CHANGE_REASONS.OBSERVED : SCROLL_POSITION_CHANGE_REASONS.REQUESTED; +var _createCallbackMemoizer2 = _interopRequireDefault(_createCallbackMemoizer); - // Synchronously set :isScrolling the first time (since _setNextState will reschedule its animation frame each time it's called) - if (!this.state.isScrolling) { - isScrollingChange(true); +var _scrollbarSize = require('dom-helpers/util/scrollbarSize'); - this.setState({ - isScrolling: true - }); - } +var _scrollbarSize2 = _interopRequireDefault(_scrollbarSize); - this._setNextState({ - isScrolling: true, - scrollLeft: scrollLeft, - scrollPositionChangeReason: scrollPositionChangeReason, - scrollTop: scrollTop - }); - } +var _raf = require('raf'); - this._invokeOnScrollMemoizer({ - scrollLeft: scrollLeft, - scrollTop: scrollTop, - totalWidth: totalWidth, - totalHeight: totalHeight - }); - } - }]); +var _raf2 = _interopRequireDefault(_raf); - return CollectionView; -}(_react.Component); +var _reactAddonsShallowCompare = require('react-addons-shallow-compare'); -CollectionView.propTypes = { - 'aria-label': _react.PropTypes.string, +var _reactAddonsShallowCompare2 = _interopRequireDefault(_reactAddonsShallowCompare); - /** - * Removes fixed height from the scrollingContainer so that the total height - * of rows can stretch the window. Intended for use with WindowScroller - */ - autoHeight: _react.PropTypes.bool, +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - /** - * Number of cells in collection. - */ - cellCount: _react.PropTypes.number.isRequired, +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - /** - * Calculates cell sizes and positions and manages rendering the appropriate cells given a specified window. - */ - cellLayoutManager: _react.PropTypes.object.isRequired, +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - /** - * Optional custom CSS class name to attach to root Collection element. - */ - className: _react.PropTypes.string, +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - /** - * Height of Collection; this property determines the number of visible (vs virtualized) rows. - */ - height: _react.PropTypes.number.isRequired, +// @TODO It would be nice to refactor Grid to use this code as well. - /** - * Enables the `Collection` to horiontally "overscan" its content similar to how `Grid` does. - * This can reduce flicker around the edges when a user scrolls quickly. - */ - horizontalOverscanSize: _react.PropTypes.number.isRequired, +/** + * Specifies the number of miliseconds during which to disable pointer events while a scroll is in progress. + * This improves performance and makes scrolling smoother. + */ +var IS_SCROLLING_TIMEOUT = 150; - isScrollingChange: _react.PropTypes.func, +/** + * Controls whether the Grid updates the DOM element's scrollLeft/scrollTop based on the current state or just observes it. + * This prevents Grid from interrupting mouse-wheel animations (see issue #2). + */ +var SCROLL_POSITION_CHANGE_REASONS = { + OBSERVED: 'observed', + REQUESTED: 'requested' +}; - /** - * Optional renderer to be used in place of rows when either :rowCount or :cellCount is 0. - */ - noContentRenderer: _react.PropTypes.func.isRequired, +/** + * Monitors changes in properties (eg. cellCount) and state (eg. scroll offsets) to determine when rendering needs to occur. + * This component does not render any visible content itself; it defers to the specified :cellLayoutManager. + */ - /** - * Callback invoked whenever the scroll offset changes within the inner scrollable region. - * This callback can be used to sync scrolling between lists, tables, or grids. - * ({ clientHeight, clientWidth, scrollHeight, scrollLeft, scrollTop, scrollWidth }): void - */ - onScroll: _react.PropTypes.func.isRequired, +var CollectionView = function (_Component) { + _inherits(CollectionView, _Component); - /** - * Callback invoked with information about the section of the Collection that was just rendered. - * This callback is passed a named :indices parameter which is an Array of the most recently rendered section indices. - */ - onSectionRendered: _react.PropTypes.func.isRequired, + function CollectionView(props, context) { + _classCallCheck(this, CollectionView); - /** - * Horizontal offset. - */ - scrollLeft: _react.PropTypes.number, + var _this = _possibleConstructorReturn(this, (CollectionView.__proto__ || Object.getPrototypeOf(CollectionView)).call(this, props, context)); - /** - * Controls scroll-to-cell behavior of the Grid. - * The default ("auto") scrolls the least amount possible to ensure that the specified cell is fully visible. - * Use "start" to align cells to the top/left of the Grid and "end" to align bottom/right. - */ - scrollToAlignment: _react.PropTypes.oneOf(['auto', 'end', 'start', 'center']).isRequired, + _this.state = { + calculateSizeAndPositionDataOnNextUpdate: false, + isScrolling: false, + scrollLeft: 0, + scrollTop: 0 + }; + + // Invokes callbacks only when their values have changed. + _this._onSectionRenderedMemoizer = (0, _createCallbackMemoizer2.default)(); + _this._onScrollMemoizer = (0, _createCallbackMemoizer2.default)(false); - /** - * Cell index to ensure visible (by forcefully scrolling if necessary). - */ - scrollToCell: _react.PropTypes.number, + // Bind functions to instance so they don't lose context when passed around. + _this._invokeOnSectionRenderedHelper = _this._invokeOnSectionRenderedHelper.bind(_this); + _this._onScroll = _this._onScroll.bind(_this); + _this._updateScrollPositionForScrollToCell = _this._updateScrollPositionForScrollToCell.bind(_this); + return _this; + } /** - * Vertical offset. + * Forced recompute of cell sizes and positions. + * This function should be called if cell sizes have changed but nothing else has. + * Since cell positions are calculated by callbacks, the collection view has no way of detecting when the underlying data has changed. */ - scrollTop: _react.PropTypes.number, - /** - * Optional custom inline style to attach to root Collection element. - */ - style: _react.PropTypes.object, - /** - * Enables the `Collection` to vertically "overscan" its content similar to how `Grid` does. - * This can reduce flicker around the edges when a user scrolls quickly. - */ - verticalOverscanSize: _react.PropTypes.number.isRequired, + _createClass(CollectionView, [{ + key: 'recomputeCellSizesAndPositions', + value: function recomputeCellSizesAndPositions() { + this.setState({ + calculateSizeAndPositionDataOnNextUpdate: true + }); + } - /** - * Width of Collection; this property determines the number of visible (vs virtualized) columns. - */ - width: _react.PropTypes.number.isRequired -}; -CollectionView.defaultProps = { - 'aria-label': 'grid', - horizontalOverscanSize: 0, - noContentRenderer: function noContentRenderer() { - return null; - }, - onScroll: function onScroll() { - return null; - }, - onSectionRendered: function onSectionRendered() { - return null; - }, - scrollToAlignment: 'auto', - style: {}, - verticalOverscanSize: 0 -}; -exports.default = CollectionView; -},{"../utils/createCallbackMemoizer":78,"classnames":undefined,"dom-helpers/util/scrollbarSize":19,"raf":29,"react":undefined,"react-addons-shallow-compare":30}],45:[function(require,module,exports){ -'use strict'; + /* ---------------------------- Component lifecycle methods ---------------------------- */ -Object.defineProperty(exports, "__esModule", { - value: true -}); + }, { + key: 'componentDidMount', + value: function componentDidMount() { + var _props = this.props; + var cellLayoutManager = _props.cellLayoutManager; + var scrollLeft = _props.scrollLeft; + var scrollToCell = _props.scrollToCell; + var scrollTop = _props.scrollTop; -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + // If this component was first rendered server-side, scrollbar size will be undefined. + // In that event we need to remeasure. -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + if (!this._scrollbarSizeMeasured) { + this._scrollbarSize = (0, _scrollbarSize2.default)(); + this._scrollbarSizeMeasured = true; + this.setState({}); + } -/** - * A section of the Window. - * Window Sections are used to group nearby cells. - * This enables us to more quickly determine which cells to display in a given region of the Window. - * Sections have a fixed size and contain 0 to many cells (tracked by their indices). - */ -var Section = function () { - function Section(_ref) { - var height = _ref.height; - var width = _ref.width; - var x = _ref.x; - var y = _ref.y; + if (scrollToCell >= 0) { + this._updateScrollPositionForScrollToCell(); + } else if (scrollLeft >= 0 || scrollTop >= 0) { + this._setScrollPosition({ scrollLeft: scrollLeft, scrollTop: scrollTop }); + } - _classCallCheck(this, Section); + // Update onSectionRendered callback. + this._invokeOnSectionRenderedHelper(); - this.height = height; - this.width = width; - this.x = x; - this.y = y; + var _cellLayoutManager$ge = cellLayoutManager.getTotalSize(); - this._indexMap = {}; - this._indices = []; - } + var totalHeight = _cellLayoutManager$ge.height; + var totalWidth = _cellLayoutManager$ge.width; - /** Add a cell to this section. */ + // Initialize onScroll callback. + this._invokeOnScrollMemoizer({ + scrollLeft: scrollLeft || 0, + scrollTop: scrollTop || 0, + totalHeight: totalHeight, + totalWidth: totalWidth + }); + } + }, { + key: 'componentDidUpdate', + value: function componentDidUpdate(prevProps, prevState) { + var _props2 = this.props; + var height = _props2.height; + var scrollToCell = _props2.scrollToCell; + var width = _props2.width; + var _state = this.state; + var scrollLeft = _state.scrollLeft; + var scrollPositionChangeReason = _state.scrollPositionChangeReason; + var scrollToAlignment = _state.scrollToAlignment; + var scrollTop = _state.scrollTop; - _createClass(Section, [{ - key: 'addCellIndex', - value: function addCellIndex(_ref2) { - var index = _ref2.index; + // Make sure requested changes to :scrollLeft or :scrollTop get applied. + // Assigning to scrollLeft/scrollTop tells the browser to interrupt any running scroll animations, + // And to discard any pending async changes to the scroll position that may have happened in the meantime (e.g. on a separate scrolling thread). + // So we only set these when we require an adjustment of the scroll position. + // See issue #2 for more information. - if (!this._indexMap[index]) { - this._indexMap[index] = true; - this._indices.push(index); + if (scrollPositionChangeReason === SCROLL_POSITION_CHANGE_REASONS.REQUESTED) { + if (scrollLeft >= 0 && scrollLeft !== prevState.scrollLeft && scrollLeft !== this._scrollingContainer.scrollLeft) { + this._scrollingContainer.scrollLeft = scrollLeft; + } + if (scrollTop >= 0 && scrollTop !== prevState.scrollTop && scrollTop !== this._scrollingContainer.scrollTop) { + this._scrollingContainer.scrollTop = scrollTop; + } + } + + // Update scroll offsets if the current :scrollToCell values requires it + if (height !== prevProps.height || scrollToAlignment !== prevProps.scrollToAlignment || scrollToCell !== prevProps.scrollToCell || width !== prevProps.width) { + this._updateScrollPositionForScrollToCell(); } + + // Update onRowsRendered callback if start/stop indices have changed + this._invokeOnSectionRenderedHelper(); } + }, { + key: 'componentWillMount', + value: function componentWillMount() { + var cellLayoutManager = this.props.cellLayoutManager; - /** Get all cell indices that have been added to this section. */ + cellLayoutManager.calculateSizeAndPositionData(); + + // If this component is being rendered server-side, getScrollbarSize() will return undefined. + // We handle this case in componentDidMount() + this._scrollbarSize = (0, _scrollbarSize2.default)(); + if (this._scrollbarSize === undefined) { + this._scrollbarSizeMeasured = false; + this._scrollbarSize = 0; + } else { + this._scrollbarSizeMeasured = true; + } + } }, { - key: 'getCellIndices', - value: function getCellIndices() { - return this._indices; + key: 'componentWillUnmount', + value: function componentWillUnmount() { + if (this._disablePointerEventsTimeoutId) { + clearTimeout(this._disablePointerEventsTimeoutId); + } + + if (this._setNextStateAnimationFrameId) { + _raf2.default.cancel(this._setNextStateAnimationFrameId); + } } - /** Intended for debugger/test purposes only */ + /** + * @private + * This method updates scrollLeft/scrollTop in state for the following conditions: + * 1) Empty content (0 rows or columns) + * 2) New scroll props overriding the current state + * 3) Cells-count or cells-size has changed, making previous scroll offsets invalid + */ }, { - key: 'toString', - value: function toString() { - return this.x + ',' + this.y + ' ' + this.width + 'x' + this.height; + key: 'componentWillUpdate', + value: function componentWillUpdate(nextProps, nextState) { + if (nextProps.cellCount === 0 && (nextState.scrollLeft !== 0 || nextState.scrollTop !== 0)) { + this._setScrollPosition({ + scrollLeft: 0, + scrollTop: 0 + }); + } else if (nextProps.scrollLeft !== this.props.scrollLeft || nextProps.scrollTop !== this.props.scrollTop) { + this._setScrollPosition({ + scrollLeft: nextProps.scrollLeft, + scrollTop: nextProps.scrollTop + }); + } + + if (nextProps.cellCount !== this.props.cellCount || nextProps.cellLayoutManager !== this.props.cellLayoutManager || nextState.calculateSizeAndPositionDataOnNextUpdate) { + nextProps.cellLayoutManager.calculateSizeAndPositionData(); + } + + if (nextState.calculateSizeAndPositionDataOnNextUpdate) { + this.setState({ + calculateSizeAndPositionDataOnNextUpdate: false + }); + } } - }]); + }, { + key: 'render', + value: function render() { + var _this2 = this; - return Section; -}(); /** @rlow */ + var _props3 = this.props; + var autoHeight = _props3.autoHeight; + var cellCount = _props3.cellCount; + var cellLayoutManager = _props3.cellLayoutManager; + var className = _props3.className; + var height = _props3.height; + var horizontalOverscanSize = _props3.horizontalOverscanSize; + var noContentRenderer = _props3.noContentRenderer; + var style = _props3.style; + var verticalOverscanSize = _props3.verticalOverscanSize; + var width = _props3.width; + var _state2 = this.state; + var isScrolling = _state2.isScrolling; + var scrollLeft = _state2.scrollLeft; + var scrollTop = _state2.scrollTop; + + var _cellLayoutManager$ge2 = cellLayoutManager.getTotalSize(); + var totalHeight = _cellLayoutManager$ge2.height; + var totalWidth = _cellLayoutManager$ge2.width; -exports.default = Section; -},{}],46:[function(require,module,exports){ -'use strict'; + // Safely expand the rendered area by the specified overscan amount -Object.defineProperty(exports, "__esModule", { - value: true -}); + var left = Math.max(0, scrollLeft - horizontalOverscanSize); + var top = Math.max(0, scrollTop - verticalOverscanSize); + var right = Math.min(totalWidth, scrollLeft + width + horizontalOverscanSize); + var bottom = Math.min(totalHeight, scrollTop + height + verticalOverscanSize); + + var childrenToDisplay = height > 0 && width > 0 ? cellLayoutManager.cellRenderers({ + height: bottom - top, + isScrolling: isScrolling, + width: right - left, + x: left, + y: top + }) : []; -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /** - * Window Sections are used to group nearby cells. - * This enables us to more quickly determine which cells to display in a given region of the Window. - * - */ + var collectionStyle = { + height: autoHeight ? 'auto' : height, + width: width + }; + // Force browser to hide scrollbars when we know they aren't necessary. + // Otherwise once scrollbars appear they may not disappear again. + // For more info see issue #116 + var verticalScrollBarSize = totalHeight > height ? this._scrollbarSize : 0; + var horizontalScrollBarSize = totalWidth > width ? this._scrollbarSize : 0; + if (totalWidth + verticalScrollBarSize <= width) { + collectionStyle.overflowX = 'hidden'; + } + if (totalHeight + horizontalScrollBarSize <= height) { + collectionStyle.overflowY = 'hidden'; + } -var _Section = require('./Section'); + return _react2.default.createElement( + 'div', + { + ref: function ref(_ref) { + _this2._scrollingContainer = _ref; + }, + 'aria-label': this.props['aria-label'], + className: (0, _classnames2.default)('Collection', className), + onScroll: this._onScroll, + role: 'grid', + style: _extends({}, collectionStyle, style), + tabIndex: 0 + }, + cellCount > 0 && _react2.default.createElement( + 'div', + { + className: 'Collection__innerScrollContainer', + style: { + height: totalHeight, + maxHeight: totalHeight, + maxWidth: totalWidth, + pointerEvents: isScrolling ? 'none' : '', + width: totalWidth + } + }, + childrenToDisplay + ), + cellCount === 0 && noContentRenderer() + ); + } + }, { + key: 'shouldComponentUpdate', + value: function shouldComponentUpdate(nextProps, nextState) { + return (0, _reactAddonsShallowCompare2.default)(this, nextProps, nextState); + } -var _Section2 = _interopRequireDefault(_Section); + /* ---------------------------- Helper methods ---------------------------- */ -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + /** + * Sets an :isScrolling flag for a small window of time. + * This flag is used to disable pointer events on the scrollable portion of the Collection. + * This prevents jerky/stuttery mouse-wheel scrolling. + */ -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + }, { + key: '_enablePointerEventsAfterDelay', + value: function _enablePointerEventsAfterDelay() { + var _this3 = this; -var SECTION_SIZE = 100; + if (this._disablePointerEventsTimeoutId) { + clearTimeout(this._disablePointerEventsTimeoutId); + } -/** - * Contains 0 to many Sections. - * Grows (and adds Sections) dynamically as cells are registered. - * Automatically adds cells to the appropriate Section(s). - */ -var SectionManager = function () { - function SectionManager() { - var sectionSize = arguments.length <= 0 || arguments[0] === undefined ? SECTION_SIZE : arguments[0]; + this._disablePointerEventsTimeoutId = setTimeout(function () { + var isScrollingChange = _this3.props.isScrollingChange; - _classCallCheck(this, SectionManager); - this._sectionSize = sectionSize; + isScrollingChange(false); - this._cellMetadata = []; - this._sections = {}; - } + _this3._disablePointerEventsTimeoutId = null; + _this3.setState({ + isScrolling: false + }); + }, IS_SCROLLING_TIMEOUT); + } + }, { + key: '_invokeOnSectionRenderedHelper', + value: function _invokeOnSectionRenderedHelper() { + var _props4 = this.props; + var cellLayoutManager = _props4.cellLayoutManager; + var onSectionRendered = _props4.onSectionRendered; - /** - * Gets all cell indices contained in the specified region. - * A region may encompass 1 or more Sections. - */ + this._onSectionRenderedMemoizer({ + callback: onSectionRendered, + indices: { + indices: cellLayoutManager.getLastRenderedIndices() + } + }); + } + }, { + key: '_invokeOnScrollMemoizer', + value: function _invokeOnScrollMemoizer(_ref2) { + var _this4 = this; - _createClass(SectionManager, [{ - key: 'getCellIndices', - value: function getCellIndices(_ref) { - var height = _ref.height; - var width = _ref.width; - var x = _ref.x; - var y = _ref.y; + var scrollLeft = _ref2.scrollLeft; + var scrollTop = _ref2.scrollTop; + var totalHeight = _ref2.totalHeight; + var totalWidth = _ref2.totalWidth; - var indices = {}; + this._onScrollMemoizer({ + callback: function callback(_ref3) { + var scrollLeft = _ref3.scrollLeft; + var scrollTop = _ref3.scrollTop; + var _props5 = _this4.props; + var height = _props5.height; + var onScroll = _props5.onScroll; + var width = _props5.width; - this.getSections({ height: height, width: width, x: x, y: y }).forEach(function (section) { - return section.getCellIndices().forEach(function (index) { - indices[index] = index; - }); - }); - // Object keys are strings; this function returns numbers - return Object.keys(indices).map(function (index) { - return indices[index]; + onScroll({ + clientHeight: height, + clientWidth: width, + scrollHeight: totalHeight, + scrollLeft: scrollLeft, + scrollTop: scrollTop, + scrollWidth: totalWidth + }); + }, + indices: { + scrollLeft: scrollLeft, + scrollTop: scrollTop + } }); } - /** Get size and position information for the cell specified. */ + /** + * Updates the state during the next animation frame. + * Use this method to avoid multiple renders in a small span of time. + * This helps performance for bursty events (like onScroll). + */ }, { - key: 'getCellMetadata', - value: function getCellMetadata(_ref2) { - var index = _ref2.index; + key: '_setNextState', + value: function _setNextState(state) { + var _this5 = this; - return this._cellMetadata[index]; + if (this._setNextStateAnimationFrameId) { + _raf2.default.cancel(this._setNextStateAnimationFrameId); + } + + this._setNextStateAnimationFrameId = (0, _raf2.default)(function () { + _this5._setNextStateAnimationFrameId = null; + _this5.setState(state); + }); } + }, { + key: '_setScrollPosition', + value: function _setScrollPosition(_ref4) { + var scrollLeft = _ref4.scrollLeft; + var scrollTop = _ref4.scrollTop; - /** Get all Sections overlapping the specified region. */ + var newState = { + scrollPositionChangeReason: SCROLL_POSITION_CHANGE_REASONS.REQUESTED + }; - }, { - key: 'getSections', - value: function getSections(_ref3) { - var height = _ref3.height; - var width = _ref3.width; - var x = _ref3.x; - var y = _ref3.y; + if (scrollLeft >= 0) { + newState.scrollLeft = scrollLeft; + } - var sectionXStart = Math.floor(x / this._sectionSize); - var sectionXStop = Math.floor((x + width - 1) / this._sectionSize); - var sectionYStart = Math.floor(y / this._sectionSize); - var sectionYStop = Math.floor((y + height - 1) / this._sectionSize); + if (scrollTop >= 0) { + newState.scrollTop = scrollTop; + } - var sections = []; + if (scrollLeft >= 0 && scrollLeft !== this.state.scrollLeft || scrollTop >= 0 && scrollTop !== this.state.scrollTop) { + this.setState(newState); + } + } + }, { + key: '_updateScrollPositionForScrollToCell', + value: function _updateScrollPositionForScrollToCell() { + var _props6 = this.props; + var cellLayoutManager = _props6.cellLayoutManager; + var height = _props6.height; + var scrollToAlignment = _props6.scrollToAlignment; + var scrollToCell = _props6.scrollToCell; + var width = _props6.width; + var _state3 = this.state; + var scrollLeft = _state3.scrollLeft; + var scrollTop = _state3.scrollTop; - for (var sectionX = sectionXStart; sectionX <= sectionXStop; sectionX++) { - for (var sectionY = sectionYStart; sectionY <= sectionYStop; sectionY++) { - var key = sectionX + '.' + sectionY; - if (!this._sections[key]) { - this._sections[key] = new _Section2.default({ - height: this._sectionSize, - width: this._sectionSize, - x: sectionX * this._sectionSize, - y: sectionY * this._sectionSize - }); - } + if (scrollToCell >= 0) { + var scrollPosition = cellLayoutManager.getScrollPositionForCell({ + align: scrollToAlignment, + cellIndex: scrollToCell, + height: height, + scrollLeft: scrollLeft, + scrollTop: scrollTop, + width: width + }); - sections.push(this._sections[key]); + if (scrollPosition.scrollLeft !== scrollLeft || scrollPosition.scrollTop !== scrollTop) { + this._setScrollPosition(scrollPosition); } } + } + }, { + key: '_onScroll', + value: function _onScroll(event) { + // In certain edge-cases React dispatches an onScroll event with an invalid target.scrollLeft / target.scrollTop. + // This invalid event can be detected by comparing event.target to this component's scrollable DOM element. + // See issue #404 for more information. + if (event.target !== this._scrollingContainer) { + return; + } - return sections; - } + // Prevent pointer events from interrupting a smooth scroll + this._enablePointerEventsAfterDelay(); - /** Total number of Sections based on the currently registered cells. */ + // When this component is shrunk drastically, React dispatches a series of back-to-back scroll events, + // Gradually converging on a scrollTop that is within the bounds of the new, smaller height. + // This causes a series of rapid renders that is slow for long lists. + // We can avoid that by doing some simple bounds checking to ensure that scrollTop never exceeds the total height. + var _props7 = this.props; + var cellLayoutManager = _props7.cellLayoutManager; + var height = _props7.height; + var isScrollingChange = _props7.isScrollingChange; + var width = _props7.width; - }, { - key: 'getTotalSectionCount', - value: function getTotalSectionCount() { - return Object.keys(this._sections).length; - } + var scrollbarSize = this._scrollbarSize; - /** Intended for debugger/test purposes only */ + var _cellLayoutManager$ge3 = cellLayoutManager.getTotalSize(); - }, { - key: 'toString', - value: function toString() { - var _this = this; + var totalHeight = _cellLayoutManager$ge3.height; + var totalWidth = _cellLayoutManager$ge3.width; - return Object.keys(this._sections).map(function (index) { - return _this._sections[index].toString(); - }); - } + var scrollLeft = Math.max(0, Math.min(totalWidth - width + scrollbarSize, event.target.scrollLeft)); + var scrollTop = Math.max(0, Math.min(totalHeight - height + scrollbarSize, event.target.scrollTop)); - /** Adds a cell to the appropriate Sections and registers it metadata for later retrievable. */ + // Certain devices (like Apple touchpad) rapid-fire duplicate events. + // Don't force a re-render if this is the case. + // The mouse may move faster then the animation frame does. + // Use requestAnimationFrame to avoid over-updating. + if (this.state.scrollLeft !== scrollLeft || this.state.scrollTop !== scrollTop) { + // Browsers with cancelable scroll events (eg. Firefox) interrupt scrolling animations if scrollTop/scrollLeft is set. + // Other browsers (eg. Safari) don't scroll as well without the help under certain conditions (DOM or style changes during scrolling). + // All things considered, this seems to be the best current work around that I'm aware of. + // For more information see https://github.com/bvaughn/react-virtualized/pull/124 + var scrollPositionChangeReason = event.cancelable ? SCROLL_POSITION_CHANGE_REASONS.OBSERVED : SCROLL_POSITION_CHANGE_REASONS.REQUESTED; - }, { - key: 'registerCell', - value: function registerCell(_ref4) { - var cellMetadatum = _ref4.cellMetadatum; - var index = _ref4.index; + // Synchronously set :isScrolling the first time (since _setNextState will reschedule its animation frame each time it's called) + if (!this.state.isScrolling) { + isScrollingChange(true); - this._cellMetadata[index] = cellMetadatum; + this.setState({ + isScrolling: true + }); + } - this.getSections(cellMetadatum).forEach(function (section) { - return section.addCellIndex({ index: index }); + this._setNextState({ + isScrolling: true, + scrollLeft: scrollLeft, + scrollPositionChangeReason: scrollPositionChangeReason, + scrollTop: scrollTop + }); + } + + this._invokeOnScrollMemoizer({ + scrollLeft: scrollLeft, + scrollTop: scrollTop, + totalWidth: totalWidth, + totalHeight: totalHeight }); } }]); - return SectionManager; -}(); + return CollectionView; +}(_react.Component); -exports.default = SectionManager; -},{"./Section":45}],47:[function(require,module,exports){ -'use strict'; +CollectionView.propTypes = { + 'aria-label': _react.PropTypes.string, -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.Collection = exports.default = undefined; + /** + * Removes fixed height from the scrollingContainer so that the total height + * of rows can stretch the window. Intended for use with WindowScroller + */ + autoHeight: _react.PropTypes.bool, -var _Collection2 = require('./Collection'); + /** + * Number of cells in collection. + */ + cellCount: _react.PropTypes.number.isRequired, -var _Collection3 = _interopRequireDefault(_Collection2); + /** + * Calculates cell sizes and positions and manages rendering the appropriate cells given a specified window. + */ + cellLayoutManager: _react.PropTypes.object.isRequired, -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + /** + * Optional custom CSS class name to attach to root Collection element. + */ + className: _react.PropTypes.string, -exports.default = _Collection3.default; -exports.Collection = _Collection3.default; -},{"./Collection":43}],48:[function(require,module,exports){ -'use strict'; + /** + * Height of Collection; this property determines the number of visible (vs virtualized) rows. + */ + height: _react.PropTypes.number.isRequired, -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.default = calculateSizeAndPositionData; + /** + * Enables the `Collection` to horiontally "overscan" its content similar to how `Grid` does. + * This can reduce flicker around the edges when a user scrolls quickly. + */ + horizontalOverscanSize: _react.PropTypes.number.isRequired, -var _SectionManager = require('../SectionManager'); + isScrollingChange: _react.PropTypes.func, -var _SectionManager2 = _interopRequireDefault(_SectionManager); + /** + * Optional renderer to be used in place of rows when either :rowCount or :cellCount is 0. + */ + noContentRenderer: _react.PropTypes.func.isRequired, -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + /** + * Callback invoked whenever the scroll offset changes within the inner scrollable region. + * This callback can be used to sync scrolling between lists, tables, or grids. + * ({ clientHeight, clientWidth, scrollHeight, scrollLeft, scrollTop, scrollWidth }): void + */ + onScroll: _react.PropTypes.func.isRequired, -function calculateSizeAndPositionData(_ref) { - var cellCount = _ref.cellCount; - var cellSizeAndPositionGetter = _ref.cellSizeAndPositionGetter; - var sectionSize = _ref.sectionSize; + /** + * Callback invoked with information about the section of the Collection that was just rendered. + * This callback is passed a named :indices parameter which is an Array of the most recently rendered section indices. + */ + onSectionRendered: _react.PropTypes.func.isRequired, - var cellMetadata = []; - var sectionManager = new _SectionManager2.default(sectionSize); - var height = 0; - var width = 0; + /** + * Horizontal offset. + */ + scrollLeft: _react.PropTypes.number, - for (var index = 0; index < cellCount; index++) { - var cellMetadatum = cellSizeAndPositionGetter({ index: index }); + /** + * Controls scroll-to-cell behavior of the Grid. + * The default ("auto") scrolls the least amount possible to ensure that the specified cell is fully visible. + * Use "start" to align cells to the top/left of the Grid and "end" to align bottom/right. + */ + scrollToAlignment: _react.PropTypes.oneOf(['auto', 'end', 'start', 'center']).isRequired, - if (cellMetadatum.height == null || isNaN(cellMetadatum.height) || cellMetadatum.width == null || isNaN(cellMetadatum.width) || cellMetadatum.x == null || isNaN(cellMetadatum.x) || cellMetadatum.y == null || isNaN(cellMetadatum.y)) { - throw Error('Invalid metadata returned for cell ' + index + ':\n x:' + cellMetadatum.x + ', y:' + cellMetadatum.y + ', width:' + cellMetadatum.width + ', height:' + cellMetadatum.height); - } + /** + * Cell index to ensure visible (by forcefully scrolling if necessary). + */ + scrollToCell: _react.PropTypes.number, - height = Math.max(height, cellMetadatum.y + cellMetadatum.height); - width = Math.max(width, cellMetadatum.x + cellMetadatum.width); + /** + * Vertical offset. + */ + scrollTop: _react.PropTypes.number, - cellMetadata[index] = cellMetadatum; - sectionManager.registerCell({ - cellMetadatum: cellMetadatum, - index: index - }); - } + /** + * Optional custom inline style to attach to root Collection element. + */ + style: _react.PropTypes.object, - return { - cellMetadata: cellMetadata, - height: height, - sectionManager: sectionManager, - width: width - }; -} -},{"../SectionManager":46}],49:[function(require,module,exports){ + /** + * Enables the `Collection` to vertically "overscan" its content similar to how `Grid` does. + * This can reduce flicker around the edges when a user scrolls quickly. + */ + verticalOverscanSize: _react.PropTypes.number.isRequired, + + /** + * Width of Collection; this property determines the number of visible (vs virtualized) columns. + */ + width: _react.PropTypes.number.isRequired +}; +CollectionView.defaultProps = { + 'aria-label': 'grid', + horizontalOverscanSize: 0, + noContentRenderer: function noContentRenderer() { + return null; + }, + onScroll: function onScroll() { + return null; + }, + onSectionRendered: function onSectionRendered() { + return null; + }, + scrollToAlignment: 'auto', + style: {}, + verticalOverscanSize: 0 +}; +exports.default = CollectionView; +},{"../utils/createCallbackMemoizer":76,"classnames":undefined,"dom-helpers/util/scrollbarSize":80,"raf":81,"react":undefined,"react-addons-shallow-compare":18}],43:[function(require,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { @@ -5011,300 +5088,306 @@ Object.defineProperty(exports, "__esModule", { var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); -var _react = require('react'); - -var _reactAddonsShallowCompare = require('react-addons-shallow-compare'); - -var _reactAddonsShallowCompare2 = _interopRequireDefault(_reactAddonsShallowCompare); - -var _Grid = require('../Grid'); - -var _Grid2 = _interopRequireDefault(_Grid); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - /** - * High-order component that auto-calculates column-widths for `Grid` cells. + * A section of the Window. + * Window Sections are used to group nearby cells. + * This enables us to more quickly determine which cells to display in a given region of the Window. + * Sections have a fixed size and contain 0 to many cells (tracked by their indices). */ -var ColumnSizer = function (_Component) { - _inherits(ColumnSizer, _Component); +var Section = function () { + function Section(_ref) { + var height = _ref.height; + var width = _ref.width; + var x = _ref.x; + var y = _ref.y; - function ColumnSizer(props, context) { - _classCallCheck(this, ColumnSizer); + _classCallCheck(this, Section); - var _this = _possibleConstructorReturn(this, (ColumnSizer.__proto__ || Object.getPrototypeOf(ColumnSizer)).call(this, props, context)); + this.height = height; + this.width = width; + this.x = x; + this.y = y; - _this._registerChild = _this._registerChild.bind(_this); - return _this; + this._indexMap = {}; + this._indices = []; } - _createClass(ColumnSizer, [{ - key: 'componentDidUpdate', - value: function componentDidUpdate(prevProps, prevState) { - var _props = this.props; - var columnMaxWidth = _props.columnMaxWidth; - var columnMinWidth = _props.columnMinWidth; - var columnCount = _props.columnCount; - var width = _props.width; + /** Add a cell to this section. */ - if (columnMaxWidth !== prevProps.columnMaxWidth || columnMinWidth !== prevProps.columnMinWidth || columnCount !== prevProps.columnCount || width !== prevProps.width) { - if (this._registeredChild) { - this._registeredChild.recomputeGridSize(); - } + _createClass(Section, [{ + key: 'addCellIndex', + value: function addCellIndex(_ref2) { + var index = _ref2.index; + + if (!this._indexMap[index]) { + this._indexMap[index] = true; + this._indices.push(index); } } - }, { - key: 'render', - value: function render() { - var _props2 = this.props; - var children = _props2.children; - var columnMaxWidth = _props2.columnMaxWidth; - var columnMinWidth = _props2.columnMinWidth; - var columnCount = _props2.columnCount; - var width = _props2.width; - - - var safeColumnMinWidth = columnMinWidth || 1; - - var safeColumnMaxWidth = columnMaxWidth ? Math.min(columnMaxWidth, width) : width; - - var columnWidth = width / columnCount; - columnWidth = Math.max(safeColumnMinWidth, columnWidth); - columnWidth = Math.min(safeColumnMaxWidth, columnWidth); - columnWidth = Math.floor(columnWidth); - var adjustedWidth = Math.min(width, columnWidth * columnCount); + /** Get all cell indices that have been added to this section. */ - return children({ - adjustedWidth: adjustedWidth, - getColumnWidth: function getColumnWidth() { - return columnWidth; - }, - registerChild: this._registerChild - }); - } }, { - key: 'shouldComponentUpdate', - value: function shouldComponentUpdate(nextProps, nextState) { - return (0, _reactAddonsShallowCompare2.default)(this, nextProps, nextState); + key: 'getCellIndices', + value: function getCellIndices() { + return this._indices; } - }, { - key: '_registerChild', - value: function _registerChild(child) { - if (child !== null && !(child instanceof _Grid2.default)) { - throw Error('Unexpected child type registered; only Grid children are supported.'); - } - this._registeredChild = child; + /** Intended for debugger/test purposes only */ - if (this._registeredChild) { - this._registeredChild.recomputeGridSize(); - } + }, { + key: 'toString', + value: function toString() { + return this.x + ',' + this.y + ' ' + this.width + 'x' + this.height; } }]); - return ColumnSizer; -}(_react.Component); - -ColumnSizer.propTypes = { - /** - * Function respondible for rendering a virtualized Grid. - * This function should implement the following signature: - * ({ adjustedWidth, getColumnWidth, registerChild }) => PropTypes.element - * - * The specified :getColumnWidth function should be passed to the Grid's :columnWidth property. - * The :registerChild should be passed to the Grid's :ref property. - * The :adjustedWidth property is optional; it reflects the lesser of the overall width or the width of all columns. - */ - children: _react.PropTypes.func.isRequired, - - /** Optional maximum allowed column width */ - columnMaxWidth: _react.PropTypes.number, - - /** Optional minimum allowed column width */ - columnMinWidth: _react.PropTypes.number, + return Section; +}(); /** @rlow */ - /** Number of columns in Grid or FlexTable child */ - columnCount: _react.PropTypes.number.isRequired, - /** Width of Grid or FlexTable child */ - width: _react.PropTypes.number.isRequired -}; -exports.default = ColumnSizer; -},{"../Grid":62,"react":undefined,"react-addons-shallow-compare":30}],50:[function(require,module,exports){ +exports.default = Section; +},{}],44:[function(require,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); -exports.ColumnSizer = exports.default = undefined; -var _ColumnSizer2 = require('./ColumnSizer'); +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /** + * Window Sections are used to group nearby cells. + * This enables us to more quickly determine which cells to display in a given region of the Window. + * + */ -var _ColumnSizer3 = _interopRequireDefault(_ColumnSizer2); + +var _Section = require('./Section'); + +var _Section2 = _interopRequireDefault(_Section); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -exports.default = _ColumnSizer3.default; -exports.ColumnSizer = _ColumnSizer3.default; -},{"./ColumnSizer":49}],51:[function(require,module,exports){ -'use strict'; +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } -Object.defineProperty(exports, "__esModule", { - value: true -}); +var SECTION_SIZE = 100; -var _react = require('react'); +/** + * Contains 0 to many Sections. + * Grows (and adds Sections) dynamically as cells are registered. + * Automatically adds cells to the appropriate Section(s). + */ +var SectionManager = function () { + function SectionManager() { + var sectionSize = arguments.length <= 0 || arguments[0] === undefined ? SECTION_SIZE : arguments[0]; -var _defaultHeaderRenderer = require('./defaultHeaderRenderer'); + _classCallCheck(this, SectionManager); -var _defaultHeaderRenderer2 = _interopRequireDefault(_defaultHeaderRenderer); + this._sectionSize = sectionSize; -var _defaultCellRenderer = require('./defaultCellRenderer'); + this._cellMetadata = []; + this._sections = {}; + } -var _defaultCellRenderer2 = _interopRequireDefault(_defaultCellRenderer); + /** + * Gets all cell indices contained in the specified region. + * A region may encompass 1 or more Sections. + */ -var _defaultCellDataGetter = require('./defaultCellDataGetter'); -var _defaultCellDataGetter2 = _interopRequireDefault(_defaultCellDataGetter); + _createClass(SectionManager, [{ + key: 'getCellIndices', + value: function getCellIndices(_ref) { + var height = _ref.height; + var width = _ref.width; + var x = _ref.x; + var y = _ref.y; -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + var indices = {}; -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + this.getSections({ height: height, width: width, x: x, y: y }).forEach(function (section) { + return section.getCellIndices().forEach(function (index) { + indices[index] = index; + }); + }); -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + // Object keys are strings; this function returns numbers + return Object.keys(indices).map(function (index) { + return indices[index]; + }); + } -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + /** Get size and position information for the cell specified. */ -/** - * Describes the header and cell contents of a table column. - */ -var Column = function (_Component) { - _inherits(Column, _Component); + }, { + key: 'getCellMetadata', + value: function getCellMetadata(_ref2) { + var index = _ref2.index; - function Column() { - _classCallCheck(this, Column); + return this._cellMetadata[index]; + } - return _possibleConstructorReturn(this, (Column.__proto__ || Object.getPrototypeOf(Column)).apply(this, arguments)); - } + /** Get all Sections overlapping the specified region. */ - return Column; -}(_react.Component); + }, { + key: 'getSections', + value: function getSections(_ref3) { + var height = _ref3.height; + var width = _ref3.width; + var x = _ref3.x; + var y = _ref3.y; -Column.defaultProps = { - cellDataGetter: _defaultCellDataGetter2.default, - cellRenderer: _defaultCellRenderer2.default, - flexGrow: 0, - flexShrink: 1, - headerRenderer: _defaultHeaderRenderer2.default, - style: {} -}; -Column.propTypes = { - /** Optional aria-label value to set on the column header */ - 'aria-label': _react.PropTypes.string, + var sectionXStart = Math.floor(x / this._sectionSize); + var sectionXStop = Math.floor((x + width - 1) / this._sectionSize); + var sectionYStart = Math.floor(y / this._sectionSize); + var sectionYStop = Math.floor((y + height - 1) / this._sectionSize); - /** - * Callback responsible for returning a cell's data, given its :dataKey - * ({ columnData: any, dataKey: string, rowData: any }): any - */ - cellDataGetter: _react.PropTypes.func, + var sections = []; - /** - * Callback responsible for rendering a cell's contents. - * ({ cellData: any, columnData: any, dataKey: string, rowData: any, rowIndex: number }): node - */ - cellRenderer: _react.PropTypes.func, + for (var sectionX = sectionXStart; sectionX <= sectionXStop; sectionX++) { + for (var sectionY = sectionYStart; sectionY <= sectionYStop; sectionY++) { + var key = sectionX + '.' + sectionY; - /** Optional CSS class to apply to cell */ - className: _react.PropTypes.string, + if (!this._sections[key]) { + this._sections[key] = new _Section2.default({ + height: this._sectionSize, + width: this._sectionSize, + x: sectionX * this._sectionSize, + y: sectionY * this._sectionSize + }); + } + + sections.push(this._sections[key]); + } + } + + return sections; + } + + /** Total number of Sections based on the currently registered cells. */ + + }, { + key: 'getTotalSectionCount', + value: function getTotalSectionCount() { + return Object.keys(this._sections).length; + } + + /** Intended for debugger/test purposes only */ + + }, { + key: 'toString', + value: function toString() { + var _this = this; - /** Optional additional data passed to this column's :cellDataGetter */ - columnData: _react.PropTypes.object, + return Object.keys(this._sections).map(function (index) { + return _this._sections[index].toString(); + }); + } - /** Uniquely identifies the row-data attribute correspnding to this cell */ - dataKey: _react.PropTypes.any.isRequired, + /** Adds a cell to the appropriate Sections and registers it metadata for later retrievable. */ - /** If sort is enabled for the table at large, disable it for this column */ - disableSort: _react.PropTypes.bool, + }, { + key: 'registerCell', + value: function registerCell(_ref4) { + var cellMetadatum = _ref4.cellMetadatum; + var index = _ref4.index; - /** Flex grow style; defaults to 0 */ - flexGrow: _react.PropTypes.number, + this._cellMetadata[index] = cellMetadatum; - /** Flex shrink style; defaults to 1 */ - flexShrink: _react.PropTypes.number, + this.getSections(cellMetadatum).forEach(function (section) { + return section.addCellIndex({ index: index }); + }); + } + }]); - /** Optional CSS class to apply to this column's header */ - headerClassName: _react.PropTypes.string, + return SectionManager; +}(); - /** - * Optional callback responsible for rendering a column header contents. - * ({ columnData: object, dataKey: string, disableSort: boolean, label: string, sortBy: string, sortDirection: string }): PropTypes.node - */ - headerRenderer: _react.PropTypes.func.isRequired, +exports.default = SectionManager; +},{"./Section":43}],45:[function(require,module,exports){ +'use strict'; - /** Header label for this column */ - label: _react.PropTypes.string, +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.Collection = exports.default = undefined; - /** Maximum width of column; this property will only be used if :flexGrow is > 0. */ - maxWidth: _react.PropTypes.number, +var _Collection2 = require('./Collection'); - /** Minimum width of column. */ - minWidth: _react.PropTypes.number, +var _Collection3 = _interopRequireDefault(_Collection2); - /** Optional inline style to apply to cell */ - style: _react.PropTypes.object, +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - /** Flex basis (width) for this column; This value can grow or shrink based on :flexGrow and :flexShrink properties. */ - width: _react.PropTypes.number.isRequired -}; -exports.default = Column; -},{"./defaultCellDataGetter":55,"./defaultCellRenderer":56,"./defaultHeaderRenderer":57,"react":undefined}],52:[function(require,module,exports){ +exports.default = _Collection3.default; +exports.Collection = _Collection3.default; +},{"./Collection":41}],46:[function(require,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = calculateSizeAndPositionData; -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; +var _SectionManager = require('../SectionManager'); -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); +var _SectionManager2 = _interopRequireDefault(_SectionManager); -var _classnames = require('classnames'); +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -var _classnames2 = _interopRequireDefault(_classnames); +function calculateSizeAndPositionData(_ref) { + var cellCount = _ref.cellCount; + var cellSizeAndPositionGetter = _ref.cellSizeAndPositionGetter; + var sectionSize = _ref.sectionSize; -var _FlexColumn = require('./FlexColumn'); + var cellMetadata = []; + var sectionManager = new _SectionManager2.default(sectionSize); + var height = 0; + var width = 0; -var _FlexColumn2 = _interopRequireDefault(_FlexColumn); + for (var index = 0; index < cellCount; index++) { + var cellMetadatum = cellSizeAndPositionGetter({ index: index }); -var _react = require('react'); + if (cellMetadatum.height == null || isNaN(cellMetadatum.height) || cellMetadatum.width == null || isNaN(cellMetadatum.width) || cellMetadatum.x == null || isNaN(cellMetadatum.x) || cellMetadatum.y == null || isNaN(cellMetadatum.y)) { + throw Error('Invalid metadata returned for cell ' + index + ':\n x:' + cellMetadatum.x + ', y:' + cellMetadatum.y + ', width:' + cellMetadatum.width + ', height:' + cellMetadatum.height); + } -var _react2 = _interopRequireDefault(_react); + height = Math.max(height, cellMetadatum.y + cellMetadatum.height); + width = Math.max(width, cellMetadatum.x + cellMetadatum.width); -var _reactDom = require('react-dom'); + cellMetadata[index] = cellMetadatum; + sectionManager.registerCell({ + cellMetadatum: cellMetadatum, + index: index + }); + } -var _reactAddonsShallowCompare = require('react-addons-shallow-compare'); + return { + cellMetadata: cellMetadata, + height: height, + sectionManager: sectionManager, + width: width + }; +} +},{"../SectionManager":44}],47:[function(require,module,exports){ +'use strict'; -var _reactAddonsShallowCompare2 = _interopRequireDefault(_reactAddonsShallowCompare); +Object.defineProperty(exports, "__esModule", { + value: true +}); -var _Grid = require('../Grid'); +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); -var _Grid2 = _interopRequireDefault(_Grid); +var _react = require('react'); -var _defaultRowRenderer = require('./defaultRowRenderer'); +var _reactAddonsShallowCompare = require('react-addons-shallow-compare'); -var _defaultRowRenderer2 = _interopRequireDefault(_defaultRowRenderer); +var _reactAddonsShallowCompare2 = _interopRequireDefault(_reactAddonsShallowCompare); -var _SortDirection = require('./SortDirection'); +var _Grid = require('../Grid'); -var _SortDirection2 = _interopRequireDefault(_SortDirection); +var _Grid2 = _interopRequireDefault(_Grid); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -5315,140 +5398,65 @@ function _possibleConstructorReturn(self, call) { if (!self) { throw new Referen function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /** - * Table component with fixed headers and virtualized rows for improved performance with large data sets. - * This component expects explicit width, height, and padding parameters. + * High-order component that auto-calculates column-widths for `Grid` cells. */ -var FlexTable = function (_Component) { - _inherits(FlexTable, _Component); - - function FlexTable(props) { - _classCallCheck(this, FlexTable); +var ColumnSizer = function (_Component) { + _inherits(ColumnSizer, _Component); - var _this = _possibleConstructorReturn(this, (FlexTable.__proto__ || Object.getPrototypeOf(FlexTable)).call(this, props)); + function ColumnSizer(props, context) { + _classCallCheck(this, ColumnSizer); - _this.state = { - scrollbarWidth: 0 - }; + var _this = _possibleConstructorReturn(this, (ColumnSizer.__proto__ || Object.getPrototypeOf(ColumnSizer)).call(this, props, context)); - _this._cellClassName = _this._cellClassName.bind(_this); - _this._cellStyle = _this._cellStyle.bind(_this); - _this._createColumn = _this._createColumn.bind(_this); - _this._createRow = _this._createRow.bind(_this); - _this._onScroll = _this._onScroll.bind(_this); - _this._onSectionRendered = _this._onSectionRendered.bind(_this); + _this._registerChild = _this._registerChild.bind(_this); return _this; } - _createClass(FlexTable, [{ - key: 'forceUpdateGrid', - value: function forceUpdateGrid() { - this.Grid.forceUpdate(); - } - - /** See Grid#measureAllCells */ - - }, { - key: 'measureAllRows', - value: function measureAllRows() { - this.Grid.measureAllCells(); - } - - /** See Grid#recomputeGridSize */ - - }, { - key: 'recomputeRowHeights', - value: function recomputeRowHeights() { - var index = arguments.length <= 0 || arguments[0] === undefined ? 0 : arguments[0]; - - this.Grid.recomputeGridSize({ - rowIndex: index - }); - this.forceUpdateGrid(); - } - }, { - key: 'componentDidMount', - value: function componentDidMount() { - this._setScrollbarWidth(); - } - }, { + _createClass(ColumnSizer, [{ key: 'componentDidUpdate', - value: function componentDidUpdate() { - this._setScrollbarWidth(); - } - }, { - key: 'render', - value: function render() { - var _this2 = this; - + value: function componentDidUpdate(prevProps, prevState) { var _props = this.props; - var children = _props.children; - var className = _props.className; - var disableHeader = _props.disableHeader; - var gridClassName = _props.gridClassName; - var gridStyle = _props.gridStyle; - var headerHeight = _props.headerHeight; - var height = _props.height; - var noRowsRenderer = _props.noRowsRenderer; - var rowClassName = _props.rowClassName; - var rowStyle = _props.rowStyle; - var scrollToIndex = _props.scrollToIndex; - var style = _props.style; + var columnMaxWidth = _props.columnMaxWidth; + var columnMinWidth = _props.columnMinWidth; + var columnCount = _props.columnCount; var width = _props.width; - var scrollbarWidth = this.state.scrollbarWidth; - - - var availableRowsHeight = height - headerHeight; - - var rowClass = rowClassName instanceof Function ? rowClassName({ index: -1 }) : rowClassName; - var rowStyleObject = rowStyle instanceof Function ? rowStyle({ index: -1 }) : rowStyle; - // Precompute and cache column styles before rendering rows and columns to speed things up - this._cachedColumnStyles = []; - _react2.default.Children.toArray(children).forEach(function (column, index) { - _this2._cachedColumnStyles[index] = _this2._getFlexStyleForColumn(column, column.props.style); - }); - // Note that we specify :numChildren, :scrollbarWidth, :sortBy, and :sortDirection as properties on Grid even though these have nothing to do with Grid. - // This is done because Grid is a pure component and won't update unless its properties or state has changed. - // Any property that should trigger a re-render of Grid then is specified here to avoid a stale display. - return _react2.default.createElement( - 'div', - { - className: (0, _classnames2.default)('FlexTable', className), - style: style - }, - !disableHeader && _react2.default.createElement( - 'div', - { - className: (0, _classnames2.default)('FlexTable__headerRow', rowClass), - style: _extends({}, rowStyleObject, { - height: headerHeight, - paddingRight: scrollbarWidth, - width: width - }) - }, - this._getRenderedHeaderRow() - ), - _react2.default.createElement(_Grid2.default, _extends({}, this.props, { - autoContainerWidth: true, - className: (0, _classnames2.default)('FlexTable__Grid', gridClassName), - cellClassName: this._cellClassName, - cellRenderer: this._createRow, - cellStyle: this._cellStyle, - columnWidth: width, - columnCount: 1, - height: availableRowsHeight, - noContentRenderer: noRowsRenderer, - onScroll: this._onScroll, - onSectionRendered: this._onSectionRendered, - ref: function ref(_ref) { - _this2.Grid = _ref; - }, - scrollbarWidth: scrollbarWidth, - scrollToRow: scrollToIndex, - style: gridStyle - })) - ); + if (columnMaxWidth !== prevProps.columnMaxWidth || columnMinWidth !== prevProps.columnMinWidth || columnCount !== prevProps.columnCount || width !== prevProps.width) { + if (this._registeredChild) { + this._registeredChild.recomputeGridSize(); + } + } + } + }, { + key: 'render', + value: function render() { + var _props2 = this.props; + var children = _props2.children; + var columnMaxWidth = _props2.columnMaxWidth; + var columnMinWidth = _props2.columnMinWidth; + var columnCount = _props2.columnCount; + var width = _props2.width; + + + var safeColumnMinWidth = columnMinWidth || 1; + + var safeColumnMaxWidth = columnMaxWidth ? Math.min(columnMaxWidth, width) : width; + + var columnWidth = width / columnCount; + columnWidth = Math.max(safeColumnMinWidth, columnWidth); + columnWidth = Math.min(safeColumnMaxWidth, columnWidth); + columnWidth = Math.floor(columnWidth); + + var adjustedWidth = Math.min(width, columnWidth * columnCount); + + return children({ + adjustedWidth: adjustedWidth, + getColumnWidth: function getColumnWidth() { + return columnWidth; + }, + registerChild: this._registerChild + }); } }, { key: 'shouldComponentUpdate', @@ -5456,780 +5464,867 @@ var FlexTable = function (_Component) { return (0, _reactAddonsShallowCompare2.default)(this, nextProps, nextState); } }, { - key: '_cellClassName', - value: function _cellClassName(_ref2) { - var rowIndex = _ref2.rowIndex; - var rowWrapperClassName = this.props.rowWrapperClassName; + key: '_registerChild', + value: function _registerChild(child) { + if (child !== null && !(child instanceof _Grid2.default)) { + throw Error('Unexpected child type registered; only Grid children are supported.'); + } + this._registeredChild = child; - return rowWrapperClassName instanceof Function ? rowWrapperClassName({ index: rowIndex - 1 }) : rowWrapperClassName; + if (this._registeredChild) { + this._registeredChild.recomputeGridSize(); + } } - }, { - key: '_cellStyle', - value: function _cellStyle(_ref3) { - var rowIndex = _ref3.rowIndex; - var rowWrapperStyle = this.props.rowWrapperStyle; + }]); + return ColumnSizer; +}(_react.Component); - return rowWrapperStyle instanceof Function ? rowWrapperStyle({ index: rowIndex - 1 }) : rowWrapperStyle; - } - }, { - key: '_createColumn', - value: function _createColumn(_ref4) { - var column = _ref4.column; - var columnIndex = _ref4.columnIndex; - var isScrolling = _ref4.isScrolling; - var rowData = _ref4.rowData; - var rowIndex = _ref4.rowIndex; - var _column$props = column.props; - var cellDataGetter = _column$props.cellDataGetter; - var cellRenderer = _column$props.cellRenderer; - var className = _column$props.className; - var columnData = _column$props.columnData; - var dataKey = _column$props.dataKey; +ColumnSizer.propTypes = { + /** + * Function respondible for rendering a virtualized Grid. + * This function should implement the following signature: + * ({ adjustedWidth, getColumnWidth, registerChild }) => PropTypes.element + * + * The specified :getColumnWidth function should be passed to the Grid's :columnWidth property. + * The :registerChild should be passed to the Grid's :ref property. + * The :adjustedWidth property is optional; it reflects the lesser of the overall width or the width of all columns. + */ + children: _react.PropTypes.func.isRequired, + /** Optional maximum allowed column width */ + columnMaxWidth: _react.PropTypes.number, - var cellData = cellDataGetter({ columnData: columnData, dataKey: dataKey, rowData: rowData }); - var renderedCell = cellRenderer({ cellData: cellData, columnData: columnData, dataKey: dataKey, isScrolling: isScrolling, rowData: rowData, rowIndex: rowIndex }); + /** Optional minimum allowed column width */ + columnMinWidth: _react.PropTypes.number, - var style = this._cachedColumnStyles[columnIndex]; + /** Number of columns in Grid or FlexTable child */ + columnCount: _react.PropTypes.number.isRequired, - var title = typeof renderedCell === 'string' ? renderedCell : null; + /** Width of Grid or FlexTable child */ + width: _react.PropTypes.number.isRequired +}; +exports.default = ColumnSizer; +},{"../Grid":60,"react":undefined,"react-addons-shallow-compare":18}],48:[function(require,module,exports){ +'use strict'; - return _react2.default.createElement( - 'div', - { - key: 'Row' + rowIndex + '-Col' + columnIndex, - className: (0, _classnames2.default)('FlexTable__rowColumn', className), - style: style, - title: title - }, - renderedCell - ); - } - }, { - key: '_createHeader', - value: function _createHeader(_ref5) { - var column = _ref5.column; - var index = _ref5.index; - var _props2 = this.props; - var headerClassName = _props2.headerClassName; - var headerStyle = _props2.headerStyle; - var onHeaderClick = _props2.onHeaderClick; - var sort = _props2.sort; - var sortBy = _props2.sortBy; - var sortDirection = _props2.sortDirection; - var _column$props2 = column.props; - var dataKey = _column$props2.dataKey; - var disableSort = _column$props2.disableSort; - var headerRenderer = _column$props2.headerRenderer; - var label = _column$props2.label; - var columnData = _column$props2.columnData; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ColumnSizer = exports.default = undefined; - var sortEnabled = !disableSort && sort; +var _ColumnSizer2 = require('./ColumnSizer'); - var classNames = (0, _classnames2.default)('FlexTable__headerColumn', headerClassName, column.props.headerClassName, { - 'FlexTable__sortableHeaderColumn': sortEnabled - }); - var style = this._getFlexStyleForColumn(column, headerStyle); +var _ColumnSizer3 = _interopRequireDefault(_ColumnSizer2); - var renderedHeader = headerRenderer({ - columnData: columnData, - dataKey: dataKey, - disableSort: disableSort, - label: label, - sortBy: sortBy, - sortDirection: sortDirection - }); +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - var a11yProps = {}; +exports.default = _ColumnSizer3.default; +exports.ColumnSizer = _ColumnSizer3.default; +},{"./ColumnSizer":47}],49:[function(require,module,exports){ +'use strict'; - if (sortEnabled || onHeaderClick) { - (function () { - // If this is a sortable header, clicking it should update the table data's sorting. - var newSortDirection = sortBy !== dataKey || sortDirection === _SortDirection2.default.DESC ? _SortDirection2.default.ASC : _SortDirection2.default.DESC; +Object.defineProperty(exports, "__esModule", { + value: true +}); - var onClick = function onClick() { - sortEnabled && sort({ - sortBy: dataKey, - sortDirection: newSortDirection - }); - onHeaderClick && onHeaderClick({ columnData: columnData, dataKey: dataKey }); - }; +var _react = require('react'); - var onKeyDown = function onKeyDown(event) { - if (event.key === 'Enter' || event.key === ' ') { - onClick(); - } - }; +var _defaultHeaderRenderer = require('./defaultHeaderRenderer'); - a11yProps['aria-label'] = column.props['aria-label'] || label || dataKey; - a11yProps.role = 'rowheader'; - a11yProps.tabIndex = 0; - a11yProps.onClick = onClick; - a11yProps.onKeyDown = onKeyDown; - })(); - } +var _defaultHeaderRenderer2 = _interopRequireDefault(_defaultHeaderRenderer); - return _react2.default.createElement( - 'div', - _extends({}, a11yProps, { - key: 'Header-Col' + index, - className: classNames, - style: style - }), - renderedHeader - ); - } - }, { - key: '_createRow', - value: function _createRow(_ref6) { - var _this3 = this; +var _defaultCellRenderer = require('./defaultCellRenderer'); + +var _defaultCellRenderer2 = _interopRequireDefault(_defaultCellRenderer); + +var _defaultCellDataGetter = require('./defaultCellDataGetter'); + +var _defaultCellDataGetter2 = _interopRequireDefault(_defaultCellDataGetter); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +/** + * Describes the header and cell contents of a table column. + */ +var Column = function (_Component) { + _inherits(Column, _Component); + + function Column() { + _classCallCheck(this, Column); + + return _possibleConstructorReturn(this, (Column.__proto__ || Object.getPrototypeOf(Column)).apply(this, arguments)); + } + + return Column; +}(_react.Component); + +Column.defaultProps = { + cellDataGetter: _defaultCellDataGetter2.default, + cellRenderer: _defaultCellRenderer2.default, + flexGrow: 0, + flexShrink: 1, + headerRenderer: _defaultHeaderRenderer2.default, + style: {} +}; +Column.propTypes = { + /** Optional aria-label value to set on the column header */ + 'aria-label': _react.PropTypes.string, + + /** + * Callback responsible for returning a cell's data, given its :dataKey + * ({ columnData: any, dataKey: string, rowData: any }): any + */ + cellDataGetter: _react.PropTypes.func, + + /** + * Callback responsible for rendering a cell's contents. + * ({ cellData: any, columnData: any, dataKey: string, rowData: any, rowIndex: number }): node + */ + cellRenderer: _react.PropTypes.func, + + /** Optional CSS class to apply to cell */ + className: _react.PropTypes.string, + + /** Optional additional data passed to this column's :cellDataGetter */ + columnData: _react.PropTypes.object, + + /** Uniquely identifies the row-data attribute correspnding to this cell */ + dataKey: _react.PropTypes.any.isRequired, - var index = _ref6.rowIndex; - var isScrolling = _ref6.isScrolling; - var _props3 = this.props; - var children = _props3.children; - var onRowClick = _props3.onRowClick; - var onRowDoubleClick = _props3.onRowDoubleClick; - var onRowMouseOver = _props3.onRowMouseOver; - var onRowMouseOut = _props3.onRowMouseOut; - var rowClassName = _props3.rowClassName; - var rowGetter = _props3.rowGetter; - var rowRenderer = _props3.rowRenderer; - var rowStyle = _props3.rowStyle; - var scrollbarWidth = this.state.scrollbarWidth; + /** If sort is enabled for the table at large, disable it for this column */ + disableSort: _react.PropTypes.bool, + /** Flex grow style; defaults to 0 */ + flexGrow: _react.PropTypes.number, - var rowClass = rowClassName instanceof Function ? rowClassName({ index: index }) : rowClassName; - var rowStyleObject = rowStyle instanceof Function ? rowStyle({ index: index }) : rowStyle; - var rowData = rowGetter({ index: index }); + /** Flex shrink style; defaults to 1 */ + flexShrink: _react.PropTypes.number, - var columns = _react2.default.Children.toArray(children).map(function (column, columnIndex) { - return _this3._createColumn({ - column: column, - columnIndex: columnIndex, - isScrolling: isScrolling, - rowData: rowData, - rowIndex: index, - scrollbarWidth: scrollbarWidth - }); - }); + /** Optional CSS class to apply to this column's header */ + headerClassName: _react.PropTypes.string, - var className = (0, _classnames2.default)('FlexTable__row', rowClass); - var style = _extends({}, rowStyleObject, { - height: this._getRowHeight(index), - paddingRight: scrollbarWidth - }); + /** + * Optional callback responsible for rendering a column header contents. + * ({ columnData: object, dataKey: string, disableSort: boolean, label: string, sortBy: string, sortDirection: string }): PropTypes.node + */ + headerRenderer: _react.PropTypes.func.isRequired, - return rowRenderer({ - className: className, - columns: columns, - index: index, - isScrolling: isScrolling, - onRowClick: onRowClick, - onRowDoubleClick: onRowDoubleClick, - onRowMouseOver: onRowMouseOver, - onRowMouseOut: onRowMouseOut, - rowData: rowData, - style: style - }); - } + /** Header label for this column */ + label: _react.PropTypes.string, - /** - * Determines the flex-shrink, flex-grow, and width values for a cell (header or column). - */ + /** Maximum width of column; this property will only be used if :flexGrow is > 0. */ + maxWidth: _react.PropTypes.number, - }, { - key: '_getFlexStyleForColumn', - value: function _getFlexStyleForColumn(column) { - var customStyle = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; + /** Minimum width of column. */ + minWidth: _react.PropTypes.number, - var flexValue = column.props.flexGrow + ' ' + column.props.flexShrink + ' ' + column.props.width + 'px'; + /** Optional inline style to apply to cell */ + style: _react.PropTypes.object, - var style = _extends({}, customStyle, { - flex: flexValue, - msFlex: flexValue, - WebkitFlex: flexValue - }); + /** Flex basis (width) for this column; This value can grow or shrink based on :flexGrow and :flexShrink properties. */ + width: _react.PropTypes.number.isRequired +}; +exports.default = Column; +},{"./defaultCellDataGetter":53,"./defaultCellRenderer":54,"./defaultHeaderRenderer":55,"react":undefined}],50:[function(require,module,exports){ +'use strict'; - if (column.props.maxWidth) { - style.maxWidth = column.props.maxWidth; - } +Object.defineProperty(exports, "__esModule", { + value: true +}); - if (column.props.minWidth) { - style.minWidth = column.props.minWidth; - } +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - return style; - } - }, { - key: '_getRenderedHeaderRow', - value: function _getRenderedHeaderRow() { - var _this4 = this; +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - var _props4 = this.props; - var children = _props4.children; - var disableHeader = _props4.disableHeader; +var _classnames = require('classnames'); - var items = disableHeader ? [] : _react2.default.Children.toArray(children); +var _classnames2 = _interopRequireDefault(_classnames); - return items.map(function (column, index) { - return _this4._createHeader({ column: column, index: index }); - }); - } - }, { - key: '_getRowHeight', - value: function _getRowHeight(rowIndex) { - var rowHeight = this.props.rowHeight; +var _FlexColumn = require('./FlexColumn'); +var _FlexColumn2 = _interopRequireDefault(_FlexColumn); - return rowHeight instanceof Function ? rowHeight({ index: rowIndex }) : rowHeight; - } - }, { - key: '_onScroll', - value: function _onScroll(_ref7) { - var clientHeight = _ref7.clientHeight; - var scrollHeight = _ref7.scrollHeight; - var scrollTop = _ref7.scrollTop; - var onScroll = this.props.onScroll; +var _react = require('react'); +var _react2 = _interopRequireDefault(_react); - onScroll({ clientHeight: clientHeight, scrollHeight: scrollHeight, scrollTop: scrollTop }); - } - }, { - key: '_onSectionRendered', - value: function _onSectionRendered(_ref8) { - var rowOverscanStartIndex = _ref8.rowOverscanStartIndex; - var rowOverscanStopIndex = _ref8.rowOverscanStopIndex; - var rowStartIndex = _ref8.rowStartIndex; - var rowStopIndex = _ref8.rowStopIndex; - var onRowsRendered = this.props.onRowsRendered; +var _reactDom = require('react-dom'); +var _reactAddonsShallowCompare = require('react-addons-shallow-compare'); - onRowsRendered({ - overscanStartIndex: rowOverscanStartIndex, - overscanStopIndex: rowOverscanStopIndex, - startIndex: rowStartIndex, - stopIndex: rowStopIndex - }); - } - }, { - key: '_setScrollbarWidth', - value: function _setScrollbarWidth() { - var Grid = (0, _reactDom.findDOMNode)(this.Grid); - var clientWidth = Grid.clientWidth || 0; - var offsetWidth = Grid.offsetWidth || 0; - var scrollbarWidth = offsetWidth - clientWidth; +var _reactAddonsShallowCompare2 = _interopRequireDefault(_reactAddonsShallowCompare); - this.setState({ scrollbarWidth: scrollbarWidth }); - } - }]); +var _Grid = require('../Grid'); - return FlexTable; -}(_react.Component); +var _Grid2 = _interopRequireDefault(_Grid); -FlexTable.propTypes = { - 'aria-label': _react.PropTypes.string, +var _defaultRowRenderer = require('./defaultRowRenderer'); - /** - * Removes fixed height from the scrollingContainer so that the total height - * of rows can stretch the window. Intended for use with WindowScroller - */ - autoHeight: _react.PropTypes.bool, +var _defaultRowRenderer2 = _interopRequireDefault(_defaultRowRenderer); - /** One or more FlexColumns describing the data displayed in this row */ - children: function children(props, propName, componentName) { - var children = _react2.default.Children.toArray(props.children); - for (var i = 0; i < children.length; i++) { - if (children[i].type !== _FlexColumn2.default) { - return new Error('FlexTable only accepts children of type FlexColumn'); - } - } - }, +var _SortDirection = require('./SortDirection'); - /** Optional CSS class name */ - className: _react.PropTypes.string, +var _SortDirection2 = _interopRequireDefault(_SortDirection); - /** Disable rendering the header at all */ - disableHeader: _react.PropTypes.bool, +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - /** - * Used to estimate the total height of a FlexTable before all of its rows have actually been measured. - * The estimated total height is adjusted as rows are rendered. - */ - estimatedRowSize: _react.PropTypes.number.isRequired, +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - /** Optional custom CSS class name to attach to inner Grid element. */ - gridClassName: _react.PropTypes.string, +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - /** Optional inline style to attach to inner Grid element. */ - gridStyle: _react.PropTypes.object, +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - /** Optional CSS class to apply to all column headers */ - headerClassName: _react.PropTypes.string, +/** + * Table component with fixed headers and virtualized rows for improved performance with large data sets. + * This component expects explicit width, height, and padding parameters. + */ +var FlexTable = function (_Component) { + _inherits(FlexTable, _Component); - /** Fixed height of header row */ - headerHeight: _react.PropTypes.number.isRequired, + function FlexTable(props) { + _classCallCheck(this, FlexTable); - /** Fixed/available height for out DOM element */ - height: _react.PropTypes.number.isRequired, + var _this = _possibleConstructorReturn(this, (FlexTable.__proto__ || Object.getPrototypeOf(FlexTable)).call(this, props)); - /** Optional renderer to be used in place of table body rows when rowCount is 0 */ - noRowsRenderer: _react.PropTypes.func, + _this.state = { + scrollbarWidth: 0 + }; - /** - * Optional callback when a column's header is clicked. - * ({ columnData: any, dataKey: string }): void - */ - onHeaderClick: _react.PropTypes.func, + _this._cellClassName = _this._cellClassName.bind(_this); + _this._cellStyle = _this._cellStyle.bind(_this); + _this._createColumn = _this._createColumn.bind(_this); + _this._createRow = _this._createRow.bind(_this); + _this._onScroll = _this._onScroll.bind(_this); + _this._onSectionRendered = _this._onSectionRendered.bind(_this); + return _this; + } - /** Optional custom inline style to attach to table header columns. */ - headerStyle: _react.PropTypes.object, + _createClass(FlexTable, [{ + key: 'forceUpdateGrid', + value: function forceUpdateGrid() { + this.Grid.forceUpdate(); + } - /** - * Callback invoked when a user clicks on a table row. - * ({ index: number }): void - */ - onRowClick: _react.PropTypes.func, + /** See Grid#measureAllCells */ + + }, { + key: 'measureAllRows', + value: function measureAllRows() { + this.Grid.measureAllCells(); + } + + /** See Grid#recomputeGridSize */ + + }, { + key: 'recomputeRowHeights', + value: function recomputeRowHeights() { + var index = arguments.length <= 0 || arguments[0] === undefined ? 0 : arguments[0]; - /** - * Callback invoked when a user double-clicks on a table row. - * ({ index: number }): void - */ - onRowDoubleClick: _react.PropTypes.func, + this.Grid.recomputeGridSize({ + rowIndex: index + }); + this.forceUpdateGrid(); + } + }, { + key: 'componentDidMount', + value: function componentDidMount() { + this._setScrollbarWidth(); + } + }, { + key: 'componentDidUpdate', + value: function componentDidUpdate() { + this._setScrollbarWidth(); + } + }, { + key: 'render', + value: function render() { + var _this2 = this; - /** - * Callback invoked when the mouse leaves a table row. - * ({ index: number }): void - */ - onRowMouseOut: _react.PropTypes.func, + var _props = this.props; + var children = _props.children; + var className = _props.className; + var disableHeader = _props.disableHeader; + var gridClassName = _props.gridClassName; + var gridStyle = _props.gridStyle; + var headerHeight = _props.headerHeight; + var height = _props.height; + var noRowsRenderer = _props.noRowsRenderer; + var rowClassName = _props.rowClassName; + var rowStyle = _props.rowStyle; + var scrollToIndex = _props.scrollToIndex; + var style = _props.style; + var width = _props.width; + var scrollbarWidth = this.state.scrollbarWidth; - /** - * Callback invoked when a user moves the mouse over a table row. - * ({ index: number }): void - */ - onRowMouseOver: _react.PropTypes.func, - /** - * Callback invoked with information about the slice of rows that were just rendered. - * ({ startIndex, stopIndex }): void - */ - onRowsRendered: _react.PropTypes.func, + var availableRowsHeight = height - headerHeight; - /** - * Callback invoked whenever the scroll offset changes within the inner scrollable region. - * This callback can be used to sync scrolling between lists, tables, or grids. - * ({ clientHeight, scrollHeight, scrollTop }): void - */ - onScroll: _react.PropTypes.func.isRequired, + var rowClass = rowClassName instanceof Function ? rowClassName({ index: -1 }) : rowClassName; + var rowStyleObject = rowStyle instanceof Function ? rowStyle({ index: -1 }) : rowStyle; - /** - * Number of rows to render above/below the visible bounds of the list. - * These rows can help for smoother scrolling on touch devices. - */ - overscanRowCount: _react.PropTypes.number.isRequired, + // Precompute and cache column styles before rendering rows and columns to speed things up + this._cachedColumnStyles = []; + _react2.default.Children.toArray(children).forEach(function (column, index) { + _this2._cachedColumnStyles[index] = _this2._getFlexStyleForColumn(column, column.props.style); + }); - /** - * Optional CSS class to apply to all table rows (including the header row). - * This property can be a CSS class name (string) or a function that returns a class name. - * If a function is provided its signature should be: ({ index: number }): string - */ - rowClassName: _react.PropTypes.oneOfType([_react.PropTypes.string, _react.PropTypes.func]), + // Note that we specify :numChildren, :scrollbarWidth, :sortBy, and :sortDirection as properties on Grid even though these have nothing to do with Grid. + // This is done because Grid is a pure component and won't update unless its properties or state has changed. + // Any property that should trigger a re-render of Grid then is specified here to avoid a stale display. + return _react2.default.createElement( + 'div', + { + className: (0, _classnames2.default)('FlexTable', className), + style: style + }, + !disableHeader && _react2.default.createElement( + 'div', + { + className: (0, _classnames2.default)('FlexTable__headerRow', rowClass), + style: _extends({}, rowStyleObject, { + height: headerHeight, + paddingRight: scrollbarWidth, + width: width + }) + }, + this._getRenderedHeaderRow() + ), + _react2.default.createElement(_Grid2.default, _extends({}, this.props, { + autoContainerWidth: true, + className: (0, _classnames2.default)('FlexTable__Grid', gridClassName), + cellClassName: this._cellClassName, + cellRenderer: this._createRow, + cellStyle: this._cellStyle, + columnWidth: width, + columnCount: 1, + height: availableRowsHeight, + noContentRenderer: noRowsRenderer, + onScroll: this._onScroll, + onSectionRendered: this._onSectionRendered, + ref: function ref(_ref) { + _this2.Grid = _ref; + }, + scrollbarWidth: scrollbarWidth, + scrollToRow: scrollToIndex, + style: gridStyle + })) + ); + } + }, { + key: 'shouldComponentUpdate', + value: function shouldComponentUpdate(nextProps, nextState) { + return (0, _reactAddonsShallowCompare2.default)(this, nextProps, nextState); + } + }, { + key: '_cellClassName', + value: function _cellClassName(_ref2) { + var rowIndex = _ref2.rowIndex; + var rowWrapperClassName = this.props.rowWrapperClassName; - /** - * Callback responsible for returning a data row given an index. - * ({ index: number }): any - */ - rowGetter: _react.PropTypes.func.isRequired, - /** - * Either a fixed row height (number) or a function that returns the height of a row given its index. - * ({ index: number }): number - */ - rowHeight: _react.PropTypes.oneOfType([_react.PropTypes.number, _react.PropTypes.func]).isRequired, + return rowWrapperClassName instanceof Function ? rowWrapperClassName({ index: rowIndex - 1 }) : rowWrapperClassName; + } + }, { + key: '_cellStyle', + value: function _cellStyle(_ref3) { + var rowIndex = _ref3.rowIndex; + var rowWrapperStyle = this.props.rowWrapperStyle; - /** Number of rows in table. */ - rowCount: _react.PropTypes.number.isRequired, - /** - * Responsible for rendering a table row given an array of columns: - * Should implement the following interface: ({ - * className: string, - * columns: Array, - * index: number, - * isScrolling: boolean, - * onRowClick: ?Function, - * onRowDoubleClick: ?Function, - * onRowMouseOver: ?Function, - * onRowMouseOut: ?Function, - * rowData: any, - * style: any - * }): PropTypes.node - */ - rowRenderer: _react.PropTypes.func, + return rowWrapperStyle instanceof Function ? rowWrapperStyle({ index: rowIndex - 1 }) : rowWrapperStyle; + } + }, { + key: '_createColumn', + value: function _createColumn(_ref4) { + var column = _ref4.column; + var columnIndex = _ref4.columnIndex; + var isScrolling = _ref4.isScrolling; + var rowData = _ref4.rowData; + var rowIndex = _ref4.rowIndex; + var _column$props = column.props; + var cellDataGetter = _column$props.cellDataGetter; + var cellRenderer = _column$props.cellRenderer; + var className = _column$props.className; + var columnData = _column$props.columnData; + var dataKey = _column$props.dataKey; - /** Optional custom inline style to attach to table rows. */ - rowStyle: _react.PropTypes.oneOfType([_react.PropTypes.object, _react.PropTypes.func]).isRequired, - /** Optional custom CSS class for individual rows */ - rowWrapperClassName: _react.PropTypes.oneOfType([_react.PropTypes.string, _react.PropTypes.func]), + var cellData = cellDataGetter({ columnData: columnData, dataKey: dataKey, rowData: rowData }); + var renderedCell = cellRenderer({ cellData: cellData, columnData: columnData, dataKey: dataKey, isScrolling: isScrolling, rowData: rowData, rowIndex: rowIndex }); - /** Optional custom CSS class for individual rows */ - rowWrapperStyle: _react.PropTypes.oneOfType([_react.PropTypes.object, _react.PropTypes.func]), + var style = this._cachedColumnStyles[columnIndex]; - /** See Grid#scrollToAlignment */ - scrollToAlignment: _react.PropTypes.oneOf(['auto', 'end', 'start', 'center']).isRequired, + var title = typeof renderedCell === 'string' ? renderedCell : null; - /** Row index to ensure visible (by forcefully scrolling if necessary) */ - scrollToIndex: _react.PropTypes.number, + return _react2.default.createElement( + 'div', + { + key: 'Row' + rowIndex + '-Col' + columnIndex, + className: (0, _classnames2.default)('FlexTable__rowColumn', className), + style: style, + title: title + }, + renderedCell + ); + } + }, { + key: '_createHeader', + value: function _createHeader(_ref5) { + var column = _ref5.column; + var index = _ref5.index; + var _props2 = this.props; + var headerClassName = _props2.headerClassName; + var headerStyle = _props2.headerStyle; + var onHeaderClick = _props2.onHeaderClick; + var sort = _props2.sort; + var sortBy = _props2.sortBy; + var sortDirection = _props2.sortDirection; + var _column$props2 = column.props; + var dataKey = _column$props2.dataKey; + var disableSort = _column$props2.disableSort; + var headerRenderer = _column$props2.headerRenderer; + var label = _column$props2.label; + var columnData = _column$props2.columnData; - /** Vertical offset. */ - scrollTop: _react.PropTypes.number, + var sortEnabled = !disableSort && sort; - /** - * Sort function to be called if a sortable header is clicked. - * ({ sortBy: string, sortDirection: SortDirection }): void - */ - sort: _react.PropTypes.func, + var classNames = (0, _classnames2.default)('FlexTable__headerColumn', headerClassName, column.props.headerClassName, { + 'FlexTable__sortableHeaderColumn': sortEnabled + }); + var style = this._getFlexStyleForColumn(column, headerStyle); - /** FlexTable data is currently sorted by this :dataKey (if it is sorted at all) */ - sortBy: _react.PropTypes.string, + var renderedHeader = headerRenderer({ + columnData: columnData, + dataKey: dataKey, + disableSort: disableSort, + label: label, + sortBy: sortBy, + sortDirection: sortDirection + }); - /** FlexTable data is currently sorted in this direction (if it is sorted at all) */ - sortDirection: _react.PropTypes.oneOf([_SortDirection2.default.ASC, _SortDirection2.default.DESC]), + var a11yProps = {}; - /** Optional inline style */ - style: _react.PropTypes.object, + if (sortEnabled || onHeaderClick) { + (function () { + // If this is a sortable header, clicking it should update the table data's sorting. + var newSortDirection = sortBy !== dataKey || sortDirection === _SortDirection2.default.DESC ? _SortDirection2.default.ASC : _SortDirection2.default.DESC; - /** Tab index for focus */ - tabIndex: _react.PropTypes.number, + var onClick = function onClick() { + sortEnabled && sort({ + sortBy: dataKey, + sortDirection: newSortDirection + }); + onHeaderClick && onHeaderClick({ columnData: columnData, dataKey: dataKey }); + }; - /** Width of list */ - width: _react.PropTypes.number.isRequired -}; -FlexTable.defaultProps = { - disableHeader: false, - estimatedRowSize: 30, - headerHeight: 0, - headerStyle: {}, - noRowsRenderer: function noRowsRenderer() { - return null; - }, - onRowsRendered: function onRowsRendered() { - return null; - }, - onScroll: function onScroll() { - return null; - }, - overscanRowCount: 10, - rowRenderer: _defaultRowRenderer2.default, - rowStyle: {}, - scrollToAlignment: 'auto', - style: {} -}; -exports.default = FlexTable; -},{"../Grid":62,"./FlexColumn":51,"./SortDirection":53,"./defaultRowRenderer":58,"classnames":undefined,"react":undefined,"react-addons-shallow-compare":30,"react-dom":undefined}],53:[function(require,module,exports){ -'use strict'; + var onKeyDown = function onKeyDown(event) { + if (event.key === 'Enter' || event.key === ' ') { + onClick(); + } + }; -Object.defineProperty(exports, "__esModule", { - value: true -}); -var SortDirection = { - /** - * Sort items in ascending order. - * This means arranging from the lowest value to the highest (e.g. a-z, 0-9). - */ - ASC: 'ASC', + a11yProps['aria-label'] = column.props['aria-label'] || label || dataKey; + a11yProps.role = 'rowheader'; + a11yProps.tabIndex = 0; + a11yProps.onClick = onClick; + a11yProps.onKeyDown = onKeyDown; + })(); + } - /** - * Sort items in descending order. - * This means arranging from the highest value to the lowest (e.g. z-a, 9-0). - */ - DESC: 'DESC' -}; + return _react2.default.createElement( + 'div', + _extends({}, a11yProps, { + key: 'Header-Col' + index, + className: classNames, + style: style + }), + renderedHeader + ); + } + }, { + key: '_createRow', + value: function _createRow(_ref6) { + var _this3 = this; -exports.default = SortDirection; -},{}],54:[function(require,module,exports){ -'use strict'; + var index = _ref6.rowIndex; + var isScrolling = _ref6.isScrolling; + var _props3 = this.props; + var children = _props3.children; + var onRowClick = _props3.onRowClick; + var onRowDoubleClick = _props3.onRowDoubleClick; + var onRowMouseOver = _props3.onRowMouseOver; + var onRowMouseOut = _props3.onRowMouseOut; + var rowClassName = _props3.rowClassName; + var rowGetter = _props3.rowGetter; + var rowRenderer = _props3.rowRenderer; + var rowStyle = _props3.rowStyle; + var scrollbarWidth = this.state.scrollbarWidth; -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.default = SortIndicator; -var _react = require('react'); + var rowClass = rowClassName instanceof Function ? rowClassName({ index: index }) : rowClassName; + var rowStyleObject = rowStyle instanceof Function ? rowStyle({ index: index }) : rowStyle; + var rowData = rowGetter({ index: index }); -var _react2 = _interopRequireDefault(_react); + var columns = _react2.default.Children.toArray(children).map(function (column, columnIndex) { + return _this3._createColumn({ + column: column, + columnIndex: columnIndex, + isScrolling: isScrolling, + rowData: rowData, + rowIndex: index, + scrollbarWidth: scrollbarWidth + }); + }); -var _classnames = require('classnames'); + var className = (0, _classnames2.default)('FlexTable__row', rowClass); + var style = _extends({}, rowStyleObject, { + height: this._getRowHeight(index), + paddingRight: scrollbarWidth + }); -var _classnames2 = _interopRequireDefault(_classnames); + return rowRenderer({ + className: className, + columns: columns, + index: index, + isScrolling: isScrolling, + onRowClick: onRowClick, + onRowDoubleClick: onRowDoubleClick, + onRowMouseOver: onRowMouseOver, + onRowMouseOut: onRowMouseOut, + rowData: rowData, + style: style + }); + } -var _SortDirection = require('./SortDirection'); + /** + * Determines the flex-shrink, flex-grow, and width values for a cell (header or column). + */ -var _SortDirection2 = _interopRequireDefault(_SortDirection); + }, { + key: '_getFlexStyleForColumn', + value: function _getFlexStyleForColumn(column) { + var customStyle = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + var flexValue = column.props.flexGrow + ' ' + column.props.flexShrink + ' ' + column.props.width + 'px'; -/** - * Displayed beside a header to indicate that a FlexTable is currently sorted by this column. - */ -function SortIndicator(_ref) { - var sortDirection = _ref.sortDirection; + var style = _extends({}, customStyle, { + flex: flexValue, + msFlex: flexValue, + WebkitFlex: flexValue + }); - var classNames = (0, _classnames2.default)('FlexTable__sortableHeaderIcon', { - 'FlexTable__sortableHeaderIcon--ASC': sortDirection === _SortDirection2.default.ASC, - 'FlexTable__sortableHeaderIcon--DESC': sortDirection === _SortDirection2.default.DESC - }); + if (column.props.maxWidth) { + style.maxWidth = column.props.maxWidth; + } - return _react2.default.createElement( - 'svg', - { - className: classNames, - width: 18, - height: 18, - viewBox: '0 0 24 24' - }, - sortDirection === _SortDirection2.default.ASC ? _react2.default.createElement('path', { d: 'M7 14l5-5 5 5z' }) : _react2.default.createElement('path', { d: 'M7 10l5 5 5-5z' }), - _react2.default.createElement('path', { d: 'M0 0h24v24H0z', fill: 'none' }) - ); -} -SortIndicator.propTypes = { - sortDirection: _react.PropTypes.oneOf([_SortDirection2.default.ASC, _SortDirection2.default.DESC]) -}; -},{"./SortDirection":53,"classnames":undefined,"react":undefined}],55:[function(require,module,exports){ -'use strict'; + if (column.props.minWidth) { + style.minWidth = column.props.minWidth; + } -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.default = defaultCellDataGetter; + return style; + } + }, { + key: '_getRenderedHeaderRow', + value: function _getRenderedHeaderRow() { + var _this4 = this; + var _props4 = this.props; + var children = _props4.children; + var disableHeader = _props4.disableHeader; -/** - * Default accessor for returning a cell value for a given attribute. - * This function expects to operate on either a vanilla Object or an Immutable Map. - * You should override the column's cellDataGetter if your data is some other type of object. - */ -function defaultCellDataGetter(_ref) { - var columnData = _ref.columnData; - var dataKey = _ref.dataKey; - var rowData = _ref.rowData; + var items = disableHeader ? [] : _react2.default.Children.toArray(children); - if (rowData.get instanceof Function) { - return rowData.get(dataKey); - } else { - return rowData[dataKey]; - } -} -},{}],56:[function(require,module,exports){ -'use strict'; + return items.map(function (column, index) { + return _this4._createHeader({ column: column, index: index }); + }); + } + }, { + key: '_getRowHeight', + value: function _getRowHeight(rowIndex) { + var rowHeight = this.props.rowHeight; -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.default = defaultCellRenderer; + return rowHeight instanceof Function ? rowHeight({ index: rowIndex }) : rowHeight; + } + }, { + key: '_onScroll', + value: function _onScroll(_ref7) { + var clientHeight = _ref7.clientHeight; + var scrollHeight = _ref7.scrollHeight; + var scrollTop = _ref7.scrollTop; + var onScroll = this.props.onScroll; -/** - * Default cell renderer that displays an attribute as a simple string - * You should override the column's cellRenderer if your data is some other type of object. - */ -function defaultCellRenderer(_ref) { - var cellData = _ref.cellData; - var cellDataKey = _ref.cellDataKey; - var columnData = _ref.columnData; - var rowData = _ref.rowData; - var rowIndex = _ref.rowIndex; - if (cellData == null) { - return ''; - } else { - return String(cellData); - } -} -},{}],57:[function(require,module,exports){ -'use strict'; + onScroll({ clientHeight: clientHeight, scrollHeight: scrollHeight, scrollTop: scrollTop }); + } + }, { + key: '_onSectionRendered', + value: function _onSectionRendered(_ref8) { + var rowOverscanStartIndex = _ref8.rowOverscanStartIndex; + var rowOverscanStopIndex = _ref8.rowOverscanStopIndex; + var rowStartIndex = _ref8.rowStartIndex; + var rowStopIndex = _ref8.rowStopIndex; + var onRowsRendered = this.props.onRowsRendered; -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.default = defaultHeaderRenderer; -var _react = require('react'); + onRowsRendered({ + overscanStartIndex: rowOverscanStartIndex, + overscanStopIndex: rowOverscanStopIndex, + startIndex: rowStartIndex, + stopIndex: rowStopIndex + }); + } + }, { + key: '_setScrollbarWidth', + value: function _setScrollbarWidth() { + var Grid = (0, _reactDom.findDOMNode)(this.Grid); + var clientWidth = Grid.clientWidth || 0; + var offsetWidth = Grid.offsetWidth || 0; + var scrollbarWidth = offsetWidth - clientWidth; -var _react2 = _interopRequireDefault(_react); + this.setState({ scrollbarWidth: scrollbarWidth }); + } + }]); -var _SortIndicator = require('./SortIndicator'); + return FlexTable; +}(_react.Component); -var _SortIndicator2 = _interopRequireDefault(_SortIndicator); +FlexTable.propTypes = { + 'aria-label': _react.PropTypes.string, -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + /** + * Removes fixed height from the scrollingContainer so that the total height + * of rows can stretch the window. Intended for use with WindowScroller + */ + autoHeight: _react.PropTypes.bool, -/** - * Default table header renderer. - */ -function defaultHeaderRenderer(_ref) { - var columnData = _ref.columnData; - var dataKey = _ref.dataKey; - var disableSort = _ref.disableSort; - var label = _ref.label; - var sortBy = _ref.sortBy; - var sortDirection = _ref.sortDirection; + /** One or more FlexColumns describing the data displayed in this row */ + children: function children(props, propName, componentName) { + var children = _react2.default.Children.toArray(props.children); + for (var i = 0; i < children.length; i++) { + if (children[i].type !== _FlexColumn2.default) { + return new Error('FlexTable only accepts children of type FlexColumn'); + } + } + }, - var showSortIndicator = sortBy === dataKey; - var children = [_react2.default.createElement( - 'span', - { - className: 'FlexTable__headerTruncatedText', - key: 'label', - title: label - }, - label - )]; + /** Optional CSS class name */ + className: _react.PropTypes.string, - if (showSortIndicator) { - children.push(_react2.default.createElement(_SortIndicator2.default, { - key: 'SortIndicator', - sortDirection: sortDirection - })); - } + /** Disable rendering the header at all */ + disableHeader: _react.PropTypes.bool, - return children; -} -},{"./SortIndicator":54,"react":undefined}],58:[function(require,module,exports){ -'use strict'; + /** + * Used to estimate the total height of a FlexTable before all of its rows have actually been measured. + * The estimated total height is adjusted as rows are rendered. + */ + estimatedRowSize: _react.PropTypes.number.isRequired, -Object.defineProperty(exports, "__esModule", { - value: true -}); + /** Optional custom CSS class name to attach to inner Grid element. */ + gridClassName: _react.PropTypes.string, -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + /** Optional inline style to attach to inner Grid element. */ + gridStyle: _react.PropTypes.object, -exports.default = defaultRowRenderer; + /** Optional CSS class to apply to all column headers */ + headerClassName: _react.PropTypes.string, -var _react = require('react'); + /** Fixed height of header row */ + headerHeight: _react.PropTypes.number.isRequired, -var _react2 = _interopRequireDefault(_react); + /** Fixed/available height for out DOM element */ + height: _react.PropTypes.number.isRequired, -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + /** Optional renderer to be used in place of table body rows when rowCount is 0 */ + noRowsRenderer: _react.PropTypes.func, -/** - * Default row renderer for FlexTable. - */ -function defaultRowRenderer(_ref) { - var className = _ref.className; - var columns = _ref.columns; - var index = _ref.index; - var isScrolling = _ref.isScrolling; - var onRowClick = _ref.onRowClick; - var onRowDoubleClick = _ref.onRowDoubleClick; - var onRowMouseOver = _ref.onRowMouseOver; - var onRowMouseOut = _ref.onRowMouseOut; - var rowData = _ref.rowData; - var style = _ref.style; + /** + * Optional callback when a column's header is clicked. + * ({ columnData: any, dataKey: string }): void + */ + onHeaderClick: _react.PropTypes.func, - var a11yProps = {}; + /** Optional custom inline style to attach to table header columns. */ + headerStyle: _react.PropTypes.object, - if (onRowClick || onRowDoubleClick || onRowMouseOver || onRowMouseOut) { - a11yProps['aria-label'] = 'row'; - a11yProps.role = 'row'; - a11yProps.tabIndex = 0; + /** + * Callback invoked when a user clicks on a table row. + * ({ index: number }): void + */ + onRowClick: _react.PropTypes.func, - if (onRowClick) { - a11yProps.onClick = function () { - return onRowClick({ index: index }); - }; - } - if (onRowDoubleClick) { - a11yProps.onDoubleClick = function () { - return onRowDoubleClick({ index: index }); - }; - } - if (onRowMouseOut) { - a11yProps.onMouseOut = function () { - return onRowMouseOut({ index: index }); - }; - } - if (onRowMouseOver) { - a11yProps.onMouseOver = function () { - return onRowMouseOver({ index: index }); - }; - } - } + /** + * Callback invoked when a user double-clicks on a table row. + * ({ index: number }): void + */ + onRowDoubleClick: _react.PropTypes.func, - return _react2.default.createElement( - 'div', - _extends({}, a11yProps, { - className: className, - style: style - }), - columns - ); -} -},{"react":undefined}],59:[function(require,module,exports){ -'use strict'; + /** + * Callback invoked when the mouse leaves a table row. + * ({ index: number }): void + */ + onRowMouseOut: _react.PropTypes.func, -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.SortIndicator = exports.SortDirection = exports.FlexColumn = exports.FlexTable = exports.defaultRowRenderer = exports.defaultHeaderRenderer = exports.defaultCellRenderer = exports.defaultCellDataGetter = exports.default = undefined; + /** + * Callback invoked when a user moves the mouse over a table row. + * ({ index: number }): void + */ + onRowMouseOver: _react.PropTypes.func, -var _FlexTable2 = require('./FlexTable'); + /** + * Callback invoked with information about the slice of rows that were just rendered. + * ({ startIndex, stopIndex }): void + */ + onRowsRendered: _react.PropTypes.func, -var _FlexTable3 = _interopRequireDefault(_FlexTable2); + /** + * Callback invoked whenever the scroll offset changes within the inner scrollable region. + * This callback can be used to sync scrolling between lists, tables, or grids. + * ({ clientHeight, scrollHeight, scrollTop }): void + */ + onScroll: _react.PropTypes.func.isRequired, -var _defaultCellDataGetter2 = require('./defaultCellDataGetter'); + /** + * Number of rows to render above/below the visible bounds of the list. + * These rows can help for smoother scrolling on touch devices. + */ + overscanRowCount: _react.PropTypes.number.isRequired, -var _defaultCellDataGetter3 = _interopRequireDefault(_defaultCellDataGetter2); + /** + * Optional CSS class to apply to all table rows (including the header row). + * This property can be a CSS class name (string) or a function that returns a class name. + * If a function is provided its signature should be: ({ index: number }): string + */ + rowClassName: _react.PropTypes.oneOfType([_react.PropTypes.string, _react.PropTypes.func]), -var _defaultCellRenderer2 = require('./defaultCellRenderer'); + /** + * Callback responsible for returning a data row given an index. + * ({ index: number }): any + */ + rowGetter: _react.PropTypes.func.isRequired, -var _defaultCellRenderer3 = _interopRequireDefault(_defaultCellRenderer2); + /** + * Either a fixed row height (number) or a function that returns the height of a row given its index. + * ({ index: number }): number + */ + rowHeight: _react.PropTypes.oneOfType([_react.PropTypes.number, _react.PropTypes.func]).isRequired, -var _defaultHeaderRenderer2 = require('./defaultHeaderRenderer'); + /** Number of rows in table. */ + rowCount: _react.PropTypes.number.isRequired, -var _defaultHeaderRenderer3 = _interopRequireDefault(_defaultHeaderRenderer2); + /** + * Responsible for rendering a table row given an array of columns: + * Should implement the following interface: ({ + * className: string, + * columns: Array, + * index: number, + * isScrolling: boolean, + * onRowClick: ?Function, + * onRowDoubleClick: ?Function, + * onRowMouseOver: ?Function, + * onRowMouseOut: ?Function, + * rowData: any, + * style: any + * }): PropTypes.node + */ + rowRenderer: _react.PropTypes.func, -var _defaultRowRenderer2 = require('./defaultRowRenderer'); + /** Optional custom inline style to attach to table rows. */ + rowStyle: _react.PropTypes.oneOfType([_react.PropTypes.object, _react.PropTypes.func]).isRequired, -var _defaultRowRenderer3 = _interopRequireDefault(_defaultRowRenderer2); + /** Optional custom CSS class for individual rows */ + rowWrapperClassName: _react.PropTypes.oneOfType([_react.PropTypes.string, _react.PropTypes.func]), -var _FlexColumn2 = require('./FlexColumn'); + /** Optional custom CSS class for individual rows */ + rowWrapperStyle: _react.PropTypes.oneOfType([_react.PropTypes.object, _react.PropTypes.func]), + + /** See Grid#scrollToAlignment */ + scrollToAlignment: _react.PropTypes.oneOf(['auto', 'end', 'start', 'center']).isRequired, + + /** Row index to ensure visible (by forcefully scrolling if necessary) */ + scrollToIndex: _react.PropTypes.number, -var _FlexColumn3 = _interopRequireDefault(_FlexColumn2); + /** Vertical offset. */ + scrollTop: _react.PropTypes.number, -var _SortDirection2 = require('./SortDirection'); + /** + * Sort function to be called if a sortable header is clicked. + * ({ sortBy: string, sortDirection: SortDirection }): void + */ + sort: _react.PropTypes.func, -var _SortDirection3 = _interopRequireDefault(_SortDirection2); + /** FlexTable data is currently sorted by this :dataKey (if it is sorted at all) */ + sortBy: _react.PropTypes.string, -var _SortIndicator2 = require('./SortIndicator'); + /** FlexTable data is currently sorted in this direction (if it is sorted at all) */ + sortDirection: _react.PropTypes.oneOf([_SortDirection2.default.ASC, _SortDirection2.default.DESC]), -var _SortIndicator3 = _interopRequireDefault(_SortIndicator2); + /** Optional inline style */ + style: _react.PropTypes.object, -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + /** Tab index for focus */ + tabIndex: _react.PropTypes.number, -exports.default = _FlexTable3.default; -exports.defaultCellDataGetter = _defaultCellDataGetter3.default; -exports.defaultCellRenderer = _defaultCellRenderer3.default; -exports.defaultHeaderRenderer = _defaultHeaderRenderer3.default; -exports.defaultRowRenderer = _defaultRowRenderer3.default; -exports.FlexTable = _FlexTable3.default; -exports.FlexColumn = _FlexColumn3.default; -exports.SortDirection = _SortDirection3.default; -exports.SortIndicator = _SortIndicator3.default; -},{"./FlexColumn":51,"./FlexTable":52,"./SortDirection":53,"./SortIndicator":54,"./defaultCellDataGetter":55,"./defaultCellRenderer":56,"./defaultHeaderRenderer":57,"./defaultRowRenderer":58}],60:[function(require,module,exports){ + /** Width of list */ + width: _react.PropTypes.number.isRequired +}; +FlexTable.defaultProps = { + disableHeader: false, + estimatedRowSize: 30, + headerHeight: 0, + headerStyle: {}, + noRowsRenderer: function noRowsRenderer() { + return null; + }, + onRowsRendered: function onRowsRendered() { + return null; + }, + onScroll: function onScroll() { + return null; + }, + overscanRowCount: 10, + rowRenderer: _defaultRowRenderer2.default, + rowStyle: {}, + scrollToAlignment: 'auto', + style: {} +}; +exports.default = FlexTable; +},{"../Grid":60,"./FlexColumn":49,"./SortDirection":51,"./defaultRowRenderer":56,"classnames":undefined,"react":undefined,"react-addons-shallow-compare":18,"react-dom":undefined}],51:[function(require,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); -exports.DEFAULT_SCROLLING_RESET_TIME_INTERVAL = undefined; +var SortDirection = { + /** + * Sort items in ascending order. + * This means arranging from the lowest value to the highest (e.g. a-z, 0-9). + */ + ASC: 'ASC', -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + /** + * Sort items in descending order. + * This means arranging from the highest value to the lowest (e.g. z-a, 9-0). + */ + DESC: 'DESC' +}; -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); +exports.default = SortDirection; +},{}],52:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = SortIndicator; var _react = require('react'); @@ -6239,1557 +6334,1554 @@ var _classnames = require('classnames'); var _classnames2 = _interopRequireDefault(_classnames); -var _calculateSizeAndPositionDataAndUpdateScrollOffset = require('./utils/calculateSizeAndPositionDataAndUpdateScrollOffset'); - -var _calculateSizeAndPositionDataAndUpdateScrollOffset2 = _interopRequireDefault(_calculateSizeAndPositionDataAndUpdateScrollOffset); - -var _ScalingCellSizeAndPositionManager = require('./utils/ScalingCellSizeAndPositionManager'); - -var _ScalingCellSizeAndPositionManager2 = _interopRequireDefault(_ScalingCellSizeAndPositionManager); - -var _createCallbackMemoizer = require('../utils/createCallbackMemoizer'); - -var _createCallbackMemoizer2 = _interopRequireDefault(_createCallbackMemoizer); - -var _getOverscanIndices = require('./utils/getOverscanIndices'); - -var _getOverscanIndices2 = _interopRequireDefault(_getOverscanIndices); - -var _scrollbarSize = require('dom-helpers/util/scrollbarSize'); - -var _scrollbarSize2 = _interopRequireDefault(_scrollbarSize); - -var _raf = require('raf'); - -var _raf2 = _interopRequireDefault(_raf); - -var _reactAddonsShallowCompare = require('react-addons-shallow-compare'); - -var _reactAddonsShallowCompare2 = _interopRequireDefault(_reactAddonsShallowCompare); - -var _updateScrollIndexHelper = require('./utils/updateScrollIndexHelper'); - -var _updateScrollIndexHelper2 = _interopRequireDefault(_updateScrollIndexHelper); - -var _defaultCellRangeRenderer = require('./defaultCellRangeRenderer'); +var _SortDirection = require('./SortDirection'); -var _defaultCellRangeRenderer2 = _interopRequireDefault(_defaultCellRangeRenderer); +var _SortDirection2 = _interopRequireDefault(_SortDirection); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - -/** - * Specifies the number of miliseconds during which to disable pointer events while a scroll is in progress. - * This improves performance and makes scrolling smoother. - */ -var DEFAULT_SCROLLING_RESET_TIME_INTERVAL = exports.DEFAULT_SCROLLING_RESET_TIME_INTERVAL = 150; - /** - * Controls whether the Grid updates the DOM element's scrollLeft/scrollTop based on the current state or just observes it. - * This prevents Grid from interrupting mouse-wheel animations (see issue #2). + * Displayed beside a header to indicate that a FlexTable is currently sorted by this column. */ -var SCROLL_POSITION_CHANGE_REASONS = { - OBSERVED: 'observed', - REQUESTED: 'requested' -}; +function SortIndicator(_ref) { + var sortDirection = _ref.sortDirection; -/** - * Renders tabular data with virtualization along the vertical and horizontal axes. - * Row heights and column widths must be known ahead of time and specified as properties. - */ + var classNames = (0, _classnames2.default)('FlexTable__sortableHeaderIcon', { + 'FlexTable__sortableHeaderIcon--ASC': sortDirection === _SortDirection2.default.ASC, + 'FlexTable__sortableHeaderIcon--DESC': sortDirection === _SortDirection2.default.DESC + }); -var Grid = function (_Component) { - _inherits(Grid, _Component); + return _react2.default.createElement( + 'svg', + { + className: classNames, + width: 18, + height: 18, + viewBox: '0 0 24 24' + }, + sortDirection === _SortDirection2.default.ASC ? _react2.default.createElement('path', { d: 'M7 14l5-5 5 5z' }) : _react2.default.createElement('path', { d: 'M7 10l5 5 5-5z' }), + _react2.default.createElement('path', { d: 'M0 0h24v24H0z', fill: 'none' }) + ); +} +SortIndicator.propTypes = { + sortDirection: _react.PropTypes.oneOf([_SortDirection2.default.ASC, _SortDirection2.default.DESC]) +}; +},{"./SortDirection":51,"classnames":undefined,"react":undefined}],53:[function(require,module,exports){ +'use strict'; - function Grid(props, context) { - _classCallCheck(this, Grid); +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = defaultCellDataGetter; - var _this = _possibleConstructorReturn(this, (Grid.__proto__ || Object.getPrototypeOf(Grid)).call(this, props, context)); - _this.state = { - isScrolling: false, - scrollDirectionHorizontal: _getOverscanIndices.SCROLL_DIRECTION_FIXED, - scrollDirectionVertical: _getOverscanIndices.SCROLL_DIRECTION_FIXED, - scrollLeft: 0, - scrollTop: 0 - }; +/** + * Default accessor for returning a cell value for a given attribute. + * This function expects to operate on either a vanilla Object or an Immutable Map. + * You should override the column's cellDataGetter if your data is some other type of object. + */ +function defaultCellDataGetter(_ref) { + var columnData = _ref.columnData; + var dataKey = _ref.dataKey; + var rowData = _ref.rowData; - // Invokes onSectionRendered callback only when start/stop row or column indices change - _this._onGridRenderedMemoizer = (0, _createCallbackMemoizer2.default)(); - _this._onScrollMemoizer = (0, _createCallbackMemoizer2.default)(false); + if (rowData.get instanceof Function) { + return rowData.get(dataKey); + } else { + return rowData[dataKey]; + } +} +},{}],54:[function(require,module,exports){ +'use strict'; - // Bind functions to instance so they don't lose context when passed around - _this._enablePointerEventsAfterDelayCallback = _this._enablePointerEventsAfterDelayCallback.bind(_this); - _this._invokeOnGridRenderedHelper = _this._invokeOnGridRenderedHelper.bind(_this); - _this._onScroll = _this._onScroll.bind(_this); - _this._setNextStateCallback = _this._setNextStateCallback.bind(_this); - _this._updateScrollLeftForScrollToColumn = _this._updateScrollLeftForScrollToColumn.bind(_this); - _this._updateScrollTopForScrollToRow = _this._updateScrollTopForScrollToRow.bind(_this); +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = defaultCellRenderer; - _this._columnWidthGetter = _this._wrapSizeGetter(props.columnWidth); - _this._rowHeightGetter = _this._wrapSizeGetter(props.rowHeight); - _this._columnSizeAndPositionManager = new _ScalingCellSizeAndPositionManager2.default({ - cellCount: props.columnCount, - cellSizeGetter: function cellSizeGetter(index) { - return _this._columnWidthGetter(index); - }, - estimatedCellSize: _this._getEstimatedColumnSize(props) - }); - _this._rowSizeAndPositionManager = new _ScalingCellSizeAndPositionManager2.default({ - cellCount: props.rowCount, - cellSizeGetter: function cellSizeGetter(index) { - return _this._rowHeightGetter(index); - }, - estimatedCellSize: _this._getEstimatedRowSize(props) - }); +/** + * Default cell renderer that displays an attribute as a simple string + * You should override the column's cellRenderer if your data is some other type of object. + */ +function defaultCellRenderer(_ref) { + var cellData = _ref.cellData; + var cellDataKey = _ref.cellDataKey; + var columnData = _ref.columnData; + var rowData = _ref.rowData; + var rowIndex = _ref.rowIndex; - // See defaultCellRangeRenderer() for more information on the usage of this cache - _this._cellCache = {}; - return _this; + if (cellData == null) { + return ''; + } else { + return String(cellData); } +} +},{}],55:[function(require,module,exports){ +'use strict'; - /** - * Pre-measure all columns and rows in a Grid. - * Typically cells are only measured as needed and estimated sizes are used for cells that have not yet been measured. - * This method ensures that the next call to getTotalSize() returns an exact size (as opposed to just an estimated one). - */ +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = defaultHeaderRenderer; +var _react = require('react'); - _createClass(Grid, [{ - key: 'measureAllCells', - value: function measureAllCells() { - var _props = this.props; - var columnCount = _props.columnCount; - var rowCount = _props.rowCount; +var _react2 = _interopRequireDefault(_react); +var _SortIndicator = require('./SortIndicator'); - this._columnSizeAndPositionManager.getSizeAndPositionOfCell(columnCount - 1); - this._rowSizeAndPositionManager.getSizeAndPositionOfCell(rowCount - 1); - } +var _SortIndicator2 = _interopRequireDefault(_SortIndicator); - /** - * Forced recompute of row heights and column widths. - * This function should be called if dynamic column or row sizes have changed but nothing else has. - * Since Grid only receives :columnCount and :rowCount it has no way of detecting when the underlying data changes. - */ +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - }, { - key: 'recomputeGridSize', - value: function recomputeGridSize() { - var _ref = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; +/** + * Default table header renderer. + */ +function defaultHeaderRenderer(_ref) { + var columnData = _ref.columnData; + var dataKey = _ref.dataKey; + var disableSort = _ref.disableSort; + var label = _ref.label; + var sortBy = _ref.sortBy; + var sortDirection = _ref.sortDirection; - var _ref$columnIndex = _ref.columnIndex; - var columnIndex = _ref$columnIndex === undefined ? 0 : _ref$columnIndex; - var _ref$rowIndex = _ref.rowIndex; - var rowIndex = _ref$rowIndex === undefined ? 0 : _ref$rowIndex; + var showSortIndicator = sortBy === dataKey; + var children = [_react2.default.createElement( + 'span', + { + className: 'FlexTable__headerTruncatedText', + key: 'label', + title: label + }, + label + )]; - this._columnSizeAndPositionManager.resetCell(columnIndex); - this._rowSizeAndPositionManager.resetCell(rowIndex); + if (showSortIndicator) { + children.push(_react2.default.createElement(_SortIndicator2.default, { + key: 'SortIndicator', + sortDirection: sortDirection + })); + } - // Clear cell cache in case we are scrolling; - // Invalid row heights likely mean invalid cached content as well. - this._cellCache = {}; + return children; +} +},{"./SortIndicator":52,"react":undefined}],56:[function(require,module,exports){ +'use strict'; - this.forceUpdate(); - } - }, { - key: 'componentDidMount', - value: function componentDidMount() { - var _props2 = this.props; - var scrollLeft = _props2.scrollLeft; - var scrollToColumn = _props2.scrollToColumn; - var scrollTop = _props2.scrollTop; - var scrollToRow = _props2.scrollToRow; +Object.defineProperty(exports, "__esModule", { + value: true +}); - // If this component was first rendered server-side, scrollbar size will be undefined. - // In that event we need to remeasure. +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - if (!this._scrollbarSizeMeasured) { - this._scrollbarSize = (0, _scrollbarSize2.default)(); - this._scrollbarSizeMeasured = true; - this.setState({}); - } +exports.default = defaultRowRenderer; - if (scrollLeft >= 0 || scrollTop >= 0) { - this._setScrollPosition({ scrollLeft: scrollLeft, scrollTop: scrollTop }); - } +var _react = require('react'); - if (scrollToColumn >= 0 || scrollToRow >= 0) { - this._updateScrollLeftForScrollToColumn(); - this._updateScrollTopForScrollToRow(); - } +var _react2 = _interopRequireDefault(_react); - // Update onRowsRendered callback - this._invokeOnGridRenderedHelper(); +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - // Initialize onScroll callback - this._invokeOnScrollMemoizer({ - scrollLeft: scrollLeft || 0, - scrollTop: scrollTop || 0, - totalColumnsWidth: this._columnSizeAndPositionManager.getTotalSize(), - totalRowsHeight: this._rowSizeAndPositionManager.getTotalSize() - }); - } +/** + * Default row renderer for FlexTable. + */ +function defaultRowRenderer(_ref) { + var className = _ref.className; + var columns = _ref.columns; + var index = _ref.index; + var isScrolling = _ref.isScrolling; + var onRowClick = _ref.onRowClick; + var onRowDoubleClick = _ref.onRowDoubleClick; + var onRowMouseOver = _ref.onRowMouseOver; + var onRowMouseOut = _ref.onRowMouseOut; + var rowData = _ref.rowData; + var style = _ref.style; - /** - * @private - * This method updates scrollLeft/scrollTop in state for the following conditions: - * 1) New scroll-to-cell props have been set - */ + var a11yProps = {}; - }, { - key: 'componentDidUpdate', - value: function componentDidUpdate(prevProps, prevState) { - var _this2 = this; + if (onRowClick || onRowDoubleClick || onRowMouseOver || onRowMouseOut) { + a11yProps['aria-label'] = 'row'; + a11yProps.role = 'row'; + a11yProps.tabIndex = 0; - var _props3 = this.props; - var autoHeight = _props3.autoHeight; - var columnCount = _props3.columnCount; - var height = _props3.height; - var rowCount = _props3.rowCount; - var scrollToAlignment = _props3.scrollToAlignment; - var scrollToColumn = _props3.scrollToColumn; - var scrollToRow = _props3.scrollToRow; - var width = _props3.width; - var _state = this.state; - var scrollLeft = _state.scrollLeft; - var scrollPositionChangeReason = _state.scrollPositionChangeReason; - var scrollTop = _state.scrollTop; + if (onRowClick) { + a11yProps.onClick = function () { + return onRowClick({ index: index }); + }; + } + if (onRowDoubleClick) { + a11yProps.onDoubleClick = function () { + return onRowDoubleClick({ index: index }); + }; + } + if (onRowMouseOut) { + a11yProps.onMouseOut = function () { + return onRowMouseOut({ index: index }); + }; + } + if (onRowMouseOver) { + a11yProps.onMouseOver = function () { + return onRowMouseOver({ index: index }); + }; + } + } - // Handle edge case where column or row count has only just increased over 0. - // In this case we may have to restore a previously-specified scroll offset. - // For more info see bvaughn/react-virtualized/issues/218 + return _react2.default.createElement( + 'div', + _extends({}, a11yProps, { + className: className, + style: style + }), + columns + ); +} +},{"react":undefined}],57:[function(require,module,exports){ +'use strict'; - var columnOrRowCountJustIncreasedFromZero = columnCount > 0 && prevProps.columnCount === 0 || rowCount > 0 && prevProps.rowCount === 0; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.SortIndicator = exports.SortDirection = exports.FlexColumn = exports.FlexTable = exports.defaultRowRenderer = exports.defaultHeaderRenderer = exports.defaultCellRenderer = exports.defaultCellDataGetter = exports.default = undefined; - // Make sure requested changes to :scrollLeft or :scrollTop get applied. - // Assigning to scrollLeft/scrollTop tells the browser to interrupt any running scroll animations, - // And to discard any pending async changes to the scroll position that may have happened in the meantime (e.g. on a separate scrolling thread). - // So we only set these when we require an adjustment of the scroll position. - // See issue #2 for more information. - if (scrollPositionChangeReason === SCROLL_POSITION_CHANGE_REASONS.REQUESTED) { - if (scrollLeft >= 0 && (scrollLeft !== prevState.scrollLeft && scrollLeft !== this._scrollingContainer.scrollLeft || columnOrRowCountJustIncreasedFromZero)) { - this._scrollingContainer.scrollLeft = scrollLeft; - } +var _FlexTable2 = require('./FlexTable'); - // @TRICKY :autoHeight property instructs Grid to leave :scrollTop management to an external HOC (eg WindowScroller). - // In this case we should avoid checking scrollingContainer.scrollTop since it forces layout/flow. - if (!autoHeight && scrollTop >= 0 && (scrollTop !== prevState.scrollTop && scrollTop !== this._scrollingContainer.scrollTop || columnOrRowCountJustIncreasedFromZero)) { - this._scrollingContainer.scrollTop = scrollTop; - } - } +var _FlexTable3 = _interopRequireDefault(_FlexTable2); - // Update scroll offsets if the current :scrollToColumn or :scrollToRow values requires it - // @TODO Do we also need this check or can the one in componentWillUpdate() suffice? - (0, _updateScrollIndexHelper2.default)({ - cellSizeAndPositionManager: this._columnSizeAndPositionManager, - previousCellsCount: prevProps.columnCount, - previousCellSize: prevProps.columnWidth, - previousScrollToAlignment: prevProps.scrollToAlignment, - previousScrollToIndex: prevProps.scrollToColumn, - previousSize: prevProps.width, - scrollOffset: scrollLeft, - scrollToAlignment: scrollToAlignment, - scrollToIndex: scrollToColumn, - size: width, - updateScrollIndexCallback: function updateScrollIndexCallback(scrollToColumn) { - return _this2._updateScrollLeftForScrollToColumn(_extends({}, _this2.props, { scrollToColumn: scrollToColumn })); - } - }); - (0, _updateScrollIndexHelper2.default)({ - cellSizeAndPositionManager: this._rowSizeAndPositionManager, - previousCellsCount: prevProps.rowCount, - previousCellSize: prevProps.rowHeight, - previousScrollToAlignment: prevProps.scrollToAlignment, - previousScrollToIndex: prevProps.scrollToRow, - previousSize: prevProps.height, - scrollOffset: scrollTop, - scrollToAlignment: scrollToAlignment, - scrollToIndex: scrollToRow, - size: height, - updateScrollIndexCallback: function updateScrollIndexCallback(scrollToRow) { - return _this2._updateScrollTopForScrollToRow(_extends({}, _this2.props, { scrollToRow: scrollToRow })); - } - }); +var _defaultCellDataGetter2 = require('./defaultCellDataGetter'); - // Update onRowsRendered callback if start/stop indices have changed - this._invokeOnGridRenderedHelper(); - } - }, { - key: 'componentWillMount', - value: function componentWillMount() { - // If this component is being rendered server-side, getScrollbarSize() will return undefined. - // We handle this case in componentDidMount() - this._scrollbarSize = (0, _scrollbarSize2.default)(); - if (this._scrollbarSize === undefined) { - this._scrollbarSizeMeasured = false; - this._scrollbarSize = 0; - } else { - this._scrollbarSizeMeasured = true; - } +var _defaultCellDataGetter3 = _interopRequireDefault(_defaultCellDataGetter2); - this._calculateChildrenToRender(); - } - }, { - key: 'componentWillUnmount', - value: function componentWillUnmount() { - if (this._disablePointerEventsTimeoutId) { - clearTimeout(this._disablePointerEventsTimeoutId); - } +var _defaultCellRenderer2 = require('./defaultCellRenderer'); - if (this._setNextStateAnimationFrameId) { - _raf2.default.cancel(this._setNextStateAnimationFrameId); - } - } +var _defaultCellRenderer3 = _interopRequireDefault(_defaultCellRenderer2); + +var _defaultHeaderRenderer2 = require('./defaultHeaderRenderer'); - /** - * @private - * This method updates scrollLeft/scrollTop in state for the following conditions: - * 1) Empty content (0 rows or columns) - * 2) New scroll props overriding the current state - * 3) Cells-count or cells-size has changed, making previous scroll offsets invalid - */ +var _defaultHeaderRenderer3 = _interopRequireDefault(_defaultHeaderRenderer2); - }, { - key: 'componentWillUpdate', - value: function componentWillUpdate(nextProps, nextState) { - var _this3 = this; +var _defaultRowRenderer2 = require('./defaultRowRenderer'); - if (nextProps.columnCount === 0 && nextState.scrollLeft !== 0 || nextProps.rowCount === 0 && nextState.scrollTop !== 0) { - this._setScrollPosition({ - scrollLeft: 0, - scrollTop: 0 - }); - } else if (nextProps.scrollLeft !== this.props.scrollLeft || nextProps.scrollTop !== this.props.scrollTop) { - this._setScrollPosition({ - scrollLeft: nextProps.scrollLeft, - scrollTop: nextProps.scrollTop - }); - } +var _defaultRowRenderer3 = _interopRequireDefault(_defaultRowRenderer2); - this._columnWidthGetter = this._wrapSizeGetter(nextProps.columnWidth); - this._rowHeightGetter = this._wrapSizeGetter(nextProps.rowHeight); +var _FlexColumn2 = require('./FlexColumn'); - this._columnSizeAndPositionManager.configure({ - cellCount: nextProps.columnCount, - estimatedCellSize: this._getEstimatedColumnSize(nextProps) - }); - this._rowSizeAndPositionManager.configure({ - cellCount: nextProps.rowCount, - estimatedCellSize: this._getEstimatedRowSize(nextProps) - }); +var _FlexColumn3 = _interopRequireDefault(_FlexColumn2); - // Update scroll offsets if the size or number of cells have changed, invalidating the previous value - (0, _calculateSizeAndPositionDataAndUpdateScrollOffset2.default)({ - cellCount: this.props.columnCount, - cellSize: this.props.columnWidth, - computeMetadataCallback: function computeMetadataCallback() { - return _this3._columnSizeAndPositionManager.resetCell(0); - }, - computeMetadataCallbackProps: nextProps, - nextCellsCount: nextProps.columnCount, - nextCellSize: nextProps.columnWidth, - nextScrollToIndex: nextProps.scrollToColumn, - scrollToIndex: this.props.scrollToColumn, - updateScrollOffsetForScrollToIndex: function updateScrollOffsetForScrollToIndex() { - return _this3._updateScrollLeftForScrollToColumn(nextProps, nextState); - } - }); - (0, _calculateSizeAndPositionDataAndUpdateScrollOffset2.default)({ - cellCount: this.props.rowCount, - cellSize: this.props.rowHeight, - computeMetadataCallback: function computeMetadataCallback() { - return _this3._rowSizeAndPositionManager.resetCell(0); - }, - computeMetadataCallbackProps: nextProps, - nextCellsCount: nextProps.rowCount, - nextCellSize: nextProps.rowHeight, - nextScrollToIndex: nextProps.scrollToRow, - scrollToIndex: this.props.scrollToRow, - updateScrollOffsetForScrollToIndex: function updateScrollOffsetForScrollToIndex() { - return _this3._updateScrollTopForScrollToRow(nextProps, nextState); - } - }); +var _SortDirection2 = require('./SortDirection'); - this._calculateChildrenToRender(nextProps, nextState); - } - }, { - key: 'render', - value: function render() { - var _this4 = this; +var _SortDirection3 = _interopRequireDefault(_SortDirection2); - var _props4 = this.props; - var autoContainerWidth = _props4.autoContainerWidth; - var autoHeight = _props4.autoHeight; - var className = _props4.className; - var height = _props4.height; - var noContentRenderer = _props4.noContentRenderer; - var style = _props4.style; - var tabIndex = _props4.tabIndex; - var width = _props4.width; - var isScrolling = this.state.isScrolling; +var _SortIndicator2 = require('./SortIndicator'); +var _SortIndicator3 = _interopRequireDefault(_SortIndicator2); - var gridStyle = { - height: autoHeight ? 'auto' : height, - width: width - }; +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - var totalColumnsWidth = this._columnSizeAndPositionManager.getTotalSize(); - var totalRowsHeight = this._rowSizeAndPositionManager.getTotalSize(); +exports.default = _FlexTable3.default; +exports.defaultCellDataGetter = _defaultCellDataGetter3.default; +exports.defaultCellRenderer = _defaultCellRenderer3.default; +exports.defaultHeaderRenderer = _defaultHeaderRenderer3.default; +exports.defaultRowRenderer = _defaultRowRenderer3.default; +exports.FlexTable = _FlexTable3.default; +exports.FlexColumn = _FlexColumn3.default; +exports.SortDirection = _SortDirection3.default; +exports.SortIndicator = _SortIndicator3.default; +},{"./FlexColumn":49,"./FlexTable":50,"./SortDirection":51,"./SortIndicator":52,"./defaultCellDataGetter":53,"./defaultCellRenderer":54,"./defaultHeaderRenderer":55,"./defaultRowRenderer":56}],58:[function(require,module,exports){ +'use strict'; - // Force browser to hide scrollbars when we know they aren't necessary. - // Otherwise once scrollbars appear they may not disappear again. - // For more info see issue #116 - var verticalScrollBarSize = totalRowsHeight > height ? this._scrollbarSize : 0; - var horizontalScrollBarSize = totalColumnsWidth > width ? this._scrollbarSize : 0; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.DEFAULT_SCROLLING_RESET_TIME_INTERVAL = undefined; - // Also explicitly init styles to 'auto' if scrollbars are required. - // This works around an obscure edge case where external CSS styles have not yet been loaded, - // But an initial scroll index of offset is set as an external prop. - // Without this style, Grid would render the correct range of cells but would NOT update its internal offset. - // This was originally reported via clauderic/react-infinite-calendar/issues/23 - gridStyle.overflowX = totalColumnsWidth + verticalScrollBarSize <= width ? 'hidden' : 'auto'; - gridStyle.overflowY = totalRowsHeight + horizontalScrollBarSize <= height ? 'hidden' : 'auto'; +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - var childrenToDisplay = this._childrenToDisplay; +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - var showNoContentRenderer = childrenToDisplay.length === 0 && height > 0 && width > 0; +var _react = require('react'); - return _react2.default.createElement( - 'div', - { - ref: function ref(_ref2) { - _this4._scrollingContainer = _ref2; - }, - 'aria-label': this.props['aria-label'], - className: (0, _classnames2.default)('Grid', className), - onScroll: this._onScroll, - role: 'grid', - style: _extends({}, gridStyle, style), - tabIndex: tabIndex - }, - childrenToDisplay.length > 0 && _react2.default.createElement( - 'div', - { - className: 'Grid__innerScrollContainer', - style: { - width: autoContainerWidth ? 'auto' : totalColumnsWidth, - height: totalRowsHeight, - maxWidth: totalColumnsWidth, - maxHeight: totalRowsHeight, - pointerEvents: isScrolling ? 'none' : '' - } - }, - childrenToDisplay - ), - showNoContentRenderer && noContentRenderer() - ); - } - }, { - key: 'shouldComponentUpdate', - value: function shouldComponentUpdate(nextProps, nextState) { - return (0, _reactAddonsShallowCompare2.default)(this, nextProps, nextState); - } +var _react2 = _interopRequireDefault(_react); - /* ---------------------------- Helper methods ---------------------------- */ +var _classnames = require('classnames'); - }, { - key: '_calculateChildrenToRender', - value: function _calculateChildrenToRender() { - var props = arguments.length <= 0 || arguments[0] === undefined ? this.props : arguments[0]; - var state = arguments.length <= 1 || arguments[1] === undefined ? this.state : arguments[1]; - var cellClassName = props.cellClassName; - var cellRenderer = props.cellRenderer; - var cellRangeRenderer = props.cellRangeRenderer; - var cellStyle = props.cellStyle; - var columnCount = props.columnCount; - var height = props.height; - var overscanColumnCount = props.overscanColumnCount; - var overscanRowCount = props.overscanRowCount; - var rowCount = props.rowCount; - var width = props.width; - var isScrolling = state.isScrolling; - var scrollDirectionHorizontal = state.scrollDirectionHorizontal; - var scrollDirectionVertical = state.scrollDirectionVertical; - var scrollLeft = state.scrollLeft; - var scrollTop = state.scrollTop; +var _classnames2 = _interopRequireDefault(_classnames); +var _calculateSizeAndPositionDataAndUpdateScrollOffset = require('./utils/calculateSizeAndPositionDataAndUpdateScrollOffset'); - this._childrenToDisplay = []; +var _calculateSizeAndPositionDataAndUpdateScrollOffset2 = _interopRequireDefault(_calculateSizeAndPositionDataAndUpdateScrollOffset); - // Render only enough columns and rows to cover the visible area of the grid. - if (height > 0 && width > 0) { - var visibleColumnIndices = this._columnSizeAndPositionManager.getVisibleCellRange({ - containerSize: width, - offset: scrollLeft - }); - var visibleRowIndices = this._rowSizeAndPositionManager.getVisibleCellRange({ - containerSize: height, - offset: scrollTop - }); +var _ScalingCellSizeAndPositionManager = require('./utils/ScalingCellSizeAndPositionManager'); - var horizontalOffsetAdjustment = this._columnSizeAndPositionManager.getOffsetAdjustment({ - containerSize: width, - offset: scrollLeft - }); - var verticalOffsetAdjustment = this._rowSizeAndPositionManager.getOffsetAdjustment({ - containerSize: height, - offset: scrollTop - }); +var _ScalingCellSizeAndPositionManager2 = _interopRequireDefault(_ScalingCellSizeAndPositionManager); - // Store for _invokeOnGridRenderedHelper() - this._renderedColumnStartIndex = visibleColumnIndices.start; - this._renderedColumnStopIndex = visibleColumnIndices.stop; - this._renderedRowStartIndex = visibleRowIndices.start; - this._renderedRowStopIndex = visibleRowIndices.stop; +var _createCallbackMemoizer = require('../utils/createCallbackMemoizer'); - var overscanColumnIndices = (0, _getOverscanIndices2.default)({ - cellCount: columnCount, - overscanCellsCount: overscanColumnCount, - scrollDirection: scrollDirectionHorizontal, - startIndex: this._renderedColumnStartIndex, - stopIndex: this._renderedColumnStopIndex - }); +var _createCallbackMemoizer2 = _interopRequireDefault(_createCallbackMemoizer); - var overscanRowIndices = (0, _getOverscanIndices2.default)({ - cellCount: rowCount, - overscanCellsCount: overscanRowCount, - scrollDirection: scrollDirectionVertical, - startIndex: this._renderedRowStartIndex, - stopIndex: this._renderedRowStopIndex - }); +var _getOverscanIndices = require('./utils/getOverscanIndices'); - // Store for _invokeOnGridRenderedHelper() - this._columnStartIndex = overscanColumnIndices.overscanStartIndex; - this._columnStopIndex = overscanColumnIndices.overscanStopIndex; - this._rowStartIndex = overscanRowIndices.overscanStartIndex; - this._rowStopIndex = overscanRowIndices.overscanStopIndex; +var _getOverscanIndices2 = _interopRequireDefault(_getOverscanIndices); - this._childrenToDisplay = cellRangeRenderer({ - cellCache: this._cellCache, - cellClassName: this._wrapCellClassNameGetter(cellClassName), - cellRenderer: cellRenderer, - cellStyle: this._wrapCellStyleGetter(cellStyle), - columnSizeAndPositionManager: this._columnSizeAndPositionManager, - columnStartIndex: this._columnStartIndex, - columnStopIndex: this._columnStopIndex, - horizontalOffsetAdjustment: horizontalOffsetAdjustment, - isScrolling: isScrolling, - rowSizeAndPositionManager: this._rowSizeAndPositionManager, - rowStartIndex: this._rowStartIndex, - rowStopIndex: this._rowStopIndex, - scrollLeft: scrollLeft, - scrollTop: scrollTop, - verticalOffsetAdjustment: verticalOffsetAdjustment - }); - } - } +var _scrollbarSize = require('dom-helpers/util/scrollbarSize'); - /** - * Sets an :isScrolling flag for a small window of time. - * This flag is used to disable pointer events on the scrollable portion of the Grid. - * This prevents jerky/stuttery mouse-wheel scrolling. - */ +var _scrollbarSize2 = _interopRequireDefault(_scrollbarSize); - }, { - key: '_enablePointerEventsAfterDelay', - value: function _enablePointerEventsAfterDelay() { - var scrollingResetTimeInterval = this.props.scrollingResetTimeInterval; +var _raf = require('raf'); +var _raf2 = _interopRequireDefault(_raf); - if (this._disablePointerEventsTimeoutId) { - clearTimeout(this._disablePointerEventsTimeoutId); - } +var _reactAddonsShallowCompare = require('react-addons-shallow-compare'); - this._disablePointerEventsTimeoutId = setTimeout(this._enablePointerEventsAfterDelayCallback, scrollingResetTimeInterval); - } - }, { - key: '_enablePointerEventsAfterDelayCallback', - value: function _enablePointerEventsAfterDelayCallback() { - this._disablePointerEventsTimeoutId = null; +var _reactAddonsShallowCompare2 = _interopRequireDefault(_reactAddonsShallowCompare); - // Throw away cell cache once scrolling is complete - this._cellCache = {}; +var _updateScrollIndexHelper = require('./utils/updateScrollIndexHelper'); - this.setState({ - isScrolling: false, - scrollDirectionHorizontal: _getOverscanIndices.SCROLL_DIRECTION_FIXED, - scrollDirectionVertical: _getOverscanIndices.SCROLL_DIRECTION_FIXED - }); - } - }, { - key: '_getEstimatedColumnSize', - value: function _getEstimatedColumnSize(props) { - return typeof props.columnWidth === 'number' ? props.columnWidth : props.estimatedColumnSize; - } - }, { - key: '_getEstimatedRowSize', - value: function _getEstimatedRowSize(props) { - return typeof props.rowHeight === 'number' ? props.rowHeight : props.estimatedRowSize; - } - }, { - key: '_invokeOnGridRenderedHelper', - value: function _invokeOnGridRenderedHelper() { - var onSectionRendered = this.props.onSectionRendered; +var _updateScrollIndexHelper2 = _interopRequireDefault(_updateScrollIndexHelper); +var _defaultCellRangeRenderer = require('./defaultCellRangeRenderer'); - this._onGridRenderedMemoizer({ - callback: onSectionRendered, - indices: { - columnOverscanStartIndex: this._columnStartIndex, - columnOverscanStopIndex: this._columnStopIndex, - columnStartIndex: this._renderedColumnStartIndex, - columnStopIndex: this._renderedColumnStopIndex, - rowOverscanStartIndex: this._rowStartIndex, - rowOverscanStopIndex: this._rowStopIndex, - rowStartIndex: this._renderedRowStartIndex, - rowStopIndex: this._renderedRowStopIndex - } - }); - } - }, { - key: '_invokeOnScrollMemoizer', - value: function _invokeOnScrollMemoizer(_ref3) { - var _this5 = this; +var _defaultCellRangeRenderer2 = _interopRequireDefault(_defaultCellRangeRenderer); - var scrollLeft = _ref3.scrollLeft; - var scrollTop = _ref3.scrollTop; - var totalColumnsWidth = _ref3.totalColumnsWidth; - var totalRowsHeight = _ref3.totalRowsHeight; +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - this._onScrollMemoizer({ - callback: function callback(_ref4) { - var scrollLeft = _ref4.scrollLeft; - var scrollTop = _ref4.scrollTop; - var _props5 = _this5.props; - var height = _props5.height; - var onScroll = _props5.onScroll; - var width = _props5.width; +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - onScroll({ - clientHeight: height, - clientWidth: width, - scrollHeight: totalRowsHeight, - scrollLeft: scrollLeft, - scrollTop: scrollTop, - scrollWidth: totalColumnsWidth - }); - }, - indices: { - scrollLeft: scrollLeft, - scrollTop: scrollTop - } - }); - } +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - /** - * Updates the state during the next animation frame. - * Use this method to avoid multiple renders in a small span of time. - * This helps performance for bursty events (like onScroll). - */ +/** + * Specifies the number of miliseconds during which to disable pointer events while a scroll is in progress. + * This improves performance and makes scrolling smoother. + */ +var DEFAULT_SCROLLING_RESET_TIME_INTERVAL = exports.DEFAULT_SCROLLING_RESET_TIME_INTERVAL = 150; - }, { - key: '_setNextState', - value: function _setNextState(state) { - this._nextState = state; +/** + * Controls whether the Grid updates the DOM element's scrollLeft/scrollTop based on the current state or just observes it. + * This prevents Grid from interrupting mouse-wheel animations (see issue #2). + */ +var SCROLL_POSITION_CHANGE_REASONS = { + OBSERVED: 'observed', + REQUESTED: 'requested' +}; - if (!this._setNextStateAnimationFrameId) { - this._setNextStateAnimationFrameId = (0, _raf2.default)(this._setNextStateCallback); - } - } - }, { - key: '_setNextStateCallback', - value: function _setNextStateCallback() { - var state = this._nextState; +/** + * Renders tabular data with virtualization along the vertical and horizontal axes. + * Row heights and column widths must be known ahead of time and specified as properties. + */ - this._setNextStateAnimationFrameId = null; - this._nextState = null; +var Grid = function (_Component) { + _inherits(Grid, _Component); - this.setState(state); - } - }, { - key: '_setScrollPosition', - value: function _setScrollPosition(_ref5) { - var scrollLeft = _ref5.scrollLeft; - var scrollTop = _ref5.scrollTop; + function Grid(props, context) { + _classCallCheck(this, Grid); - var newState = { - scrollPositionChangeReason: SCROLL_POSITION_CHANGE_REASONS.REQUESTED - }; + var _this = _possibleConstructorReturn(this, (Grid.__proto__ || Object.getPrototypeOf(Grid)).call(this, props, context)); - if (scrollLeft >= 0) { - newState.scrollLeft = scrollLeft; - } + _this.state = { + isScrolling: false, + scrollDirectionHorizontal: _getOverscanIndices.SCROLL_DIRECTION_FIXED, + scrollDirectionVertical: _getOverscanIndices.SCROLL_DIRECTION_FIXED, + scrollLeft: 0, + scrollTop: 0 + }; - if (scrollTop >= 0) { - newState.scrollTop = scrollTop; - } + // Invokes onSectionRendered callback only when start/stop row or column indices change + _this._onGridRenderedMemoizer = (0, _createCallbackMemoizer2.default)(); + _this._onScrollMemoizer = (0, _createCallbackMemoizer2.default)(false); - if (scrollLeft >= 0 && scrollLeft !== this.state.scrollLeft || scrollTop >= 0 && scrollTop !== this.state.scrollTop) { - this.setState(newState); - } - } - }, { - key: '_wrapCellClassNameGetter', - value: function _wrapCellClassNameGetter(className) { - return this._wrapPropertyGetter(className); - } - }, { - key: '_wrapCellStyleGetter', - value: function _wrapCellStyleGetter(style) { - return this._wrapPropertyGetter(style); - } - }, { - key: '_wrapPropertyGetter', - value: function _wrapPropertyGetter(value) { - return value instanceof Function ? value : function () { - return value; - }; - } - }, { - key: '_wrapSizeGetter', - value: function _wrapSizeGetter(size) { - return this._wrapPropertyGetter(size); + // Bind functions to instance so they don't lose context when passed around + _this._enablePointerEventsAfterDelayCallback = _this._enablePointerEventsAfterDelayCallback.bind(_this); + _this._invokeOnGridRenderedHelper = _this._invokeOnGridRenderedHelper.bind(_this); + _this._onScroll = _this._onScroll.bind(_this); + _this._setNextStateCallback = _this._setNextStateCallback.bind(_this); + _this._updateScrollLeftForScrollToColumn = _this._updateScrollLeftForScrollToColumn.bind(_this); + _this._updateScrollTopForScrollToRow = _this._updateScrollTopForScrollToRow.bind(_this); + + _this._columnWidthGetter = _this._wrapSizeGetter(props.columnWidth); + _this._rowHeightGetter = _this._wrapSizeGetter(props.rowHeight); + + _this._columnSizeAndPositionManager = new _ScalingCellSizeAndPositionManager2.default({ + cellCount: props.columnCount, + cellSizeGetter: function cellSizeGetter(index) { + return _this._columnWidthGetter(index); + }, + estimatedCellSize: _this._getEstimatedColumnSize(props) + }); + _this._rowSizeAndPositionManager = new _ScalingCellSizeAndPositionManager2.default({ + cellCount: props.rowCount, + cellSizeGetter: function cellSizeGetter(index) { + return _this._rowHeightGetter(index); + }, + estimatedCellSize: _this._getEstimatedRowSize(props) + }); + + // See defaultCellRangeRenderer() for more information on the usage of this cache + _this._cellCache = {}; + return _this; + } + + /** + * Pre-measure all columns and rows in a Grid. + * Typically cells are only measured as needed and estimated sizes are used for cells that have not yet been measured. + * This method ensures that the next call to getTotalSize() returns an exact size (as opposed to just an estimated one). + */ + + + _createClass(Grid, [{ + key: 'measureAllCells', + value: function measureAllCells() { + var _props = this.props; + var columnCount = _props.columnCount; + var rowCount = _props.rowCount; + + + this._columnSizeAndPositionManager.getSizeAndPositionOfCell(columnCount - 1); + this._rowSizeAndPositionManager.getSizeAndPositionOfCell(rowCount - 1); } - }, { - key: '_updateScrollLeftForScrollToColumn', - value: function _updateScrollLeftForScrollToColumn() { - var props = arguments.length <= 0 || arguments[0] === undefined ? this.props : arguments[0]; - var state = arguments.length <= 1 || arguments[1] === undefined ? this.state : arguments[1]; - var columnCount = props.columnCount; - var scrollToAlignment = props.scrollToAlignment; - var scrollToColumn = props.scrollToColumn; - var width = props.width; - var scrollLeft = state.scrollLeft; + /** + * Forced recompute of row heights and column widths. + * This function should be called if dynamic column or row sizes have changed but nothing else has. + * Since Grid only receives :columnCount and :rowCount it has no way of detecting when the underlying data changes. + */ + + }, { + key: 'recomputeGridSize', + value: function recomputeGridSize() { + var _ref = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; + + var _ref$columnIndex = _ref.columnIndex; + var columnIndex = _ref$columnIndex === undefined ? 0 : _ref$columnIndex; + var _ref$rowIndex = _ref.rowIndex; + var rowIndex = _ref$rowIndex === undefined ? 0 : _ref$rowIndex; - if (scrollToColumn >= 0 && columnCount > 0) { - var targetIndex = Math.max(0, Math.min(columnCount - 1, scrollToColumn)); + this._columnSizeAndPositionManager.resetCell(columnIndex); + this._rowSizeAndPositionManager.resetCell(rowIndex); - var calculatedScrollLeft = this._columnSizeAndPositionManager.getUpdatedOffsetForIndex({ - align: scrollToAlignment, - containerSize: width, - currentOffset: scrollLeft, - targetIndex: targetIndex - }); + // Clear cell cache in case we are scrolling; + // Invalid row heights likely mean invalid cached content as well. + this._cellCache = {}; - if (scrollLeft !== calculatedScrollLeft) { - this._setScrollPosition({ - scrollLeft: calculatedScrollLeft - }); - } - } + this.forceUpdate(); } }, { - key: '_updateScrollTopForScrollToRow', - value: function _updateScrollTopForScrollToRow() { - var props = arguments.length <= 0 || arguments[0] === undefined ? this.props : arguments[0]; - var state = arguments.length <= 1 || arguments[1] === undefined ? this.state : arguments[1]; - var height = props.height; - var rowCount = props.rowCount; - var scrollToAlignment = props.scrollToAlignment; - var scrollToRow = props.scrollToRow; - var scrollTop = state.scrollTop; + key: 'componentDidMount', + value: function componentDidMount() { + var _props2 = this.props; + var scrollLeft = _props2.scrollLeft; + var scrollToColumn = _props2.scrollToColumn; + var scrollTop = _props2.scrollTop; + var scrollToRow = _props2.scrollToRow; + // If this component was first rendered server-side, scrollbar size will be undefined. + // In that event we need to remeasure. - if (scrollToRow >= 0 && rowCount > 0) { - var targetIndex = Math.max(0, Math.min(rowCount - 1, scrollToRow)); + if (!this._scrollbarSizeMeasured) { + this._scrollbarSize = (0, _scrollbarSize2.default)(); + this._scrollbarSizeMeasured = true; + this.setState({}); + } - var calculatedScrollTop = this._rowSizeAndPositionManager.getUpdatedOffsetForIndex({ - align: scrollToAlignment, - containerSize: height, - currentOffset: scrollTop, - targetIndex: targetIndex - }); + if (scrollLeft >= 0 || scrollTop >= 0) { + this._setScrollPosition({ scrollLeft: scrollLeft, scrollTop: scrollTop }); + } - if (scrollTop !== calculatedScrollTop) { - this._setScrollPosition({ - scrollTop: calculatedScrollTop - }); - } + if (scrollToColumn >= 0 || scrollToRow >= 0) { + this._updateScrollLeftForScrollToColumn(); + this._updateScrollTopForScrollToRow(); } + + // Update onRowsRendered callback + this._invokeOnGridRenderedHelper(); + + // Initialize onScroll callback + this._invokeOnScrollMemoizer({ + scrollLeft: scrollLeft || 0, + scrollTop: scrollTop || 0, + totalColumnsWidth: this._columnSizeAndPositionManager.getTotalSize(), + totalRowsHeight: this._rowSizeAndPositionManager.getTotalSize() + }); } - }, { - key: '_onScroll', - value: function _onScroll(event) { - // In certain edge-cases React dispatches an onScroll event with an invalid target.scrollLeft / target.scrollTop. - // This invalid event can be detected by comparing event.target to this component's scrollable DOM element. - // See issue #404 for more information. - if (event.target !== this._scrollingContainer) { - return; - } - // Prevent pointer events from interrupting a smooth scroll - this._enablePointerEventsAfterDelay(); + /** + * @private + * This method updates scrollLeft/scrollTop in state for the following conditions: + * 1) New scroll-to-cell props have been set + */ - // When this component is shrunk drastically, React dispatches a series of back-to-back scroll events, - // Gradually converging on a scrollTop that is within the bounds of the new, smaller height. - // This causes a series of rapid renders that is slow for long lists. - // We can avoid that by doing some simple bounds checking to ensure that scrollTop never exceeds the total height. - var _props6 = this.props; - var height = _props6.height; - var width = _props6.width; + }, { + key: 'componentDidUpdate', + value: function componentDidUpdate(prevProps, prevState) { + var _this2 = this; - var scrollbarSize = this._scrollbarSize; - var totalRowsHeight = this._rowSizeAndPositionManager.getTotalSize(); - var totalColumnsWidth = this._columnSizeAndPositionManager.getTotalSize(); - var scrollLeft = Math.min(Math.max(0, totalColumnsWidth - width + scrollbarSize), event.target.scrollLeft); - var scrollTop = Math.min(Math.max(0, totalRowsHeight - height + scrollbarSize), event.target.scrollTop); + var _props3 = this.props; + var autoHeight = _props3.autoHeight; + var columnCount = _props3.columnCount; + var height = _props3.height; + var rowCount = _props3.rowCount; + var scrollToAlignment = _props3.scrollToAlignment; + var scrollToColumn = _props3.scrollToColumn; + var scrollToRow = _props3.scrollToRow; + var width = _props3.width; + var _state = this.state; + var scrollLeft = _state.scrollLeft; + var scrollPositionChangeReason = _state.scrollPositionChangeReason; + var scrollTop = _state.scrollTop; - // Certain devices (like Apple touchpad) rapid-fire duplicate events. - // Don't force a re-render if this is the case. - // The mouse may move faster then the animation frame does. - // Use requestAnimationFrame to avoid over-updating. - if (this.state.scrollLeft !== scrollLeft || this.state.scrollTop !== scrollTop) { - // Browsers with cancelable scroll events (eg. Firefox) interrupt scrolling animations if scrollTop/scrollLeft is set. - // Other browsers (eg. Safari) don't scroll as well without the help under certain conditions (DOM or style changes during scrolling). - // All things considered, this seems to be the best current work around that I'm aware of. - // For more information see https://github.com/bvaughn/react-virtualized/pull/124 - var scrollPositionChangeReason = event.cancelable ? SCROLL_POSITION_CHANGE_REASONS.OBSERVED : SCROLL_POSITION_CHANGE_REASONS.REQUESTED; + // Handle edge case where column or row count has only just increased over 0. + // In this case we may have to restore a previously-specified scroll offset. + // For more info see bvaughn/react-virtualized/issues/218 - // Track scrolling direction so we can more efficiently overscan rows to reduce empty space around the edges while scrolling. - var scrollDirectionVertical = scrollTop > this.state.scrollTop ? _getOverscanIndices.SCROLL_DIRECTION_FORWARD : _getOverscanIndices.SCROLL_DIRECTION_BACKWARD; - var scrollDirectionHorizontal = scrollLeft > this.state.scrollLeft ? _getOverscanIndices.SCROLL_DIRECTION_FORWARD : _getOverscanIndices.SCROLL_DIRECTION_BACKWARD; + var columnOrRowCountJustIncreasedFromZero = columnCount > 0 && prevProps.columnCount === 0 || rowCount > 0 && prevProps.rowCount === 0; - if (!this.state.isScrolling) { - this.setState({ - isScrolling: true - }); + // Make sure requested changes to :scrollLeft or :scrollTop get applied. + // Assigning to scrollLeft/scrollTop tells the browser to interrupt any running scroll animations, + // And to discard any pending async changes to the scroll position that may have happened in the meantime (e.g. on a separate scrolling thread). + // So we only set these when we require an adjustment of the scroll position. + // See issue #2 for more information. + if (scrollPositionChangeReason === SCROLL_POSITION_CHANGE_REASONS.REQUESTED) { + if (scrollLeft >= 0 && (scrollLeft !== prevState.scrollLeft && scrollLeft !== this._scrollingContainer.scrollLeft || columnOrRowCountJustIncreasedFromZero)) { + this._scrollingContainer.scrollLeft = scrollLeft; } - this._setNextState({ - isScrolling: true, - scrollDirectionHorizontal: scrollDirectionHorizontal, - scrollDirectionVertical: scrollDirectionVertical, - scrollLeft: scrollLeft, - scrollPositionChangeReason: scrollPositionChangeReason, - scrollTop: scrollTop - }); + // @TRICKY :autoHeight property instructs Grid to leave :scrollTop management to an external HOC (eg WindowScroller). + // In this case we should avoid checking scrollingContainer.scrollTop since it forces layout/flow. + if (!autoHeight && scrollTop >= 0 && (scrollTop !== prevState.scrollTop && scrollTop !== this._scrollingContainer.scrollTop || columnOrRowCountJustIncreasedFromZero)) { + this._scrollingContainer.scrollTop = scrollTop; + } } - this._invokeOnScrollMemoizer({ scrollLeft: scrollLeft, scrollTop: scrollTop, totalColumnsWidth: totalColumnsWidth, totalRowsHeight: totalRowsHeight }); - } - }]); + // Update scroll offsets if the current :scrollToColumn or :scrollToRow values requires it + // @TODO Do we also need this check or can the one in componentWillUpdate() suffice? + (0, _updateScrollIndexHelper2.default)({ + cellSizeAndPositionManager: this._columnSizeAndPositionManager, + previousCellsCount: prevProps.columnCount, + previousCellSize: prevProps.columnWidth, + previousScrollToAlignment: prevProps.scrollToAlignment, + previousScrollToIndex: prevProps.scrollToColumn, + previousSize: prevProps.width, + scrollOffset: scrollLeft, + scrollToAlignment: scrollToAlignment, + scrollToIndex: scrollToColumn, + size: width, + updateScrollIndexCallback: function updateScrollIndexCallback(scrollToColumn) { + return _this2._updateScrollLeftForScrollToColumn(_extends({}, _this2.props, { scrollToColumn: scrollToColumn })); + } + }); + (0, _updateScrollIndexHelper2.default)({ + cellSizeAndPositionManager: this._rowSizeAndPositionManager, + previousCellsCount: prevProps.rowCount, + previousCellSize: prevProps.rowHeight, + previousScrollToAlignment: prevProps.scrollToAlignment, + previousScrollToIndex: prevProps.scrollToRow, + previousSize: prevProps.height, + scrollOffset: scrollTop, + scrollToAlignment: scrollToAlignment, + scrollToIndex: scrollToRow, + size: height, + updateScrollIndexCallback: function updateScrollIndexCallback(scrollToRow) { + return _this2._updateScrollTopForScrollToRow(_extends({}, _this2.props, { scrollToRow: scrollToRow })); + } + }); - return Grid; -}(_react.Component); + // Update onRowsRendered callback if start/stop indices have changed + this._invokeOnGridRenderedHelper(); + } + }, { + key: 'componentWillMount', + value: function componentWillMount() { + // If this component is being rendered server-side, getScrollbarSize() will return undefined. + // We handle this case in componentDidMount() + this._scrollbarSize = (0, _scrollbarSize2.default)(); + if (this._scrollbarSize === undefined) { + this._scrollbarSizeMeasured = false; + this._scrollbarSize = 0; + } else { + this._scrollbarSizeMeasured = true; + } -Grid.propTypes = { - 'aria-label': _react.PropTypes.string, + this._calculateChildrenToRender(); + } + }, { + key: 'componentWillUnmount', + value: function componentWillUnmount() { + if (this._disablePointerEventsTimeoutId) { + clearTimeout(this._disablePointerEventsTimeoutId); + } - /** - * Set the width of the inner scrollable container to 'auto'. - * This is useful for single-column Grids to ensure that the column doesn't extend below a vertical scrollbar. - */ - autoContainerWidth: _react.PropTypes.bool, + if (this._setNextStateAnimationFrameId) { + _raf2.default.cancel(this._setNextStateAnimationFrameId); + } + } - /** - * Removes fixed height from the scrollingContainer so that the total height - * of rows can stretch the window. Intended for use with WindowScroller - */ - autoHeight: _react.PropTypes.bool, + /** + * @private + * This method updates scrollLeft/scrollTop in state for the following conditions: + * 1) Empty content (0 rows or columns) + * 2) New scroll props overriding the current state + * 3) Cells-count or cells-size has changed, making previous scroll offsets invalid + */ - /** Optional custom CSS class for individual cells */ - cellClassName: _react.PropTypes.oneOfType([_react.PropTypes.string, _react.PropTypes.func]), + }, { + key: 'componentWillUpdate', + value: function componentWillUpdate(nextProps, nextState) { + var _this3 = this; - /** Optional custom styles for individual cells */ - cellStyle: _react.PropTypes.oneOfType([_react.PropTypes.object, _react.PropTypes.func]), + if (nextProps.columnCount === 0 && nextState.scrollLeft !== 0 || nextProps.rowCount === 0 && nextState.scrollTop !== 0) { + this._setScrollPosition({ + scrollLeft: 0, + scrollTop: 0 + }); + } else if (nextProps.scrollLeft !== this.props.scrollLeft || nextProps.scrollTop !== this.props.scrollTop) { + this._setScrollPosition({ + scrollLeft: nextProps.scrollLeft, + scrollTop: nextProps.scrollTop + }); + } - /** - * Responsible for rendering a cell given an row and column index. - * Should implement the following interface: ({ columnIndex: number, rowIndex: number }): PropTypes.node - */ - cellRenderer: _react.PropTypes.func.isRequired, + this._columnWidthGetter = this._wrapSizeGetter(nextProps.columnWidth); + this._rowHeightGetter = this._wrapSizeGetter(nextProps.rowHeight); - /** - * Responsible for rendering a group of cells given their index ranges. - * Should implement the following interface: ({ - * cellCache: Map, - * cellRenderer: Function, - * columnSizeAndPositionManager: CellSizeAndPositionManager, - * columnStartIndex: number, - * columnStopIndex: number, - * isScrolling: boolean, - * rowSizeAndPositionManager: CellSizeAndPositionManager, - * rowStartIndex: number, - * rowStopIndex: number, - * scrollLeft: number, - * scrollTop: number - * }): Array - */ - cellRangeRenderer: _react.PropTypes.func.isRequired, + this._columnSizeAndPositionManager.configure({ + cellCount: nextProps.columnCount, + estimatedCellSize: this._getEstimatedColumnSize(nextProps) + }); + this._rowSizeAndPositionManager.configure({ + cellCount: nextProps.rowCount, + estimatedCellSize: this._getEstimatedRowSize(nextProps) + }); - /** - * Optional custom CSS class name to attach to root Grid element. - */ - className: _react.PropTypes.string, + // Update scroll offsets if the size or number of cells have changed, invalidating the previous value + (0, _calculateSizeAndPositionDataAndUpdateScrollOffset2.default)({ + cellCount: this.props.columnCount, + cellSize: this.props.columnWidth, + computeMetadataCallback: function computeMetadataCallback() { + return _this3._columnSizeAndPositionManager.resetCell(0); + }, + computeMetadataCallbackProps: nextProps, + nextCellsCount: nextProps.columnCount, + nextCellSize: nextProps.columnWidth, + nextScrollToIndex: nextProps.scrollToColumn, + scrollToIndex: this.props.scrollToColumn, + updateScrollOffsetForScrollToIndex: function updateScrollOffsetForScrollToIndex() { + return _this3._updateScrollLeftForScrollToColumn(nextProps, nextState); + } + }); + (0, _calculateSizeAndPositionDataAndUpdateScrollOffset2.default)({ + cellCount: this.props.rowCount, + cellSize: this.props.rowHeight, + computeMetadataCallback: function computeMetadataCallback() { + return _this3._rowSizeAndPositionManager.resetCell(0); + }, + computeMetadataCallbackProps: nextProps, + nextCellsCount: nextProps.rowCount, + nextCellSize: nextProps.rowHeight, + nextScrollToIndex: nextProps.scrollToRow, + scrollToIndex: this.props.scrollToRow, + updateScrollOffsetForScrollToIndex: function updateScrollOffsetForScrollToIndex() { + return _this3._updateScrollTopForScrollToRow(nextProps, nextState); + } + }); - /** - * Number of columns in grid. - */ - columnCount: _react.PropTypes.number.isRequired, + this._calculateChildrenToRender(nextProps, nextState); + } + }, { + key: 'render', + value: function render() { + var _this4 = this; - /** - * Either a fixed column width (number) or a function that returns the width of a column given its index. - * Should implement the following interface: (index: number): number - */ - columnWidth: _react.PropTypes.oneOfType([_react.PropTypes.number, _react.PropTypes.func]).isRequired, + var _props4 = this.props; + var autoContainerWidth = _props4.autoContainerWidth; + var autoHeight = _props4.autoHeight; + var className = _props4.className; + var height = _props4.height; + var noContentRenderer = _props4.noContentRenderer; + var style = _props4.style; + var tabIndex = _props4.tabIndex; + var width = _props4.width; + var isScrolling = this.state.isScrolling; - /** - * Used to estimate the total width of a Grid before all of its columns have actually been measured. - * The estimated total width is adjusted as columns are rendered. - */ - estimatedColumnSize: _react.PropTypes.number.isRequired, - /** - * Used to estimate the total height of a Grid before all of its rows have actually been measured. - * The estimated total height is adjusted as rows are rendered. - */ - estimatedRowSize: _react.PropTypes.number.isRequired, + var gridStyle = { + height: autoHeight ? 'auto' : height, + width: width + }; - /** - * Height of Grid; this property determines the number of visible (vs virtualized) rows. - */ - height: _react.PropTypes.number.isRequired, + var totalColumnsWidth = this._columnSizeAndPositionManager.getTotalSize(); + var totalRowsHeight = this._rowSizeAndPositionManager.getTotalSize(); - /** - * Optional renderer to be used in place of rows when either :rowCount or :columnCount is 0. - */ - noContentRenderer: _react.PropTypes.func.isRequired, + // Force browser to hide scrollbars when we know they aren't necessary. + // Otherwise once scrollbars appear they may not disappear again. + // For more info see issue #116 + var verticalScrollBarSize = totalRowsHeight > height ? this._scrollbarSize : 0; + var horizontalScrollBarSize = totalColumnsWidth > width ? this._scrollbarSize : 0; - /** - * Callback invoked whenever the scroll offset changes within the inner scrollable region. - * This callback can be used to sync scrolling between lists, tables, or grids. - * ({ clientHeight, clientWidth, scrollHeight, scrollLeft, scrollTop, scrollWidth }): void - */ - onScroll: _react.PropTypes.func.isRequired, + // Also explicitly init styles to 'auto' if scrollbars are required. + // This works around an obscure edge case where external CSS styles have not yet been loaded, + // But an initial scroll index of offset is set as an external prop. + // Without this style, Grid would render the correct range of cells but would NOT update its internal offset. + // This was originally reported via clauderic/react-infinite-calendar/issues/23 + gridStyle.overflowX = totalColumnsWidth + verticalScrollBarSize <= width ? 'hidden' : 'auto'; + gridStyle.overflowY = totalRowsHeight + horizontalScrollBarSize <= height ? 'hidden' : 'auto'; - /** - * Callback invoked with information about the section of the Grid that was just rendered. - * ({ columnStartIndex, columnStopIndex, rowStartIndex, rowStopIndex }): void - */ - onSectionRendered: _react.PropTypes.func.isRequired, + var childrenToDisplay = this._childrenToDisplay; - /** - * Number of columns to render before/after the visible section of the grid. - * These columns can help for smoother scrolling on touch devices or browsers that send scroll events infrequently. - */ - overscanColumnCount: _react.PropTypes.number.isRequired, + var showNoContentRenderer = childrenToDisplay.length === 0 && height > 0 && width > 0; - /** - * Number of rows to render above/below the visible section of the grid. - * These rows can help for smoother scrolling on touch devices or browsers that send scroll events infrequently. - */ - overscanRowCount: _react.PropTypes.number.isRequired, + return _react2.default.createElement( + 'div', + { + ref: function ref(_ref2) { + _this4._scrollingContainer = _ref2; + }, + 'aria-label': this.props['aria-label'], + className: (0, _classnames2.default)('Grid', className), + onScroll: this._onScroll, + role: 'grid', + style: _extends({}, gridStyle, style), + tabIndex: tabIndex + }, + childrenToDisplay.length > 0 && _react2.default.createElement( + 'div', + { + className: 'Grid__innerScrollContainer', + style: { + width: autoContainerWidth ? 'auto' : totalColumnsWidth, + height: totalRowsHeight, + maxWidth: totalColumnsWidth, + maxHeight: totalRowsHeight, + pointerEvents: isScrolling ? 'none' : '' + } + }, + childrenToDisplay + ), + showNoContentRenderer && noContentRenderer() + ); + } + }, { + key: 'shouldComponentUpdate', + value: function shouldComponentUpdate(nextProps, nextState) { + return (0, _reactAddonsShallowCompare2.default)(this, nextProps, nextState); + } - /** - * Either a fixed row height (number) or a function that returns the height of a row given its index. - * Should implement the following interface: ({ index: number }): number - */ - rowHeight: _react.PropTypes.oneOfType([_react.PropTypes.number, _react.PropTypes.func]).isRequired, + /* ---------------------------- Helper methods ---------------------------- */ - /** - * Number of rows in grid. - */ - rowCount: _react.PropTypes.number.isRequired, + }, { + key: '_calculateChildrenToRender', + value: function _calculateChildrenToRender() { + var props = arguments.length <= 0 || arguments[0] === undefined ? this.props : arguments[0]; + var state = arguments.length <= 1 || arguments[1] === undefined ? this.state : arguments[1]; + var cellClassName = props.cellClassName; + var cellRenderer = props.cellRenderer; + var cellRangeRenderer = props.cellRangeRenderer; + var cellStyle = props.cellStyle; + var columnCount = props.columnCount; + var height = props.height; + var overscanColumnCount = props.overscanColumnCount; + var overscanRowCount = props.overscanRowCount; + var rowCount = props.rowCount; + var width = props.width; + var isScrolling = state.isScrolling; + var scrollDirectionHorizontal = state.scrollDirectionHorizontal; + var scrollDirectionVertical = state.scrollDirectionVertical; + var scrollLeft = state.scrollLeft; + var scrollTop = state.scrollTop; - /** Wait this amount of time after the last scroll event before resetting Grid `pointer-events`. */ - scrollingResetTimeInterval: _react.PropTypes.number, - /** Horizontal offset. */ - scrollLeft: _react.PropTypes.number, + this._childrenToDisplay = []; - /** - * Controls scroll-to-cell behavior of the Grid. - * The default ("auto") scrolls the least amount possible to ensure that the specified cell is fully visible. - * Use "start" to align cells to the top/left of the Grid and "end" to align bottom/right. - */ - scrollToAlignment: _react.PropTypes.oneOf(['auto', 'end', 'start', 'center']).isRequired, + // Render only enough columns and rows to cover the visible area of the grid. + if (height > 0 && width > 0) { + var visibleColumnIndices = this._columnSizeAndPositionManager.getVisibleCellRange({ + containerSize: width, + offset: scrollLeft + }); + var visibleRowIndices = this._rowSizeAndPositionManager.getVisibleCellRange({ + containerSize: height, + offset: scrollTop + }); - /** - * Column index to ensure visible (by forcefully scrolling if necessary) - */ - scrollToColumn: _react.PropTypes.number, + var horizontalOffsetAdjustment = this._columnSizeAndPositionManager.getOffsetAdjustment({ + containerSize: width, + offset: scrollLeft + }); + var verticalOffsetAdjustment = this._rowSizeAndPositionManager.getOffsetAdjustment({ + containerSize: height, + offset: scrollTop + }); - /** Vertical offset. */ - scrollTop: _react.PropTypes.number, + // Store for _invokeOnGridRenderedHelper() + this._renderedColumnStartIndex = visibleColumnIndices.start; + this._renderedColumnStopIndex = visibleColumnIndices.stop; + this._renderedRowStartIndex = visibleRowIndices.start; + this._renderedRowStopIndex = visibleRowIndices.stop; - /** - * Row index to ensure visible (by forcefully scrolling if necessary) - */ - scrollToRow: _react.PropTypes.number, + var overscanColumnIndices = (0, _getOverscanIndices2.default)({ + cellCount: columnCount, + overscanCellsCount: overscanColumnCount, + scrollDirection: scrollDirectionHorizontal, + startIndex: this._renderedColumnStartIndex, + stopIndex: this._renderedColumnStopIndex + }); - /** Optional inline style */ - style: _react.PropTypes.object, + var overscanRowIndices = (0, _getOverscanIndices2.default)({ + cellCount: rowCount, + overscanCellsCount: overscanRowCount, + scrollDirection: scrollDirectionVertical, + startIndex: this._renderedRowStartIndex, + stopIndex: this._renderedRowStopIndex + }); - /** Tab index for focus */ - tabIndex: _react.PropTypes.number, + // Store for _invokeOnGridRenderedHelper() + this._columnStartIndex = overscanColumnIndices.overscanStartIndex; + this._columnStopIndex = overscanColumnIndices.overscanStopIndex; + this._rowStartIndex = overscanRowIndices.overscanStartIndex; + this._rowStopIndex = overscanRowIndices.overscanStopIndex; - /** - * Width of Grid; this property determines the number of visible (vs virtualized) columns. - */ - width: _react.PropTypes.number.isRequired -}; -Grid.defaultProps = { - 'aria-label': 'grid', - cellStyle: {}, - cellRangeRenderer: _defaultCellRangeRenderer2.default, - estimatedColumnSize: 100, - estimatedRowSize: 30, - noContentRenderer: function noContentRenderer() { - return null; - }, - onScroll: function onScroll() { - return null; - }, - onSectionRendered: function onSectionRendered() { - return null; - }, - overscanColumnCount: 0, - overscanRowCount: 10, - scrollingResetTimeInterval: DEFAULT_SCROLLING_RESET_TIME_INTERVAL, - scrollToAlignment: 'auto', - style: {}, - tabIndex: 0 -}; -exports.default = Grid; -},{"../utils/createCallbackMemoizer":78,"./defaultCellRangeRenderer":61,"./utils/ScalingCellSizeAndPositionManager":64,"./utils/calculateSizeAndPositionDataAndUpdateScrollOffset":65,"./utils/getOverscanIndices":66,"./utils/updateScrollIndexHelper":67,"classnames":undefined,"dom-helpers/util/scrollbarSize":19,"raf":29,"react":undefined,"react-addons-shallow-compare":30}],61:[function(require,module,exports){ -'use strict'; + this._childrenToDisplay = cellRangeRenderer({ + cellCache: this._cellCache, + cellClassName: this._wrapCellClassNameGetter(cellClassName), + cellRenderer: cellRenderer, + cellStyle: this._wrapCellStyleGetter(cellStyle), + columnSizeAndPositionManager: this._columnSizeAndPositionManager, + columnStartIndex: this._columnStartIndex, + columnStopIndex: this._columnStopIndex, + horizontalOffsetAdjustment: horizontalOffsetAdjustment, + isScrolling: isScrolling, + rowSizeAndPositionManager: this._rowSizeAndPositionManager, + rowStartIndex: this._rowStartIndex, + rowStopIndex: this._rowStopIndex, + scrollLeft: scrollLeft, + scrollTop: scrollTop, + verticalOffsetAdjustment: verticalOffsetAdjustment + }); + } + } -Object.defineProperty(exports, "__esModule", { - value: true -}); + /** + * Sets an :isScrolling flag for a small window of time. + * This flag is used to disable pointer events on the scrollable portion of the Grid. + * This prevents jerky/stuttery mouse-wheel scrolling. + */ -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + }, { + key: '_enablePointerEventsAfterDelay', + value: function _enablePointerEventsAfterDelay() { + var scrollingResetTimeInterval = this.props.scrollingResetTimeInterval; -exports.default = defaultCellRangeRenderer; -var _react = require('react'); + if (this._disablePointerEventsTimeoutId) { + clearTimeout(this._disablePointerEventsTimeoutId); + } -var _react2 = _interopRequireDefault(_react); + this._disablePointerEventsTimeoutId = setTimeout(this._enablePointerEventsAfterDelayCallback, scrollingResetTimeInterval); + } + }, { + key: '_enablePointerEventsAfterDelayCallback', + value: function _enablePointerEventsAfterDelayCallback() { + this._disablePointerEventsTimeoutId = null; -var _classnames = require('classnames'); + // Throw away cell cache once scrolling is complete + this._cellCache = {}; -var _classnames2 = _interopRequireDefault(_classnames); + this.setState({ + isScrolling: false, + scrollDirectionHorizontal: _getOverscanIndices.SCROLL_DIRECTION_FIXED, + scrollDirectionVertical: _getOverscanIndices.SCROLL_DIRECTION_FIXED + }); + } + }, { + key: '_getEstimatedColumnSize', + value: function _getEstimatedColumnSize(props) { + return typeof props.columnWidth === 'number' ? props.columnWidth : props.estimatedColumnSize; + } + }, { + key: '_getEstimatedRowSize', + value: function _getEstimatedRowSize(props) { + return typeof props.rowHeight === 'number' ? props.rowHeight : props.estimatedRowSize; + } + }, { + key: '_invokeOnGridRenderedHelper', + value: function _invokeOnGridRenderedHelper() { + var onSectionRendered = this.props.onSectionRendered; -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -/** - * Default implementation of cellRangeRenderer used by Grid. - * This renderer supports cell-caching while the user is scrolling. - */ -function defaultCellRangeRenderer(_ref) { - var cellCache = _ref.cellCache; - var cellClassName = _ref.cellClassName; - var cellRenderer = _ref.cellRenderer; - var cellStyle = _ref.cellStyle; - var columnSizeAndPositionManager = _ref.columnSizeAndPositionManager; - var columnStartIndex = _ref.columnStartIndex; - var columnStopIndex = _ref.columnStopIndex; - var horizontalOffsetAdjustment = _ref.horizontalOffsetAdjustment; - var isScrolling = _ref.isScrolling; - var rowSizeAndPositionManager = _ref.rowSizeAndPositionManager; - var rowStartIndex = _ref.rowStartIndex; - var rowStopIndex = _ref.rowStopIndex; - var scrollLeft = _ref.scrollLeft; - var scrollTop = _ref.scrollTop; - var verticalOffsetAdjustment = _ref.verticalOffsetAdjustment; + this._onGridRenderedMemoizer({ + callback: onSectionRendered, + indices: { + columnOverscanStartIndex: this._columnStartIndex, + columnOverscanStopIndex: this._columnStopIndex, + columnStartIndex: this._renderedColumnStartIndex, + columnStopIndex: this._renderedColumnStopIndex, + rowOverscanStartIndex: this._rowStartIndex, + rowOverscanStopIndex: this._rowStopIndex, + rowStartIndex: this._renderedRowStartIndex, + rowStopIndex: this._renderedRowStopIndex + } + }); + } + }, { + key: '_invokeOnScrollMemoizer', + value: function _invokeOnScrollMemoizer(_ref3) { + var _this5 = this; - var renderedCells = []; + var scrollLeft = _ref3.scrollLeft; + var scrollTop = _ref3.scrollTop; + var totalColumnsWidth = _ref3.totalColumnsWidth; + var totalRowsHeight = _ref3.totalRowsHeight; - for (var rowIndex = rowStartIndex; rowIndex <= rowStopIndex; rowIndex++) { - var rowDatum = rowSizeAndPositionManager.getSizeAndPositionOfCell(rowIndex); + this._onScrollMemoizer({ + callback: function callback(_ref4) { + var scrollLeft = _ref4.scrollLeft; + var scrollTop = _ref4.scrollTop; + var _props5 = _this5.props; + var height = _props5.height; + var onScroll = _props5.onScroll; + var width = _props5.width; - for (var columnIndex = columnStartIndex; columnIndex <= columnStopIndex; columnIndex++) { - var columnDatum = columnSizeAndPositionManager.getSizeAndPositionOfCell(columnIndex); - var key = rowIndex + '-' + columnIndex; - var cellStyleObject = cellStyle({ rowIndex: rowIndex, columnIndex: columnIndex }); - var renderedCell = void 0; - // Avoid re-creating cells while scrolling. - // This can lead to the same cell being created many times and can cause performance issues for "heavy" cells. - // If a scroll is in progress- cache and reuse cells. - // This cache will be thrown away once scrolling complets. - if (isScrolling) { - if (!cellCache[key]) { - cellCache[key] = cellRenderer({ - columnIndex: columnIndex, - isScrolling: isScrolling, - rowIndex: rowIndex + onScroll({ + clientHeight: height, + clientWidth: width, + scrollHeight: totalRowsHeight, + scrollLeft: scrollLeft, + scrollTop: scrollTop, + scrollWidth: totalColumnsWidth }); + }, + indices: { + scrollLeft: scrollLeft, + scrollTop: scrollTop } - renderedCell = cellCache[key]; - // If the user is no longer scrolling, don't cache cells. - // This makes dynamic cell content difficult for users and would also lead to a heavier memory footprint. - } else { - renderedCell = cellRenderer({ - columnIndex: columnIndex, - isScrolling: isScrolling, - rowIndex: rowIndex - }); + }); + } + + /** + * Updates the state during the next animation frame. + * Use this method to avoid multiple renders in a small span of time. + * This helps performance for bursty events (like onScroll). + */ + + }, { + key: '_setNextState', + value: function _setNextState(state) { + this._nextState = state; + + if (!this._setNextStateAnimationFrameId) { + this._setNextStateAnimationFrameId = (0, _raf2.default)(this._setNextStateCallback); } + } + }, { + key: '_setNextStateCallback', + value: function _setNextStateCallback() { + var state = this._nextState; + + this._setNextStateAnimationFrameId = null; + this._nextState = null; + + this.setState(state); + } + }, { + key: '_setScrollPosition', + value: function _setScrollPosition(_ref5) { + var scrollLeft = _ref5.scrollLeft; + var scrollTop = _ref5.scrollTop; - if (renderedCell == null || renderedCell === false) { - continue; - } + var newState = { + scrollPositionChangeReason: SCROLL_POSITION_CHANGE_REASONS.REQUESTED + }; - var className = cellClassName({ columnIndex: columnIndex, rowIndex: rowIndex }); + if (scrollLeft >= 0) { + newState.scrollLeft = scrollLeft; + } - var child = _react2.default.createElement( - 'div', - { - key: key, - className: (0, _classnames2.default)('Grid__cell', className), - style: _extends({ - height: rowDatum.size, - left: columnDatum.offset + horizontalOffsetAdjustment, - top: rowDatum.offset + verticalOffsetAdjustment, - width: columnDatum.size - }, cellStyleObject) - }, - renderedCell - ); + if (scrollTop >= 0) { + newState.scrollTop = scrollTop; + } - renderedCells.push(child); + if (scrollLeft >= 0 && scrollLeft !== this.state.scrollLeft || scrollTop >= 0 && scrollTop !== this.state.scrollTop) { + this.setState(newState); + } } - } - - return renderedCells; -} -},{"classnames":undefined,"react":undefined}],62:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.defaultCellRangeRenderer = exports.Grid = exports.default = undefined; + }, { + key: '_wrapCellClassNameGetter', + value: function _wrapCellClassNameGetter(className) { + return this._wrapPropertyGetter(className); + } + }, { + key: '_wrapCellStyleGetter', + value: function _wrapCellStyleGetter(style) { + return this._wrapPropertyGetter(style); + } + }, { + key: '_wrapPropertyGetter', + value: function _wrapPropertyGetter(value) { + return value instanceof Function ? value : function () { + return value; + }; + } + }, { + key: '_wrapSizeGetter', + value: function _wrapSizeGetter(size) { + return this._wrapPropertyGetter(size); + } + }, { + key: '_updateScrollLeftForScrollToColumn', + value: function _updateScrollLeftForScrollToColumn() { + var props = arguments.length <= 0 || arguments[0] === undefined ? this.props : arguments[0]; + var state = arguments.length <= 1 || arguments[1] === undefined ? this.state : arguments[1]; + var columnCount = props.columnCount; + var scrollToAlignment = props.scrollToAlignment; + var scrollToColumn = props.scrollToColumn; + var width = props.width; + var scrollLeft = state.scrollLeft; -var _Grid2 = require('./Grid'); -var _Grid3 = _interopRequireDefault(_Grid2); + if (scrollToColumn >= 0 && columnCount > 0) { + var targetIndex = Math.max(0, Math.min(columnCount - 1, scrollToColumn)); -var _defaultCellRangeRenderer2 = require('./defaultCellRangeRenderer'); + var calculatedScrollLeft = this._columnSizeAndPositionManager.getUpdatedOffsetForIndex({ + align: scrollToAlignment, + containerSize: width, + currentOffset: scrollLeft, + targetIndex: targetIndex + }); -var _defaultCellRangeRenderer3 = _interopRequireDefault(_defaultCellRangeRenderer2); + if (scrollLeft !== calculatedScrollLeft) { + this._setScrollPosition({ + scrollLeft: calculatedScrollLeft + }); + } + } + } + }, { + key: '_updateScrollTopForScrollToRow', + value: function _updateScrollTopForScrollToRow() { + var props = arguments.length <= 0 || arguments[0] === undefined ? this.props : arguments[0]; + var state = arguments.length <= 1 || arguments[1] === undefined ? this.state : arguments[1]; + var height = props.height; + var rowCount = props.rowCount; + var scrollToAlignment = props.scrollToAlignment; + var scrollToRow = props.scrollToRow; + var scrollTop = state.scrollTop; -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -exports.default = _Grid3.default; -exports.Grid = _Grid3.default; -exports.defaultCellRangeRenderer = _defaultCellRangeRenderer3.default; -},{"./Grid":60,"./defaultCellRangeRenderer":61}],63:[function(require,module,exports){ -'use strict'; + if (scrollToRow >= 0 && rowCount > 0) { + var targetIndex = Math.max(0, Math.min(rowCount - 1, scrollToRow)); -Object.defineProperty(exports, "__esModule", { - value: true -}); + var calculatedScrollTop = this._rowSizeAndPositionManager.getUpdatedOffsetForIndex({ + align: scrollToAlignment, + containerSize: height, + currentOffset: scrollTop, + targetIndex: targetIndex + }); -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + if (scrollTop !== calculatedScrollTop) { + this._setScrollPosition({ + scrollTop: calculatedScrollTop + }); + } + } + } + }, { + key: '_onScroll', + value: function _onScroll(event) { + // In certain edge-cases React dispatches an onScroll event with an invalid target.scrollLeft / target.scrollTop. + // This invalid event can be detected by comparing event.target to this component's scrollable DOM element. + // See issue #404 for more information. + if (event.target !== this._scrollingContainer) { + return; + } -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + // Prevent pointer events from interrupting a smooth scroll + this._enablePointerEventsAfterDelay(); -/** - * Just-in-time calculates and caches size and position information for a collection of cells. - */ -var CellSizeAndPositionManager = function () { - function CellSizeAndPositionManager(_ref) { - var cellCount = _ref.cellCount; - var cellSizeGetter = _ref.cellSizeGetter; - var estimatedCellSize = _ref.estimatedCellSize; + // When this component is shrunk drastically, React dispatches a series of back-to-back scroll events, + // Gradually converging on a scrollTop that is within the bounds of the new, smaller height. + // This causes a series of rapid renders that is slow for long lists. + // We can avoid that by doing some simple bounds checking to ensure that scrollTop never exceeds the total height. + var _props6 = this.props; + var height = _props6.height; + var width = _props6.width; - _classCallCheck(this, CellSizeAndPositionManager); + var scrollbarSize = this._scrollbarSize; + var totalRowsHeight = this._rowSizeAndPositionManager.getTotalSize(); + var totalColumnsWidth = this._columnSizeAndPositionManager.getTotalSize(); + var scrollLeft = Math.min(Math.max(0, totalColumnsWidth - width + scrollbarSize), event.target.scrollLeft); + var scrollTop = Math.min(Math.max(0, totalRowsHeight - height + scrollbarSize), event.target.scrollTop); - this._cellSizeGetter = cellSizeGetter; - this._cellCount = cellCount; - this._estimatedCellSize = estimatedCellSize; + // Certain devices (like Apple touchpad) rapid-fire duplicate events. + // Don't force a re-render if this is the case. + // The mouse may move faster then the animation frame does. + // Use requestAnimationFrame to avoid over-updating. + if (this.state.scrollLeft !== scrollLeft || this.state.scrollTop !== scrollTop) { + // Browsers with cancelable scroll events (eg. Firefox) interrupt scrolling animations if scrollTop/scrollLeft is set. + // Other browsers (eg. Safari) don't scroll as well without the help under certain conditions (DOM or style changes during scrolling). + // All things considered, this seems to be the best current work around that I'm aware of. + // For more information see https://github.com/bvaughn/react-virtualized/pull/124 + var scrollPositionChangeReason = event.cancelable ? SCROLL_POSITION_CHANGE_REASONS.OBSERVED : SCROLL_POSITION_CHANGE_REASONS.REQUESTED; - // Cache of size and position data for cells, mapped by cell index. - // Note that invalid values may exist in this map so only rely on cells up to this._lastMeasuredIndex - this._cellSizeAndPositionData = {}; + // Track scrolling direction so we can more efficiently overscan rows to reduce empty space around the edges while scrolling. + var scrollDirectionVertical = scrollTop > this.state.scrollTop ? _getOverscanIndices.SCROLL_DIRECTION_FORWARD : _getOverscanIndices.SCROLL_DIRECTION_BACKWARD; + var scrollDirectionHorizontal = scrollLeft > this.state.scrollLeft ? _getOverscanIndices.SCROLL_DIRECTION_FORWARD : _getOverscanIndices.SCROLL_DIRECTION_BACKWARD; - // Measurements for cells up to this index can be trusted; cells afterward should be estimated. - this._lastMeasuredIndex = -1; - } + if (!this.state.isScrolling) { + this.setState({ + isScrolling: true + }); + } - _createClass(CellSizeAndPositionManager, [{ - key: 'configure', - value: function configure(_ref2) { - var cellCount = _ref2.cellCount; - var estimatedCellSize = _ref2.estimatedCellSize; + this._setNextState({ + isScrolling: true, + scrollDirectionHorizontal: scrollDirectionHorizontal, + scrollDirectionVertical: scrollDirectionVertical, + scrollLeft: scrollLeft, + scrollPositionChangeReason: scrollPositionChangeReason, + scrollTop: scrollTop + }); + } - this._cellCount = cellCount; - this._estimatedCellSize = estimatedCellSize; - } - }, { - key: 'getCellCount', - value: function getCellCount() { - return this._cellCount; - } - }, { - key: 'getEstimatedCellSize', - value: function getEstimatedCellSize() { - return this._estimatedCellSize; - } - }, { - key: 'getLastMeasuredIndex', - value: function getLastMeasuredIndex() { - return this._lastMeasuredIndex; + this._invokeOnScrollMemoizer({ scrollLeft: scrollLeft, scrollTop: scrollTop, totalColumnsWidth: totalColumnsWidth, totalRowsHeight: totalRowsHeight }); } + }]); - /** - * This method returns the size and position for the cell at the specified index. - * It just-in-time calculates (or used cached values) for cells leading up to the index. - */ + return Grid; +}(_react.Component); - }, { - key: 'getSizeAndPositionOfCell', - value: function getSizeAndPositionOfCell(index) { - if (index < 0 || index >= this._cellCount) { - throw Error('Requested index ' + index + ' is outside of range 0..' + this._cellCount); - } +Grid.propTypes = { + 'aria-label': _react.PropTypes.string, - if (index > this._lastMeasuredIndex) { - var lastMeasuredCellSizeAndPosition = this.getSizeAndPositionOfLastMeasuredCell(); - var _offset = lastMeasuredCellSizeAndPosition.offset + lastMeasuredCellSizeAndPosition.size; + /** + * Set the width of the inner scrollable container to 'auto'. + * This is useful for single-column Grids to ensure that the column doesn't extend below a vertical scrollbar. + */ + autoContainerWidth: _react.PropTypes.bool, - for (var i = this._lastMeasuredIndex + 1; i <= index; i++) { - var _size = this._cellSizeGetter({ index: i }); + /** + * Removes fixed height from the scrollingContainer so that the total height + * of rows can stretch the window. Intended for use with WindowScroller + */ + autoHeight: _react.PropTypes.bool, - if (_size == null || isNaN(_size)) { - throw Error('Invalid size returned for cell ' + i + ' of value ' + _size); - } + /** Optional custom CSS class for individual cells */ + cellClassName: _react.PropTypes.oneOfType([_react.PropTypes.string, _react.PropTypes.func]), - this._cellSizeAndPositionData[i] = { - offset: _offset, - size: _size - }; + /** Optional custom styles for individual cells */ + cellStyle: _react.PropTypes.oneOfType([_react.PropTypes.object, _react.PropTypes.func]), - _offset += _size; - } + /** + * Responsible for rendering a cell given an row and column index. + * Should implement the following interface: ({ columnIndex: number, rowIndex: number }): PropTypes.node + */ + cellRenderer: _react.PropTypes.func.isRequired, - this._lastMeasuredIndex = index; - } + /** + * Responsible for rendering a group of cells given their index ranges. + * Should implement the following interface: ({ + * cellCache: Map, + * cellRenderer: Function, + * columnSizeAndPositionManager: CellSizeAndPositionManager, + * columnStartIndex: number, + * columnStopIndex: number, + * isScrolling: boolean, + * rowSizeAndPositionManager: CellSizeAndPositionManager, + * rowStartIndex: number, + * rowStopIndex: number, + * scrollLeft: number, + * scrollTop: number + * }): Array + */ + cellRangeRenderer: _react.PropTypes.func.isRequired, - return this._cellSizeAndPositionData[index]; - } - }, { - key: 'getSizeAndPositionOfLastMeasuredCell', - value: function getSizeAndPositionOfLastMeasuredCell() { - return this._lastMeasuredIndex >= 0 ? this._cellSizeAndPositionData[this._lastMeasuredIndex] : { - offset: 0, - size: 0 - }; - } + /** + * Optional custom CSS class name to attach to root Grid element. + */ + className: _react.PropTypes.string, - /** - * Total size of all cells being measured. - * This value will be completedly estimated initially. - * As cells as measured the estimate will be updated. - */ + /** + * Number of columns in grid. + */ + columnCount: _react.PropTypes.number.isRequired, - }, { - key: 'getTotalSize', - value: function getTotalSize() { - var lastMeasuredCellSizeAndPosition = this.getSizeAndPositionOfLastMeasuredCell(); + /** + * Either a fixed column width (number) or a function that returns the width of a column given its index. + * Should implement the following interface: (index: number): number + */ + columnWidth: _react.PropTypes.oneOfType([_react.PropTypes.number, _react.PropTypes.func]).isRequired, - return lastMeasuredCellSizeAndPosition.offset + lastMeasuredCellSizeAndPosition.size + (this._cellCount - this._lastMeasuredIndex - 1) * this._estimatedCellSize; - } + /** + * Used to estimate the total width of a Grid before all of its columns have actually been measured. + * The estimated total width is adjusted as columns are rendered. + */ + estimatedColumnSize: _react.PropTypes.number.isRequired, - /** - * Determines a new offset that ensures a certain cell is visible, given the current offset. - * If the cell is already visible then the current offset will be returned. - * If the current offset is too great or small, it will be adjusted just enough to ensure the specified index is visible. - * - * @param align Desired alignment within container; one of "auto" (default), "start", or "end" - * @param containerSize Size (width or height) of the container viewport - * @param currentOffset Container's current (x or y) offset - * @param totalSize Total size (width or height) of all cells - * @return Offset to use to ensure the specified cell is visible - */ + /** + * Used to estimate the total height of a Grid before all of its rows have actually been measured. + * The estimated total height is adjusted as rows are rendered. + */ + estimatedRowSize: _react.PropTypes.number.isRequired, - }, { - key: 'getUpdatedOffsetForIndex', - value: function getUpdatedOffsetForIndex(_ref3) { - var _ref3$align = _ref3.align; - var align = _ref3$align === undefined ? 'auto' : _ref3$align; - var containerSize = _ref3.containerSize; - var currentOffset = _ref3.currentOffset; - var targetIndex = _ref3.targetIndex; + /** + * Height of Grid; this property determines the number of visible (vs virtualized) rows. + */ + height: _react.PropTypes.number.isRequired, - var datum = this.getSizeAndPositionOfCell(targetIndex); - var maxOffset = datum.offset; - var minOffset = maxOffset - containerSize + datum.size; + /** + * Optional renderer to be used in place of rows when either :rowCount or :columnCount is 0. + */ + noContentRenderer: _react.PropTypes.func.isRequired, - var idealOffset = void 0; + /** + * Callback invoked whenever the scroll offset changes within the inner scrollable region. + * This callback can be used to sync scrolling between lists, tables, or grids. + * ({ clientHeight, clientWidth, scrollHeight, scrollLeft, scrollTop, scrollWidth }): void + */ + onScroll: _react.PropTypes.func.isRequired, - switch (align) { - case 'start': - idealOffset = maxOffset; - break; - case 'end': - idealOffset = minOffset; - break; - case 'center': - idealOffset = maxOffset - (containerSize - datum.size) / 2; - break; - default: - idealOffset = Math.max(minOffset, Math.min(maxOffset, currentOffset)); - break; - } + /** + * Callback invoked with information about the section of the Grid that was just rendered. + * ({ columnStartIndex, columnStopIndex, rowStartIndex, rowStopIndex }): void + */ + onSectionRendered: _react.PropTypes.func.isRequired, - var totalSize = this.getTotalSize(); + /** + * Number of columns to render before/after the visible section of the grid. + * These columns can help for smoother scrolling on touch devices or browsers that send scroll events infrequently. + */ + overscanColumnCount: _react.PropTypes.number.isRequired, - return Math.max(0, Math.min(totalSize - containerSize, idealOffset)); - } - }, { - key: 'getVisibleCellRange', - value: function getVisibleCellRange(_ref4) { - var containerSize = _ref4.containerSize; - var offset = _ref4.offset; + /** + * Number of rows to render above/below the visible section of the grid. + * These rows can help for smoother scrolling on touch devices or browsers that send scroll events infrequently. + */ + overscanRowCount: _react.PropTypes.number.isRequired, - var totalSize = this.getTotalSize(); + /** + * Either a fixed row height (number) or a function that returns the height of a row given its index. + * Should implement the following interface: ({ index: number }): number + */ + rowHeight: _react.PropTypes.oneOfType([_react.PropTypes.number, _react.PropTypes.func]).isRequired, - if (totalSize === 0) { - return {}; - } + /** + * Number of rows in grid. + */ + rowCount: _react.PropTypes.number.isRequired, - var maxOffset = offset + containerSize; - var start = this._findNearestCell(offset); + /** Wait this amount of time after the last scroll event before resetting Grid `pointer-events`. */ + scrollingResetTimeInterval: _react.PropTypes.number, - var datum = this.getSizeAndPositionOfCell(start); - offset = datum.offset + datum.size; + /** Horizontal offset. */ + scrollLeft: _react.PropTypes.number, - var stop = start; + /** + * Controls scroll-to-cell behavior of the Grid. + * The default ("auto") scrolls the least amount possible to ensure that the specified cell is fully visible. + * Use "start" to align cells to the top/left of the Grid and "end" to align bottom/right. + */ + scrollToAlignment: _react.PropTypes.oneOf(['auto', 'end', 'start', 'center']).isRequired, - while (offset < maxOffset && stop < this._cellCount - 1) { - stop++; + /** + * Column index to ensure visible (by forcefully scrolling if necessary) + */ + scrollToColumn: _react.PropTypes.number, - offset += this.getSizeAndPositionOfCell(stop).size; - } + /** Vertical offset. */ + scrollTop: _react.PropTypes.number, - return { - start: start, - stop: stop - }; - } + /** + * Row index to ensure visible (by forcefully scrolling if necessary) + */ + scrollToRow: _react.PropTypes.number, - /** - * Clear all cached values for cells after the specified index. - * This method should be called for any cell that has changed its size. - * It will not immediately perform any calculations; they'll be performed the next time getSizeAndPositionOfCell() is called. - */ + /** Optional inline style */ + style: _react.PropTypes.object, - }, { - key: 'resetCell', - value: function resetCell(index) { - this._lastMeasuredIndex = Math.min(this._lastMeasuredIndex, index - 1); - } - }, { - key: '_binarySearch', - value: function _binarySearch(_ref5) { - var high = _ref5.high; - var low = _ref5.low; - var offset = _ref5.offset; + /** Tab index for focus */ + tabIndex: _react.PropTypes.number, - var middle = void 0; - var currentOffset = void 0; + /** + * Width of Grid; this property determines the number of visible (vs virtualized) columns. + */ + width: _react.PropTypes.number.isRequired +}; +Grid.defaultProps = { + 'aria-label': 'grid', + cellStyle: {}, + cellRangeRenderer: _defaultCellRangeRenderer2.default, + estimatedColumnSize: 100, + estimatedRowSize: 30, + noContentRenderer: function noContentRenderer() { + return null; + }, + onScroll: function onScroll() { + return null; + }, + onSectionRendered: function onSectionRendered() { + return null; + }, + overscanColumnCount: 0, + overscanRowCount: 10, + scrollingResetTimeInterval: DEFAULT_SCROLLING_RESET_TIME_INTERVAL, + scrollToAlignment: 'auto', + style: {}, + tabIndex: 0 +}; +exports.default = Grid; +},{"../utils/createCallbackMemoizer":76,"./defaultCellRangeRenderer":59,"./utils/ScalingCellSizeAndPositionManager":62,"./utils/calculateSizeAndPositionDataAndUpdateScrollOffset":63,"./utils/getOverscanIndices":64,"./utils/updateScrollIndexHelper":65,"classnames":undefined,"dom-helpers/util/scrollbarSize":80,"raf":81,"react":undefined,"react-addons-shallow-compare":18}],59:[function(require,module,exports){ +'use strict'; - while (low <= high) { - middle = low + Math.floor((high - low) / 2); - currentOffset = this.getSizeAndPositionOfCell(middle).offset; +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - if (currentOffset === offset) { - return middle; - } else if (currentOffset < offset) { - low = middle + 1; - } else if (currentOffset > offset) { - high = middle - 1; - } - } +exports.default = defaultCellRangeRenderer; - if (low > 0) { - return low - 1; - } - } - }, { - key: '_exponentialSearch', - value: function _exponentialSearch(_ref6) { - var index = _ref6.index; - var offset = _ref6.offset; +var _react = require('react'); - var interval = 1; +var _react2 = _interopRequireDefault(_react); - while (index < this._cellCount && this.getSizeAndPositionOfCell(index).offset < offset) { - index += interval; - interval *= 2; - } +var _classnames = require('classnames'); - return this._binarySearch({ - high: Math.min(index, this._cellCount - 1), - low: Math.floor(index / 2), - offset: offset - }); - } +var _classnames2 = _interopRequireDefault(_classnames); - /** - * Searches for the cell (index) nearest the specified offset. - * - * If no exact match is found the next lowest cell index will be returned. - * This allows partially visible cells (with offsets just before/above the fold) to be visible. - */ +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - }, { - key: '_findNearestCell', - value: function _findNearestCell(offset) { - if (isNaN(offset)) { - throw Error('Invalid offset ' + offset + ' specified'); - } +/** + * Default implementation of cellRangeRenderer used by Grid. + * This renderer supports cell-caching while the user is scrolling. + */ +function defaultCellRangeRenderer(_ref) { + var cellCache = _ref.cellCache; + var cellClassName = _ref.cellClassName; + var cellRenderer = _ref.cellRenderer; + var cellStyle = _ref.cellStyle; + var columnSizeAndPositionManager = _ref.columnSizeAndPositionManager; + var columnStartIndex = _ref.columnStartIndex; + var columnStopIndex = _ref.columnStopIndex; + var horizontalOffsetAdjustment = _ref.horizontalOffsetAdjustment; + var isScrolling = _ref.isScrolling; + var rowSizeAndPositionManager = _ref.rowSizeAndPositionManager; + var rowStartIndex = _ref.rowStartIndex; + var rowStopIndex = _ref.rowStopIndex; + var scrollLeft = _ref.scrollLeft; + var scrollTop = _ref.scrollTop; + var verticalOffsetAdjustment = _ref.verticalOffsetAdjustment; - // Our search algorithms find the nearest match at or below the specified offset. - // So make sure the offset is at least 0 or no match will be found. - offset = Math.max(0, offset); + var renderedCells = []; - var lastMeasuredCellSizeAndPosition = this.getSizeAndPositionOfLastMeasuredCell(); - var lastMeasuredIndex = Math.max(0, this._lastMeasuredIndex); + for (var rowIndex = rowStartIndex; rowIndex <= rowStopIndex; rowIndex++) { + var rowDatum = rowSizeAndPositionManager.getSizeAndPositionOfCell(rowIndex); - if (lastMeasuredCellSizeAndPosition.offset >= offset) { - // If we've already measured cells within this range just use a binary search as it's faster. - return this._binarySearch({ - high: lastMeasuredIndex, - low: 0, - offset: offset - }); + for (var columnIndex = columnStartIndex; columnIndex <= columnStopIndex; columnIndex++) { + var columnDatum = columnSizeAndPositionManager.getSizeAndPositionOfCell(columnIndex); + var key = rowIndex + '-' + columnIndex; + var cellStyleObject = cellStyle({ rowIndex: rowIndex, columnIndex: columnIndex }); + var renderedCell = void 0; + + // Avoid re-creating cells while scrolling. + // This can lead to the same cell being created many times and can cause performance issues for "heavy" cells. + // If a scroll is in progress- cache and reuse cells. + // This cache will be thrown away once scrolling complets. + if (isScrolling) { + if (!cellCache[key]) { + cellCache[key] = cellRenderer({ + columnIndex: columnIndex, + isScrolling: isScrolling, + rowIndex: rowIndex + }); + } + renderedCell = cellCache[key]; + // If the user is no longer scrolling, don't cache cells. + // This makes dynamic cell content difficult for users and would also lead to a heavier memory footprint. } else { - // If we haven't yet measured this high, fallback to an exponential search with an inner binary search. - // The exponential search avoids pre-computing sizes for the full set of cells as a binary search would. - // The overall complexity for this approach is O(log n). - return this._exponentialSearch({ - index: lastMeasuredIndex, - offset: offset + renderedCell = cellRenderer({ + columnIndex: columnIndex, + isScrolling: isScrolling, + rowIndex: rowIndex }); } - } - }]); - return CellSizeAndPositionManager; -}(); + if (renderedCell == null || renderedCell === false) { + continue; + } -exports.default = CellSizeAndPositionManager; -},{}],64:[function(require,module,exports){ + var className = cellClassName({ columnIndex: columnIndex, rowIndex: rowIndex }); + + var child = _react2.default.createElement( + 'div', + { + key: key, + className: (0, _classnames2.default)('Grid__cell', className), + style: _extends({ + height: rowDatum.size, + left: columnDatum.offset + horizontalOffsetAdjustment, + top: rowDatum.offset + verticalOffsetAdjustment, + width: columnDatum.size + }, cellStyleObject) + }, + renderedCell + ); + + renderedCells.push(child); + } + } + + return renderedCells; +} +},{"classnames":undefined,"react":undefined}],60:[function(require,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); -exports.DEFAULT_MAX_SCROLL_SIZE = undefined; +exports.defaultCellRangeRenderer = exports.Grid = exports.default = undefined; -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); +var _Grid2 = require('./Grid'); -var _CellSizeAndPositionManager = require('./CellSizeAndPositionManager'); +var _Grid3 = _interopRequireDefault(_Grid2); -var _CellSizeAndPositionManager2 = _interopRequireDefault(_CellSizeAndPositionManager); +var _defaultCellRangeRenderer2 = require('./defaultCellRangeRenderer'); + +var _defaultCellRangeRenderer3 = _interopRequireDefault(_defaultCellRangeRenderer2); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } +exports.default = _Grid3.default; +exports.Grid = _Grid3.default; +exports.defaultCellRangeRenderer = _defaultCellRangeRenderer3.default; +},{"./Grid":58,"./defaultCellRangeRenderer":59}],61:[function(require,module,exports){ +'use strict'; -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } +Object.defineProperty(exports, "__esModule", { + value: true +}); -/** - * Browsers have scroll offset limitations (eg Chrome stops scrolling at ~33.5M pixels where as Edge tops out at ~1.5M pixels). - * After a certain position, the browser won't allow the user to scroll further (even via JavaScript scroll offset adjustments). - * This util picks a lower ceiling for max size and artificially adjusts positions within to make it transparent for users. - */ -var DEFAULT_MAX_SCROLL_SIZE = exports.DEFAULT_MAX_SCROLL_SIZE = 1500000; +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /** - * Extends CellSizeAndPositionManager and adds scaling behavior for lists that are too large to fit within a browser's native limits. + * Just-in-time calculates and caches size and position information for a collection of cells. */ +var CellSizeAndPositionManager = function () { + function CellSizeAndPositionManager(_ref) { + var cellCount = _ref.cellCount; + var cellSizeGetter = _ref.cellSizeGetter; + var estimatedCellSize = _ref.estimatedCellSize; -var ScalingCellSizeAndPositionManager = function () { - function ScalingCellSizeAndPositionManager(_ref) { - var _ref$maxScrollSize = _ref.maxScrollSize; - var maxScrollSize = _ref$maxScrollSize === undefined ? DEFAULT_MAX_SCROLL_SIZE : _ref$maxScrollSize; + _classCallCheck(this, CellSizeAndPositionManager); - var params = _objectWithoutProperties(_ref, ['maxScrollSize']); + this._cellSizeGetter = cellSizeGetter; + this._cellCount = cellCount; + this._estimatedCellSize = estimatedCellSize; - _classCallCheck(this, ScalingCellSizeAndPositionManager); + // Cache of size and position data for cells, mapped by cell index. + // Note that invalid values may exist in this map so only rely on cells up to this._lastMeasuredIndex + this._cellSizeAndPositionData = {}; - // Favor composition over inheritance to simplify IE10 support - this._cellSizeAndPositionManager = new _CellSizeAndPositionManager2.default(params); - this._maxScrollSize = maxScrollSize; + // Measurements for cells up to this index can be trusted; cells afterward should be estimated. + this._lastMeasuredIndex = -1; } - _createClass(ScalingCellSizeAndPositionManager, [{ + _createClass(CellSizeAndPositionManager, [{ key: 'configure', - value: function configure(params) { - this._cellSizeAndPositionManager.configure(params); + value: function configure(_ref2) { + var cellCount = _ref2.cellCount; + var estimatedCellSize = _ref2.estimatedCellSize; + + this._cellCount = cellCount; + this._estimatedCellSize = estimatedCellSize; } }, { key: 'getCellCount', value: function getCellCount() { - return this._cellSizeAndPositionManager.getCellCount(); + return this._cellCount; } }, { key: 'getEstimatedCellSize', value: function getEstimatedCellSize() { - return this._cellSizeAndPositionManager.getEstimatedCellSize(); + return this._estimatedCellSize; } }, { key: 'getLastMeasuredIndex', value: function getLastMeasuredIndex() { - return this._cellSizeAndPositionManager.getLastMeasuredIndex(); + return this._lastMeasuredIndex; } /** - * Number of pixels a cell at the given position (offset) should be shifted in order to fit within the scaled container. - * The offset passed to this function is scalled (safe) as well. + * This method returns the size and position for the cell at the specified index. + * It just-in-time calculates (or used cached values) for cells leading up to the index. */ - }, { - key: 'getOffsetAdjustment', - value: function getOffsetAdjustment(_ref2) { - var containerSize = _ref2.containerSize; - var offset = _ref2.offset; - - var totalSize = this._cellSizeAndPositionManager.getTotalSize(); - var safeTotalSize = this.getTotalSize(); - var offsetPercentage = this._getOffsetPercentage({ - containerSize: containerSize, - offset: offset, - totalSize: safeTotalSize - }); - - return Math.round(offsetPercentage * (safeTotalSize - totalSize)); - } }, { key: 'getSizeAndPositionOfCell', value: function getSizeAndPositionOfCell(index) { - return this._cellSizeAndPositionManager.getSizeAndPositionOfCell(index); + if (index < 0 || index >= this._cellCount) { + throw Error('Requested index ' + index + ' is outside of range 0..' + this._cellCount); + } + + if (index > this._lastMeasuredIndex) { + var lastMeasuredCellSizeAndPosition = this.getSizeAndPositionOfLastMeasuredCell(); + var _offset = lastMeasuredCellSizeAndPosition.offset + lastMeasuredCellSizeAndPosition.size; + + for (var i = this._lastMeasuredIndex + 1; i <= index; i++) { + var _size = this._cellSizeGetter({ index: i }); + + if (_size == null || isNaN(_size)) { + throw Error('Invalid size returned for cell ' + i + ' of value ' + _size); + } + + this._cellSizeAndPositionData[i] = { + offset: _offset, + size: _size + }; + + _offset += _size; + } + + this._lastMeasuredIndex = index; + } + + return this._cellSizeAndPositionData[index]; } }, { key: 'getSizeAndPositionOfLastMeasuredCell', value: function getSizeAndPositionOfLastMeasuredCell() { - return this._cellSizeAndPositionManager.getSizeAndPositionOfLastMeasuredCell(); + return this._lastMeasuredIndex >= 0 ? this._cellSizeAndPositionData[this._lastMeasuredIndex] : { + offset: 0, + size: 0 + }; } - /** See CellSizeAndPositionManager#getTotalSize */ + /** + * Total size of all cells being measured. + * This value will be completedly estimated initially. + * As cells as measured the estimate will be updated. + */ }, { key: 'getTotalSize', value: function getTotalSize() { - return Math.min(this._maxScrollSize, this._cellSizeAndPositionManager.getTotalSize()); + var lastMeasuredCellSizeAndPosition = this.getSizeAndPositionOfLastMeasuredCell(); + + return lastMeasuredCellSizeAndPosition.offset + lastMeasuredCellSizeAndPosition.size + (this._cellCount - this._lastMeasuredIndex - 1) * this._estimatedCellSize; } - /** See CellSizeAndPositionManager#getUpdatedOffsetForIndex */ + /** + * Determines a new offset that ensures a certain cell is visible, given the current offset. + * If the cell is already visible then the current offset will be returned. + * If the current offset is too great or small, it will be adjusted just enough to ensure the specified index is visible. + * + * @param align Desired alignment within container; one of "auto" (default), "start", or "end" + * @param containerSize Size (width or height) of the container viewport + * @param currentOffset Container's current (x or y) offset + * @param totalSize Total size (width or height) of all cells + * @return Offset to use to ensure the specified cell is visible + */ }, { key: 'getUpdatedOffsetForIndex', @@ -7799,701 +7891,553 @@ var ScalingCellSizeAndPositionManager = function () { var containerSize = _ref3.containerSize; var currentOffset = _ref3.currentOffset; var targetIndex = _ref3.targetIndex; - var totalSize = _ref3.totalSize; - currentOffset = this._safeOffsetToOffset({ - containerSize: containerSize, - offset: currentOffset - }); + var datum = this.getSizeAndPositionOfCell(targetIndex); + var maxOffset = datum.offset; + var minOffset = maxOffset - containerSize + datum.size; - var offset = this._cellSizeAndPositionManager.getUpdatedOffsetForIndex({ - align: align, - containerSize: containerSize, - currentOffset: currentOffset, - targetIndex: targetIndex, - totalSize: totalSize - }); + var idealOffset = void 0; - return this._offsetToSafeOffset({ - containerSize: containerSize, - offset: offset - }); - } + switch (align) { + case 'start': + idealOffset = maxOffset; + break; + case 'end': + idealOffset = minOffset; + break; + case 'center': + idealOffset = maxOffset - (containerSize - datum.size) / 2; + break; + default: + idealOffset = Math.max(minOffset, Math.min(maxOffset, currentOffset)); + break; + } - /** See CellSizeAndPositionManager#getVisibleCellRange */ + var totalSize = this.getTotalSize(); + return Math.max(0, Math.min(totalSize - containerSize, idealOffset)); + } }, { key: 'getVisibleCellRange', value: function getVisibleCellRange(_ref4) { var containerSize = _ref4.containerSize; var offset = _ref4.offset; - offset = this._safeOffsetToOffset({ - containerSize: containerSize, - offset: offset - }); + var totalSize = this.getTotalSize(); - return this._cellSizeAndPositionManager.getVisibleCellRange({ - containerSize: containerSize, - offset: offset - }); + if (totalSize === 0) { + return {}; + } + + var maxOffset = offset + containerSize; + var start = this._findNearestCell(offset); + + var datum = this.getSizeAndPositionOfCell(start); + offset = datum.offset + datum.size; + + var stop = start; + + while (offset < maxOffset && stop < this._cellCount - 1) { + stop++; + + offset += this.getSizeAndPositionOfCell(stop).size; + } + + return { + start: start, + stop: stop + }; } + + /** + * Clear all cached values for cells after the specified index. + * This method should be called for any cell that has changed its size. + * It will not immediately perform any calculations; they'll be performed the next time getSizeAndPositionOfCell() is called. + */ + }, { key: 'resetCell', value: function resetCell(index) { - this._cellSizeAndPositionManager.resetCell(index); + this._lastMeasuredIndex = Math.min(this._lastMeasuredIndex, index - 1); } }, { - key: '_getOffsetPercentage', - value: function _getOffsetPercentage(_ref5) { - var containerSize = _ref5.containerSize; + key: '_binarySearch', + value: function _binarySearch(_ref5) { + var high = _ref5.high; + var low = _ref5.low; var offset = _ref5.offset; - var totalSize = _ref5.totalSize; - return totalSize <= containerSize ? 0 : offset / (totalSize - containerSize); - } - }, { - key: '_offsetToSafeOffset', - value: function _offsetToSafeOffset(_ref6) { - var containerSize = _ref6.containerSize; - var offset = _ref6.offset; + var middle = void 0; + var currentOffset = void 0; - var totalSize = this._cellSizeAndPositionManager.getTotalSize(); - var safeTotalSize = this.getTotalSize(); + while (low <= high) { + middle = low + Math.floor((high - low) / 2); + currentOffset = this.getSizeAndPositionOfCell(middle).offset; - if (totalSize === safeTotalSize) { - return offset; - } else { - var offsetPercentage = this._getOffsetPercentage({ - containerSize: containerSize, - offset: offset, - totalSize: totalSize - }); + if (currentOffset === offset) { + return middle; + } else if (currentOffset < offset) { + low = middle + 1; + } else if (currentOffset > offset) { + high = middle - 1; + } + } - return Math.round(offsetPercentage * (safeTotalSize - containerSize)); + if (low > 0) { + return low - 1; } } }, { - key: '_safeOffsetToOffset', - value: function _safeOffsetToOffset(_ref7) { - var containerSize = _ref7.containerSize; - var offset = _ref7.offset; - - var totalSize = this._cellSizeAndPositionManager.getTotalSize(); - var safeTotalSize = this.getTotalSize(); + key: '_exponentialSearch', + value: function _exponentialSearch(_ref6) { + var index = _ref6.index; + var offset = _ref6.offset; - if (totalSize === safeTotalSize) { - return offset; - } else { - var offsetPercentage = this._getOffsetPercentage({ - containerSize: containerSize, - offset: offset, - totalSize: safeTotalSize - }); + var interval = 1; - return Math.round(offsetPercentage * (totalSize - containerSize)); + while (index < this._cellCount && this.getSizeAndPositionOfCell(index).offset < offset) { + index += interval; + interval *= 2; } - } - }]); - - return ScalingCellSizeAndPositionManager; -}(); - -exports.default = ScalingCellSizeAndPositionManager; -},{"./CellSizeAndPositionManager":63}],65:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.default = calculateSizeAndPositionDataAndUpdateScrollOffset; -/** - * Helper method that determines when to recalculate row or column metadata. - * - * @param cellCount Number of rows or columns in the current axis - * @param cellsSize Width or height of cells for the current axis - * @param computeMetadataCallback Method to invoke if cell metadata should be recalculated - * @param computeMetadataCallbackProps Parameters to pass to :computeMetadataCallback - * @param nextCellsCount Newly updated number of rows or columns in the current axis - * @param nextCellsSize Newly updated width or height of cells for the current axis - * @param nextScrollToIndex Newly updated scroll-to-index - * @param scrollToIndex Scroll-to-index - * @param updateScrollOffsetForScrollToIndex Callback to invoke if the scroll position should be recalculated - */ -function calculateSizeAndPositionDataAndUpdateScrollOffset(_ref) { - var cellCount = _ref.cellCount; - var cellSize = _ref.cellSize; - var computeMetadataCallback = _ref.computeMetadataCallback; - var computeMetadataCallbackProps = _ref.computeMetadataCallbackProps; - var nextCellsCount = _ref.nextCellsCount; - var nextCellSize = _ref.nextCellSize; - var nextScrollToIndex = _ref.nextScrollToIndex; - var scrollToIndex = _ref.scrollToIndex; - var updateScrollOffsetForScrollToIndex = _ref.updateScrollOffsetForScrollToIndex; - - // Don't compare cell sizes if they are functions because inline functions would cause infinite loops. - // In that event users should use the manual recompute methods to inform of changes. - if (cellCount !== nextCellsCount || (typeof cellSize === 'number' || typeof nextCellSize === 'number') && cellSize !== nextCellSize) { - computeMetadataCallback(computeMetadataCallbackProps); - - // Updated cell metadata may have hidden the previous scrolled-to item. - // In this case we should also update the scrollTop to ensure it stays visible. - if (scrollToIndex >= 0 && scrollToIndex === nextScrollToIndex) { - updateScrollOffsetForScrollToIndex(); - } - } -} -},{}],66:[function(require,module,exports){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.default = getOverscanIndices; -var SCROLL_DIRECTION_BACKWARD = exports.SCROLL_DIRECTION_BACKWARD = -1; -var SCROLL_DIRECTION_FIXED = exports.SCROLL_DIRECTION_FIXED = 0; -var SCROLL_DIRECTION_FORWARD = exports.SCROLL_DIRECTION_FORWARD = 1; -/** - * Calculates the number of cells to overscan before and after a specified range. - * This function ensures that overscanning doesn't exceed the available cells. - * - * @param cellCount Number of rows or columns in the current axis - * @param scrollDirection One of SCROLL_DIRECTION_BACKWARD - * @param overscanCellsCount Maximum number of cells to over-render in either direction - * @param startIndex Begin of range of visible cells - * @param stopIndex End of range of visible cells - */ -function getOverscanIndices(_ref) { - var cellCount = _ref.cellCount; - var overscanCellsCount = _ref.overscanCellsCount; - var scrollDirection = _ref.scrollDirection; - var startIndex = _ref.startIndex; - var stopIndex = _ref.stopIndex; + return this._binarySearch({ + high: Math.min(index, this._cellCount - 1), + low: Math.floor(index / 2), + offset: offset + }); + } - var overscanStartIndex = void 0; - var overscanStopIndex = void 0; + /** + * Searches for the cell (index) nearest the specified offset. + * + * If no exact match is found the next lowest cell index will be returned. + * This allows partially visible cells (with offsets just before/above the fold) to be visible. + */ - if (scrollDirection === SCROLL_DIRECTION_FORWARD) { - overscanStartIndex = startIndex; - overscanStopIndex = stopIndex + overscanCellsCount * 2; - } else if (scrollDirection === SCROLL_DIRECTION_BACKWARD) { - overscanStartIndex = startIndex - overscanCellsCount * 2; - overscanStopIndex = stopIndex; - } else { - overscanStartIndex = startIndex - overscanCellsCount; - overscanStopIndex = stopIndex + overscanCellsCount; - } + }, { + key: '_findNearestCell', + value: function _findNearestCell(offset) { + if (isNaN(offset)) { + throw Error('Invalid offset ' + offset + ' specified'); + } - return { - overscanStartIndex: Math.max(0, overscanStartIndex), - overscanStopIndex: Math.min(cellCount - 1, overscanStopIndex) - }; -} -},{}],67:[function(require,module,exports){ -'use strict'; + // Our search algorithms find the nearest match at or below the specified offset. + // So make sure the offset is at least 0 or no match will be found. + offset = Math.max(0, offset); -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.default = updateScrollIndexHelper; -/** - * Helper function that determines when to update scroll offsets to ensure that a scroll-to-index remains visible. - * This function also ensures that the scroll ofset isn't past the last column/row of cells. - * - * @param cellsSize Width or height of cells for the current axis - * @param cellSizeAndPositionManager Manages size and position metadata of cells - * @param previousCellsCount Previous number of rows or columns - * @param previousCellsSize Previous width or height of cells - * @param previousScrollToIndex Previous scroll-to-index - * @param previousSize Previous width or height of the virtualized container - * @param scrollOffset Current scrollLeft or scrollTop - * @param scrollToIndex Scroll-to-index - * @param size Width or height of the virtualized container - * @param updateScrollIndexCallback Callback to invoke with an scroll-to-index value - */ -function updateScrollIndexHelper(_ref) { - var cellSize = _ref.cellSize; - var cellSizeAndPositionManager = _ref.cellSizeAndPositionManager; - var previousCellsCount = _ref.previousCellsCount; - var previousCellSize = _ref.previousCellSize; - var previousScrollToAlignment = _ref.previousScrollToAlignment; - var previousScrollToIndex = _ref.previousScrollToIndex; - var previousSize = _ref.previousSize; - var scrollOffset = _ref.scrollOffset; - var scrollToAlignment = _ref.scrollToAlignment; - var scrollToIndex = _ref.scrollToIndex; - var size = _ref.size; - var updateScrollIndexCallback = _ref.updateScrollIndexCallback; + var lastMeasuredCellSizeAndPosition = this.getSizeAndPositionOfLastMeasuredCell(); + var lastMeasuredIndex = Math.max(0, this._lastMeasuredIndex); - var cellCount = cellSizeAndPositionManager.getCellCount(); - var hasScrollToIndex = scrollToIndex >= 0 && scrollToIndex < cellCount; - var sizeHasChanged = size !== previousSize || !previousCellSize || typeof cellSize === 'number' && cellSize !== previousCellSize; + if (lastMeasuredCellSizeAndPosition.offset >= offset) { + // If we've already measured cells within this range just use a binary search as it's faster. + return this._binarySearch({ + high: lastMeasuredIndex, + low: 0, + offset: offset + }); + } else { + // If we haven't yet measured this high, fallback to an exponential search with an inner binary search. + // The exponential search avoids pre-computing sizes for the full set of cells as a binary search would. + // The overall complexity for this approach is O(log n). + return this._exponentialSearch({ + index: lastMeasuredIndex, + offset: offset + }); + } + } + }]); - // If we have a new scroll target OR if height/row-height has changed, - // We should ensure that the scroll target is visible. - if (hasScrollToIndex && (sizeHasChanged || scrollToAlignment !== previousScrollToAlignment || scrollToIndex !== previousScrollToIndex)) { - updateScrollIndexCallback(scrollToIndex); + return CellSizeAndPositionManager; +}(); - // If we don't have a selected item but list size or number of children have decreased, - // Make sure we aren't scrolled too far past the current content. - } else if (!hasScrollToIndex && cellCount > 0 && (size < previousSize || cellCount < previousCellsCount)) { - // We need to ensure that the current scroll offset is still within the collection's range. - // To do this, we don't need to measure everything; CellMeasurer would perform poorly. - // Just check to make sure we're still okay. - // Only adjust the scroll position if we've scrolled below the last set of rows. - if (scrollOffset > cellSizeAndPositionManager.getTotalSize() - size) { - updateScrollIndexCallback(cellCount - 1); - } - } -} -},{}],68:[function(require,module,exports){ +exports.default = CellSizeAndPositionManager; +},{}],62:[function(require,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); +exports.DEFAULT_MAX_SCROLL_SIZE = undefined; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); -exports.isRangeVisible = isRangeVisible; -exports.scanForUnloadedRanges = scanForUnloadedRanges; -exports.forceUpdateReactVirtualizedComponent = forceUpdateReactVirtualizedComponent; - -var _react = require('react'); - -var _reactAddonsShallowCompare = require('react-addons-shallow-compare'); - -var _reactAddonsShallowCompare2 = _interopRequireDefault(_reactAddonsShallowCompare); - -var _createCallbackMemoizer = require('../utils/createCallbackMemoizer'); +var _CellSizeAndPositionManager = require('./CellSizeAndPositionManager'); -var _createCallbackMemoizer2 = _interopRequireDefault(_createCallbackMemoizer); +var _CellSizeAndPositionManager2 = _interopRequireDefault(_CellSizeAndPositionManager); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } +function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } +/** + * Browsers have scroll offset limitations (eg Chrome stops scrolling at ~33.5M pixels where as Edge tops out at ~1.5M pixels). + * After a certain position, the browser won't allow the user to scroll further (even via JavaScript scroll offset adjustments). + * This util picks a lower ceiling for max size and artificially adjusts positions within to make it transparent for users. + */ +var DEFAULT_MAX_SCROLL_SIZE = exports.DEFAULT_MAX_SCROLL_SIZE = 1500000; /** - * Higher-order component that manages lazy-loading for "infinite" data. - * This component decorates a virtual component and just-in-time prefetches rows as a user scrolls. - * It is intended as a convenience component; fork it if you'd like finer-grained control over data-loading. + * Extends CellSizeAndPositionManager and adds scaling behavior for lists that are too large to fit within a browser's native limits. */ -var InfiniteLoader = function (_Component) { - _inherits(InfiniteLoader, _Component); - function InfiniteLoader(props, context) { - _classCallCheck(this, InfiniteLoader); +var ScalingCellSizeAndPositionManager = function () { + function ScalingCellSizeAndPositionManager(_ref) { + var _ref$maxScrollSize = _ref.maxScrollSize; + var maxScrollSize = _ref$maxScrollSize === undefined ? DEFAULT_MAX_SCROLL_SIZE : _ref$maxScrollSize; - var _this = _possibleConstructorReturn(this, (InfiniteLoader.__proto__ || Object.getPrototypeOf(InfiniteLoader)).call(this, props, context)); + var params = _objectWithoutProperties(_ref, ['maxScrollSize']); - _this._loadMoreRowsMemoizer = (0, _createCallbackMemoizer2.default)(); + _classCallCheck(this, ScalingCellSizeAndPositionManager); - _this._onRowsRendered = _this._onRowsRendered.bind(_this); - _this._registerChild = _this._registerChild.bind(_this); - return _this; + // Favor composition over inheritance to simplify IE10 support + this._cellSizeAndPositionManager = new _CellSizeAndPositionManager2.default(params); + this._maxScrollSize = maxScrollSize; } - _createClass(InfiniteLoader, [{ - key: 'render', - value: function render() { - var children = this.props.children; - - - return children({ - onRowsRendered: this._onRowsRendered, - registerChild: this._registerChild - }); + _createClass(ScalingCellSizeAndPositionManager, [{ + key: 'configure', + value: function configure(params) { + this._cellSizeAndPositionManager.configure(params); } }, { - key: 'shouldComponentUpdate', - value: function shouldComponentUpdate(nextProps, nextState) { - return (0, _reactAddonsShallowCompare2.default)(this, nextProps, nextState); + key: 'getCellCount', + value: function getCellCount() { + return this._cellSizeAndPositionManager.getCellCount(); } }, { - key: '_loadUnloadedRanges', - value: function _loadUnloadedRanges(unloadedRanges) { - var _this2 = this; - - var loadMoreRows = this.props.loadMoreRows; - - - unloadedRanges.forEach(function (unloadedRange) { - var promise = loadMoreRows(unloadedRange); - if (promise) { - promise.then(function () { - // Refresh the visible rows if any of them have just been loaded. - // Otherwise they will remain in their unloaded visual state. - if (isRangeVisible({ - lastRenderedStartIndex: _this2._lastRenderedStartIndex, - lastRenderedStopIndex: _this2._lastRenderedStopIndex, - startIndex: unloadedRange.startIndex, - stopIndex: unloadedRange.stopIndex - })) { - if (_this2._registeredChild) { - forceUpdateReactVirtualizedComponent(_this2._registeredChild); - } - } - }); - } - }); + key: 'getEstimatedCellSize', + value: function getEstimatedCellSize() { + return this._cellSizeAndPositionManager.getEstimatedCellSize(); } }, { - key: '_onRowsRendered', - value: function _onRowsRendered(_ref) { - var _this3 = this; - - var startIndex = _ref.startIndex; - var stopIndex = _ref.stopIndex; - var _props = this.props; - var isRowLoaded = _props.isRowLoaded; - var minimumBatchSize = _props.minimumBatchSize; - var rowCount = _props.rowCount; - var threshold = _props.threshold; + key: 'getLastMeasuredIndex', + value: function getLastMeasuredIndex() { + return this._cellSizeAndPositionManager.getLastMeasuredIndex(); + } + /** + * Number of pixels a cell at the given position (offset) should be shifted in order to fit within the scaled container. + * The offset passed to this function is scalled (safe) as well. + */ - this._lastRenderedStartIndex = startIndex; - this._lastRenderedStopIndex = stopIndex; + }, { + key: 'getOffsetAdjustment', + value: function getOffsetAdjustment(_ref2) { + var containerSize = _ref2.containerSize; + var offset = _ref2.offset; - var unloadedRanges = scanForUnloadedRanges({ - isRowLoaded: isRowLoaded, - minimumBatchSize: minimumBatchSize, - rowCount: rowCount, - startIndex: Math.max(0, startIndex - threshold), - stopIndex: Math.min(rowCount - 1, stopIndex + threshold) + var totalSize = this._cellSizeAndPositionManager.getTotalSize(); + var safeTotalSize = this.getTotalSize(); + var offsetPercentage = this._getOffsetPercentage({ + containerSize: containerSize, + offset: offset, + totalSize: safeTotalSize }); - // For memoize comparison - var squashedUnloadedRanges = unloadedRanges.reduce(function (reduced, unloadedRange) { - return reduced.concat([unloadedRange.startIndex, unloadedRange.stopIndex]); - }, []); - - this._loadMoreRowsMemoizer({ - callback: function callback() { - _this3._loadUnloadedRanges(unloadedRanges); - }, - indices: { squashedUnloadedRanges: squashedUnloadedRanges } - }); + return Math.round(offsetPercentage * (safeTotalSize - totalSize)); + } + }, { + key: 'getSizeAndPositionOfCell', + value: function getSizeAndPositionOfCell(index) { + return this._cellSizeAndPositionManager.getSizeAndPositionOfCell(index); } }, { - key: '_registerChild', - value: function _registerChild(registeredChild) { - this._registeredChild = registeredChild; + key: 'getSizeAndPositionOfLastMeasuredCell', + value: function getSizeAndPositionOfLastMeasuredCell() { + return this._cellSizeAndPositionManager.getSizeAndPositionOfLastMeasuredCell(); } - }]); - - return InfiniteLoader; -}(_react.Component); - -/** - * Determines if the specified start/stop range is visible based on the most recently rendered range. - */ - - -InfiniteLoader.propTypes = { - /** - * Function respondible for rendering a virtualized component. - * This function should implement the following signature: - * ({ onRowsRendered, registerChild }) => PropTypes.element - * - * The specified :onRowsRendered function should be passed through to the child's :onRowsRendered property. - * The :registerChild callback should be set as the virtualized component's :ref. - */ - children: _react.PropTypes.func.isRequired, - /** - * Function responsible for tracking the loaded state of each row. - * It should implement the following signature: ({ index: number }): boolean - */ - isRowLoaded: _react.PropTypes.func.isRequired, + /** See CellSizeAndPositionManager#getTotalSize */ - /** - * Callback to be invoked when more rows must be loaded. - * It should implement the following signature: ({ startIndex, stopIndex }): Promise - * The returned Promise should be resolved once row data has finished loading. - * It will be used to determine when to refresh the list with the newly-loaded data. - * This callback may be called multiple times in reaction to a single scroll event. - */ - loadMoreRows: _react.PropTypes.func.isRequired, + }, { + key: 'getTotalSize', + value: function getTotalSize() { + return Math.min(this._maxScrollSize, this._cellSizeAndPositionManager.getTotalSize()); + } - /** - * Minimum number of rows to be loaded at a time. - * This property can be used to batch requests to reduce HTTP requests. - */ - minimumBatchSize: _react.PropTypes.number.isRequired, + /** See CellSizeAndPositionManager#getUpdatedOffsetForIndex */ - /** - * Number of rows in list; can be arbitrary high number if actual number is unknown. - */ - rowCount: _react.PropTypes.number.isRequired, + }, { + key: 'getUpdatedOffsetForIndex', + value: function getUpdatedOffsetForIndex(_ref3) { + var _ref3$align = _ref3.align; + var align = _ref3$align === undefined ? 'auto' : _ref3$align; + var containerSize = _ref3.containerSize; + var currentOffset = _ref3.currentOffset; + var targetIndex = _ref3.targetIndex; + var totalSize = _ref3.totalSize; - /** - * Threshold at which to pre-fetch data. - * A threshold X means that data will start loading when a user scrolls within X rows. - * This value defaults to 15. - */ - threshold: _react.PropTypes.number.isRequired -}; -InfiniteLoader.defaultProps = { - minimumBatchSize: 10, - rowCount: 0, - threshold: 15 -}; -exports.default = InfiniteLoader; -function isRangeVisible(_ref2) { - var lastRenderedStartIndex = _ref2.lastRenderedStartIndex; - var lastRenderedStopIndex = _ref2.lastRenderedStopIndex; - var startIndex = _ref2.startIndex; - var stopIndex = _ref2.stopIndex; + currentOffset = this._safeOffsetToOffset({ + containerSize: containerSize, + offset: currentOffset + }); - return !(startIndex > lastRenderedStopIndex || stopIndex < lastRenderedStartIndex); -} + var offset = this._cellSizeAndPositionManager.getUpdatedOffsetForIndex({ + align: align, + containerSize: containerSize, + currentOffset: currentOffset, + targetIndex: targetIndex, + totalSize: totalSize + }); -/** - * Returns all of the ranges within a larger range that contain unloaded rows. - */ -function scanForUnloadedRanges(_ref3) { - var isRowLoaded = _ref3.isRowLoaded; - var minimumBatchSize = _ref3.minimumBatchSize; - var rowCount = _ref3.rowCount; - var startIndex = _ref3.startIndex; - var stopIndex = _ref3.stopIndex; + return this._offsetToSafeOffset({ + containerSize: containerSize, + offset: offset + }); + } - var unloadedRanges = []; + /** See CellSizeAndPositionManager#getVisibleCellRange */ - var rangeStartIndex = null; - var rangeStopIndex = null; + }, { + key: 'getVisibleCellRange', + value: function getVisibleCellRange(_ref4) { + var containerSize = _ref4.containerSize; + var offset = _ref4.offset; - for (var index = startIndex; index <= stopIndex; index++) { - var loaded = isRowLoaded({ index: index }); + offset = this._safeOffsetToOffset({ + containerSize: containerSize, + offset: offset + }); - if (!loaded) { - rangeStopIndex = index; - if (rangeStartIndex === null) { - rangeStartIndex = index; - } - } else if (rangeStopIndex !== null) { - unloadedRanges.push({ - startIndex: rangeStartIndex, - stopIndex: rangeStopIndex + return this._cellSizeAndPositionManager.getVisibleCellRange({ + containerSize: containerSize, + offset: offset }); + } + }, { + key: 'resetCell', + value: function resetCell(index) { + this._cellSizeAndPositionManager.resetCell(index); + } + }, { + key: '_getOffsetPercentage', + value: function _getOffsetPercentage(_ref5) { + var containerSize = _ref5.containerSize; + var offset = _ref5.offset; + var totalSize = _ref5.totalSize; - rangeStartIndex = rangeStopIndex = null; + return totalSize <= containerSize ? 0 : offset / (totalSize - containerSize); } - } + }, { + key: '_offsetToSafeOffset', + value: function _offsetToSafeOffset(_ref6) { + var containerSize = _ref6.containerSize; + var offset = _ref6.offset; - // If :rangeStopIndex is not null it means we haven't ran out of unloaded rows. - // Scan forward to try filling our :minimumBatchSize. - if (rangeStopIndex !== null) { - var potentialStopIndex = Math.min(Math.max(rangeStopIndex, rangeStartIndex + minimumBatchSize - 1), rowCount - 1); + var totalSize = this._cellSizeAndPositionManager.getTotalSize(); + var safeTotalSize = this.getTotalSize(); - for (var _index = rangeStopIndex + 1; _index <= potentialStopIndex; _index++) { - if (!isRowLoaded({ index: _index })) { - rangeStopIndex = _index; + if (totalSize === safeTotalSize) { + return offset; } else { - break; + var offsetPercentage = this._getOffsetPercentage({ + containerSize: containerSize, + offset: offset, + totalSize: totalSize + }); + + return Math.round(offsetPercentage * (safeTotalSize - containerSize)); } } + }, { + key: '_safeOffsetToOffset', + value: function _safeOffsetToOffset(_ref7) { + var containerSize = _ref7.containerSize; + var offset = _ref7.offset; - unloadedRanges.push({ - startIndex: rangeStartIndex, - stopIndex: rangeStopIndex - }); - } - - // Check to see if our first range ended prematurely. - // In this case we should scan backwards to try filling our :minimumBatchSize. - if (unloadedRanges.length) { - var firstUnloadedRange = unloadedRanges[0]; - - while (firstUnloadedRange.stopIndex - firstUnloadedRange.startIndex + 1 < minimumBatchSize && firstUnloadedRange.startIndex > 0) { - var _index2 = firstUnloadedRange.startIndex - 1; + var totalSize = this._cellSizeAndPositionManager.getTotalSize(); + var safeTotalSize = this.getTotalSize(); - if (!isRowLoaded({ index: _index2 })) { - firstUnloadedRange.startIndex = _index2; + if (totalSize === safeTotalSize) { + return offset; } else { - break; + var offsetPercentage = this._getOffsetPercentage({ + containerSize: containerSize, + offset: offset, + totalSize: safeTotalSize + }); + + return Math.round(offsetPercentage * (totalSize - containerSize)); } } - } + }]); - return unloadedRanges; -} + return ScalingCellSizeAndPositionManager; +}(); -/** - * Since RV components use shallowCompare we need to force a render (even though props haven't changed). - * However InfiniteLoader may wrap a Grid or it may wrap a FlexTable or VirtualScroll. - * In the first case the built-in React forceUpdate() method is sufficient to force a re-render, - * But in the latter cases we need to use the RV-specific forceUpdateGrid() method. - * Else the inner Grid will not be re-rendered and visuals may be stale. - */ -function forceUpdateReactVirtualizedComponent(component) { - typeof component.forceUpdateGrid === 'function' ? component.forceUpdateGrid() : component.forceUpdate(); -} -},{"../utils/createCallbackMemoizer":78,"react":undefined,"react-addons-shallow-compare":30}],69:[function(require,module,exports){ +exports.default = ScalingCellSizeAndPositionManager; +},{"./CellSizeAndPositionManager":61}],63:[function(require,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); -exports.InfiniteLoader = exports.default = undefined; - -var _InfiniteLoader2 = require('./InfiniteLoader'); - -var _InfiniteLoader3 = _interopRequireDefault(_InfiniteLoader2); +exports.default = calculateSizeAndPositionDataAndUpdateScrollOffset; +/** + * Helper method that determines when to recalculate row or column metadata. + * + * @param cellCount Number of rows or columns in the current axis + * @param cellsSize Width or height of cells for the current axis + * @param computeMetadataCallback Method to invoke if cell metadata should be recalculated + * @param computeMetadataCallbackProps Parameters to pass to :computeMetadataCallback + * @param nextCellsCount Newly updated number of rows or columns in the current axis + * @param nextCellsSize Newly updated width or height of cells for the current axis + * @param nextScrollToIndex Newly updated scroll-to-index + * @param scrollToIndex Scroll-to-index + * @param updateScrollOffsetForScrollToIndex Callback to invoke if the scroll position should be recalculated + */ +function calculateSizeAndPositionDataAndUpdateScrollOffset(_ref) { + var cellCount = _ref.cellCount; + var cellSize = _ref.cellSize; + var computeMetadataCallback = _ref.computeMetadataCallback; + var computeMetadataCallbackProps = _ref.computeMetadataCallbackProps; + var nextCellsCount = _ref.nextCellsCount; + var nextCellSize = _ref.nextCellSize; + var nextScrollToIndex = _ref.nextScrollToIndex; + var scrollToIndex = _ref.scrollToIndex; + var updateScrollOffsetForScrollToIndex = _ref.updateScrollOffsetForScrollToIndex; -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + // Don't compare cell sizes if they are functions because inline functions would cause infinite loops. + // In that event users should use the manual recompute methods to inform of changes. + if (cellCount !== nextCellsCount || (typeof cellSize === 'number' || typeof nextCellSize === 'number') && cellSize !== nextCellSize) { + computeMetadataCallback(computeMetadataCallbackProps); -exports.default = _InfiniteLoader3.default; -exports.InfiniteLoader = _InfiniteLoader3.default; -},{"./InfiniteLoader":68}],70:[function(require,module,exports){ -'use strict'; + // Updated cell metadata may have hidden the previous scrolled-to item. + // In this case we should also update the scrollTop to ensure it stays visible. + if (scrollToIndex >= 0 && scrollToIndex === nextScrollToIndex) { + updateScrollOffsetForScrollToIndex(); + } + } +} +},{}],64:[function(require,module,exports){ +"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _react = require('react'); - -var _reactAddonsShallowCompare = require('react-addons-shallow-compare'); - -var _reactAddonsShallowCompare2 = _interopRequireDefault(_reactAddonsShallowCompare); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } +exports.default = getOverscanIndices; +var SCROLL_DIRECTION_BACKWARD = exports.SCROLL_DIRECTION_BACKWARD = -1; +var SCROLL_DIRECTION_FIXED = exports.SCROLL_DIRECTION_FIXED = 0; +var SCROLL_DIRECTION_FORWARD = exports.SCROLL_DIRECTION_FORWARD = 1; /** - * HOC that simplifies the process of synchronizing scrolling between two or more virtualized components. + * Calculates the number of cells to overscan before and after a specified range. + * This function ensures that overscanning doesn't exceed the available cells. + * + * @param cellCount Number of rows or columns in the current axis + * @param scrollDirection One of SCROLL_DIRECTION_BACKWARD + * @param overscanCellsCount Maximum number of cells to over-render in either direction + * @param startIndex Begin of range of visible cells + * @param stopIndex End of range of visible cells */ -var ScrollSync = function (_Component) { - _inherits(ScrollSync, _Component); - - function ScrollSync(props, context) { - _classCallCheck(this, ScrollSync); - - var _this = _possibleConstructorReturn(this, (ScrollSync.__proto__ || Object.getPrototypeOf(ScrollSync)).call(this, props, context)); +function getOverscanIndices(_ref) { + var cellCount = _ref.cellCount; + var overscanCellsCount = _ref.overscanCellsCount; + var scrollDirection = _ref.scrollDirection; + var startIndex = _ref.startIndex; + var stopIndex = _ref.stopIndex; - _this.state = { - clientHeight: 0, - clientWidth: 0, - scrollHeight: 0, - scrollLeft: 0, - scrollTop: 0, - scrollWidth: 0 - }; + var overscanStartIndex = void 0; + var overscanStopIndex = void 0; - _this._onScroll = _this._onScroll.bind(_this); - return _this; + if (scrollDirection === SCROLL_DIRECTION_FORWARD) { + overscanStartIndex = startIndex; + overscanStopIndex = stopIndex + overscanCellsCount * 2; + } else if (scrollDirection === SCROLL_DIRECTION_BACKWARD) { + overscanStartIndex = startIndex - overscanCellsCount * 2; + overscanStopIndex = stopIndex; + } else { + overscanStartIndex = startIndex - overscanCellsCount; + overscanStopIndex = stopIndex + overscanCellsCount; } - _createClass(ScrollSync, [{ - key: 'render', - value: function render() { - var children = this.props.children; - var _state = this.state; - var clientHeight = _state.clientHeight; - var clientWidth = _state.clientWidth; - var scrollHeight = _state.scrollHeight; - var scrollLeft = _state.scrollLeft; - var scrollTop = _state.scrollTop; - var scrollWidth = _state.scrollWidth; - - - return children({ - clientHeight: clientHeight, - clientWidth: clientWidth, - onScroll: this._onScroll, - scrollHeight: scrollHeight, - scrollLeft: scrollLeft, - scrollTop: scrollTop, - scrollWidth: scrollWidth - }); - } - }, { - key: 'shouldComponentUpdate', - value: function shouldComponentUpdate(nextProps, nextState) { - return (0, _reactAddonsShallowCompare2.default)(this, nextProps, nextState); - } - }, { - key: '_onScroll', - value: function _onScroll(_ref) { - var clientHeight = _ref.clientHeight; - var clientWidth = _ref.clientWidth; - var scrollHeight = _ref.scrollHeight; - var scrollLeft = _ref.scrollLeft; - var scrollTop = _ref.scrollTop; - var scrollWidth = _ref.scrollWidth; - - this.setState({ clientHeight: clientHeight, clientWidth: clientWidth, scrollHeight: scrollHeight, scrollLeft: scrollLeft, scrollTop: scrollTop, scrollWidth: scrollWidth }); - } - }]); - - return ScrollSync; -}(_react.Component); - -ScrollSync.propTypes = { - /** - * Function respondible for rendering 2 or more virtualized components. - * This function should implement the following signature: - * ({ onScroll, scrollLeft, scrollTop }) => PropTypes.element - */ - children: _react.PropTypes.func.isRequired -}; -exports.default = ScrollSync; -},{"react":undefined,"react-addons-shallow-compare":30}],71:[function(require,module,exports){ + return { + overscanStartIndex: Math.max(0, overscanStartIndex), + overscanStopIndex: Math.min(cellCount - 1, overscanStopIndex) + }; +} +},{}],65:[function(require,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); -exports.ScrollSync = exports.default = undefined; - -var _ScrollSync2 = require('./ScrollSync'); +exports.default = updateScrollIndexHelper; +/** + * Helper function that determines when to update scroll offsets to ensure that a scroll-to-index remains visible. + * This function also ensures that the scroll ofset isn't past the last column/row of cells. + * + * @param cellsSize Width or height of cells for the current axis + * @param cellSizeAndPositionManager Manages size and position metadata of cells + * @param previousCellsCount Previous number of rows or columns + * @param previousCellsSize Previous width or height of cells + * @param previousScrollToIndex Previous scroll-to-index + * @param previousSize Previous width or height of the virtualized container + * @param scrollOffset Current scrollLeft or scrollTop + * @param scrollToIndex Scroll-to-index + * @param size Width or height of the virtualized container + * @param updateScrollIndexCallback Callback to invoke with an scroll-to-index value + */ +function updateScrollIndexHelper(_ref) { + var cellSize = _ref.cellSize; + var cellSizeAndPositionManager = _ref.cellSizeAndPositionManager; + var previousCellsCount = _ref.previousCellsCount; + var previousCellSize = _ref.previousCellSize; + var previousScrollToAlignment = _ref.previousScrollToAlignment; + var previousScrollToIndex = _ref.previousScrollToIndex; + var previousSize = _ref.previousSize; + var scrollOffset = _ref.scrollOffset; + var scrollToAlignment = _ref.scrollToAlignment; + var scrollToIndex = _ref.scrollToIndex; + var size = _ref.size; + var updateScrollIndexCallback = _ref.updateScrollIndexCallback; -var _ScrollSync3 = _interopRequireDefault(_ScrollSync2); + var cellCount = cellSizeAndPositionManager.getCellCount(); + var hasScrollToIndex = scrollToIndex >= 0 && scrollToIndex < cellCount; + var sizeHasChanged = size !== previousSize || !previousCellSize || typeof cellSize === 'number' && cellSize !== previousCellSize; -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + // If we have a new scroll target OR if height/row-height has changed, + // We should ensure that the scroll target is visible. + if (hasScrollToIndex && (sizeHasChanged || scrollToAlignment !== previousScrollToAlignment || scrollToIndex !== previousScrollToIndex)) { + updateScrollIndexCallback(scrollToIndex); -exports.default = _ScrollSync3.default; -exports.ScrollSync = _ScrollSync3.default; -},{"./ScrollSync":70}],72:[function(require,module,exports){ + // If we don't have a selected item but list size or number of children have decreased, + // Make sure we aren't scrolled too far past the current content. + } else if (!hasScrollToIndex && cellCount > 0 && (size < previousSize || cellCount < previousCellsCount)) { + // We need to ensure that the current scroll offset is still within the collection's range. + // To do this, we don't need to measure everything; CellMeasurer would perform poorly. + // Just check to make sure we're still okay. + // Only adjust the scroll position if we've scrolled below the last set of rows. + if (scrollOffset > cellSizeAndPositionManager.getTotalSize() - size) { + updateScrollIndexCallback(cellCount - 1); + } + } +} +},{}],66:[function(require,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); -var _Grid = require('../Grid'); - -var _Grid2 = _interopRequireDefault(_Grid); +exports.isRangeVisible = isRangeVisible; +exports.scanForUnloadedRanges = scanForUnloadedRanges; +exports.forceUpdateReactVirtualizedComponent = forceUpdateReactVirtualizedComponent; var _react = require('react'); -var _react2 = _interopRequireDefault(_react); - -var _classnames = require('classnames'); - -var _classnames2 = _interopRequireDefault(_classnames); - var _reactAddonsShallowCompare = require('react-addons-shallow-compare'); var _reactAddonsShallowCompare2 = _interopRequireDefault(_reactAddonsShallowCompare); +var _createCallbackMemoizer = require('../utils/createCallbackMemoizer'); + +var _createCallbackMemoizer2 = _interopRequireDefault(_createCallbackMemoizer); + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } @@ -8503,85 +8447,35 @@ function _possibleConstructorReturn(self, call) { if (!self) { throw new Referen function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /** - * It is inefficient to create and manage a large list of DOM elements within a scrolling container - * if only a few of those elements are visible. The primary purpose of this component is to improve - * performance by only rendering the DOM nodes that a user is able to see based on their current - * scroll position. - * - * This component renders a virtualized list of elements with either fixed or dynamic heights. + * Higher-order component that manages lazy-loading for "infinite" data. + * This component decorates a virtual component and just-in-time prefetches rows as a user scrolls. + * It is intended as a convenience component; fork it if you'd like finer-grained control over data-loading. */ -var VirtualScroll = function (_Component) { - _inherits(VirtualScroll, _Component); - - function VirtualScroll(props, context) { - _classCallCheck(this, VirtualScroll); - - var _this = _possibleConstructorReturn(this, (VirtualScroll.__proto__ || Object.getPrototypeOf(VirtualScroll)).call(this, props, context)); - - _this._cellRenderer = _this._cellRenderer.bind(_this); - _this._createRowClassNameGetter = _this._createRowClassNameGetter.bind(_this); - _this._createRowStyleGetter = _this._createRowStyleGetter.bind(_this); - _this._onScroll = _this._onScroll.bind(_this); - _this._onSectionRendered = _this._onSectionRendered.bind(_this); - return _this; - } - - _createClass(VirtualScroll, [{ - key: 'forceUpdateGrid', - value: function forceUpdateGrid() { - this.Grid.forceUpdate(); - } +var InfiniteLoader = function (_Component) { + _inherits(InfiniteLoader, _Component); - /** See Grid#measureAllCells */ + function InfiniteLoader(props, context) { + _classCallCheck(this, InfiniteLoader); - }, { - key: 'measureAllRows', - value: function measureAllRows() { - this.Grid.measureAllCells(); - } + var _this = _possibleConstructorReturn(this, (InfiniteLoader.__proto__ || Object.getPrototypeOf(InfiniteLoader)).call(this, props, context)); - /** See Grid#recomputeGridSize */ + _this._loadMoreRowsMemoizer = (0, _createCallbackMemoizer2.default)(); - }, { - key: 'recomputeRowHeights', - value: function recomputeRowHeights() { - var index = arguments.length <= 0 || arguments[0] === undefined ? 0 : arguments[0]; + _this._onRowsRendered = _this._onRowsRendered.bind(_this); + _this._registerChild = _this._registerChild.bind(_this); + return _this; + } - this.Grid.recomputeGridSize({ - rowIndex: index - }); - this.forceUpdateGrid(); - } - }, { + _createClass(InfiniteLoader, [{ key: 'render', value: function render() { - var _this2 = this; - - var _props = this.props; - var className = _props.className; - var noRowsRenderer = _props.noRowsRenderer; - var scrollToIndex = _props.scrollToIndex; - var width = _props.width; - + var children = this.props.children; - var classNames = (0, _classnames2.default)('VirtualScroll', className); - return _react2.default.createElement(_Grid2.default, _extends({}, this.props, { - autoContainerWidth: true, - cellRenderer: this._cellRenderer, - cellClassName: this._createRowClassNameGetter(), - cellStyle: this._createRowStyleGetter(), - className: classNames, - columnWidth: width, - columnCount: 1, - noContentRenderer: noRowsRenderer, - onScroll: this._onScroll, - onSectionRendered: this._onSectionRendered, - ref: function ref(_ref) { - _this2.Grid = _ref; - }, - scrollToRow: scrollToIndex - })); + return children({ + onRowsRendered: this._onRowsRendered, + registerChild: this._registerChild + }); } }, { key: 'shouldComponentUpdate', @@ -8589,195 +8483,242 @@ var VirtualScroll = function (_Component) { return (0, _reactAddonsShallowCompare2.default)(this, nextProps, nextState); } }, { - key: '_cellRenderer', - value: function _cellRenderer(_ref2) { - var columnIndex = _ref2.columnIndex; - var isScrolling = _ref2.isScrolling; - var rowIndex = _ref2.rowIndex; - var rowRenderer = this.props.rowRenderer; + key: '_loadUnloadedRanges', + value: function _loadUnloadedRanges(unloadedRanges) { + var _this2 = this; + + var loadMoreRows = this.props.loadMoreRows; - return rowRenderer({ - index: rowIndex, - isScrolling: isScrolling + unloadedRanges.forEach(function (unloadedRange) { + var promise = loadMoreRows(unloadedRange); + if (promise) { + promise.then(function () { + // Refresh the visible rows if any of them have just been loaded. + // Otherwise they will remain in their unloaded visual state. + if (isRangeVisible({ + lastRenderedStartIndex: _this2._lastRenderedStartIndex, + lastRenderedStopIndex: _this2._lastRenderedStopIndex, + startIndex: unloadedRange.startIndex, + stopIndex: unloadedRange.stopIndex + })) { + if (_this2._registeredChild) { + forceUpdateReactVirtualizedComponent(_this2._registeredChild); + } + } + }); + } }); } }, { - key: '_createRowClassNameGetter', - value: function _createRowClassNameGetter() { - var rowClassName = this.props.rowClassName; - + key: '_onRowsRendered', + value: function _onRowsRendered(_ref) { + var _this3 = this; - return rowClassName instanceof Function ? function (_ref3) { - var rowIndex = _ref3.rowIndex; - return rowClassName({ index: rowIndex }); - } : function () { - return rowClassName; - }; - } - }, { - key: '_createRowStyleGetter', - value: function _createRowStyleGetter() { - var rowStyle = this.props.rowStyle; + var startIndex = _ref.startIndex; + var stopIndex = _ref.stopIndex; + var _props = this.props; + var isRowLoaded = _props.isRowLoaded; + var minimumBatchSize = _props.minimumBatchSize; + var rowCount = _props.rowCount; + var threshold = _props.threshold; - var wrapped = rowStyle instanceof Function ? rowStyle : function () { - return rowStyle; - }; + this._lastRenderedStartIndex = startIndex; + this._lastRenderedStopIndex = stopIndex; - // Default width to 100% to prevent list rows from flowing under the vertical scrollbar - return function (_ref4) { - var rowIndex = _ref4.rowIndex; - return _extends({ - width: '100%' - }, wrapped({ index: rowIndex })); - }; - } - }, { - key: '_onScroll', - value: function _onScroll(_ref5) { - var clientHeight = _ref5.clientHeight; - var scrollHeight = _ref5.scrollHeight; - var scrollTop = _ref5.scrollTop; - var onScroll = this.props.onScroll; + var unloadedRanges = scanForUnloadedRanges({ + isRowLoaded: isRowLoaded, + minimumBatchSize: minimumBatchSize, + rowCount: rowCount, + startIndex: Math.max(0, startIndex - threshold), + stopIndex: Math.min(rowCount - 1, stopIndex + threshold) + }); + // For memoize comparison + var squashedUnloadedRanges = unloadedRanges.reduce(function (reduced, unloadedRange) { + return reduced.concat([unloadedRange.startIndex, unloadedRange.stopIndex]); + }, []); - onScroll({ clientHeight: clientHeight, scrollHeight: scrollHeight, scrollTop: scrollTop }); + this._loadMoreRowsMemoizer({ + callback: function callback() { + _this3._loadUnloadedRanges(unloadedRanges); + }, + indices: { squashedUnloadedRanges: squashedUnloadedRanges } + }); } }, { - key: '_onSectionRendered', - value: function _onSectionRendered(_ref6) { - var rowOverscanStartIndex = _ref6.rowOverscanStartIndex; - var rowOverscanStopIndex = _ref6.rowOverscanStopIndex; - var rowStartIndex = _ref6.rowStartIndex; - var rowStopIndex = _ref6.rowStopIndex; - var onRowsRendered = this.props.onRowsRendered; - - - onRowsRendered({ - overscanStartIndex: rowOverscanStartIndex, - overscanStopIndex: rowOverscanStopIndex, - startIndex: rowStartIndex, - stopIndex: rowStopIndex - }); + key: '_registerChild', + value: function _registerChild(registeredChild) { + this._registeredChild = registeredChild; } }]); - return VirtualScroll; + return InfiniteLoader; }(_react.Component); -VirtualScroll.propTypes = { - 'aria-label': _react.PropTypes.string, +/** + * Determines if the specified start/stop range is visible based on the most recently rendered range. + */ + +InfiniteLoader.propTypes = { /** - * Removes fixed height from the scrollingContainer so that the total height - * of rows can stretch the window. Intended for use with WindowScroller + * Function respondible for rendering a virtualized component. + * This function should implement the following signature: + * ({ onRowsRendered, registerChild }) => PropTypes.element + * + * The specified :onRowsRendered function should be passed through to the child's :onRowsRendered property. + * The :registerChild callback should be set as the virtualized component's :ref. */ - autoHeight: _react.PropTypes.bool, - - /** Optional CSS class name */ - className: _react.PropTypes.string, + children: _react.PropTypes.func.isRequired, /** - * Used to estimate the total height of a VirtualScroll before all of its rows have actually been measured. - * The estimated total height is adjusted as rows are rendered. + * Function responsible for tracking the loaded state of each row. + * It should implement the following signature: ({ index: number }): boolean */ - estimatedRowSize: _react.PropTypes.number.isRequired, - - /** Height constraint for list (determines how many actual rows are rendered) */ - height: _react.PropTypes.number.isRequired, - - /** Optional renderer to be used in place of rows when rowCount is 0 */ - noRowsRenderer: _react.PropTypes.func.isRequired, + isRowLoaded: _react.PropTypes.func.isRequired, /** - * Callback invoked with information about the slice of rows that were just rendered. - * ({ startIndex, stopIndex }): void + * Callback to be invoked when more rows must be loaded. + * It should implement the following signature: ({ startIndex, stopIndex }): Promise + * The returned Promise should be resolved once row data has finished loading. + * It will be used to determine when to refresh the list with the newly-loaded data. + * This callback may be called multiple times in reaction to a single scroll event. */ - onRowsRendered: _react.PropTypes.func.isRequired, + loadMoreRows: _react.PropTypes.func.isRequired, /** - * Number of rows to render above/below the visible bounds of the list. - * These rows can help for smoother scrolling on touch devices. + * Minimum number of rows to be loaded at a time. + * This property can be used to batch requests to reduce HTTP requests. */ - overscanRowCount: _react.PropTypes.number.isRequired, + minimumBatchSize: _react.PropTypes.number.isRequired, /** - * Callback invoked whenever the scroll offset changes within the inner scrollable region. - * This callback can be used to sync scrolling between lists, tables, or grids. - * ({ clientHeight, scrollHeight, scrollTop }): void + * Number of rows in list; can be arbitrary high number if actual number is unknown. */ - onScroll: _react.PropTypes.func.isRequired, + rowCount: _react.PropTypes.number.isRequired, /** - * Either a fixed row height (number) or a function that returns the height of a row given its index. - * ({ index: number }): number + * Threshold at which to pre-fetch data. + * A threshold X means that data will start loading when a user scrolls within X rows. + * This value defaults to 15. */ - rowHeight: _react.PropTypes.oneOfType([_react.PropTypes.number, _react.PropTypes.func]).isRequired, + threshold: _react.PropTypes.number.isRequired +}; +InfiniteLoader.defaultProps = { + minimumBatchSize: 10, + rowCount: 0, + threshold: 15 +}; +exports.default = InfiniteLoader; +function isRangeVisible(_ref2) { + var lastRenderedStartIndex = _ref2.lastRenderedStartIndex; + var lastRenderedStopIndex = _ref2.lastRenderedStopIndex; + var startIndex = _ref2.startIndex; + var stopIndex = _ref2.stopIndex; - /** Responsbile for rendering a row given an index; ({ index: number }): node */ - rowRenderer: _react.PropTypes.func.isRequired, + return !(startIndex > lastRenderedStopIndex || stopIndex < lastRenderedStartIndex); +} + +/** + * Returns all of the ranges within a larger range that contain unloaded rows. + */ +function scanForUnloadedRanges(_ref3) { + var isRowLoaded = _ref3.isRowLoaded; + var minimumBatchSize = _ref3.minimumBatchSize; + var rowCount = _ref3.rowCount; + var startIndex = _ref3.startIndex; + var stopIndex = _ref3.stopIndex; + + var unloadedRanges = []; + + var rangeStartIndex = null; + var rangeStopIndex = null; + + for (var index = startIndex; index <= stopIndex; index++) { + var loaded = isRowLoaded({ index: index }); + + if (!loaded) { + rangeStopIndex = index; + if (rangeStartIndex === null) { + rangeStartIndex = index; + } + } else if (rangeStopIndex !== null) { + unloadedRanges.push({ + startIndex: rangeStartIndex, + stopIndex: rangeStopIndex + }); - /** Optional custom CSS class for individual rows */ - rowClassName: _react.PropTypes.oneOfType([_react.PropTypes.string, _react.PropTypes.func]), + rangeStartIndex = rangeStopIndex = null; + } + } - /** Number of rows in list. */ - rowCount: _react.PropTypes.number.isRequired, + // If :rangeStopIndex is not null it means we haven't ran out of unloaded rows. + // Scan forward to try filling our :minimumBatchSize. + if (rangeStopIndex !== null) { + var potentialStopIndex = Math.min(Math.max(rangeStopIndex, rangeStartIndex + minimumBatchSize - 1), rowCount - 1); - /** Optional custom styles for individual cells */ - rowStyle: _react.PropTypes.oneOfType([_react.PropTypes.object, _react.PropTypes.func]), + for (var _index = rangeStopIndex + 1; _index <= potentialStopIndex; _index++) { + if (!isRowLoaded({ index: _index })) { + rangeStopIndex = _index; + } else { + break; + } + } - /** See Grid#scrollToAlignment */ - scrollToAlignment: _react.PropTypes.oneOf(['auto', 'end', 'start', 'center']).isRequired, + unloadedRanges.push({ + startIndex: rangeStartIndex, + stopIndex: rangeStopIndex + }); + } - /** Row index to ensure visible (by forcefully scrolling if necessary) */ - scrollToIndex: _react.PropTypes.number, + // Check to see if our first range ended prematurely. + // In this case we should scan backwards to try filling our :minimumBatchSize. + if (unloadedRanges.length) { + var firstUnloadedRange = unloadedRanges[0]; - /** Vertical offset. */ - scrollTop: _react.PropTypes.number, + while (firstUnloadedRange.stopIndex - firstUnloadedRange.startIndex + 1 < minimumBatchSize && firstUnloadedRange.startIndex > 0) { + var _index2 = firstUnloadedRange.startIndex - 1; - /** Optional inline style */ - style: _react.PropTypes.object, + if (!isRowLoaded({ index: _index2 })) { + firstUnloadedRange.startIndex = _index2; + } else { + break; + } + } + } - /** Tab index for focus */ - tabIndex: _react.PropTypes.number, + return unloadedRanges; +} - /** Width of list */ - width: _react.PropTypes.number.isRequired -}; -VirtualScroll.defaultProps = { - estimatedRowSize: 30, - noRowsRenderer: function noRowsRenderer() { - return null; - }, - onRowsRendered: function onRowsRendered() { - return null; - }, - onScroll: function onScroll() { - return null; - }, - overscanRowCount: 10, - scrollToAlignment: 'auto', - style: {} -}; -exports.default = VirtualScroll; -},{"../Grid":62,"classnames":undefined,"react":undefined,"react-addons-shallow-compare":30}],73:[function(require,module,exports){ +/** + * Since RV components use shallowCompare we need to force a render (even though props haven't changed). + * However InfiniteLoader may wrap a Grid or it may wrap a FlexTable or VirtualScroll. + * In the first case the built-in React forceUpdate() method is sufficient to force a re-render, + * But in the latter cases we need to use the RV-specific forceUpdateGrid() method. + * Else the inner Grid will not be re-rendered and visuals may be stale. + */ +function forceUpdateReactVirtualizedComponent(component) { + typeof component.forceUpdateGrid === 'function' ? component.forceUpdateGrid() : component.forceUpdate(); +} +},{"../utils/createCallbackMemoizer":76,"react":undefined,"react-addons-shallow-compare":18}],67:[function(require,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); -exports.VirtualScroll = exports.default = undefined; +exports.InfiniteLoader = exports.default = undefined; -var _VirtualScroll2 = require('./VirtualScroll'); +var _InfiniteLoader2 = require('./InfiniteLoader'); -var _VirtualScroll3 = _interopRequireDefault(_VirtualScroll2); +var _InfiniteLoader3 = _interopRequireDefault(_InfiniteLoader2); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -exports.default = _VirtualScroll3.default; -exports.VirtualScroll = _VirtualScroll3.default; -},{"./VirtualScroll":72}],74:[function(require,module,exports){ +exports.default = _InfiniteLoader3.default; +exports.InfiniteLoader = _InfiniteLoader3.default; +},{"./InfiniteLoader":66}],68:[function(require,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { @@ -8788,22 +8729,10 @@ var _createClass = function () { function defineProperties(target, props) { for var _react = require('react'); -var _react2 = _interopRequireDefault(_react); - -var _reactDom = require('react-dom'); - -var _reactDom2 = _interopRequireDefault(_reactDom); - var _reactAddonsShallowCompare = require('react-addons-shallow-compare'); var _reactAddonsShallowCompare2 = _interopRequireDefault(_reactAddonsShallowCompare); -var _raf = require('raf'); - -var _raf2 = _interopRequireDefault(_raf); - -var _onScroll = require('./utils/onScroll'); - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } @@ -8812,1161 +8741,1255 @@ function _possibleConstructorReturn(self, call) { if (!self) { throw new Referen function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } -var WindowScroller = function (_Component) { - _inherits(WindowScroller, _Component); - - function WindowScroller(props) { - _classCallCheck(this, WindowScroller); +/** + * HOC that simplifies the process of synchronizing scrolling between two or more virtualized components. + */ +var ScrollSync = function (_Component) { + _inherits(ScrollSync, _Component); - var _this = _possibleConstructorReturn(this, (WindowScroller.__proto__ || Object.getPrototypeOf(WindowScroller)).call(this, props)); + function ScrollSync(props, context) { + _classCallCheck(this, ScrollSync); - var height = typeof window !== 'undefined' ? window.innerHeight : 0; + var _this = _possibleConstructorReturn(this, (ScrollSync.__proto__ || Object.getPrototypeOf(ScrollSync)).call(this, props, context)); _this.state = { - isScrolling: false, - height: height, - scrollTop: 0 + clientHeight: 0, + clientWidth: 0, + scrollHeight: 0, + scrollLeft: 0, + scrollTop: 0, + scrollWidth: 0 }; - _this._onScrollWindow = _this._onScrollWindow.bind(_this); - _this._onResizeWindow = _this._onResizeWindow.bind(_this); - _this._enablePointerEventsAfterDelayCallback = _this._enablePointerEventsAfterDelayCallback.bind(_this); + _this._onScroll = _this._onScroll.bind(_this); return _this; } - _createClass(WindowScroller, [{ - key: 'componentDidMount', - value: function componentDidMount() { - var height = this.state.height; - - // Subtract documentElement top to handle edge-case where a user is navigating back (history) from an already-scrolled bage. - // In this case the body's top position will be a negative number and this element's top will be increased (by that amount). - - this._positionFromTop = _reactDom2.default.findDOMNode(this).getBoundingClientRect().top - document.documentElement.getBoundingClientRect().top; - - if (height !== window.innerHeight) { - this.setState({ - height: window.innerHeight - }); - } - - (0, _onScroll.registerScrollListener)(this); - window.addEventListener('resize', this._onResizeWindow, false); - } - }, { - key: 'componentWillUnmount', - value: function componentWillUnmount() { - (0, _onScroll.unregisterScrollListener)(this); - - window.removeEventListener('resize', this._onResizeWindow, false); - } - - /** - * Updates the state during the next animation frame. - * Use this method to avoid multiple renders in a small span of time. - * This helps performance for bursty events (like onScroll). - */ - - }, { - key: '_setNextState', - value: function _setNextState(state) { - var _this2 = this; - - if (this._setNextStateAnimationFrameId) { - _raf2.default.cancel(this._setNextStateAnimationFrameId); - } - - this._setNextStateAnimationFrameId = (0, _raf2.default)(function () { - _this2._setNextStateAnimationFrameId = null; - _this2.setState(state); - }); - } - }, { + _createClass(ScrollSync, [{ key: 'render', value: function render() { var children = this.props.children; var _state = this.state; - var isScrolling = _state.isScrolling; + var clientHeight = _state.clientHeight; + var clientWidth = _state.clientWidth; + var scrollHeight = _state.scrollHeight; + var scrollLeft = _state.scrollLeft; var scrollTop = _state.scrollTop; - var height = _state.height; - - - return _react2.default.createElement( - 'div', - null, - children({ - height: height, - isScrolling: isScrolling, - scrollTop: scrollTop - }) - ); - } - }, { - key: 'shouldComponentUpdate', - value: function shouldComponentUpdate(nextProps, nextState) { - return (0, _reactAddonsShallowCompare2.default)(this, nextProps, nextState); - } - }, { - key: '_enablePointerEventsAfterDelayCallback', - value: function _enablePointerEventsAfterDelayCallback() { - this.setState({ - isScrolling: false - }); - } - }, { - key: '_onResizeWindow', - value: function _onResizeWindow(event) { - var onResize = this.props.onResize; - - - var height = window.innerHeight || 0; - - this.setState({ height: height }); - - onResize({ height: height }); - } - }, { - key: '_onScrollWindow', - value: function _onScrollWindow(event) { - var onScroll = this.props.onScroll; - - // In IE10+ scrollY is undefined, so we replace that with the latter - - var scrollY = 'scrollY' in window ? window.scrollY : document.documentElement.scrollTop; - - var scrollTop = Math.max(0, scrollY - this._positionFromTop); + var scrollWidth = _state.scrollWidth; - var state = { - isScrolling: true, - scrollTop: scrollTop - }; - if (!this.state.isScrolling) { - this.setState(state); - } else { - this._setNextState(state); - } + return children({ + clientHeight: clientHeight, + clientWidth: clientWidth, + onScroll: this._onScroll, + scrollHeight: scrollHeight, + scrollLeft: scrollLeft, + scrollTop: scrollTop, + scrollWidth: scrollWidth + }); + } + }, { + key: 'shouldComponentUpdate', + value: function shouldComponentUpdate(nextProps, nextState) { + return (0, _reactAddonsShallowCompare2.default)(this, nextProps, nextState); + } + }, { + key: '_onScroll', + value: function _onScroll(_ref) { + var clientHeight = _ref.clientHeight; + var clientWidth = _ref.clientWidth; + var scrollHeight = _ref.scrollHeight; + var scrollLeft = _ref.scrollLeft; + var scrollTop = _ref.scrollTop; + var scrollWidth = _ref.scrollWidth; - onScroll({ scrollTop: scrollTop }); + this.setState({ clientHeight: clientHeight, clientWidth: clientWidth, scrollHeight: scrollHeight, scrollLeft: scrollLeft, scrollTop: scrollTop, scrollWidth: scrollWidth }); } }]); - return WindowScroller; + return ScrollSync; }(_react.Component); -WindowScroller.propTypes = { +ScrollSync.propTypes = { /** - * Function respondible for rendering children. + * Function respondible for rendering 2 or more virtualized components. * This function should implement the following signature: - * ({ height, scrollTop }) => PropTypes.element + * ({ onScroll, scrollLeft, scrollTop }) => PropTypes.element */ - children: _react.PropTypes.func.isRequired, - - /** Callback to be invoked on-resize: ({ height }) */ - onResize: _react.PropTypes.func.isRequired, - - /** Callback to be invoked on-scroll: ({ scrollTop }) */ - onScroll: _react.PropTypes.func.isRequired -}; -WindowScroller.defaultProps = { - onResize: function onResize() {}, - onScroll: function onScroll() {} + children: _react.PropTypes.func.isRequired }; -exports.default = WindowScroller; -},{"./utils/onScroll":76,"raf":29,"react":undefined,"react-addons-shallow-compare":30,"react-dom":undefined}],75:[function(require,module,exports){ +exports.default = ScrollSync; +},{"react":undefined,"react-addons-shallow-compare":18}],69:[function(require,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); -exports.IS_SCROLLING_TIMEOUT = exports.WindowScroller = exports.default = undefined; - -var _WindowScroller2 = require('./WindowScroller'); - -var _WindowScroller3 = _interopRequireDefault(_WindowScroller2); +exports.ScrollSync = exports.default = undefined; -var _onScroll = require('./utils/onScroll'); +var _ScrollSync2 = require('./ScrollSync'); -var _onScroll2 = _interopRequireDefault(_onScroll); +var _ScrollSync3 = _interopRequireDefault(_ScrollSync2); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -exports.default = _WindowScroller3.default; -exports.WindowScroller = _WindowScroller3.default; -exports.IS_SCROLLING_TIMEOUT = _onScroll2.default; -},{"./WindowScroller":74,"./utils/onScroll":76}],76:[function(require,module,exports){ +exports.default = _ScrollSync3.default; +exports.ScrollSync = _ScrollSync3.default; +},{"./ScrollSync":68}],70:[function(require,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); -exports.registerScrollListener = registerScrollListener; -exports.unregisterScrollListener = unregisterScrollListener; -var mountedInstances = []; -var originalBodyPointerEvents = null; -var disablePointerEventsTimeoutId = null; + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _Grid = require('../Grid'); + +var _Grid2 = _interopRequireDefault(_Grid); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _classnames = require('classnames'); + +var _classnames2 = _interopRequireDefault(_classnames); + +var _reactAddonsShallowCompare = require('react-addons-shallow-compare'); + +var _reactAddonsShallowCompare2 = _interopRequireDefault(_reactAddonsShallowCompare); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /** - * Specifies the number of miliseconds during which to disable pointer events while a scroll is in progress. - * This improves performance and makes scrolling smoother. + * It is inefficient to create and manage a large list of DOM elements within a scrolling container + * if only a few of those elements are visible. The primary purpose of this component is to improve + * performance by only rendering the DOM nodes that a user is able to see based on their current + * scroll position. + * + * This component renders a virtualized list of elements with either fixed or dynamic heights. */ -var IS_SCROLLING_TIMEOUT = exports.IS_SCROLLING_TIMEOUT = 150; +var VirtualScroll = function (_Component) { + _inherits(VirtualScroll, _Component); -function enablePointerEventsIfDisabled() { - if (disablePointerEventsTimeoutId) { - disablePointerEventsTimeoutId = null; + function VirtualScroll(props, context) { + _classCallCheck(this, VirtualScroll); - document.body.style.pointerEvents = originalBodyPointerEvents; + var _this = _possibleConstructorReturn(this, (VirtualScroll.__proto__ || Object.getPrototypeOf(VirtualScroll)).call(this, props, context)); - originalBodyPointerEvents = null; + _this._cellRenderer = _this._cellRenderer.bind(_this); + _this._createRowClassNameGetter = _this._createRowClassNameGetter.bind(_this); + _this._createRowStyleGetter = _this._createRowStyleGetter.bind(_this); + _this._onScroll = _this._onScroll.bind(_this); + _this._onSectionRendered = _this._onSectionRendered.bind(_this); + return _this; } -} -function enablePointerEventsAfterDelayCallback() { - enablePointerEventsIfDisabled(); - mountedInstances.forEach(function (component) { - return component._enablePointerEventsAfterDelayCallback(); - }); -} + _createClass(VirtualScroll, [{ + key: 'forceUpdateGrid', + value: function forceUpdateGrid() { + this.Grid.forceUpdate(); + } -function enablePointerEventsAfterDelay() { - if (disablePointerEventsTimeoutId) { - clearTimeout(disablePointerEventsTimeoutId); - } + /** See Grid#measureAllCells */ - disablePointerEventsTimeoutId = setTimeout(enablePointerEventsAfterDelayCallback, IS_SCROLLING_TIMEOUT); -} + }, { + key: 'measureAllRows', + value: function measureAllRows() { + this.Grid.measureAllCells(); + } -function onScrollWindow(event) { - if (originalBodyPointerEvents == null) { - originalBodyPointerEvents = document.body.style.pointerEvents; + /** See Grid#recomputeGridSize */ - document.body.style.pointerEvents = 'none'; + }, { + key: 'recomputeRowHeights', + value: function recomputeRowHeights() { + var index = arguments.length <= 0 || arguments[0] === undefined ? 0 : arguments[0]; - enablePointerEventsAfterDelay(); - } - mountedInstances.forEach(function (component) { - return component._onScrollWindow(event); - }); -} + this.Grid.recomputeGridSize({ + rowIndex: index + }); + this.forceUpdateGrid(); + } + }, { + key: 'render', + value: function render() { + var _this2 = this; + + var _props = this.props; + var className = _props.className; + var noRowsRenderer = _props.noRowsRenderer; + var scrollToIndex = _props.scrollToIndex; + var width = _props.width; + + + var classNames = (0, _classnames2.default)('VirtualScroll', className); + + return _react2.default.createElement(_Grid2.default, _extends({}, this.props, { + autoContainerWidth: true, + cellRenderer: this._cellRenderer, + cellClassName: this._createRowClassNameGetter(), + cellStyle: this._createRowStyleGetter(), + className: classNames, + columnWidth: width, + columnCount: 1, + noContentRenderer: noRowsRenderer, + onScroll: this._onScroll, + onSectionRendered: this._onSectionRendered, + ref: function ref(_ref) { + _this2.Grid = _ref; + }, + scrollToRow: scrollToIndex + })); + } + }, { + key: 'shouldComponentUpdate', + value: function shouldComponentUpdate(nextProps, nextState) { + return (0, _reactAddonsShallowCompare2.default)(this, nextProps, nextState); + } + }, { + key: '_cellRenderer', + value: function _cellRenderer(_ref2) { + var columnIndex = _ref2.columnIndex; + var isScrolling = _ref2.isScrolling; + var rowIndex = _ref2.rowIndex; + var rowRenderer = this.props.rowRenderer; + + + return rowRenderer({ + index: rowIndex, + isScrolling: isScrolling + }); + } + }, { + key: '_createRowClassNameGetter', + value: function _createRowClassNameGetter() { + var rowClassName = this.props.rowClassName; + + + return rowClassName instanceof Function ? function (_ref3) { + var rowIndex = _ref3.rowIndex; + return rowClassName({ index: rowIndex }); + } : function () { + return rowClassName; + }; + } + }, { + key: '_createRowStyleGetter', + value: function _createRowStyleGetter() { + var rowStyle = this.props.rowStyle; + + + var wrapped = rowStyle instanceof Function ? rowStyle : function () { + return rowStyle; + }; + + // Default width to 100% to prevent list rows from flowing under the vertical scrollbar + return function (_ref4) { + var rowIndex = _ref4.rowIndex; + return _extends({ + width: '100%' + }, wrapped({ index: rowIndex })); + }; + } + }, { + key: '_onScroll', + value: function _onScroll(_ref5) { + var clientHeight = _ref5.clientHeight; + var scrollHeight = _ref5.scrollHeight; + var scrollTop = _ref5.scrollTop; + var onScroll = this.props.onScroll; + + + onScroll({ clientHeight: clientHeight, scrollHeight: scrollHeight, scrollTop: scrollTop }); + } + }, { + key: '_onSectionRendered', + value: function _onSectionRendered(_ref6) { + var rowOverscanStartIndex = _ref6.rowOverscanStartIndex; + var rowOverscanStopIndex = _ref6.rowOverscanStopIndex; + var rowStartIndex = _ref6.rowStartIndex; + var rowStopIndex = _ref6.rowStopIndex; + var onRowsRendered = this.props.onRowsRendered; -function registerScrollListener(component) { - if (!mountedInstances.length) { - window.addEventListener('scroll', onScrollWindow); - } - mountedInstances.push(component); -} -function unregisterScrollListener(component) { - mountedInstances = mountedInstances.filter(function (c) { - return c !== component; - }); - if (!mountedInstances.length) { - window.removeEventListener('scroll', onScrollWindow); - if (disablePointerEventsTimeoutId) { - clearTimeout(disablePointerEventsTimeoutId); - enablePointerEventsIfDisabled(); + onRowsRendered({ + overscanStartIndex: rowOverscanStartIndex, + overscanStopIndex: rowOverscanStopIndex, + startIndex: rowStartIndex, + stopIndex: rowStopIndex + }); } - } -} -},{}],77:[function(require,module,exports){ -'use strict'; + }]); -Object.defineProperty(exports, "__esModule", { - value: true -}); + return VirtualScroll; +}(_react.Component); -var _ArrowKeyStepper = require('./ArrowKeyStepper'); +VirtualScroll.propTypes = { + 'aria-label': _react.PropTypes.string, -Object.defineProperty(exports, 'ArrowKeyStepper', { - enumerable: true, - get: function get() { - return _ArrowKeyStepper.ArrowKeyStepper; - } -}); + /** + * Removes fixed height from the scrollingContainer so that the total height + * of rows can stretch the window. Intended for use with WindowScroller + */ + autoHeight: _react.PropTypes.bool, -var _AutoSizer = require('./AutoSizer'); + /** Optional CSS class name */ + className: _react.PropTypes.string, -Object.defineProperty(exports, 'AutoSizer', { - enumerable: true, - get: function get() { - return _AutoSizer.AutoSizer; - } -}); + /** + * Used to estimate the total height of a VirtualScroll before all of its rows have actually been measured. + * The estimated total height is adjusted as rows are rendered. + */ + estimatedRowSize: _react.PropTypes.number.isRequired, -var _CellMeasurer = require('./CellMeasurer'); + /** Height constraint for list (determines how many actual rows are rendered) */ + height: _react.PropTypes.number.isRequired, -Object.defineProperty(exports, 'CellMeasurer', { - enumerable: true, - get: function get() { - return _CellMeasurer.CellMeasurer; - } -}); -Object.defineProperty(exports, 'defaultCellMeasurerCellSizeCache', { - enumerable: true, - get: function get() { - return _CellMeasurer.defaultCellSizeCache; - } -}); -Object.defineProperty(exports, 'uniformSizeCellMeasurerCellSizeCache', { - enumerable: true, - get: function get() { - return _CellMeasurer.defaultCellSizeCache; - } -}); + /** Optional renderer to be used in place of rows when rowCount is 0 */ + noRowsRenderer: _react.PropTypes.func.isRequired, -var _Collection = require('./Collection'); + /** + * Callback invoked with information about the slice of rows that were just rendered. + * ({ startIndex, stopIndex }): void + */ + onRowsRendered: _react.PropTypes.func.isRequired, -Object.defineProperty(exports, 'Collection', { - enumerable: true, - get: function get() { - return _Collection.Collection; - } -}); + /** + * Number of rows to render above/below the visible bounds of the list. + * These rows can help for smoother scrolling on touch devices. + */ + overscanRowCount: _react.PropTypes.number.isRequired, -var _ColumnSizer = require('./ColumnSizer'); + /** + * Callback invoked whenever the scroll offset changes within the inner scrollable region. + * This callback can be used to sync scrolling between lists, tables, or grids. + * ({ clientHeight, scrollHeight, scrollTop }): void + */ + onScroll: _react.PropTypes.func.isRequired, -Object.defineProperty(exports, 'ColumnSizer', { - enumerable: true, - get: function get() { - return _ColumnSizer.ColumnSizer; - } -}); + /** + * Either a fixed row height (number) or a function that returns the height of a row given its index. + * ({ index: number }): number + */ + rowHeight: _react.PropTypes.oneOfType([_react.PropTypes.number, _react.PropTypes.func]).isRequired, -var _FlexTable = require('./FlexTable'); + /** Responsbile for rendering a row given an index; ({ index: number }): node */ + rowRenderer: _react.PropTypes.func.isRequired, -Object.defineProperty(exports, 'defaultFlexTableCellDataGetter', { - enumerable: true, - get: function get() { - return _FlexTable.defaultCellDataGetter; - } -}); -Object.defineProperty(exports, 'defaultFlexTableCellRenderer', { - enumerable: true, - get: function get() { - return _FlexTable.defaultCellRenderer; - } -}); -Object.defineProperty(exports, 'defaultFlexTableHeaderRenderer', { - enumerable: true, - get: function get() { - return _FlexTable.defaultHeaderRenderer; - } -}); -Object.defineProperty(exports, 'defaultFlexTableRowRenderer', { - enumerable: true, - get: function get() { - return _FlexTable.defaultRowRenderer; - } -}); -Object.defineProperty(exports, 'FlexTable', { - enumerable: true, - get: function get() { - return _FlexTable.FlexTable; - } -}); -Object.defineProperty(exports, 'FlexColumn', { - enumerable: true, - get: function get() { - return _FlexTable.FlexColumn; - } -}); -Object.defineProperty(exports, 'SortDirection', { - enumerable: true, - get: function get() { - return _FlexTable.SortDirection; - } -}); -Object.defineProperty(exports, 'SortIndicator', { - enumerable: true, - get: function get() { - return _FlexTable.SortIndicator; - } -}); + /** Optional custom CSS class for individual rows */ + rowClassName: _react.PropTypes.oneOfType([_react.PropTypes.string, _react.PropTypes.func]), -var _Grid = require('./Grid'); + /** Number of rows in list. */ + rowCount: _react.PropTypes.number.isRequired, -Object.defineProperty(exports, 'defaultCellRangeRenderer', { - enumerable: true, - get: function get() { - return _Grid.defaultCellRangeRenderer; - } -}); -Object.defineProperty(exports, 'Grid', { - enumerable: true, - get: function get() { - return _Grid.Grid; - } -}); + /** Optional custom styles for individual cells */ + rowStyle: _react.PropTypes.oneOfType([_react.PropTypes.object, _react.PropTypes.func]), -var _InfiniteLoader = require('./InfiniteLoader'); + /** See Grid#scrollToAlignment */ + scrollToAlignment: _react.PropTypes.oneOf(['auto', 'end', 'start', 'center']).isRequired, -Object.defineProperty(exports, 'InfiniteLoader', { - enumerable: true, - get: function get() { - return _InfiniteLoader.InfiniteLoader; - } -}); + /** Row index to ensure visible (by forcefully scrolling if necessary) */ + scrollToIndex: _react.PropTypes.number, -var _ScrollSync = require('./ScrollSync'); + /** Vertical offset. */ + scrollTop: _react.PropTypes.number, -Object.defineProperty(exports, 'ScrollSync', { - enumerable: true, - get: function get() { - return _ScrollSync.ScrollSync; - } -}); + /** Optional inline style */ + style: _react.PropTypes.object, -var _VirtualScroll = require('./VirtualScroll'); + /** Tab index for focus */ + tabIndex: _react.PropTypes.number, -Object.defineProperty(exports, 'VirtualScroll', { - enumerable: true, - get: function get() { - return _VirtualScroll.VirtualScroll; - } + /** Width of list */ + width: _react.PropTypes.number.isRequired +}; +VirtualScroll.defaultProps = { + estimatedRowSize: 30, + noRowsRenderer: function noRowsRenderer() { + return null; + }, + onRowsRendered: function onRowsRendered() { + return null; + }, + onScroll: function onScroll() { + return null; + }, + overscanRowCount: 10, + scrollToAlignment: 'auto', + style: {} +}; +exports.default = VirtualScroll; +},{"../Grid":60,"classnames":undefined,"react":undefined,"react-addons-shallow-compare":18}],71:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true }); +exports.VirtualScroll = exports.default = undefined; -var _WindowScroller = require('./WindowScroller'); +var _VirtualScroll2 = require('./VirtualScroll'); -Object.defineProperty(exports, 'WindowScroller', { - enumerable: true, - get: function get() { - return _WindowScroller.WindowScroller; - } -}); -},{"./ArrowKeyStepper":37,"./AutoSizer":39,"./CellMeasurer":42,"./Collection":47,"./ColumnSizer":50,"./FlexTable":59,"./Grid":62,"./InfiniteLoader":69,"./ScrollSync":71,"./VirtualScroll":73,"./WindowScroller":75}],78:[function(require,module,exports){ +var _VirtualScroll3 = _interopRequireDefault(_VirtualScroll2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = _VirtualScroll3.default; +exports.VirtualScroll = _VirtualScroll3.default; +},{"./VirtualScroll":70}],72:[function(require,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); -exports.default = createCallbackMemoizer; -/** - * Helper utility that updates the specified callback whenever any of the specified indices have changed. - */ -function createCallbackMemoizer() { - var requireAllKeys = arguments.length <= 0 || arguments[0] === undefined ? true : arguments[0]; - var cachedIndices = {}; +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - return function (_ref) { - var callback = _ref.callback; - var indices = _ref.indices; +var _react = require('react'); - var keys = Object.keys(indices); - var allInitialized = !requireAllKeys || keys.every(function (key) { - var value = indices[key]; - return Array.isArray(value) ? value.length > 0 : value >= 0; - }); - var indexChanged = keys.length !== Object.keys(cachedIndices).length || keys.some(function (key) { - var cachedValue = cachedIndices[key]; - var value = indices[key]; +var _react2 = _interopRequireDefault(_react); - return Array.isArray(value) ? cachedValue.join(',') !== value.join(',') : cachedValue !== value; - }); +var _reactDom = require('react-dom'); - cachedIndices = indices; +var _reactDom2 = _interopRequireDefault(_reactDom); - if (allInitialized && indexChanged) { - callback(indices); - } - }; -} -},{}],79:[function(require,module,exports){ -'use strict'; +var _reactAddonsShallowCompare = require('react-addons-shallow-compare'); -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.default = getUpdatedOffsetForIndex; -/** - * Determines a new offset that ensures a certain cell is visible, given the current offset. - * If the cell is already visible then the current offset will be returned. - * If the current offset is too great or small, it will be adjusted just enough to ensure the specified index is visible. - * - * @param align Desired alignment within container; one of "auto" (default), "start", or "end" - * @param cellOffset Offset (x or y) position for cell - * @param cellSize Size (width or height) of cell - * @param containerSize Total size (width or height) of the container - * @param currentOffset Container's current (x or y) offset - * @return Offset to use to ensure the specified cell is visible - */ -function getUpdatedOffsetForIndex(_ref) { - var _ref$align = _ref.align; - var align = _ref$align === undefined ? 'auto' : _ref$align; - var cellOffset = _ref.cellOffset; - var cellSize = _ref.cellSize; - var containerSize = _ref.containerSize; - var currentOffset = _ref.currentOffset; +var _reactAddonsShallowCompare2 = _interopRequireDefault(_reactAddonsShallowCompare); - var maxOffset = cellOffset; - var minOffset = maxOffset - containerSize + cellSize; +var _raf = require('raf'); - switch (align) { - case 'start': - return maxOffset; - case 'end': - return minOffset; - case 'center': - return maxOffset - (containerSize - cellSize) / 2; - default: - return Math.max(minOffset, Math.min(maxOffset, currentOffset)); - } -} -},{}],80:[function(require,module,exports){ -'use strict'; +var _raf2 = _interopRequireDefault(_raf); -/** -* Detect Element Resize. -* Forked in order to guard against unsafe 'window' and 'document' references. -* -* https://github.com/sdecima/javascript-detect-element-resize -* Sebastian Decima -* -* version: 0.5.3 -**/ +var _onScroll = require('./utils/onScroll'); -// Check `document` and `window` in case of server-side rendering -var _window; -if (typeof window !== 'undefined') { - _window = window; -} else if (typeof self !== 'undefined') { - _window = self; -} else { - _window = undefined; -} +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -var attachEvent = typeof document !== 'undefined' && document.attachEvent; -var stylesCreated = false; +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } -if (!attachEvent) { - var requestFrame = function () { - var raf = _window.requestAnimationFrame || _window.mozRequestAnimationFrame || _window.webkitRequestAnimationFrame || function (fn) { - return _window.setTimeout(fn, 20); - }; - return function (fn) { - return raf(fn); - }; - }(); +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - var cancelFrame = function () { - var cancel = _window.cancelAnimationFrame || _window.mozCancelAnimationFrame || _window.webkitCancelAnimationFrame || _window.clearTimeout; - return function (id) { - return cancel(id); +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var WindowScroller = function (_Component) { + _inherits(WindowScroller, _Component); + + function WindowScroller(props) { + _classCallCheck(this, WindowScroller); + + var _this = _possibleConstructorReturn(this, (WindowScroller.__proto__ || Object.getPrototypeOf(WindowScroller)).call(this, props)); + + var height = typeof window !== 'undefined' ? window.innerHeight : 0; + + _this.state = { + isScrolling: false, + height: height, + scrollTop: 0 }; - }(); - var resetTriggers = function resetTriggers(element) { - var triggers = element.__resizeTriggers__, - expand = triggers.firstElementChild, - contract = triggers.lastElementChild, - expandChild = expand.firstElementChild; - contract.scrollLeft = contract.scrollWidth; - contract.scrollTop = contract.scrollHeight; - expandChild.style.width = expand.offsetWidth + 1 + 'px'; - expandChild.style.height = expand.offsetHeight + 1 + 'px'; - expand.scrollLeft = expand.scrollWidth; - expand.scrollTop = expand.scrollHeight; - }; + _this._onScrollWindow = _this._onScrollWindow.bind(_this); + _this._onResizeWindow = _this._onResizeWindow.bind(_this); + _this._enablePointerEventsAfterDelayCallback = _this._enablePointerEventsAfterDelayCallback.bind(_this); + return _this; + } - var checkTriggers = function checkTriggers(element) { - return element.offsetWidth != element.__resizeLast__.width || element.offsetHeight != element.__resizeLast__.height; - }; + _createClass(WindowScroller, [{ + key: 'componentDidMount', + value: function componentDidMount() { + var height = this.state.height; - var scrollListener = function scrollListener(e) { - var element = this; - resetTriggers(this); - if (this.__resizeRAF__) cancelFrame(this.__resizeRAF__); - this.__resizeRAF__ = requestFrame(function () { - if (checkTriggers(element)) { - element.__resizeLast__.width = element.offsetWidth; - element.__resizeLast__.height = element.offsetHeight; - element.__resizeListeners__.forEach(function (fn) { - fn.call(element, e); + // Subtract documentElement top to handle edge-case where a user is navigating back (history) from an already-scrolled bage. + // In this case the body's top position will be a negative number and this element's top will be increased (by that amount). + + this._positionFromTop = _reactDom2.default.findDOMNode(this).getBoundingClientRect().top - document.documentElement.getBoundingClientRect().top; + + if (height !== window.innerHeight) { + this.setState({ + height: window.innerHeight }); } - }); - }; - /* Detect CSS Animations support to detect element display/re-attach */ - var animation = false, - animationstring = 'animation', - keyframeprefix = '', - animationstartevent = 'animationstart', - domPrefixes = 'Webkit Moz O ms'.split(' '), - startEvents = 'webkitAnimationStart animationstart oAnimationStart MSAnimationStart'.split(' '), - pfx = ''; - { - var elm = document.createElement('fakeelement'); - if (elm.style.animationName !== undefined) { - animation = true; + (0, _onScroll.registerScrollListener)(this); + window.addEventListener('resize', this._onResizeWindow, false); + } + }, { + key: 'componentWillUnmount', + value: function componentWillUnmount() { + (0, _onScroll.unregisterScrollListener)(this); + + window.removeEventListener('resize', this._onResizeWindow, false); + } + + /** + * Updates the state during the next animation frame. + * Use this method to avoid multiple renders in a small span of time. + * This helps performance for bursty events (like onScroll). + */ + + }, { + key: '_setNextState', + value: function _setNextState(state) { + var _this2 = this; + + if (this._setNextStateAnimationFrameId) { + _raf2.default.cancel(this._setNextStateAnimationFrameId); + } + + this._setNextStateAnimationFrameId = (0, _raf2.default)(function () { + _this2._setNextStateAnimationFrameId = null; + _this2.setState(state); + }); + } + }, { + key: 'render', + value: function render() { + var children = this.props.children; + var _state = this.state; + var isScrolling = _state.isScrolling; + var scrollTop = _state.scrollTop; + var height = _state.height; + + + return _react2.default.createElement( + 'div', + null, + children({ + height: height, + isScrolling: isScrolling, + scrollTop: scrollTop + }) + ); + } + }, { + key: 'shouldComponentUpdate', + value: function shouldComponentUpdate(nextProps, nextState) { + return (0, _reactAddonsShallowCompare2.default)(this, nextProps, nextState); + } + }, { + key: '_enablePointerEventsAfterDelayCallback', + value: function _enablePointerEventsAfterDelayCallback() { + this.setState({ + isScrolling: false + }); + } + }, { + key: '_onResizeWindow', + value: function _onResizeWindow(event) { + var onResize = this.props.onResize; + + + var height = window.innerHeight || 0; + + this.setState({ height: height }); + + onResize({ height: height }); } + }, { + key: '_onScrollWindow', + value: function _onScrollWindow(event) { + var onScroll = this.props.onScroll; - if (animation === false) { - for (var i = 0; i < domPrefixes.length; i++) { - if (elm.style[domPrefixes[i] + 'AnimationName'] !== undefined) { - pfx = domPrefixes[i]; - animationstring = pfx + 'Animation'; - keyframeprefix = '-' + pfx.toLowerCase() + '-'; - animationstartevent = startEvents[i]; - animation = true; - break; - } + // In IE10+ scrollY is undefined, so we replace that with the latter + + var scrollY = 'scrollY' in window ? window.scrollY : document.documentElement.scrollTop; + + var scrollTop = Math.max(0, scrollY - this._positionFromTop); + + var state = { + isScrolling: true, + scrollTop: scrollTop + }; + + if (!this.state.isScrolling) { + this.setState(state); + } else { + this._setNextState(state); } + + onScroll({ scrollTop: scrollTop }); } - } + }]); - var animationName = 'resizeanim'; - var animationKeyframes = '@' + keyframeprefix + 'keyframes ' + animationName + ' { from { opacity: 0; } to { opacity: 0; } } '; - var animationStyle = keyframeprefix + 'animation: 1ms ' + animationName + '; '; -} + return WindowScroller; +}(_react.Component); -var createStyles = function createStyles() { - if (!stylesCreated) { - //opacity:0 works around a chrome bug https://code.google.com/p/chromium/issues/detail?id=286360 - var css = (animationKeyframes ? animationKeyframes : '') + '.resize-triggers { ' + (animationStyle ? animationStyle : '') + 'visibility: hidden; opacity: 0; } ' + '.resize-triggers, .resize-triggers > div, .contract-trigger:before { content: \" \"; display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden; } .resize-triggers > div { background: #eee; overflow: auto; } .contract-trigger:before { width: 200%; height: 200%; }', - head = document.head || document.getElementsByTagName('head')[0], - style = document.createElement('style'); +WindowScroller.propTypes = { + /** + * Function respondible for rendering children. + * This function should implement the following signature: + * ({ height, scrollTop }) => PropTypes.element + */ + children: _react.PropTypes.func.isRequired, - style.type = 'text/css'; - if (style.styleSheet) { - style.styleSheet.cssText = css; - } else { - style.appendChild(document.createTextNode(css)); - } + /** Callback to be invoked on-resize: ({ height }) */ + onResize: _react.PropTypes.func.isRequired, - head.appendChild(style); - stylesCreated = true; - } + /** Callback to be invoked on-scroll: ({ scrollTop }) */ + onScroll: _react.PropTypes.func.isRequired +}; +WindowScroller.defaultProps = { + onResize: function onResize() {}, + onScroll: function onScroll() {} }; +exports.default = WindowScroller; +},{"./utils/onScroll":74,"raf":81,"react":undefined,"react-addons-shallow-compare":18,"react-dom":undefined}],73:[function(require,module,exports){ +'use strict'; -var addResizeListener = function addResizeListener(element, fn) { - if (attachEvent) element.attachEvent('onresize', fn);else { - if (!element.__resizeTriggers__) { - if (getComputedStyle(element).position == 'static') element.style.position = 'relative'; - createStyles(); - element.__resizeLast__ = {}; - element.__resizeListeners__ = []; - (element.__resizeTriggers__ = document.createElement('div')).className = 'resize-triggers'; - element.__resizeTriggers__.innerHTML = '
' + '
'; - element.appendChild(element.__resizeTriggers__); - resetTriggers(element); - element.addEventListener('scroll', scrollListener, true); +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.IS_SCROLLING_TIMEOUT = exports.WindowScroller = exports.default = undefined; - /* Listen for a css animation to detect element display/re-attach */ - animationstartevent && element.__resizeTriggers__.addEventListener(animationstartevent, function (e) { - if (e.animationName == animationName) resetTriggers(element); - }); - } - element.__resizeListeners__.push(fn); - } -}; +var _WindowScroller2 = require('./WindowScroller'); -var removeResizeListener = function removeResizeListener(element, fn) { - if (attachEvent) element.detachEvent('onresize', fn);else { - element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1); - if (!element.__resizeListeners__.length) { - element.removeEventListener('scroll', scrollListener, true); - element.__resizeTriggers__ = !element.removeChild(element.__resizeTriggers__); - } - } -}; +var _WindowScroller3 = _interopRequireDefault(_WindowScroller2); -module.exports = { - addResizeListener: addResizeListener, - removeResizeListener: removeResizeListener -}; -},{}],81:[function(require,module,exports){ -/** - * Copyright 2013-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - */ +var _onScroll = require('./utils/onScroll'); + +var _onScroll2 = _interopRequireDefault(_onScroll); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +exports.default = _WindowScroller3.default; +exports.WindowScroller = _WindowScroller3.default; +exports.IS_SCROLLING_TIMEOUT = _onScroll2.default; +},{"./WindowScroller":72,"./utils/onScroll":74}],74:[function(require,module,exports){ 'use strict'; -var shallowEqual = require('fbjs/lib/shallowEqual'); +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.registerScrollListener = registerScrollListener; +exports.unregisterScrollListener = unregisterScrollListener; +var mountedInstances = []; +var originalBodyPointerEvents = null; +var disablePointerEventsTimeoutId = null; /** - * Does a shallow comparison for props and state. - * See ReactComponentWithPureRenderMixin - * See also https://facebook.github.io/react/docs/shallow-compare.html + * Specifies the number of miliseconds during which to disable pointer events while a scroll is in progress. + * This improves performance and makes scrolling smoother. */ -function shallowCompare(instance, nextProps, nextState) { - return !shallowEqual(instance.props, nextProps) || !shallowEqual(instance.state, nextState); -} +var IS_SCROLLING_TIMEOUT = exports.IS_SCROLLING_TIMEOUT = 150; -module.exports = shallowCompare; -},{"fbjs/lib/shallowEqual":20}],82:[function(require,module,exports){ -'use strict'; -module.exports = function (str) { - return encodeURIComponent(str).replace(/[!'()*]/g, function (c) { - return '%' + c.charCodeAt(0).toString(16).toUpperCase(); - }); -}; +function enablePointerEventsIfDisabled() { + if (disablePointerEventsTimeoutId) { + disablePointerEventsTimeoutId = null; -},{}],83:[function(require,module,exports){ -(function(self) { - 'use strict'; + document.body.style.pointerEvents = originalBodyPointerEvents; - if (self.fetch) { - return + originalBodyPointerEvents = null; } +} - var support = { - searchParams: 'URLSearchParams' in self, - iterable: 'Symbol' in self && 'iterator' in Symbol, - blob: 'FileReader' in self && 'Blob' in self && (function() { - try { - new Blob() - return true - } catch(e) { - return false - } - })(), - formData: 'FormData' in self, - arrayBuffer: 'ArrayBuffer' in self +function enablePointerEventsAfterDelayCallback() { + enablePointerEventsIfDisabled(); + mountedInstances.forEach(function (component) { + return component._enablePointerEventsAfterDelayCallback(); + }); +} + +function enablePointerEventsAfterDelay() { + if (disablePointerEventsTimeoutId) { + clearTimeout(disablePointerEventsTimeoutId); } - if (support.arrayBuffer) { - var viewClasses = [ - '[object Int8Array]', - '[object Uint8Array]', - '[object Uint8ClampedArray]', - '[object Int16Array]', - '[object Uint16Array]', - '[object Int32Array]', - '[object Uint32Array]', - '[object Float32Array]', - '[object Float64Array]' - ] + disablePointerEventsTimeoutId = setTimeout(enablePointerEventsAfterDelayCallback, IS_SCROLLING_TIMEOUT); +} - var isDataView = function(obj) { - return obj && DataView.prototype.isPrototypeOf(obj) - } +function onScrollWindow(event) { + if (originalBodyPointerEvents == null) { + originalBodyPointerEvents = document.body.style.pointerEvents; - var isArrayBufferView = ArrayBuffer.isView || function(obj) { - return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1 - } - } + document.body.style.pointerEvents = 'none'; - function normalizeName(name) { - if (typeof name !== 'string') { - name = String(name) - } - if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) { - throw new TypeError('Invalid character in header field name') - } - return name.toLowerCase() + enablePointerEventsAfterDelay(); } + mountedInstances.forEach(function (component) { + return component._onScrollWindow(event); + }); +} - function normalizeValue(value) { - if (typeof value !== 'string') { - value = String(value) - } - return value +function registerScrollListener(component) { + if (!mountedInstances.length) { + window.addEventListener('scroll', onScrollWindow); } + mountedInstances.push(component); +} - // Build a destructive iterator for the value list - function iteratorFor(items) { - var iterator = { - next: function() { - var value = items.shift() - return {done: value === undefined, value: value} - } - } - - if (support.iterable) { - iterator[Symbol.iterator] = function() { - return iterator - } +function unregisterScrollListener(component) { + mountedInstances = mountedInstances.filter(function (c) { + return c !== component; + }); + if (!mountedInstances.length) { + window.removeEventListener('scroll', onScrollWindow); + if (disablePointerEventsTimeoutId) { + clearTimeout(disablePointerEventsTimeoutId); + enablePointerEventsIfDisabled(); } - - return iterator } +} +},{}],75:[function(require,module,exports){ +'use strict'; - function Headers(headers) { - this.map = {} +Object.defineProperty(exports, "__esModule", { + value: true +}); - if (headers instanceof Headers) { - headers.forEach(function(value, name) { - this.append(name, value) - }, this) +var _ArrowKeyStepper = require('./ArrowKeyStepper'); - } else if (headers) { - Object.getOwnPropertyNames(headers).forEach(function(name) { - this.append(name, headers[name]) - }, this) - } +Object.defineProperty(exports, 'ArrowKeyStepper', { + enumerable: true, + get: function get() { + return _ArrowKeyStepper.ArrowKeyStepper; } +}); - Headers.prototype.append = function(name, value) { - name = normalizeName(name) - value = normalizeValue(value) - var oldValue = this.map[name] - this.map[name] = oldValue ? oldValue+','+value : value - } +var _AutoSizer = require('./AutoSizer'); - Headers.prototype['delete'] = function(name) { - delete this.map[normalizeName(name)] +Object.defineProperty(exports, 'AutoSizer', { + enumerable: true, + get: function get() { + return _AutoSizer.AutoSizer; } +}); - Headers.prototype.get = function(name) { - name = normalizeName(name) - return this.has(name) ? this.map[name] : null - } +var _CellMeasurer = require('./CellMeasurer'); - Headers.prototype.has = function(name) { - return this.map.hasOwnProperty(normalizeName(name)) +Object.defineProperty(exports, 'CellMeasurer', { + enumerable: true, + get: function get() { + return _CellMeasurer.CellMeasurer; } - - Headers.prototype.set = function(name, value) { - this.map[normalizeName(name)] = normalizeValue(value) +}); +Object.defineProperty(exports, 'defaultCellMeasurerCellSizeCache', { + enumerable: true, + get: function get() { + return _CellMeasurer.defaultCellSizeCache; } - - Headers.prototype.forEach = function(callback, thisArg) { - for (var name in this.map) { - if (this.map.hasOwnProperty(name)) { - callback.call(thisArg, this.map[name], name, this) - } - } +}); +Object.defineProperty(exports, 'uniformSizeCellMeasurerCellSizeCache', { + enumerable: true, + get: function get() { + return _CellMeasurer.defaultCellSizeCache; } +}); - Headers.prototype.keys = function() { - var items = [] - this.forEach(function(value, name) { items.push(name) }) - return iteratorFor(items) - } +var _Collection = require('./Collection'); - Headers.prototype.values = function() { - var items = [] - this.forEach(function(value) { items.push(value) }) - return iteratorFor(items) +Object.defineProperty(exports, 'Collection', { + enumerable: true, + get: function get() { + return _Collection.Collection; } +}); - Headers.prototype.entries = function() { - var items = [] - this.forEach(function(value, name) { items.push([name, value]) }) - return iteratorFor(items) - } +var _ColumnSizer = require('./ColumnSizer'); - if (support.iterable) { - Headers.prototype[Symbol.iterator] = Headers.prototype.entries +Object.defineProperty(exports, 'ColumnSizer', { + enumerable: true, + get: function get() { + return _ColumnSizer.ColumnSizer; } +}); - function consumed(body) { - if (body.bodyUsed) { - return Promise.reject(new TypeError('Already read')) - } - body.bodyUsed = true - } +var _FlexTable = require('./FlexTable'); - function fileReaderReady(reader) { - return new Promise(function(resolve, reject) { - reader.onload = function() { - resolve(reader.result) - } - reader.onerror = function() { - reject(reader.error) - } - }) +Object.defineProperty(exports, 'defaultFlexTableCellDataGetter', { + enumerable: true, + get: function get() { + return _FlexTable.defaultCellDataGetter; + } +}); +Object.defineProperty(exports, 'defaultFlexTableCellRenderer', { + enumerable: true, + get: function get() { + return _FlexTable.defaultCellRenderer; + } +}); +Object.defineProperty(exports, 'defaultFlexTableHeaderRenderer', { + enumerable: true, + get: function get() { + return _FlexTable.defaultHeaderRenderer; + } +}); +Object.defineProperty(exports, 'defaultFlexTableRowRenderer', { + enumerable: true, + get: function get() { + return _FlexTable.defaultRowRenderer; + } +}); +Object.defineProperty(exports, 'FlexTable', { + enumerable: true, + get: function get() { + return _FlexTable.FlexTable; + } +}); +Object.defineProperty(exports, 'FlexColumn', { + enumerable: true, + get: function get() { + return _FlexTable.FlexColumn; + } +}); +Object.defineProperty(exports, 'SortDirection', { + enumerable: true, + get: function get() { + return _FlexTable.SortDirection; + } +}); +Object.defineProperty(exports, 'SortIndicator', { + enumerable: true, + get: function get() { + return _FlexTable.SortIndicator; } +}); - function readBlobAsArrayBuffer(blob) { - var reader = new FileReader() - var promise = fileReaderReady(reader) - reader.readAsArrayBuffer(blob) - return promise +var _Grid = require('./Grid'); + +Object.defineProperty(exports, 'defaultCellRangeRenderer', { + enumerable: true, + get: function get() { + return _Grid.defaultCellRangeRenderer; + } +}); +Object.defineProperty(exports, 'Grid', { + enumerable: true, + get: function get() { + return _Grid.Grid; } +}); - function readBlobAsText(blob) { - var reader = new FileReader() - var promise = fileReaderReady(reader) - reader.readAsText(blob) - return promise +var _InfiniteLoader = require('./InfiniteLoader'); + +Object.defineProperty(exports, 'InfiniteLoader', { + enumerable: true, + get: function get() { + return _InfiniteLoader.InfiniteLoader; } +}); - function readArrayBufferAsText(buf) { - var view = new Uint8Array(buf) - var chars = new Array(view.length) +var _ScrollSync = require('./ScrollSync'); - for (var i = 0; i < view.length; i++) { - chars[i] = String.fromCharCode(view[i]) - } - return chars.join('') +Object.defineProperty(exports, 'ScrollSync', { + enumerable: true, + get: function get() { + return _ScrollSync.ScrollSync; } +}); - function bufferClone(buf) { - if (buf.slice) { - return buf.slice(0) - } else { - var view = new Uint8Array(buf.byteLength) - view.set(new Uint8Array(buf)) - return view.buffer - } +var _VirtualScroll = require('./VirtualScroll'); + +Object.defineProperty(exports, 'VirtualScroll', { + enumerable: true, + get: function get() { + return _VirtualScroll.VirtualScroll; } +}); - function Body() { - this.bodyUsed = false +var _WindowScroller = require('./WindowScroller'); - this._initBody = function(body) { - this._bodyInit = body - if (!body) { - this._bodyText = '' - } else if (typeof body === 'string') { - this._bodyText = body - } else if (support.blob && Blob.prototype.isPrototypeOf(body)) { - this._bodyBlob = body - } else if (support.formData && FormData.prototype.isPrototypeOf(body)) { - this._bodyFormData = body - } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) { - this._bodyText = body.toString() - } else if (support.arrayBuffer && support.blob && isDataView(body)) { - this._bodyArrayBuffer = bufferClone(body.buffer) - // IE 10-11 can't handle a DataView body. - this._bodyInit = new Blob([this._bodyArrayBuffer]) - } else if (support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) { - this._bodyArrayBuffer = bufferClone(body) - } else { - throw new Error('unsupported BodyInit type') - } +Object.defineProperty(exports, 'WindowScroller', { + enumerable: true, + get: function get() { + return _WindowScroller.WindowScroller; + } +}); +},{"./ArrowKeyStepper":35,"./AutoSizer":37,"./CellMeasurer":40,"./Collection":45,"./ColumnSizer":48,"./FlexTable":57,"./Grid":60,"./InfiniteLoader":67,"./ScrollSync":69,"./VirtualScroll":71,"./WindowScroller":73}],76:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = createCallbackMemoizer; +/** + * Helper utility that updates the specified callback whenever any of the specified indices have changed. + */ +function createCallbackMemoizer() { + var requireAllKeys = arguments.length <= 0 || arguments[0] === undefined ? true : arguments[0]; - if (!this.headers.get('content-type')) { - if (typeof body === 'string') { - this.headers.set('content-type', 'text/plain;charset=UTF-8') - } else if (this._bodyBlob && this._bodyBlob.type) { - this.headers.set('content-type', this._bodyBlob.type) - } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) { - this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8') - } - } - } + var cachedIndices = {}; - if (support.blob) { - this.blob = function() { - var rejected = consumed(this) - if (rejected) { - return rejected - } + return function (_ref) { + var callback = _ref.callback; + var indices = _ref.indices; - if (this._bodyBlob) { - return Promise.resolve(this._bodyBlob) - } else if (this._bodyArrayBuffer) { - return Promise.resolve(new Blob([this._bodyArrayBuffer])) - } else if (this._bodyFormData) { - throw new Error('could not read FormData body as blob') - } else { - return Promise.resolve(new Blob([this._bodyText])) - } - } + var keys = Object.keys(indices); + var allInitialized = !requireAllKeys || keys.every(function (key) { + var value = indices[key]; + return Array.isArray(value) ? value.length > 0 : value >= 0; + }); + var indexChanged = keys.length !== Object.keys(cachedIndices).length || keys.some(function (key) { + var cachedValue = cachedIndices[key]; + var value = indices[key]; - this.arrayBuffer = function() { - if (this._bodyArrayBuffer) { - return consumed(this) || Promise.resolve(this._bodyArrayBuffer) - } else { - return this.blob().then(readBlobAsArrayBuffer) - } - } - } + return Array.isArray(value) ? cachedValue.join(',') !== value.join(',') : cachedValue !== value; + }); - this.text = function() { - var rejected = consumed(this) - if (rejected) { - return rejected - } + cachedIndices = indices; - if (this._bodyBlob) { - return readBlobAsText(this._bodyBlob) - } else if (this._bodyArrayBuffer) { - return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer)) - } else if (this._bodyFormData) { - throw new Error('could not read FormData body as text') - } else { - return Promise.resolve(this._bodyText) - } + if (allInitialized && indexChanged) { + callback(indices); } + }; +} +},{}],77:[function(require,module,exports){ +'use strict'; - if (support.formData) { - this.formData = function() { - return this.text().then(decode) - } - } +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = getUpdatedOffsetForIndex; +/** + * Determines a new offset that ensures a certain cell is visible, given the current offset. + * If the cell is already visible then the current offset will be returned. + * If the current offset is too great or small, it will be adjusted just enough to ensure the specified index is visible. + * + * @param align Desired alignment within container; one of "auto" (default), "start", or "end" + * @param cellOffset Offset (x or y) position for cell + * @param cellSize Size (width or height) of cell + * @param containerSize Total size (width or height) of the container + * @param currentOffset Container's current (x or y) offset + * @return Offset to use to ensure the specified cell is visible + */ +function getUpdatedOffsetForIndex(_ref) { + var _ref$align = _ref.align; + var align = _ref$align === undefined ? 'auto' : _ref$align; + var cellOffset = _ref.cellOffset; + var cellSize = _ref.cellSize; + var containerSize = _ref.containerSize; + var currentOffset = _ref.currentOffset; - this.json = function() { - return this.text().then(JSON.parse) - } + var maxOffset = cellOffset; + var minOffset = maxOffset - containerSize + cellSize; - return this + switch (align) { + case 'start': + return maxOffset; + case 'end': + return minOffset; + case 'center': + return maxOffset - (containerSize - cellSize) / 2; + default: + return Math.max(minOffset, Math.min(maxOffset, currentOffset)); } +} +},{}],78:[function(require,module,exports){ +'use strict'; - // HTTP methods whose capitalization should be normalized - var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT'] +/** +* Detect Element Resize. +* Forked in order to guard against unsafe 'window' and 'document' references. +* +* https://github.com/sdecima/javascript-detect-element-resize +* Sebastian Decima +* +* version: 0.5.3 +**/ - function normalizeMethod(method) { - var upcased = method.toUpperCase() - return (methods.indexOf(upcased) > -1) ? upcased : method - } +// Check `document` and `window` in case of server-side rendering +var _window; +if (typeof window !== 'undefined') { + _window = window; +} else if (typeof self !== 'undefined') { + _window = self; +} else { + _window = undefined; +} - function Request(input, options) { - options = options || {} - var body = options.body +var attachEvent = typeof document !== 'undefined' && document.attachEvent; +var stylesCreated = false; - if (input instanceof Request) { - if (input.bodyUsed) { - throw new TypeError('Already read') - } - this.url = input.url - this.credentials = input.credentials - if (!options.headers) { - this.headers = new Headers(input.headers) - } - this.method = input.method - this.mode = input.mode - if (!body && input._bodyInit != null) { - body = input._bodyInit - input.bodyUsed = true - } - } else { - this.url = String(input) - } +if (!attachEvent) { + var requestFrame = function () { + var raf = _window.requestAnimationFrame || _window.mozRequestAnimationFrame || _window.webkitRequestAnimationFrame || function (fn) { + return _window.setTimeout(fn, 20); + }; + return function (fn) { + return raf(fn); + }; + }(); - this.credentials = options.credentials || this.credentials || 'omit' - if (options.headers || !this.headers) { - this.headers = new Headers(options.headers) - } - this.method = normalizeMethod(options.method || this.method || 'GET') - this.mode = options.mode || this.mode || null - this.referrer = null + var cancelFrame = function () { + var cancel = _window.cancelAnimationFrame || _window.mozCancelAnimationFrame || _window.webkitCancelAnimationFrame || _window.clearTimeout; + return function (id) { + return cancel(id); + }; + }(); - if ((this.method === 'GET' || this.method === 'HEAD') && body) { - throw new TypeError('Body not allowed for GET or HEAD requests') - } - this._initBody(body) - } + var resetTriggers = function resetTriggers(element) { + var triggers = element.__resizeTriggers__, + expand = triggers.firstElementChild, + contract = triggers.lastElementChild, + expandChild = expand.firstElementChild; + contract.scrollLeft = contract.scrollWidth; + contract.scrollTop = contract.scrollHeight; + expandChild.style.width = expand.offsetWidth + 1 + 'px'; + expandChild.style.height = expand.offsetHeight + 1 + 'px'; + expand.scrollLeft = expand.scrollWidth; + expand.scrollTop = expand.scrollHeight; + }; - Request.prototype.clone = function() { - return new Request(this, { body: this._bodyInit }) - } + var checkTriggers = function checkTriggers(element) { + return element.offsetWidth != element.__resizeLast__.width || element.offsetHeight != element.__resizeLast__.height; + }; - function decode(body) { - var form = new FormData() - body.trim().split('&').forEach(function(bytes) { - if (bytes) { - var split = bytes.split('=') - var name = split.shift().replace(/\+/g, ' ') - var value = split.join('=').replace(/\+/g, ' ') - form.append(decodeURIComponent(name), decodeURIComponent(value)) + var scrollListener = function scrollListener(e) { + var element = this; + resetTriggers(this); + if (this.__resizeRAF__) cancelFrame(this.__resizeRAF__); + this.__resizeRAF__ = requestFrame(function () { + if (checkTriggers(element)) { + element.__resizeLast__.width = element.offsetWidth; + element.__resizeLast__.height = element.offsetHeight; + element.__resizeListeners__.forEach(function (fn) { + fn.call(element, e); + }); + } + }); + }; + + /* Detect CSS Animations support to detect element display/re-attach */ + var animation = false, + animationstring = 'animation', + keyframeprefix = '', + animationstartevent = 'animationstart', + domPrefixes = 'Webkit Moz O ms'.split(' '), + startEvents = 'webkitAnimationStart animationstart oAnimationStart MSAnimationStart'.split(' '), + pfx = ''; + { + var elm = document.createElement('fakeelement'); + if (elm.style.animationName !== undefined) { + animation = true; + } + + if (animation === false) { + for (var i = 0; i < domPrefixes.length; i++) { + if (elm.style[domPrefixes[i] + 'AnimationName'] !== undefined) { + pfx = domPrefixes[i]; + animationstring = pfx + 'Animation'; + keyframeprefix = '-' + pfx.toLowerCase() + '-'; + animationstartevent = startEvents[i]; + animation = true; + break; + } } - }) - return form + } } - function parseHeaders(rawHeaders) { - var headers = new Headers() - rawHeaders.split(/\r?\n/).forEach(function(line) { - var parts = line.split(':') - var key = parts.shift().trim() - if (key) { - var value = parts.join(':').trim() - headers.append(key, value) - } - }) - return headers - } + var animationName = 'resizeanim'; + var animationKeyframes = '@' + keyframeprefix + 'keyframes ' + animationName + ' { from { opacity: 0; } to { opacity: 0; } } '; + var animationStyle = keyframeprefix + 'animation: 1ms ' + animationName + '; '; +} - Body.call(Request.prototype) +var createStyles = function createStyles() { + if (!stylesCreated) { + //opacity:0 works around a chrome bug https://code.google.com/p/chromium/issues/detail?id=286360 + var css = (animationKeyframes ? animationKeyframes : '') + '.resize-triggers { ' + (animationStyle ? animationStyle : '') + 'visibility: hidden; opacity: 0; } ' + '.resize-triggers, .resize-triggers > div, .contract-trigger:before { content: \" \"; display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden; } .resize-triggers > div { background: #eee; overflow: auto; } .contract-trigger:before { width: 200%; height: 200%; }', + head = document.head || document.getElementsByTagName('head')[0], + style = document.createElement('style'); - function Response(bodyInit, options) { - if (!options) { - options = {} + style.type = 'text/css'; + if (style.styleSheet) { + style.styleSheet.cssText = css; + } else { + style.appendChild(document.createTextNode(css)); } - this.type = 'default' - this.status = 'status' in options ? options.status : 200 - this.ok = this.status >= 200 && this.status < 300 - this.statusText = 'statusText' in options ? options.statusText : 'OK' - this.headers = new Headers(options.headers) - this.url = options.url || '' - this._initBody(bodyInit) + head.appendChild(style); + stylesCreated = true; } +}; - Body.call(Response.prototype) +var addResizeListener = function addResizeListener(element, fn) { + if (attachEvent) element.attachEvent('onresize', fn);else { + if (!element.__resizeTriggers__) { + if (getComputedStyle(element).position == 'static') element.style.position = 'relative'; + createStyles(); + element.__resizeLast__ = {}; + element.__resizeListeners__ = []; + (element.__resizeTriggers__ = document.createElement('div')).className = 'resize-triggers'; + element.__resizeTriggers__.innerHTML = '
' + '
'; + element.appendChild(element.__resizeTriggers__); + resetTriggers(element); + element.addEventListener('scroll', scrollListener, true); - Response.prototype.clone = function() { - return new Response(this._bodyInit, { - status: this.status, - statusText: this.statusText, - headers: new Headers(this.headers), - url: this.url - }) + /* Listen for a css animation to detect element display/re-attach */ + animationstartevent && element.__resizeTriggers__.addEventListener(animationstartevent, function (e) { + if (e.animationName == animationName) resetTriggers(element); + }); + } + element.__resizeListeners__.push(fn); } +}; - Response.error = function() { - var response = new Response(null, {status: 0, statusText: ''}) - response.type = 'error' - return response +var removeResizeListener = function removeResizeListener(element, fn) { + if (attachEvent) element.detachEvent('onresize', fn);else { + element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1); + if (!element.__resizeListeners__.length) { + element.removeEventListener('scroll', scrollListener, true); + element.__resizeTriggers__ = !element.removeChild(element.__resizeTriggers__); + } } +}; - var redirectStatuses = [301, 302, 303, 307, 308] +module.exports = { + addResizeListener: addResizeListener, + removeResizeListener: removeResizeListener +}; +},{}],79:[function(require,module,exports){ +'use strict'; +module.exports = !!(typeof window !== 'undefined' && window.document && window.document.createElement); +},{}],80:[function(require,module,exports){ +'use strict'; - Response.redirect = function(url, status) { - if (redirectStatuses.indexOf(status) === -1) { - throw new RangeError('Invalid status code') - } +var canUseDOM = require('./inDOM'); - return new Response(null, {status: status, headers: {location: url}}) +var size; + +module.exports = function (recalc) { + if (!size || recalc) { + if (canUseDOM) { + var scrollDiv = document.createElement('div'); + + scrollDiv.style.position = 'absolute'; + scrollDiv.style.top = '-9999px'; + scrollDiv.style.width = '50px'; + scrollDiv.style.height = '50px'; + scrollDiv.style.overflow = 'scroll'; + + document.body.appendChild(scrollDiv); + size = scrollDiv.offsetWidth - scrollDiv.clientWidth; + document.body.removeChild(scrollDiv); + } } - self.Headers = Headers - self.Request = Request - self.Response = Response + return size; +}; +},{"./inDOM":79}],81:[function(require,module,exports){ +(function (global){ +var now = require('performance-now') + , root = typeof window === 'undefined' ? global : window + , vendors = ['moz', 'webkit'] + , suffix = 'AnimationFrame' + , raf = root['request' + suffix] + , caf = root['cancel' + suffix] || root['cancelRequest' + suffix] - self.fetch = function(input, init) { - return new Promise(function(resolve, reject) { - var request = new Request(input, init) - var xhr = new XMLHttpRequest() +for(var i = 0; !raf && i < vendors.length; i++) { + raf = root[vendors[i] + 'Request' + suffix] + caf = root[vendors[i] + 'Cancel' + suffix] + || root[vendors[i] + 'CancelRequest' + suffix] +} - xhr.onload = function() { - var options = { - status: xhr.status, - statusText: xhr.statusText, - headers: parseHeaders(xhr.getAllResponseHeaders() || '') +// Some versions of FF have rAF but not cAF +if(!raf || !caf) { + var last = 0 + , id = 0 + , queue = [] + , frameDuration = 1000 / 60 + + raf = function(callback) { + if(queue.length === 0) { + var _now = now() + , next = Math.max(0, frameDuration - (_now - last)) + last = next + _now + setTimeout(function() { + var cp = queue.slice(0) + // Clear queue here to prevent + // callbacks from appending listeners + // to the current frame's queue + queue.length = 0 + for(var i = 0; i < cp.length; i++) { + if(!cp[i].cancelled) { + try{ + cp[i].callback(last) + } catch(e) { + setTimeout(function() { throw e }, 0) + } + } } - options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL') - var body = 'response' in xhr ? xhr.response : xhr.responseText - resolve(new Response(body, options)) - } + }, Math.round(next)) + } + queue.push({ + handle: ++id, + callback: callback, + cancelled: false + }) + return id + } - xhr.onerror = function() { - reject(new TypeError('Network request failed')) + caf = function(handle) { + for(var i = 0; i < queue.length; i++) { + if(queue[i].handle === handle) { + queue[i].cancelled = true } + } + } +} - xhr.ontimeout = function() { - reject(new TypeError('Network request failed')) - } +module.exports = function(fn) { + // Wrap in a new function to prevent + // `cancel` potentially being assigned + // to the native rAF function + return raf.call(root, fn) +} +module.exports.cancel = function() { + caf.apply(root, arguments) +} +module.exports.polyfill = function() { + root.requestAnimationFrame = raf + root.cancelAnimationFrame = caf +} - xhr.open(request.method, request.url, true) +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) - if (request.credentials === 'include') { - xhr.withCredentials = true - } +},{"performance-now":82}],82:[function(require,module,exports){ +(function (process){ +// Generated by CoffeeScript 1.12.2 +(function() { + var getNanoSeconds, hrtime, loadTime, moduleLoadTime, nodeLoadTime, upTime; - if ('responseType' in xhr && support.blob) { - xhr.responseType = 'blob' - } + if ((typeof performance !== "undefined" && performance !== null) && performance.now) { + module.exports = function() { + return performance.now(); + }; + } else if ((typeof process !== "undefined" && process !== null) && process.hrtime) { + module.exports = function() { + return (getNanoSeconds() - nodeLoadTime) / 1e6; + }; + hrtime = process.hrtime; + getNanoSeconds = function() { + var hr; + hr = hrtime(); + return hr[0] * 1e9 + hr[1]; + }; + moduleLoadTime = getNanoSeconds(); + upTime = process.uptime() * 1e9; + nodeLoadTime = moduleLoadTime - upTime; + } else if (Date.now) { + module.exports = function() { + return Date.now() - loadTime; + }; + loadTime = Date.now(); + } else { + module.exports = function() { + return new Date().getTime() - loadTime; + }; + loadTime = new Date().getTime(); + } - request.headers.forEach(function(value, name) { - xhr.setRequestHeader(name, value) - }) +}).call(this); - xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit) - }) - } - self.fetch.polyfill = true -})(typeof self !== 'undefined' ? self : this); -},{}]},{},[1]); + +}).call(this,require('_process')) + +},{"_process":20}]},{},[1]) +//# sourceMappingURL=data:application/json;charset:utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9yZWFjdC1jb21wb25lbnQtZ3VscC10YXNrcy9ub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvYnJvd3Nlci1wYWNrL19wcmVsdWRlLmpzIiwiL1VzZXJzL3Nlcmthbm96ZXIvcHJvamVjdHMvcmVhY3Qtc2VsZWN0L2V4YW1wbGVzL3NyYy9hcHAuanMiLCIvVXNlcnMvc2Vya2Fub3plci9wcm9qZWN0cy9yZWFjdC1zZWxlY3QvZXhhbXBsZXMvc3JjL2NvbXBvbmVudHMvQm9vbGVhblNlbGVjdC5qcyIsIi9Vc2Vycy9zZXJrYW5vemVyL3Byb2plY3RzL3JlYWN0LXNlbGVjdC9leGFtcGxlcy9zcmMvY29tcG9uZW50cy9Db250cmlidXRvcnMuanMiLCIvVXNlcnMvc2Vya2Fub3plci9wcm9qZWN0cy9yZWFjdC1zZWxlY3QvZXhhbXBsZXMvc3JjL2NvbXBvbmVudHMvQ3JlYXRhYmxlLmpzIiwiL1VzZXJzL3Nlcmthbm96ZXIvcHJvamVjdHMvcmVhY3Qtc2VsZWN0L2V4YW1wbGVzL3NyYy9jb21wb25lbnRzL0N1c3RvbUNvbXBvbmVudHMuanMiLCIvVXNlcnMvc2Vya2Fub3plci9wcm9qZWN0cy9yZWFjdC1zZWxlY3QvZXhhbXBsZXMvc3JjL2NvbXBvbmVudHMvQ3VzdG9tUmVuZGVyLmpzIiwiL1VzZXJzL3Nlcmthbm96ZXIvcHJvamVjdHMvcmVhY3Qtc2VsZWN0L2V4YW1wbGVzL3NyYy9jb21wb25lbnRzL0dpdGh1YlVzZXJzLmpzIiwiL1VzZXJzL3Nlcmthbm96ZXIvcHJvamVjdHMvcmVhY3Qtc2VsZWN0L2V4YW1wbGVzL3NyYy9jb21wb25lbnRzL011bHRpc2VsZWN0LmpzIiwiL1VzZXJzL3Nlcmthbm96ZXIvcHJvamVjdHMvcmVhY3Qtc2VsZWN0L2V4YW1wbGVzL3NyYy9jb21wb25lbnRzL051bWVyaWNTZWxlY3QuanMiLCIvVXNlcnMvc2Vya2Fub3plci9wcm9qZWN0cy9yZWFjdC1zZWxlY3QvZXhhbXBsZXMvc3JjL2NvbXBvbmVudHMvU3RhdGVzLmpzIiwiL1VzZXJzL3Nlcmthbm96ZXIvcHJvamVjdHMvcmVhY3Qtc2VsZWN0L2V4YW1wbGVzL3NyYy9jb21wb25lbnRzL1ZpcnR1YWxpemVkLmpzIiwiL1VzZXJzL3Nlcmthbm96ZXIvcHJvamVjdHMvcmVhY3Qtc2VsZWN0L2V4YW1wbGVzL3NyYy9kYXRhL2NpdGllcy5qcyIsIi9Vc2Vycy9zZXJrYW5vemVyL3Byb2plY3RzL3JlYWN0LXNlbGVjdC9leGFtcGxlcy9zcmMvZGF0YS9jb250cmlidXRvcnMuanMiLCIvVXNlcnMvc2Vya2Fub3plci9wcm9qZWN0cy9yZWFjdC1zZWxlY3QvZXhhbXBsZXMvc3JjL2RhdGEvc3RhdGVzLmpzIiwiL1VzZXJzL3Nlcmthbm96ZXIvcHJvamVjdHMvcmVhY3Qtc2VsZWN0L2V4YW1wbGVzL3NyYy9kYXRhL3VzZXJzLmpzIiwibm9kZV9tb2R1bGVzL2lzb21vcnBoaWMtZmV0Y2gvZmV0Y2gtbnBtLWJyb3dzZXJpZnkuanMiLCJub2RlX21vZHVsZXMvaXNvbW9ycGhpYy1mZXRjaC9ub2RlX21vZHVsZXMvd2hhdHdnLWZldGNoL2ZldGNoLmpzIiwibm9kZV9tb2R1bGVzL3JlYWN0LWFkZG9ucy1zaGFsbG93LWNvbXBhcmUvaW5kZXguanMiLCJub2RlX21vZHVsZXMvcmVhY3QtYWRkb25zLXNoYWxsb3ctY29tcGFyZS9ub2RlX21vZHVsZXMvZmJqcy9saWIvc2hhbGxvd0VxdWFsLmpzIiwibm9kZV9tb2R1bGVzL3JlYWN0LWNvbXBvbmVudC1ndWxwLXRhc2tzL25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9wcm9jZXNzL2Jyb3dzZXIuanMiLCJub2RlX21vZHVsZXMvcmVhY3QtZ3JhdmF0YXIvZGlzdC9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9yZWFjdC1ncmF2YXRhci9ub2RlX21vZHVsZXMvaXMtcmV0aW5hL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3JlYWN0LWdyYXZhdGFyL25vZGVfbW9kdWxlcy9tZDUvbWQ1LmpzIiwibm9kZV9tb2R1bGVzL3JlYWN0LWdyYXZhdGFyL25vZGVfbW9kdWxlcy9tZDUvbm9kZV9tb2R1bGVzL2NoYXJlbmMvY2hhcmVuYy5qcyIsIm5vZGVfbW9kdWxlcy9yZWFjdC1ncmF2YXRhci9ub2RlX21vZHVsZXMvbWQ1L25vZGVfbW9kdWxlcy9jcnlwdC9jcnlwdC5qcyIsIm5vZGVfbW9kdWxlcy9yZWFjdC1ncmF2YXRhci9ub2RlX21vZHVsZXMvbWQ1L25vZGVfbW9kdWxlcy9pcy1idWZmZXIvaW5kZXguanMiLCJub2RlX21vZHVsZXMvcmVhY3QtZ3JhdmF0YXIvbm9kZV9tb2R1bGVzL3F1ZXJ5LXN0cmluZy9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9yZWFjdC1ncmF2YXRhci9ub2RlX21vZHVsZXMvcXVlcnktc3RyaW5nL25vZGVfbW9kdWxlcy9vYmplY3QtYXNzaWduL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3JlYWN0LWdyYXZhdGFyL25vZGVfbW9kdWxlcy9xdWVyeS1zdHJpbmcvbm9kZV9tb2R1bGVzL3N0cmljdC11cmktZW5jb2RlL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3JlYWN0LWhpZ2hsaWdodC13b3Jkcy9kaXN0L21haW4uanMiLCJub2RlX21vZHVsZXMvcmVhY3QtdmlydHVhbGl6ZWQtc2VsZWN0L2Rpc3QvY29tbW9uanMvVmlydHVhbGl6ZWRTZWxlY3QvVmlydHVhbGl6ZWRTZWxlY3QuanMiLCJub2RlX21vZHVsZXMvcmVhY3QtdmlydHVhbGl6ZWQtc2VsZWN0L2Rpc3QvY29tbW9uanMvVmlydHVhbGl6ZWRTZWxlY3QvaW5kZXguanMiLCJub2RlX21vZHVsZXMvcmVhY3QtdmlydHVhbGl6ZWQvZGlzdC9jb21tb25qcy9BcnJvd0tleVN0ZXBwZXIvQXJyb3dLZXlTdGVwcGVyLmpzIiwibm9kZV9tb2R1bGVzL3JlYWN0LXZpcnR1YWxpemVkL2Rpc3QvY29tbW9uanMvQXJyb3dLZXlTdGVwcGVyL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3JlYWN0LXZpcnR1YWxpemVkL2Rpc3QvY29tbW9uanMvQXV0b1NpemVyL0F1dG9TaXplci5qcyIsIm5vZGVfbW9kdWxlcy9yZWFjdC12aXJ0dWFsaXplZC9kaXN0L2NvbW1vbmpzL0F1dG9TaXplci9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9yZWFjdC12aXJ0dWFsaXplZC9kaXN0L2NvbW1vbmpzL0NlbGxNZWFzdXJlci9DZWxsTWVhc3VyZXIuanMiLCJub2RlX21vZHVsZXMvcmVhY3QtdmlydHVhbGl6ZWQvZGlzdC9jb21tb25qcy9DZWxsTWVhc3VyZXIvZGVmYXVsdENlbGxTaXplQ2FjaGUuanMiLCJub2RlX21vZHVsZXMvcmVhY3QtdmlydHVhbGl6ZWQvZGlzdC9jb21tb25qcy9DZWxsTWVhc3VyZXIvaW5kZXguanMiLCJub2RlX21vZHVsZXMvcmVhY3QtdmlydHVhbGl6ZWQvZGlzdC9jb21tb25qcy9Db2xsZWN0aW9uL0NvbGxlY3Rpb24uanMiLCJub2RlX21vZHVsZXMvcmVhY3QtdmlydHVhbGl6ZWQvZGlzdC9jb21tb25qcy9Db2xsZWN0aW9uL0NvbGxlY3Rpb25WaWV3LmpzIiwibm9kZV9tb2R1bGVzL3JlYWN0LXZpcnR1YWxpemVkL2Rpc3QvY29tbW9uanMvQ29sbGVjdGlvbi9TZWN0aW9uLmpzIiwibm9kZV9tb2R1bGVzL3JlYWN0LXZpcnR1YWxpemVkL2Rpc3QvY29tbW9uanMvQ29sbGVjdGlvbi9TZWN0aW9uTWFuYWdlci5qcyIsIm5vZGVfbW9kdWxlcy9yZWFjdC12aXJ0dWFsaXplZC9kaXN0L2NvbW1vbmpzL0NvbGxlY3Rpb24vaW5kZXguanMiLCJub2RlX21vZHVsZXMvcmVhY3QtdmlydHVhbGl6ZWQvZGlzdC9jb21tb25qcy9Db2xsZWN0aW9uL3V0aWxzL2NhbGN1bGF0ZVNpemVBbmRQb3NpdGlvbkRhdGEuanMiLCJub2RlX21vZHVsZXMvcmVhY3QtdmlydHVhbGl6ZWQvZGlzdC9jb21tb25qcy9Db2x1bW5TaXplci9Db2x1bW5TaXplci5qcyIsIm5vZGVfbW9kdWxlcy9yZWFjdC12aXJ0dWFsaXplZC9kaXN0L2NvbW1vbmpzL0NvbHVtblNpemVyL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3JlYWN0LXZpcnR1YWxpemVkL2Rpc3QvY29tbW9uanMvRmxleFRhYmxlL0ZsZXhDb2x1bW4uanMiLCJub2RlX21vZHVsZXMvcmVhY3QtdmlydHVhbGl6ZWQvZGlzdC9jb21tb25qcy9GbGV4VGFibGUvRmxleFRhYmxlLmpzIiwibm9kZV9tb2R1bGVzL3JlYWN0LXZpcnR1YWxpemVkL2Rpc3QvY29tbW9uanMvRmxleFRhYmxlL1NvcnREaXJlY3Rpb24uanMiLCJub2RlX21vZHVsZXMvcmVhY3QtdmlydHVhbGl6ZWQvZGlzdC9jb21tb25qcy9GbGV4VGFibGUvU29ydEluZGljYXRvci5qcyIsIm5vZGVfbW9kdWxlcy9yZWFjdC12aXJ0dWFsaXplZC9kaXN0L2NvbW1vbmpzL0ZsZXhUYWJsZS9kZWZhdWx0Q2VsbERhdGFHZXR0ZXIuanMiLCJub2RlX21vZHVsZXMvcmVhY3QtdmlydHVhbGl6ZWQvZGlzdC9jb21tb25qcy9GbGV4VGFibGUvZGVmYXVsdENlbGxSZW5kZXJlci5qcyIsIm5vZGVfbW9kdWxlcy9yZWFjdC12aXJ0dWFsaXplZC9kaXN0L2NvbW1vbmpzL0ZsZXhUYWJsZS9kZWZhdWx0SGVhZGVyUmVuZGVyZXIuanMiLCJub2RlX21vZHVsZXMvcmVhY3QtdmlydHVhbGl6ZWQvZGlzdC9jb21tb25qcy9GbGV4VGFibGUvZGVmYXVsdFJvd1JlbmRlcmVyLmpzIiwibm9kZV9tb2R1bGVzL3JlYWN0LXZpcnR1YWxpemVkL2Rpc3QvY29tbW9uanMvRmxleFRhYmxlL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3JlYWN0LXZpcnR1YWxpemVkL2Rpc3QvY29tbW9uanMvR3JpZC9HcmlkLmpzIiwibm9kZV9tb2R1bGVzL3JlYWN0LXZpcnR1YWxpemVkL2Rpc3QvY29tbW9uanMvR3JpZC9kZWZhdWx0Q2VsbFJhbmdlUmVuZGVyZXIuanMiLCJub2RlX21vZHVsZXMvcmVhY3QtdmlydHVhbGl6ZWQvZGlzdC9jb21tb25qcy9HcmlkL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3JlYWN0LXZpcnR1YWxpemVkL2Rpc3QvY29tbW9uanMvR3JpZC91dGlscy9DZWxsU2l6ZUFuZFBvc2l0aW9uTWFuYWdlci5qcyIsIm5vZGVfbW9kdWxlcy9yZWFjdC12aXJ0dWFsaXplZC9kaXN0L2NvbW1vbmpzL0dyaWQvdXRpbHMvU2NhbGluZ0NlbGxTaXplQW5kUG9zaXRpb25NYW5hZ2VyLmpzIiwibm9kZV9tb2R1bGVzL3JlYWN0LXZpcnR1YWxpemVkL2Rpc3QvY29tbW9uanMvR3JpZC91dGlscy9jYWxjdWxhdGVTaXplQW5kUG9zaXRpb25EYXRhQW5kVXBkYXRlU2Nyb2xsT2Zmc2V0LmpzIiwibm9kZV9tb2R1bGVzL3JlYWN0LXZpcnR1YWxpemVkL2Rpc3QvY29tbW9uanMvR3JpZC91dGlscy9nZXRPdmVyc2NhbkluZGljZXMuanMiLCJub2RlX21vZHVsZXMvcmVhY3QtdmlydHVhbGl6ZWQvZGlzdC9jb21tb25qcy9HcmlkL3V0aWxzL3VwZGF0ZVNjcm9sbEluZGV4SGVscGVyLmpzIiwibm9kZV9tb2R1bGVzL3JlYWN0LXZpcnR1YWxpemVkL2Rpc3QvY29tbW9uanMvSW5maW5pdGVMb2FkZXIvSW5maW5pdGVMb2FkZXIuanMiLCJub2RlX21vZHVsZXMvcmVhY3QtdmlydHVhbGl6ZWQvZGlzdC9jb21tb25qcy9JbmZpbml0ZUxvYWRlci9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9yZWFjdC12aXJ0dWFsaXplZC9kaXN0L2NvbW1vbmpzL1Njcm9sbFN5bmMvU2Nyb2xsU3luYy5qcyIsIm5vZGVfbW9kdWxlcy9yZWFjdC12aXJ0dWFsaXplZC9kaXN0L2NvbW1vbmpzL1Njcm9sbFN5bmMvaW5kZXguanMiLCJub2RlX21vZHVsZXMvcmVhY3QtdmlydHVhbGl6ZWQvZGlzdC9jb21tb25qcy9WaXJ0dWFsU2Nyb2xsL1ZpcnR1YWxTY3JvbGwuanMiLCJub2RlX21vZHVsZXMvcmVhY3QtdmlydHVhbGl6ZWQvZGlzdC9jb21tb25qcy9WaXJ0dWFsU2Nyb2xsL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3JlYWN0LXZpcnR1YWxpemVkL2Rpc3QvY29tbW9uanMvV2luZG93U2Nyb2xsZXIvV2luZG93U2Nyb2xsZXIuanMiLCJub2RlX21vZHVsZXMvcmVhY3QtdmlydHVhbGl6ZWQvZGlzdC9jb21tb25qcy9XaW5kb3dTY3JvbGxlci9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9yZWFjdC12aXJ0dWFsaXplZC9kaXN0L2NvbW1vbmpzL1dpbmRvd1Njcm9sbGVyL3V0aWxzL29uU2Nyb2xsLmpzIiwibm9kZV9tb2R1bGVzL3JlYWN0LXZpcnR1YWxpemVkL2Rpc3QvY29tbW9uanMvaW5kZXguanMiLCJub2RlX21vZHVsZXMvcmVhY3QtdmlydHVhbGl6ZWQvZGlzdC9jb21tb25qcy91dGlscy9jcmVhdGVDYWxsYmFja01lbW9pemVyLmpzIiwibm9kZV9tb2R1bGVzL3JlYWN0LXZpcnR1YWxpemVkL2Rpc3QvY29tbW9uanMvdXRpbHMvZ2V0VXBkYXRlZE9mZnNldEZvckluZGV4LmpzIiwibm9kZV9tb2R1bGVzL3JlYWN0LXZpcnR1YWxpemVkL2Rpc3QvY29tbW9uanMvdmVuZG9yL2RldGVjdEVsZW1lbnRSZXNpemUuanMiLCJub2RlX21vZHVsZXMvcmVhY3QtdmlydHVhbGl6ZWQvbm9kZV9tb2R1bGVzL2RvbS1oZWxwZXJzL3V0aWwvaW5ET00uanMiLCJub2RlX21vZHVsZXMvcmVhY3QtdmlydHVhbGl6ZWQvbm9kZV9tb2R1bGVzL2RvbS1oZWxwZXJzL3V0aWwvc2Nyb2xsYmFyU2l6ZS5qcyIsIm5vZGVfbW9kdWxlcy9yZWFjdC12aXJ0dWFsaXplZC9ub2RlX21vZHVsZXMvcmFmL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3JlYWN0LXZpcnR1YWxpemVkL25vZGVfbW9kdWxlcy9yYWYvbm9kZV9tb2R1bGVzL3BlcmZvcm1hbmNlLW5vdy9saWIvcGVyZm9ybWFuY2Utbm93LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7O3FCQ0VrQixPQUFPOzs7O3dCQUNK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QUUsRUFDM0IsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLEVBQ3BCLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxFQUNwQixFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsRUFDdkIsRUFBRSxJQUFJLEVBQUUsY0FBYyxFQUFFLEVBQ3hCLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxFQUNuQixFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsRUFDbkIsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLEVBQ3BCLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxFQUNwQixFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsRUFDdkIsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLEVBQ3JCLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxFQUNuQixFQUFFLElBQUksRUFBRSxjQUFjLEVBQUUsRUFDeEIsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLEVBQ3RCLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxFQUNwQixFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsRUFDcEIsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLEVBQ3RCLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxFQUN0QixFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsRUFDbEIsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLEVBQ2hCLEVBQUUsSUFBSSxFQUFFLGFBQWEsRUFBRSxFQUN2QixFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsRUFDcEIsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLEVBQ2xCLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxFQUNyQixFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsRUFDbkIsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLEVBQ3BCLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxFQUNsQixFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsRUFDdEIsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLEVBQ3RCLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFB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bkIsRUFBRSxJQUFJLEVBQUUsY0FBYyxFQUFFLEVBQ3hCLEVBQUUsSUFBSSxFQUFFLGlCQUFpQixFQUFFLEVBQzNCLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxFQUN0QixFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsRUFDdkIsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLEVBQ3RCLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxFQUN0QixFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsRUFDdEIsRUFBRSxJQUFJLEVBQUUsaUJBQWlCLEVBQUUsRUFDM0IsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLEVBQ3BCLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxFQUNyQixFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsRUFDcEIsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLEVBQ25CLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxFQUNsQixFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsRUFDdkIsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLEVBQ2xCLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxFQUNyQixFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsRUFDdkIsRUFBRSxJQUFJLEVBQUUsY0FBYyxFQUFFLEVBQ3hCLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxFQUNyQixFQUFFLElBQUksRUFBRSxjQUFjLEVBQUUsRUFDeEIsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLEVBQ25CLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxFQUNuQixFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsRUFDaEIsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLEVBQ3BCLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxFQUN0QixFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsRUFDdEIsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLEVBQ25CLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxFQUNsQixFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUs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RUFBRSxRQUFRLEVBQUUsRUFDbEIsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLEVBQ3JCLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxFQUNsQixFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsRUFDbkIsRUFBRSxJQUFJLEVBQUUsZUFBZSxFQUFFLEVBQ3pCLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxFQUNyQixFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsRUFDdEIsRUFBRSxJQUFJLEVBQUUsYUFBYSxFQUFFLEVBQ3ZCLEVBQUUsSUFBSSxFQUFFLGFBQWEsRUFBRSxFQUN2QixFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsRUFDbEIsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLEVBQ2xCLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxFQUNsQixFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsRUFDbEIsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLEVBQ3JCLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxFQUNuQixFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsRUFDaEIsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLEVBQ3BCLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxFQUNyQixFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsRUFDbkIsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLEVBQ3JCLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxFQUNwQixFQUFFLElBQUksRUFBRSxXQUFXLEVBQUUsRUFDckIsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLEVBQ3JCLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxFQUNsQixFQUFFLElBQUksRUFBRSxXQUFXLEVBQUUsRUFDckIsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLEVBQ3BCLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxFQUNuQixFQUFFLElBQUksRUFBRSxXQUFXLEVBQUUsRUFDckIsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLEVBQ3JCLEVBQUUsSUFBSSxF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QUksRUFBRSxVQUFVLEVBQUUsRUFDcEIsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLEVBQ2xCLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxFQUNuQixFQUFFLElBQUksRUFBRSxXQUFXLEVBQUUsRUFDckIsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLEVBQ2hCLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxFQUNuQixFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsRUFDakIsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLEVBQ2xCLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxFQUNuQixFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsRUFDbkIsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLEVBQ2xCLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxFQUNwQixFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsRUFDdEIsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLEVBQ3JCLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxFQUNuQixFQUFFLElBQUksRUFBRSxXQUFXLEVBQUUsRUFDckIsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLEVBQ3JCLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxFQUNuQixFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsRUFDdkIsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLEVBQ3JCLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxFQUNsQixFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsRUFDbkIsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLEVBQ3BCLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxFQUNwQixFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsRUFDdkIsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLEVBQ3BCLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxFQUN0QixFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsRUFDbkIsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLEVBQ3BCLEVBQUUsSUFB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LEVBQUUsV0FBVyxFQUFFLEVBQ3JCLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxFQUNuQixFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsRUFDbkIsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLEVBQ3RCLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxFQUNuQixFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsRUFDZixFQUFFLElBQUksRUFBRSxXQUFXLEVBQUUsRUFDckIsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLEVBQ3RCLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxFQUNuQixFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsRUFDakIsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLEVBQ2pCLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxFQUNsQixFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsRUFDbkIsRUFBRSxJQUFJLEVBQUUsZ0JBQWdCLEVBQUUsRUFDMUIsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLEVBQ3JCLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxFQUN0QixFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsRUFDdkIsRUFBRSxJQUFJLEVBQUUsZ0JBQWdCLEVBQUUsRUFDMUIsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLEVBQ3JCLEVBQUUsSUFBSSxFQUFFLDRCQUE0QixFQUFFLEVBQ3RDLEVBQUUsSUFBSSxFQUFFLGNBQWMsRUFBRSxFQUN4QixFQUFFLElBQUksRUFBRSxXQUFXLEVBQUUsRUFDckIsRUFBRSxJQUFJLEVBQUUsZUFBZSxFQUFFLEVBQ3pCLEVBQUUsSUFBSSxFQUFFLGFBQWEsRUFBRSxFQUN2QixFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsRUFDdkIsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLEVBQ3BCLEVBQUUsSUFBSSxFQUFFLGFBQWEsRUFBRSxFQUN2QixFQUFFLElBQUksRUFBRSxpQkFBaUIsRUFBRSxFQUMzQixFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsRUFDdEIsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLEVBQ3RCLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxFQUNyQixFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsRUFDdEIsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLEVBQ3JCLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxFQUNqQixFQUFFLElBQUksRUFBRSxlQUFlLEVBQUUsRUFDekIsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLEVBQ25CLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxFQUNyQixFQUFFLElBQUksRUFBRSxlQUFlLEVBQUUsRUFDekIsRUFBRSxJQUFJLEVBQUUsYUFBYSxFQUFFLEVBQ3ZCLEVBQUUsSUFBSSxFQUFFLGVBQWUsRUFBRSxFQUN6QixFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsRUFDdEIsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLEVBQ3BCLEVBQUUsSUFBSSxFQUFFLGFBQWEsRUFBRSxFQUN2QixFQUFFLElBQUksRUFBRSxjQUFjLEVBQUUsRUFDeEIsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLEVBQ3RCLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxFQUNsQixFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsRUFDcEIsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLEVBQ3BCLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxFQUN0QixFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsRUFDdEIsRUFBRSxJQUFJLEVBQUUsYUFBYSxFQUFFLEVBQ3ZCLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxFQUN0QixFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsRUFDcEIsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLEVBQ25CLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxFQUNwQixFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsRUFDbkIsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLEVBQ3JCLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxFQUNuQixFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsRUFDbkIsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLEVBQ3JCLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxFQUN0QixFQUFFLElBQUksRUFBRSxjQUFjLEVBQUUsRUFDeEIsRUFBRSxJQUFJLEVBQUUsYUFBYSxFQUFFLEVBQ3ZCLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxFQUN0QixFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsRUFDdkIsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLEVBQ2xCLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxFQUNsQixFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsRUFDbEIsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLEVBQ3RCLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxFQUN0QixFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsRUFDdEIsRUFBRSxJQUFJLEVBQUUsY0FBYyxFQUFFLEVBQ3hCLEVBQUUsSUFBSSxFQUFFLHFCQUFxQixFQUFFLEVBQy9CLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxFQUNyQixFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsRUFDdEIsRUFBRSxJQUFJLEVBQUUsY0FBYyxFQUFFLEVBQ3hCLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxFQUNsQixFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsRUFDdkIsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLEVBQ25CLEVBQUUsSUFBSSxFQUFFLGdCQUFnQixFQUFFLEVBQzFCLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxFQUN0QixFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsRUFDdkIsRUFBRSxJQUFJLEVBQUUsYUFBYSxFQUFFLEVBQ3ZCLEVBQUUsSUFBSSxFQUFFLGFBQWEsRUFBRSxFQUN2QixFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsRUFDdkIsRUFBRSxJQUFJLEVBQUUsYUFBYSxFQUFFLEVBQ3ZCLEVBQUUsSUFBSSxFQUFFLGFBQWEsRUFBRSxFQUN2QixF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LElBQUksRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLEVBQ2xDLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLEVBQ2pDLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLEVBQzlCLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLEVBQ2hDLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLEVBQ2xDLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsV0FBVyxFQUFFLEVBQ25DLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQy9CLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsa0JBQWtCLEVBQUUsRUFDMUMsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUUsRUFDbEMsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxlQUFlLEVBQUUsRUFDdkMsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUUsRUFDbEMsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxXQUFXLEVBQUUsRUFDbkMsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxhQUFhLEVBQUUsRUFDckMsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUUsRUFDbEMsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsRUFDakMsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUUsRUFDbEMsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsRUFDaEMsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxlQUFlLEVBQUUs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QTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3Y0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeExBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNySkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNiQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvUUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcE9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUNiQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNkQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeFRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaFVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNscUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3R0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RwQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9DQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoaENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdk5BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNkQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25LQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqS0E7QUFDQTs7QUNEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDeEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7OztBQ3hFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt2YXIgZj1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpO3Rocm93IGYuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixmfXZhciBsPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChsLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGwsbC5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfSkiLCIvKiBlc2xpbnQgcmVhY3QvcHJvcC10eXBlczogMCAqL1xuXG5pbXBvcnQgUmVhY3QgZnJvbSAncmVhY3QnO1xuaW1wb3J0IFJlYWN0RE9NIGZyb20gJ3JlYWN0LWRvbSc7XG5pbXBvcnQgU2VsZWN0IGZyb20gJ3JlYWN0LXNlbGVjdCc7XG5cbmltcG9ydCBDcmVhdGFibGUgZnJvbSAnLi9jb21wb25lbnRzL0NyZWF0YWJsZSc7XG5pbXBvcnQgQ29udHJpYnV0b3JzIGZyb20gJy4vY29tcG9uZW50cy9Db250cmlidXRvcnMnO1xuaW1wb3J0IEdpdGh1YlVzZXJzIGZyb20gJy4vY29tcG9uZW50cy9HaXRodWJVc2Vycyc7XG5pbXBvcnQgQ3VzdG9tQ29tcG9uZW50cyBmcm9tICcuL2NvbXBvbmVudHMvQ3VzdG9tQ29tcG9uZW50cyc7XG5pbXBvcnQgQ3VzdG9tUmVuZGVyIGZyb20gJy4vY29tcG9uZW50cy9DdXN0b21SZW5kZXInO1xuaW1wb3J0IE11bHRpc2VsZWN0IGZyb20gJy4vY29tcG9uZW50cy9NdWx0aXNlbGVjdCc7XG5pbXBvcnQgTnVtZXJpY1NlbGVjdCBmcm9tICcuL2NvbXBvbmVudHMvTnVtZXJpY1NlbGVjdCc7XG5pbXBvcnQgQm9vbGVhblNlbGVjdCBmcm9tICcuL2NvbXBvbmVudHMvQm9vbGVhblNlbGVjdCc7XG5pbXBvcnQgVmlydHVhbGl6ZWQgZnJvbSAnLi9jb21wb25lbnRzL1ZpcnR1YWxpemVkJztcbmltcG9ydCBTdGF0ZXMgZnJvbSAnLi9jb21wb25lbnRzL1N0YXRlcyc7XG5cblJlYWN0RE9NLnJlbmRlcihcblx0PGRpdj5cblx0XHQ8U3RhdGVzIGxhYmVsPVwiU3RhdGVzXCIgc2VhcmNoYWJsZSAvPlxuXHRcdDxNdWx0aXNlbGVjdCBsYWJlbD1cIk11bHRpc2VsZWN0XCIgLz5cblx0XHQ8VmlydHVhbGl6ZWQgbGFiZWw9XCJWaXJ0dWFsaXplZFwiIC8+XG5cdFx0PENvbnRyaWJ1dG9ycyBsYWJlbD1cIkNvbnRyaWJ1dG9ycyAoQXN5bmMpXCIgLz5cblx0XHQ8R2l0aHViVXNlcnMgbGFiZWw9XCJHaXRodWIgdXNlcnMgKEFzeW5jIHdpdGggZmV0Y2guanMpXCIgLz5cblx0XHQ8TnVtZXJpY1NlbGVjdCBsYWJlbD1cIk51bWVyaWMgVmFsdWVzXCIgLz5cblx0XHQ8Qm9vbGVhblNlbGVjdCBsYWJlbD1cIkJvb2xlYW4gVmFsdWVzXCIgLz5cblx0XHQ8Q3VzdG9tUmVuZGVyIGxhYmVsPVwiQ3VzdG9tIFJlbmRlciBNZXRob2RzXCIvPlxuXHRcdDxDdXN0b21Db21wb25lbnRzIGxhYmVsPVwiQ3VzdG9tIFBsYWNlaG9sZGVyLCBPcHRpb24sIFZhbHVlLCBhbmQgQXJyb3cgQ29tcG9uZW50c1wiIC8+XG5cdFx0PENyZWF0YWJsZVxuXHRcdFx0aGludD1cIkVudGVyIGEgdmFsdWUgdGhhdCdzIE5PVCBpbiB0aGUgbGlzdCwgdGhlbiBoaXQgcmV0dXJuXCJcblx0XHRcdGxhYmVsPVwiQ3VzdG9tIHRhZyBjcmVhdGlvblwiXG5cdFx0Lz5cblx0PC9kaXY+LFxuXHRkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZXhhbXBsZScpXG4pO1xuIiwiaW1wb3J0IFJlYWN0IGZyb20gJ3JlYWN0JztcbmltcG9ydCBjcmVhdGVDbGFzcyBmcm9tICdjcmVhdGUtcmVhY3QtY2xhc3MnO1xuaW1wb3J0IFByb3BUeXBlcyBmcm9tICdwcm9wLXR5cGVzJztcbmltcG9ydCBTZWxlY3QgZnJvbSAncmVhY3Qtc2VsZWN0JztcblxudmFyIFZhbHVlc0FzQm9vbGVhbnNGaWVsZCA9IGNyZWF0ZUNsYXNzKHtcblx0ZGlzcGxheU5hbWU6ICdWYWx1ZXNBc0Jvb2xlYW5zRmllbGQnLFxuXHRwcm9wVHlwZXM6IHtcblx0XHRsYWJlbDogUHJvcFR5cGVzLnN0cmluZ1xuXHR9LFxuXHRnZXRJbml0aWFsU3RhdGUgKCkge1xuXHRcdHJldHVybiB7XG5cdFx0XHRvcHRpb25zOiBbXG5cdFx0XHRcdHsgdmFsdWU6IHRydWUsIGxhYmVsOiAnWWVzJyB9LFxuXHRcdFx0XHR7IHZhbHVlOiBmYWxzZSwgbGFiZWw6ICdObycgfVxuXHRcdFx0XSxcblx0XHRcdHZhbHVlOiBudWxsXG5cdFx0fTtcblx0fSxcblx0b25DaGFuZ2UodmFsdWUpIHtcblx0XHR0aGlzLnNldFN0YXRlKHsgdmFsdWUgfSk7XG5cdFx0Y29uc29sZS5sb2coJ0Jvb2xlYW4gU2VsZWN0IHZhbHVlIGNoYW5nZWQgdG8nLCB2YWx1ZSk7XG5cdH0sXG5cdHJlbmRlciAoKSB7XG5cdFx0cmV0dXJuIChcblx0XHRcdDxkaXYgY2xhc3NOYW1lPVwic2VjdGlvblwiPlxuXHRcdFx0XHQ8aDMgY2xhc3NOYW1lPVwic2VjdGlvbi1oZWFkaW5nXCI+e3RoaXMucHJvcHMubGFiZWx9PC9oMz5cblx0XHRcdFx0PFNlbGVjdFxuXHRcdFx0XHRcdG9uQ2hhbmdlPXt0aGlzLm9uQ2hhbmdlfVxuXHRcdFx0XHRcdG9wdGlvbnM9e3RoaXMuc3RhdGUub3B0aW9uc31cblx0XHRcdFx0XHRzaW1wbGVWYWx1ZVxuXHRcdFx0XHRcdHZhbHVlPXt0aGlzLnN0YXRlLnZhbHVlfVxuXHRcdFx0XHRcdC8+XG5cdFx0XHRcdDxkaXYgY2xhc3NOYW1lPVwiaGludFwiPlRoaXMgZXhhbXBsZSB1c2VzIHNpbXBsZSBib29sZWFuIHZhbHVlczwvZGl2PlxuXHRcdFx0PC9kaXY+XG5cdFx0KTtcblx0fVxufSk7XG5cbm1vZHVsZS5leHBvcnRzID0gVmFsdWVzQXNCb29sZWFuc0ZpZWxkO1xuIiwiaW1wb3J0IFJlYWN0IGZyb20gJ3JlYWN0JztcbmltcG9ydCBjcmVhdGVDbGFzcyBmcm9tICdjcmVhdGUtcmVhY3QtY2xhc3MnO1xuaW1wb3J0IFByb3BUeXBlcyBmcm9tICdwcm9wLXR5cGVzJztcbmltcG9ydCBTZWxlY3QgZnJvbSAncmVhY3Qtc2VsZWN0JztcblxuY29uc3QgQ09OVFJJQlVUT1JTID0gcmVxdWlyZSgnLi4vZGF0YS9jb250cmlidXRvcnMnKTtcbmNvbnN0IE1BWF9DT05UUklCVVRPUlMgPSA2O1xuY29uc3QgQVNZTkNfREVMQVkgPSA1MDA7XG5cbmNvbnN0IENvbnRyaWJ1dG9ycyA9IGNyZWF0ZUNsYXNzKHtcblx0ZGlzcGxheU5hbWU6ICdDb250cmlidXRvcnMnLFxuXHRwcm9wVHlwZXM6IHtcblx0XHRsYWJlbDogUHJvcFR5cGVzLnN0cmluZyxcblx0fSxcblx0Z2V0SW5pdGlhbFN0YXRlICgpIHtcblx0XHRyZXR1cm4ge1xuXHRcdFx0bXVsdGk6IHRydWUsXG5cdFx0XHR2YWx1ZTogW0NPTlRSSUJVVE9SU1swXV0sXG5cdFx0fTtcblx0fSxcblx0b25DaGFuZ2UgKHZhbHVlKSB7XG5cdFx0dGhpcy5zZXRTdGF0ZSh7XG5cdFx0XHR2YWx1ZTogdmFsdWUsXG5cdFx0fSk7XG5cdH0sXG5cdHN3aXRjaFRvTXVsdGkgKCkge1xuXHRcdHRoaXMuc2V0U3RhdGUoe1xuXHRcdFx0bXVsdGk6IHRydWUsXG5cdFx0XHR2YWx1ZTogW3RoaXMuc3RhdGUudmFsdWVdLFxuXHRcdH0pO1xuXHR9LFxuXHRzd2l0Y2hUb1NpbmdsZSAoKSB7XG5cdFx0dGhpcy5zZXRTdGF0ZSh7XG5cdFx0XHRtdWx0aTogZmFsc2UsXG5cdFx0XHR2YWx1ZTogdGhpcy5zdGF0ZS52YWx1ZVswXSxcblx0XHR9KTtcblx0fSxcblx0Z2V0Q29udHJpYnV0b3JzIChpbnB1dCwgY2FsbGJhY2spIHtcblx0XHRpbnB1dCA9IGlucHV0LnRvTG93ZXJDYXNlKCk7XG5cdFx0dmFyIG9wdGlvbnMgPSBDT05UUklCVVRPUlMuZmlsdGVyKGkgPT4ge1xuXHRcdFx0cmV0dXJuIGkuZ2l0aHViLnN1YnN0cigwLCBpbnB1dC5sZW5ndGgpID09PSBpbnB1dDtcblx0XHR9KTtcblx0XHR2YXIgZGF0YSA9IHtcblx0XHRcdG9wdGlvbnM6IG9wdGlvbnMuc2xpY2UoMCwgTUFYX0NPTlRSSUJVVE9SUyksXG5cdFx0XHRjb21wbGV0ZTogb3B0aW9ucy5sZW5ndGggPD0gTUFYX0NPTlRSSUJVVE9SUyxcblx0XHR9O1xuXHRcdHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG5cdFx0XHRjYWxsYmFjayhudWxsLCBkYXRhKTtcblx0XHR9LCBBU1lOQ19ERUxBWSk7XG5cdH0sXG5cdGdvdG9Db250cmlidXRvciAodmFsdWUsIGV2ZW50KSB7XG5cdFx0d2luZG93Lm9wZW4oJ2h0dHBzOi8vZ2l0aHViLmNvbS8nICsgdmFsdWUuZ2l0aHViKTtcblx0fSxcblx0cmVuZGVyICgpIHtcblx0XHRyZXR1cm4gKFxuXHRcdFx0PGRpdiBjbGFzc05hbWU9XCJzZWN0aW9uXCI+XG5cdFx0XHRcdDxoMyBjbGFzc05hbWU9XCJzZWN0aW9uLWhlYWRpbmdcIj57dGhpcy5wcm9wcy5sYWJlbH08L2gzPlxuXHRcdFx0XHQ8U2VsZWN0LkFzeW5jIG11bHRpPXt0aGlzLnN0YXRlLm11bHRpfSB2YWx1ZT17dGhpcy5zdGF0ZS52YWx1ZX0gb25DaGFuZ2U9e3RoaXMub25DaGFuZ2V9IG9uVmFsdWVDbGljaz17dGhpcy5nb3RvQ29udHJpYnV0b3J9IHZhbHVlS2V5PVwiZ2l0aHViXCIgbGFiZWxLZXk9XCJuYW1lXCIgbG9hZE9wdGlvbnM9e3RoaXMuZ2V0Q29udHJpYnV0b3JzfSAvPlxuXHRcdFx0XHQ8ZGl2IGNsYXNzTmFtZT1cImNoZWNrYm94LWxpc3RcIj5cblx0XHRcdFx0XHQ8bGFiZWwgY2xhc3NOYW1lPVwiY2hlY2tib3hcIj5cblx0XHRcdFx0XHRcdDxpbnB1dCB0eXBlPVwicmFkaW9cIiBjbGFzc05hbWU9XCJjaGVja2JveC1jb250cm9sXCIgY2hlY2tlZD17dGhpcy5zdGF0ZS5tdWx0aX0gb25DaGFuZ2U9e3RoaXMuc3dpdGNoVG9NdWx0aX0vPlxuXHRcdFx0XHRcdFx0PHNwYW4gY2xhc3NOYW1lPVwiY2hlY2tib3gtbGFiZWxcIj5NdWx0aXNlbGVjdDwvc3Bhbj5cblx0XHRcdFx0XHQ8L2xhYmVsPlxuXHRcdFx0XHRcdDxsYWJlbCBjbGFzc05hbWU9XCJjaGVja2JveFwiPlxuXHRcdFx0XHRcdFx0PGlucHV0IHR5cGU9XCJyYWRpb1wiIGNsYXNzTmFtZT1cImNoZWNrYm94LWNvbnRyb2xcIiBjaGVja2VkPXshdGhpcy5zdGF0ZS5tdWx0aX0gb25DaGFuZ2U9e3RoaXMuc3dpdGNoVG9TaW5nbGV9Lz5cblx0XHRcdFx0XHRcdDxzcGFuIGNsYXNzTmFtZT1cImNoZWNrYm94LWxhYmVsXCI+U2luZ2xlIFZhbHVlPC9zcGFuPlxuXHRcdFx0XHRcdDwvbGFiZWw+XG5cdFx0XHRcdDwvZGl2PlxuXHRcdFx0XHQ8ZGl2IGNsYXNzTmFtZT1cImhpbnRcIj5UaGlzIGV4YW1wbGUgaW1wbGVtZW50cyBjdXN0b20gbGFiZWwgYW5kIHZhbHVlIHByb3BlcnRpZXMsIGFzeW5jIG9wdGlvbnMgYW5kIG9wZW5zIHRoZSBnaXRodWIgcHJvZmlsZXMgaW4gYSBuZXcgd2luZG93IHdoZW4gdmFsdWVzIGFyZSBjbGlja2VkPC9kaXY+XG5cdFx0XHQ8L2Rpdj5cblx0XHQpO1xuXHR9XG59KTtcblxubW9kdWxlLmV4cG9ydHMgPSBDb250cmlidXRvcnM7XG4iLCJpbXBvcnQgUmVhY3QgZnJvbSAncmVhY3QnO1xuaW1wb3J0IGNyZWF0ZUNsYXNzIGZyb20gJ2NyZWF0ZS1yZWFjdC1jbGFzcyc7XG5pbXBvcnQgUHJvcFR5cGVzIGZyb20gJ3Byb3AtdHlwZXMnO1xuaW1wb3J0IFNlbGVjdCBmcm9tICdyZWFjdC1zZWxlY3QnO1xuXG52YXIgQ3JlYXRhYmxlRGVtbyA9IGNyZWF0ZUNsYXNzKHtcblx0ZGlzcGxheU5hbWU6ICdDcmVhdGFibGVEZW1vJyxcblx0cHJvcFR5cGVzOiB7XG5cdFx0aGludDogUHJvcFR5cGVzLnN0cmluZyxcblx0XHRsYWJlbDogUHJvcFR5cGVzLnN0cmluZ1xuXHR9LFxuXHRnZXRJbml0aWFsU3RhdGUgKCkge1xuXHRcdHJldHVybiB7XG5cdFx0XHRtdWx0aTogdHJ1ZSxcblx0XHRcdG11bHRpVmFsdWU6IFtdLFxuXHRcdFx0b3B0aW9uczogW1xuXHRcdFx0XHR7IHZhbHVlOiAnUicsIGxhYmVsOiAnUmVkJyB9LFxuXHRcdFx0XHR7IHZhbHVlOiAnRycsIGxhYmVsOiAnR3JlZW4nIH0sXG5cdFx0XHRcdHsgdmFsdWU6ICdCJywgbGFiZWw6ICdCbHVlJyB9XG5cdFx0XHRdLFxuXHRcdFx0dmFsdWU6IHVuZGVmaW5lZFxuXHRcdH07XG5cdH0sXG5cdGhhbmRsZU9uQ2hhbmdlICh2YWx1ZSkge1xuXHRcdGNvbnN0IHsgbXVsdGkgfSA9IHRoaXMuc3RhdGU7XG5cdFx0aWYgKG11bHRpKSB7XG5cdFx0XHR0aGlzLnNldFN0YXRlKHsgbXVsdGlWYWx1ZTogdmFsdWUgfSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuc2V0U3RhdGUoeyB2YWx1ZSB9KTtcblx0XHR9XG5cdH0sXG5cdHJlbmRlciAoKSB7XG5cdFx0Y29uc3QgeyBtdWx0aSwgbXVsdGlWYWx1ZSwgb3B0aW9ucywgdmFsdWUgfSA9IHRoaXMuc3RhdGU7XG5cdFx0cmV0dXJuIChcblx0XHRcdDxkaXYgY2xhc3NOYW1lPVwic2VjdGlvblwiPlxuXHRcdFx0XHQ8aDMgY2xhc3NOYW1lPVwic2VjdGlvbi1oZWFkaW5nXCI+e3RoaXMucHJvcHMubGFiZWx9PC9oMz5cblx0XHRcdFx0PFNlbGVjdC5DcmVhdGFibGVcblx0XHRcdFx0XHRtdWx0aT17bXVsdGl9XG5cdFx0XHRcdFx0b3B0aW9ucz17b3B0aW9uc31cblx0XHRcdFx0XHRvbkNoYW5nZT17dGhpcy5oYW5kbGVPbkNoYW5nZX1cblx0XHRcdFx0XHR2YWx1ZT17bXVsdGkgPyBtdWx0aVZhbHVlIDogdmFsdWV9XG5cdFx0XHRcdC8+XG5cdFx0XHRcdDxkaXYgY2xhc3NOYW1lPVwiaGludFwiPnt0aGlzLnByb3BzLmhpbnR9PC9kaXY+XG5cdFx0XHRcdDxkaXYgY2xhc3NOYW1lPVwiY2hlY2tib3gtbGlzdFwiPlxuXHRcdFx0XHRcdDxsYWJlbCBjbGFzc05hbWU9XCJjaGVja2JveFwiPlxuXHRcdFx0XHRcdFx0PGlucHV0XG5cdFx0XHRcdFx0XHRcdHR5cGU9XCJyYWRpb1wiXG5cdFx0XHRcdFx0XHRcdGNsYXNzTmFtZT1cImNoZWNrYm94LWNvbnRyb2xcIlxuXHRcdFx0XHRcdFx0XHRjaGVja2VkPXttdWx0aX1cblx0XHRcdFx0XHRcdFx0b25DaGFuZ2U9eygpID0+IHRoaXMuc2V0U3RhdGUoeyBtdWx0aTogdHJ1ZSB9KX1cblx0XHRcdFx0XHRcdC8+XG5cdFx0XHRcdFx0XHQ8c3BhbiBjbGFzc05hbWU9XCJjaGVja2JveC1sYWJlbFwiPk11bHRpc2VsZWN0PC9zcGFuPlxuXHRcdFx0XHRcdDwvbGFiZWw+XG5cdFx0XHRcdFx0PGxhYmVsIGNsYXNzTmFtZT1cImNoZWNrYm94XCI+XG5cdFx0XHRcdFx0XHQ8aW5wdXRcblx0XHRcdFx0XHRcdFx0dHlwZT1cInJhZGlvXCJcblx0XHRcdFx0XHRcdFx0Y2xhc3NOYW1lPVwiY2hlY2tib3gtY29udHJvbFwiXG5cdFx0XHRcdFx0XHRcdGNoZWNrZWQ9eyFtdWx0aX1cblx0XHRcdFx0XHRcdFx0b25DaGFuZ2U9eygpID0+IHRoaXMuc2V0U3RhdGUoeyBtdWx0aTogZmFsc2UgfSl9XG5cdFx0XHRcdFx0XHQvPlxuXHRcdFx0XHRcdFx0PHNwYW4gY2xhc3NOYW1lPVwiY2hlY2tib3gtbGFiZWxcIj5TaW5nbGUgVmFsdWU8L3NwYW4+XG5cdFx0XHRcdFx0PC9sYWJlbD5cblx0XHRcdFx0PC9kaXY+XG5cdFx0XHQ8L2Rpdj5cblx0XHQpO1xuXHR9XG59KTtcblxubW9kdWxlLmV4cG9ydHMgPSBDcmVhdGFibGVEZW1vO1xuIiwiaW1wb3J0IFJlYWN0IGZyb20gJ3JlYWN0JztcbmltcG9ydCBjcmVhdGVDbGFzcyBmcm9tICdjcmVhdGUtcmVhY3QtY2xhc3MnO1xuaW1wb3J0IFByb3BUeXBlcyBmcm9tICdwcm9wLXR5cGVzJztcbmltcG9ydCBTZWxlY3QgZnJvbSAncmVhY3Qtc2VsZWN0JztcbmltcG9ydCBHcmF2YXRhciBmcm9tICdyZWFjdC1ncmF2YXRhcic7XG5cbmNvbnN0IFVTRVJTID0gcmVxdWlyZSgnLi4vZGF0YS91c2VycycpO1xuY29uc3QgR1JBVkFUQVJfU0laRSA9IDE1O1xuXG5jb25zdCBHcmF2YXRhck9wdGlvbiA9IGNyZWF0ZUNsYXNzKHtcblx0cHJvcFR5cGVzOiB7XG5cdFx0Y2hpbGRyZW46IFByb3BUeXBlcy5ub2RlLFxuXHRcdGNsYXNzTmFtZTogUHJvcFR5cGVzLnN0cmluZyxcblx0XHRpc0Rpc2FibGVkOiBQcm9wVHlwZXMuYm9vbCxcblx0XHRpc0ZvY3VzZWQ6IFByb3BUeXBlcy5ib29sLFxuXHRcdGlzU2VsZWN0ZWQ6IFByb3BUeXBlcy5ib29sLFxuXHRcdG9uRm9jdXM6IFByb3BUeXBlcy5mdW5jLFxuXHRcdG9uU2VsZWN0OiBQcm9wVHlwZXMuZnVuYyxcblx0XHRvcHRpb246IFByb3BUeXBlcy5vYmplY3QuaXNSZXF1aXJlZCxcblx0fSxcblx0aGFuZGxlTW91c2VEb3duIChldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0ZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cdFx0dGhpcy5wcm9wcy5vblNlbGVjdCh0aGlzLnByb3BzLm9wdGlvbiwgZXZlbnQpO1xuXHR9LFxuXHRoYW5kbGVNb3VzZUVudGVyIChldmVudCkge1xuXHRcdHRoaXMucHJvcHMub25Gb2N1cyh0aGlzLnByb3BzLm9wdGlvbiwgZXZlbnQpO1xuXHR9LFxuXHRoYW5kbGVNb3VzZU1vdmUgKGV2ZW50KSB7XG5cdFx0aWYgKHRoaXMucHJvcHMuaXNGb2N1c2VkKSByZXR1cm47XG5cdFx0dGhpcy5wcm9wcy5vbkZvY3VzKHRoaXMucHJvcHMub3B0aW9uLCBldmVudCk7XG5cdH0sXG5cdHJlbmRlciAoKSB7XG5cdFx0bGV0IGdyYXZhdGFyU3R5bGUgPSB7XG5cdFx0XHRib3JkZXJSYWRpdXM6IDMsXG5cdFx0XHRkaXNwbGF5OiAnaW5saW5lLWJsb2NrJyxcblx0XHRcdG1hcmdpblJpZ2h0OiAxMCxcblx0XHRcdHBvc2l0aW9uOiAncmVsYXRpdmUnLFxuXHRcdFx0dG9wOiAtMixcblx0XHRcdHZlcnRpY2FsQWxpZ246ICdtaWRkbGUnLFxuXHRcdH07XG5cdFx0cmV0dXJuIChcblx0XHRcdDxkaXYgY2xhc3NOYW1lPXt0aGlzLnByb3BzLmNsYXNzTmFtZX1cblx0XHRcdFx0b25Nb3VzZURvd249e3RoaXMuaGFuZGxlTW91c2VEb3dufVxuXHRcdFx0XHRvbk1vdXNlRW50ZXI9e3RoaXMuaGFuZGxlTW91c2VFbnRlcn1cblx0XHRcdFx0b25Nb3VzZU1vdmU9e3RoaXMuaGFuZGxlTW91c2VNb3ZlfVxuXHRcdFx0XHR0aXRsZT17dGhpcy5wcm9wcy5vcHRpb24udGl0bGV9PlxuXHRcdFx0XHQ8R3JhdmF0YXIgZW1haWw9e3RoaXMucHJvcHMub3B0aW9uLmVtYWlsfSBzaXplPXtHUkFWQVRBUl9TSVpFfSBzdHlsZT17Z3JhdmF0YXJTdHlsZX0gLz5cblx0XHRcdFx0e3RoaXMucHJvcHMuY2hpbGRyZW59XG5cdFx0XHQ8L2Rpdj5cblx0XHQpO1xuXHR9XG59KTtcblxuY29uc3QgR3JhdmF0YXJWYWx1ZSA9IGNyZWF0ZUNsYXNzKHtcblx0cHJvcFR5cGVzOiB7XG5cdFx0Y2hpbGRyZW46IFByb3BUeXBlcy5ub2RlLFxuXHRcdHBsYWNlaG9sZGVyOiBQcm9wVHlwZXMuc3RyaW5nLFxuXHRcdHZhbHVlOiBQcm9wVHlwZXMub2JqZWN0XG5cdH0sXG5cdHJlbmRlciAoKSB7XG5cdFx0dmFyIGdyYXZhdGFyU3R5bGUgPSB7XG5cdFx0XHRib3JkZXJSYWRpdXM6IDMsXG5cdFx0XHRkaXNwbGF5OiAnaW5saW5lLWJsb2NrJyxcblx0XHRcdG1hcmdpblJpZ2h0OiAxMCxcblx0XHRcdHBvc2l0aW9uOiAncmVsYXRpdmUnLFxuXHRcdFx0dG9wOiAtMixcblx0XHRcdHZlcnRpY2FsQWxpZ246ICdtaWRkbGUnLFxuXHRcdH07XG5cdFx0cmV0dXJuIChcblx0XHRcdDxkaXYgY2xhc3NOYW1lPVwiU2VsZWN0LXZhbHVlXCIgdGl0bGU9e3RoaXMucHJvcHMudmFsdWUudGl0bGV9PlxuXHRcdFx0XHQ8c3BhbiBjbGFzc05hbWU9XCJTZWxlY3QtdmFsdWUtbGFiZWxcIj5cblx0XHRcdFx0XHQ8R3JhdmF0YXIgZW1haWw9e3RoaXMucHJvcHMudmFsdWUuZW1haWx9IHNpemU9e0dSQVZBVEFSX1NJWkV9IHN0eWxlPXtncmF2YXRhclN0eWxlfSAvPlxuXHRcdFx0XHRcdHt0aGlzLnByb3BzLmNoaWxkcmVufVxuXHRcdFx0XHQ8L3NwYW4+XG5cdFx0XHQ8L2Rpdj5cblx0XHQpO1xuXHR9XG59KTtcblxuY29uc3QgVXNlcnNGaWVsZCA9IGNyZWF0ZUNsYXNzKHtcblx0cHJvcFR5cGVzOiB7XG5cdFx0aGludDogUHJvcFR5cGVzLnN0cmluZyxcblx0XHRsYWJlbDogUHJvcFR5cGVzLnN0cmluZyxcblx0fSxcblx0Z2V0SW5pdGlhbFN0YXRlICgpIHtcblx0XHRyZXR1cm4ge307XG5cdH0sXG5cdHNldFZhbHVlICh2YWx1ZSkge1xuXHRcdHRoaXMuc2V0U3RhdGUoeyB2YWx1ZSB9KTtcblx0fSxcblx0cmVuZGVyICgpIHtcblx0XHR2YXIgcGxhY2Vob2xkZXIgPSA8c3Bhbj4mIzk3ODY7IFNlbGVjdCBVc2VyPC9zcGFuPjtcblxuXHRcdHJldHVybiAoXG5cdFx0XHQ8ZGl2IGNsYXNzTmFtZT1cInNlY3Rpb25cIj5cblx0XHRcdFx0PGgzIGNsYXNzTmFtZT1cInNlY3Rpb24taGVhZGluZ1wiPnt0aGlzLnByb3BzLmxhYmVsfTwvaDM+XG5cdFx0XHRcdDxTZWxlY3Rcblx0XHRcdFx0XHRhcnJvd1JlbmRlcmVyPXthcnJvd1JlbmRlcmVyfVxuXHRcdFx0XHRcdG9uQ2hhbmdlPXt0aGlzLnNldFZhbHVlfVxuXHRcdFx0XHRcdG9wdGlvbkNvbXBvbmVudD17R3JhdmF0YXJPcHRpb259XG5cdFx0XHRcdFx0b3B0aW9ucz17VVNFUlN9XG5cdFx0XHRcdFx0cGxhY2Vob2xkZXI9e3BsYWNlaG9sZGVyfVxuXHRcdFx0XHRcdHZhbHVlPXt0aGlzLnN0YXRlLnZhbHVlfVxuXHRcdFx0XHRcdHZhbHVlQ29tcG9uZW50PXtHcmF2YXRhclZhbHVlfVxuXHRcdFx0XHRcdC8+XG5cdFx0XHRcdDxkaXYgY2xhc3NOYW1lPVwiaGludFwiPlxuXHRcdFx0XHRcdFRoaXMgZXhhbXBsZSBpbXBsZW1lbnRzIGN1c3RvbSBPcHRpb24gYW5kIFZhbHVlIGNvbXBvbmVudHMgdG8gcmVuZGVyIGEgR3JhdmF0YXIgaW1hZ2UgZm9yIGVhY2ggdXNlciBiYXNlZCBvbiB0aGVpciBlbWFpbC5cblx0XHRcdFx0XHRJdCBhbHNvIGRlbW9uc3RyYXRlcyByZW5kZXJpbmcgSFRNTCBlbGVtZW50cyBhcyB0aGUgcGxhY2Vob2xkZXIuXG5cdFx0XHRcdDwvZGl2PlxuXHRcdFx0PC9kaXY+XG5cdFx0KTtcblx0fVxufSk7XG5cbmZ1bmN0aW9uIGFycm93UmVuZGVyZXIgKCkge1xuXHRyZXR1cm4gKFxuXHRcdDxzcGFuPis8L3NwYW4+XG5cdCk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gVXNlcnNGaWVsZDtcbiIsImltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCc7XG5pbXBvcnQgY3JlYXRlQ2xhc3MgZnJvbSAnY3JlYXRlLXJlYWN0LWNsYXNzJztcbmltcG9ydCBQcm9wVHlwZXMgZnJvbSAncHJvcC10eXBlcyc7XG5pbXBvcnQgU2VsZWN0IGZyb20gJ3JlYWN0LXNlbGVjdCc7XG5pbXBvcnQgSGlnaGxpZ2h0ZXIgZnJvbSAncmVhY3QtaGlnaGxpZ2h0LXdvcmRzJztcblxudmFyIERpc2FibGVkVXBzZWxsT3B0aW9ucyA9IGNyZWF0ZUNsYXNzKHtcblx0ZGlzcGxheU5hbWU6ICdEaXNhYmxlZFVwc2VsbE9wdGlvbnMnLFxuXHRwcm9wVHlwZXM6IHtcblx0XHRsYWJlbDogUHJvcFR5cGVzLnN0cmluZyxcblx0fSxcblx0Z2V0SW5pdGlhbFN0YXRlICgpIHtcblx0XHRyZXR1cm4ge307XG5cdH0sXG5cdHNldFZhbHVlICh2YWx1ZSkge1xuXHRcdHRoaXMuc2V0U3RhdGUoeyB2YWx1ZSB9KTtcblx0XHRpZiAodmFsdWUpIHtcblx0XHRcdGNvbnNvbGUubG9nKCdTdXBwb3J0IGxldmVsIHNlbGVjdGVkOicsIHZhbHVlLmxhYmVsKTtcblx0XHR9XG5cdH0sXG5cdHJlbmRlckxpbms6IGZ1bmN0aW9uKCkge1xuXHRcdHJldHVybiA8YSBzdHlsZT17eyBtYXJnaW5MZWZ0OiA1IH19IGhyZWY9XCIvdXBncmFkZVwiIHRhcmdldD1cIl9ibGFua1wiPlVwZ3JhZGUgaGVyZSE8L2E+O1xuXHR9LFxuXHRyZW5kZXJPcHRpb246IGZ1bmN0aW9uKG9wdGlvbikge1xuXHRcdHJldHVybiAoXG5cdFx0XHQ8SGlnaGxpZ2h0ZXJcblx0XHRcdCAgc2VhcmNoV29yZHM9e1t0aGlzLl9pbnB1dFZhbHVlXX1cblx0XHRcdCAgdGV4dFRvSGlnaGxpZ2h0PXtvcHRpb24ubGFiZWx9XG5cdFx0XHQvPlxuXHRcdCk7XG5cdH0sXG5cdHJlbmRlclZhbHVlOiBmdW5jdGlvbihvcHRpb24pIHtcblx0XHRyZXR1cm4gPHN0cm9uZyBzdHlsZT17eyBjb2xvcjogb3B0aW9uLmNvbG9yIH19PntvcHRpb24ubGFiZWx9PC9zdHJvbmc+O1xuXHR9LFxuXHRyZW5kZXI6IGZ1bmN0aW9uKCkge1xuXHRcdHZhciBvcHRpb25zID0gW1xuXHRcdFx0eyBsYWJlbDogJ0Jhc2ljIGN1c3RvbWVyIHN1cHBvcnQnLCB2YWx1ZTogJ2Jhc2ljJywgY29sb3I6ICcjRTMxODY0JyB9LFxuXHRcdFx0eyBsYWJlbDogJ1ByZW1pdW0gY3VzdG9tZXIgc3VwcG9ydCcsIHZhbHVlOiAncHJlbWl1bScsIGNvbG9yOiAnIzYyMTZBMycgfSxcblx0XHRcdHsgbGFiZWw6ICdQcm8gY3VzdG9tZXIgc3VwcG9ydCcsIHZhbHVlOiAncHJvJywgZGlzYWJsZWQ6IHRydWUsIGxpbms6IHRoaXMucmVuZGVyTGluaygpIH0sXG5cdFx0XTtcblx0XHRyZXR1cm4gKFxuXHRcdFx0PGRpdiBjbGFzc05hbWU9XCJzZWN0aW9uXCI+XG5cdFx0XHRcdDxoMyBjbGFzc05hbWU9XCJzZWN0aW9uLWhlYWRpbmdcIj57dGhpcy5wcm9wcy5sYWJlbH08L2gzPlxuXHRcdFx0XHQ8U2VsZWN0XG5cdFx0XHRcdFx0b25JbnB1dENoYW5nZT17KGlucHV0VmFsdWUpID0+IHRoaXMuX2lucHV0VmFsdWUgPSBpbnB1dFZhbHVlfVxuXHRcdFx0XHRcdG9wdGlvbnM9e29wdGlvbnN9XG5cdFx0XHRcdFx0b3B0aW9uUmVuZGVyZXI9e3RoaXMucmVuZGVyT3B0aW9ufVxuXHRcdFx0XHRcdG9uQ2hhbmdlPXt0aGlzLnNldFZhbHVlfVxuXHRcdFx0XHRcdHZhbHVlPXt0aGlzLnN0YXRlLnZhbHVlfVxuXHRcdFx0XHRcdHZhbHVlUmVuZGVyZXI9e3RoaXMucmVuZGVyVmFsdWV9XG5cdFx0XHRcdFx0Lz5cblx0XHRcdFx0PGRpdiBjbGFzc05hbWU9XCJoaW50XCI+VGhpcyBkZW1vbnN0YXRlcyBjdXN0b20gcmVuZGVyIG1ldGhvZHMgYW5kIGxpbmtzIGluIGRpc2FibGVkIG9wdGlvbnM8L2Rpdj5cblx0XHRcdDwvZGl2PlxuXHRcdCk7XG5cdH1cbn0pO1xubW9kdWxlLmV4cG9ydHMgPSBEaXNhYmxlZFVwc2VsbE9wdGlvbnM7XG4iLCJpbXBvcnQgUmVhY3QgZnJvbSAncmVhY3QnO1xuaW1wb3J0IGNyZWF0ZUNsYXNzIGZyb20gJ2NyZWF0ZS1yZWFjdC1jbGFzcyc7XG5pbXBvcnQgUHJvcFR5cGVzIGZyb20gJ3Byb3AtdHlwZXMnO1xuaW1wb3J0IFNlbGVjdCBmcm9tICdyZWFjdC1zZWxlY3QnO1xuaW1wb3J0IGZldGNoIGZyb20gJ2lzb21vcnBoaWMtZmV0Y2gnO1xuXG5cbmNvbnN0IEdpdGh1YlVzZXJzID0gY3JlYXRlQ2xhc3Moe1xuXHRkaXNwbGF5TmFtZTogJ0dpdGh1YlVzZXJzJyxcblx0cHJvcFR5cGVzOiB7XG5cdFx0bGFiZWw6IFByb3BUeXBlcy5zdHJpbmcsXG5cdH0sXG5cdGdldEluaXRpYWxTdGF0ZSAoKSB7XG5cdFx0cmV0dXJuIHtcblx0XHRcdGJhY2tzcGFjZVJlbW92ZXM6IHRydWUsXG5cdFx0XHRtdWx0aTogdHJ1ZVxuXHRcdH07XG5cdH0sXG5cdG9uQ2hhbmdlICh2YWx1ZSkge1xuXHRcdHRoaXMuc2V0U3RhdGUoe1xuXHRcdFx0dmFsdWU6IHZhbHVlLFxuXHRcdH0pO1xuXHR9LFxuXHRzd2l0Y2hUb011bHRpICgpIHtcblx0XHR0aGlzLnNldFN0YXRlKHtcblx0XHRcdG11bHRpOiB0cnVlLFxuXHRcdFx0dmFsdWU6IFt0aGlzLnN0YXRlLnZhbHVlXSxcblx0XHR9KTtcblx0fSxcblx0c3dpdGNoVG9TaW5nbGUgKCkge1xuXHRcdHRoaXMuc2V0U3RhdGUoe1xuXHRcdFx0bXVsdGk6IGZhbHNlLFxuXHRcdFx0dmFsdWU6IHRoaXMuc3RhdGUudmFsdWUgPyB0aGlzLnN0YXRlLnZhbHVlWzBdIDogbnVsbFxuXHRcdH0pO1xuXHR9LFxuXHRnZXRVc2VycyAoaW5wdXQpIHtcblx0XHRpZiAoIWlucHV0KSB7XG5cdFx0XHRyZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHsgb3B0aW9uczogW10gfSk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGZldGNoKGBodHRwczovL2FwaS5naXRodWIuY29tL3NlYXJjaC91c2Vycz9xPSR7aW5wdXR9YClcblx0XHQudGhlbigocmVzcG9uc2UpID0+IHJlc3BvbnNlLmpzb24oKSlcblx0XHQudGhlbigoanNvbikgPT4ge1xuXHRcdFx0cmV0dXJuIHsgb3B0aW9uczoganNvbi5pdGVtcyB9O1xuXHRcdH0pO1xuXHR9LFxuXHRnb3RvVXNlciAodmFsdWUsIGV2ZW50KSB7XG5cdFx0d2luZG93Lm9wZW4odmFsdWUuaHRtbF91cmwpO1xuXHR9LFxuXHR0b2dnbGVCYWNrc3BhY2VSZW1vdmVzICgpIHtcblx0XHR0aGlzLnNldFN0YXRlKHtcblx0XHRcdGJhY2tzcGFjZVJlbW92ZXM6ICF0aGlzLnN0YXRlLmJhY2tzcGFjZVJlbW92ZXNcblx0XHR9KTtcblx0fSxcblx0dG9nZ2xlQ3JlYXRhYmxlICgpIHtcblx0XHR0aGlzLnNldFN0YXRlKHtcblx0XHRcdGNyZWF0YWJsZTogIXRoaXMuc3RhdGUuY3JlYXRhYmxlXG5cdFx0fSk7XG5cdH0sXG5cdHJlbmRlciAoKSB7XG5cdFx0Y29uc3QgQXN5bmNDb21wb25lbnQgPSB0aGlzLnN0YXRlLmNyZWF0YWJsZVxuXHRcdFx0PyBTZWxlY3QuQXN5bmNDcmVhdGFibGVcblx0XHRcdDogU2VsZWN0LkFzeW5jO1xuXG5cdFx0cmV0dXJuIChcblx0XHRcdDxkaXYgY2xhc3NOYW1lPVwic2VjdGlvblwiPlxuXHRcdFx0XHQ8aDMgY2xhc3NOYW1lPVwic2VjdGlvbi1oZWFkaW5nXCI+e3RoaXMucHJvcHMubGFiZWx9PC9oMz5cblx0XHRcdFx0PEFzeW5jQ29tcG9uZW50IG11bHRpPXt0aGlzLnN0YXRlLm11bHRpfSB2YWx1ZT17dGhpcy5zdGF0ZS52YWx1ZX0gb25DaGFuZ2U9e3RoaXMub25DaGFuZ2V9IG9uVmFsdWVDbGljaz17dGhpcy5nb3RvVXNlcn0gdmFsdWVLZXk9XCJpZFwiIGxhYmVsS2V5PVwibG9naW5cIiBsb2FkT3B0aW9ucz17dGhpcy5nZXRVc2Vyc30gYmFja3NwYWNlUmVtb3Zlcz17dGhpcy5zdGF0ZS5iYWNrc3BhY2VSZW1vdmVzfSAvPlxuXHRcdFx0XHQ8ZGl2IGNsYXNzTmFtZT1cImNoZWNrYm94LWxpc3RcIj5cblx0XHRcdFx0XHQ8bGFiZWwgY2xhc3NOYW1lPVwiY2hlY2tib3hcIj5cblx0XHRcdFx0XHRcdDxpbnB1dCB0eXBlPVwicmFkaW9cIiBjbGFzc05hbWU9XCJjaGVja2JveC1jb250cm9sXCIgY2hlY2tlZD17dGhpcy5zdGF0ZS5tdWx0aX0gb25DaGFuZ2U9e3RoaXMuc3dpdGNoVG9NdWx0aX0vPlxuXHRcdFx0XHRcdFx0PHNwYW4gY2xhc3NOYW1lPVwiY2hlY2tib3gtbGFiZWxcIj5NdWx0aXNlbGVjdDwvc3Bhbj5cblx0XHRcdFx0XHQ8L2xhYmVsPlxuXHRcdFx0XHRcdDxsYWJlbCBjbGFzc05hbWU9XCJjaGVja2JveFwiPlxuXHRcdFx0XHRcdFx0PGlucHV0IHR5cGU9XCJyYWRpb1wiIGNsYXNzTmFtZT1cImNoZWNrYm94LWNvbnRyb2xcIiBjaGVja2VkPXshdGhpcy5zdGF0ZS5tdWx0aX0gb25DaGFuZ2U9e3RoaXMuc3dpdGNoVG9TaW5nbGV9Lz5cblx0XHRcdFx0XHRcdDxzcGFuIGNsYXNzTmFtZT1cImNoZWNrYm94LWxhYmVsXCI+U2luZ2xlIFZhbHVlPC9zcGFuPlxuXHRcdFx0XHRcdDwvbGFiZWw+XG5cdFx0XHRcdDwvZGl2PlxuXHRcdFx0XHQ8ZGl2IGNsYXNzTmFtZT1cImNoZWNrYm94LWxpc3RcIj5cblx0XHRcdFx0XHQ8bGFiZWwgY2xhc3NOYW1lPVwiY2hlY2tib3hcIj5cblx0XHRcdFx0XHQgICA8aW5wdXQgdHlwZT1cImNoZWNrYm94XCIgY2xhc3NOYW1lPVwiY2hlY2tib3gtY29udHJvbFwiIGNoZWNrZWQ9e3RoaXMuc3RhdGUuY3JlYXRhYmxlfSBvbkNoYW5nZT17dGhpcy50b2dnbGVDcmVhdGFibGV9IC8+XG5cdFx0XHRcdFx0ICAgPHNwYW4gY2xhc3NOYW1lPVwiY2hlY2tib3gtbGFiZWxcIj5DcmVhdGFibGU/PC9zcGFuPlxuXHRcdFx0XHRcdDwvbGFiZWw+XG5cdFx0XHRcdFx0PGxhYmVsIGNsYXNzTmFtZT1cImNoZWNrYm94XCI+XG5cdFx0XHRcdFx0ICAgPGlucHV0IHR5cGU9XCJjaGVja2JveFwiIGNsYXNzTmFtZT1cImNoZWNrYm94LWNvbnRyb2xcIiBjaGVja2VkPXt0aGlzLnN0YXRlLmJhY2tzcGFjZVJlbW92ZXN9IG9uQ2hhbmdlPXt0aGlzLnRvZ2dsZUJhY2tzcGFjZVJlbW92ZXN9IC8+XG5cdFx0XHRcdFx0ICAgPHNwYW4gY2xhc3NOYW1lPVwiY2hlY2tib3gtbGFiZWxcIj5CYWNrc3BhY2UgUmVtb3Zlcz88L3NwYW4+XG5cdFx0XHRcdFx0PC9sYWJlbD5cblx0XHRcdFx0PC9kaXY+XG5cdFx0XHRcdDxkaXYgY2xhc3NOYW1lPVwiaGludFwiPlRoaXMgZXhhbXBsZSB1c2VzIGZldGNoLmpzIGZvciBzaG93aW5nIEFzeW5jIG9wdGlvbnMgd2l0aCBQcm9taXNlczwvZGl2PlxuXHRcdFx0PC9kaXY+XG5cdFx0KTtcblx0fVxufSk7XG5cbm1vZHVsZS5leHBvcnRzID0gR2l0aHViVXNlcnM7XG4iLCJpbXBvcnQgUmVhY3QgZnJvbSAncmVhY3QnO1xuaW1wb3J0IGNyZWF0ZUNsYXNzIGZyb20gJ2NyZWF0ZS1yZWFjdC1jbGFzcyc7XG5pbXBvcnQgUHJvcFR5cGVzIGZyb20gJ3Byb3AtdHlwZXMnO1xuaW1wb3J0IFNlbGVjdCBmcm9tICdyZWFjdC1zZWxlY3QnO1xuXG5jb25zdCBGTEFWT1VSUyA9IFtcblx0eyBsYWJlbDogJ0Nob2NvbGF0ZScsIHZhbHVlOiAnY2hvY29sYXRlJyB9LFxuXHR7IGxhYmVsOiAnVmFuaWxsYScsIHZhbHVlOiAndmFuaWxsYScgfSxcblx0eyBsYWJlbDogJ1N0cmF3YmVycnknLCB2YWx1ZTogJ3N0cmF3YmVycnknIH0sXG5cdHsgbGFiZWw6ICdDYXJhbWVsJywgdmFsdWU6ICdjYXJhbWVsJyB9LFxuXHR7IGxhYmVsOiAnQ29va2llcyBhbmQgQ3JlYW0nLCB2YWx1ZTogJ2Nvb2tpZXNjcmVhbScgfSxcblx0eyBsYWJlbDogJ1BlcHBlcm1pbnQnLCB2YWx1ZTogJ3BlcHBlcm1pbnQnIH0sXG5dO1xuXG5jb25zdCBXSFlfV09VTERfWU9VID0gW1xuXHR7IGxhYmVsOiAnQ2hvY29sYXRlIChhcmUgeW91IGNyYXp5PyknLCB2YWx1ZTogJ2Nob2NvbGF0ZScsIGRpc2FibGVkOiB0cnVlIH0sXG5dLmNvbmNhdChGTEFWT1VSUy5zbGljZSgxKSk7XG5cbnZhciBNdWx0aVNlbGVjdEZpZWxkID0gY3JlYXRlQ2xhc3Moe1xuXHRkaXNwbGF5TmFtZTogJ011bHRpU2VsZWN0RmllbGQnLFxuXHRwcm9wVHlwZXM6IHtcblx0XHRsYWJlbDogUHJvcFR5cGVzLnN0cmluZyxcblx0fSxcblx0Z2V0SW5pdGlhbFN0YXRlICgpIHtcblx0XHRyZXR1cm4ge1xuXHRcdFx0ZGlzYWJsZWQ6IGZhbHNlLFxuXHRcdFx0Y3Jhenk6IGZhbHNlLFxuXHRcdFx0b3B0aW9uczogRkxBVk9VUlMsXG5cdFx0XHR2YWx1ZTogW10sXG5cdFx0fTtcblx0fSxcblx0aGFuZGxlU2VsZWN0Q2hhbmdlICh2YWx1ZSkge1xuXHRcdGNvbnNvbGUubG9nKCdZb3VcXCd2ZSBzZWxlY3RlZDonLCB2YWx1ZSk7XG5cdFx0dGhpcy5zZXRTdGF0ZSh7IHZhbHVlIH0pO1xuXHR9LFxuXHR0b2dnbGVEaXNhYmxlZCAoZSkge1xuXHRcdHRoaXMuc2V0U3RhdGUoeyBkaXNhYmxlZDogZS50YXJnZXQuY2hlY2tlZCB9KTtcblx0fSxcblx0dG9nZ2xlQ2hvY29sYXRlIChlKSB7XG5cdFx0bGV0IGNyYXp5ID0gZS50YXJnZXQuY2hlY2tlZDtcblx0XHR0aGlzLnNldFN0YXRlKHtcblx0XHRcdGNyYXp5OiBjcmF6eSxcblx0XHRcdG9wdGlvbnM6IGNyYXp5ID8gV0hZX1dPVUxEX1lPVSA6IEZMQVZPVVJTLFxuXHRcdH0pO1xuXHR9LFxuXHRyZW5kZXIgKCkge1xuXHRcdHJldHVybiAoXG5cdFx0XHQ8ZGl2IGNsYXNzTmFtZT1cInNlY3Rpb25cIj5cblx0XHRcdFx0PGgzIGNsYXNzTmFtZT1cInNlY3Rpb24taGVhZGluZ1wiPnt0aGlzLnByb3BzLmxhYmVsfTwvaDM+XG5cdFx0XHRcdDxTZWxlY3QgbXVsdGkgc2ltcGxlVmFsdWUgZGlzYWJsZWQ9e3RoaXMuc3RhdGUuZGlzYWJsZWR9IHZhbHVlPXt0aGlzLnN0YXRlLnZhbHVlfSBwbGFjZWhvbGRlcj1cIlNlbGVjdCB5b3VyIGZhdm91cml0ZShzKVwiIG9wdGlvbnM9e3RoaXMuc3RhdGUub3B0aW9uc30gb25DaGFuZ2U9e3RoaXMuaGFuZGxlU2VsZWN0Q2hhbmdlfSAvPlxuXG5cdFx0XHRcdDxkaXYgY2xhc3NOYW1lPVwiY2hlY2tib3gtbGlzdFwiPlxuXHRcdFx0XHRcdDxsYWJlbCBjbGFzc05hbWU9XCJjaGVja2JveFwiPlxuXHRcdFx0XHRcdFx0PGlucHV0IHR5cGU9XCJjaGVja2JveFwiIGNsYXNzTmFtZT1cImNoZWNrYm94LWNvbnRyb2xcIiBjaGVja2VkPXt0aGlzLnN0YXRlLmRpc2FibGVkfSBvbkNoYW5nZT17dGhpcy50b2dnbGVEaXNhYmxlZH0gLz5cblx0XHRcdFx0XHRcdDxzcGFuIGNsYXNzTmFtZT1cImNoZWNrYm94LWxhYmVsXCI+RGlzYWJsZSB0aGUgY29udHJvbDwvc3Bhbj5cblx0XHRcdFx0XHQ8L2xhYmVsPlxuXHRcdFx0XHRcdDxsYWJlbCBjbGFzc05hbWU9XCJjaGVja2JveFwiPlxuXHRcdFx0XHRcdFx0PGlucHV0IHR5cGU9XCJjaGVja2JveFwiIGNsYXNzTmFtZT1cImNoZWNrYm94LWNvbnRyb2xcIiBjaGVja2VkPXt0aGlzLnN0YXRlLmNyYXp5fSBvbkNoYW5nZT17dGhpcy50b2dnbGVDaG9jb2xhdGV9IC8+XG5cdFx0XHRcdFx0XHQ8c3BhbiBjbGFzc05hbWU9XCJjaGVja2JveC1sYWJlbFwiPkkgZG9uJ3QgbGlrZSBDaG9jb2xhdGUgKGRpc2FibGVkIHRoZSBvcHRpb24pPC9zcGFuPlxuXHRcdFx0XHRcdDwvbGFiZWw+XG5cdFx0XHRcdDwvZGl2PlxuXHRcdFx0PC9kaXY+XG5cdFx0KTtcblx0fVxufSk7XG5cbm1vZHVsZS5leHBvcnRzID0gTXVsdGlTZWxlY3RGaWVsZDtcbiIsImltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCc7XG5pbXBvcnQgY3JlYXRlQ2xhc3MgZnJvbSAnY3JlYXRlLXJlYWN0LWNsYXNzJztcbmltcG9ydCBQcm9wVHlwZXMgZnJvbSAncHJvcC10eXBlcyc7XG5pbXBvcnQgU2VsZWN0IGZyb20gJ3JlYWN0LXNlbGVjdCc7XG5cbnZhciBWYWx1ZXNBc051bWJlcnNGaWVsZCA9IGNyZWF0ZUNsYXNzKHtcblx0ZGlzcGxheU5hbWU6ICdWYWx1ZXNBc051bWJlcnNGaWVsZCcsXG5cdHByb3BUeXBlczoge1xuXHRcdGxhYmVsOiBQcm9wVHlwZXMuc3RyaW5nXG5cdH0sXG5cdGdldEluaXRpYWxTdGF0ZSAoKSB7XG5cdFx0cmV0dXJuIHtcblx0XHRcdG9wdGlvbnM6IFtcblx0XHRcdFx0eyB2YWx1ZTogMTAsIGxhYmVsOiAnVGVuJyB9LFxuXHRcdFx0XHR7IHZhbHVlOiAxMSwgbGFiZWw6ICdFbGV2ZW4nIH0sXG5cdFx0XHRcdHsgdmFsdWU6IDEyLCBsYWJlbDogJ1R3ZWx2ZScgfSxcblx0XHRcdFx0eyB2YWx1ZTogMjMsIGxhYmVsOiAnVHdlbnR5LXRocmVlJyB9LFxuXHRcdFx0XHR7IHZhbHVlOiAyNCwgbGFiZWw6ICdUd2VudHktZm91cicgfVxuXHRcdFx0XSxcblx0XHRcdG1hdGNoUG9zOiAnYW55Jyxcblx0XHRcdG1hdGNoVmFsdWU6IHRydWUsXG5cdFx0XHRtYXRjaExhYmVsOiB0cnVlLFxuXHRcdFx0dmFsdWU6IG51bGwsXG5cdFx0XHRtdWx0aTogZmFsc2Vcblx0XHR9O1xuXHR9LFxuXHRvbkNoYW5nZU1hdGNoU3RhcnQoZXZlbnQpIHtcblx0XHR0aGlzLnNldFN0YXRlKHtcblx0XHRcdG1hdGNoUG9zOiBldmVudC50YXJnZXQuY2hlY2tlZCA/ICdzdGFydCcgOiAnYW55J1xuXHRcdH0pO1xuXHR9LFxuXHRvbkNoYW5nZU1hdGNoVmFsdWUoZXZlbnQpIHtcblx0XHR0aGlzLnNldFN0YXRlKHtcblx0XHRcdG1hdGNoVmFsdWU6IGV2ZW50LnRhcmdldC5jaGVja2VkXG5cdFx0fSk7XG5cdH0sXG5cdG9uQ2hhbmdlTWF0Y2hMYWJlbChldmVudCkge1xuXHRcdHRoaXMuc2V0U3RhdGUoe1xuXHRcdFx0bWF0Y2hMYWJlbDogZXZlbnQudGFyZ2V0LmNoZWNrZWRcblx0XHR9KTtcblx0fSxcblx0b25DaGFuZ2UodmFsdWUpIHtcblx0XHR0aGlzLnNldFN0YXRlKHsgdmFsdWUgfSk7XG5cdFx0Y29uc29sZS5sb2coJ051bWVyaWMgU2VsZWN0IHZhbHVlIGNoYW5nZWQgdG8nLCB2YWx1ZSk7XG5cdH0sXG5cdG9uQ2hhbmdlTXVsdGkoZXZlbnQpIHtcblx0XHR0aGlzLnNldFN0YXRlKHtcblx0XHRcdG11bHRpOiBldmVudC50YXJnZXQuY2hlY2tlZFxuXHRcdH0pO1xuXHR9LFxuXHRyZW5kZXIgKCkge1xuXHRcdHZhciBtYXRjaFByb3AgPSAnYW55Jztcblx0XHRpZiAodGhpcy5zdGF0ZS5tYXRjaExhYmVsICYmICF0aGlzLnN0YXRlLm1hdGNoVmFsdWUpIHtcblx0XHRcdG1hdGNoUHJvcCA9ICdsYWJlbCc7XG5cdFx0fVxuXHRcdGlmICghdGhpcy5zdGF0ZS5tYXRjaExhYmVsICYmIHRoaXMuc3RhdGUubWF0Y2hWYWx1ZSkge1xuXHRcdFx0bWF0Y2hQcm9wID0gJ3ZhbHVlJztcblx0XHR9XG5cdFx0cmV0dXJuIChcblx0XHRcdDxkaXYgY2xhc3NOYW1lPVwic2VjdGlvblwiPlxuXHRcdFx0XHQ8aDMgY2xhc3NOYW1lPVwic2VjdGlvbi1oZWFkaW5nXCI+e3RoaXMucHJvcHMubGFiZWx9PC9oMz5cblx0XHRcdFx0PFNlbGVjdFxuXHRcdFx0XHRcdG1hdGNoUG9zPXt0aGlzLnN0YXRlLm1hdGNoUG9zfVxuXHRcdFx0XHRcdG1hdGNoUHJvcD17bWF0Y2hQcm9wfVxuXHRcdFx0XHRcdG11bHRpPXt0aGlzLnN0YXRlLm11bHRpfVxuXHRcdFx0XHRcdG9uQ2hhbmdlPXt0aGlzLm9uQ2hhbmdlfVxuXHRcdFx0XHRcdG9wdGlvbnM9e3RoaXMuc3RhdGUub3B0aW9uc31cblx0XHRcdFx0XHRzaW1wbGVWYWx1ZVxuXHRcdFx0XHRcdHZhbHVlPXt0aGlzLnN0YXRlLnZhbHVlfVxuXHRcdFx0XHRcdC8+XG5cdFx0XHRcdDxkaXYgY2xhc3NOYW1lPVwiY2hlY2tib3gtbGlzdFwiPlxuXHRcdFx0XHRcdDxsYWJlbCBjbGFzc05hbWU9XCJjaGVja2JveFwiPlxuXHRcdFx0XHRcdFx0PGlucHV0IHR5cGU9XCJjaGVja2JveFwiIGNsYXNzTmFtZT1cImNoZWNrYm94LWNvbnRyb2xcIiBjaGVja2VkPXt0aGlzLnN0YXRlLm11bHRpfSBvbkNoYW5nZT17dGhpcy5vbkNoYW5nZU11bHRpfSAvPlxuXHRcdFx0XHRcdFx0PHNwYW4gY2xhc3NOYW1lPVwiY2hlY2tib3gtbGFiZWxcIj5NdWx0aS1TZWxlY3Q8L3NwYW4+XG5cdFx0XHRcdFx0PC9sYWJlbD5cblx0XHRcdFx0XHQ8bGFiZWwgY2xhc3NOYW1lPVwiY2hlY2tib3hcIj5cblx0XHRcdFx0XHRcdDxpbnB1dCB0eXBlPVwiY2hlY2tib3hcIiBjbGFzc05hbWU9XCJjaGVja2JveC1jb250cm9sXCIgY2hlY2tlZD17dGhpcy5zdGF0ZS5tYXRjaFZhbHVlfSBvbkNoYW5nZT17dGhpcy5vbkNoYW5nZU1hdGNoVmFsdWV9IC8+XG5cdFx0XHRcdFx0XHQ8c3BhbiBjbGFzc05hbWU9XCJjaGVja2JveC1sYWJlbFwiPk1hdGNoIHZhbHVlPC9zcGFuPlxuXHRcdFx0XHRcdDwvbGFiZWw+XG5cdFx0XHRcdFx0PGxhYmVsIGNsYXNzTmFtZT1cImNoZWNrYm94XCI+XG5cdFx0XHRcdFx0XHQ8aW5wdXQgdHlwZT1cImNoZWNrYm94XCIgY2xhc3NOYW1lPVwiY2hlY2tib3gtY29udHJvbFwiIGNoZWNrZWQ9e3RoaXMuc3RhdGUubWF0Y2hMYWJlbH0gb25DaGFuZ2U9e3RoaXMub25DaGFuZ2VNYXRjaExhYmVsfSAvPlxuXHRcdFx0XHRcdFx0PHNwYW4gY2xhc3NOYW1lPVwiY2hlY2tib3gtbGFiZWxcIj5NYXRjaCBsYWJlbDwvc3Bhbj5cblx0XHRcdFx0XHQ8L2xhYmVsPlxuXHRcdFx0XHRcdDxsYWJlbCBjbGFzc05hbWU9XCJjaGVja2JveFwiPlxuXHRcdFx0XHRcdFx0PGlucHV0IHR5cGU9XCJjaGVja2JveFwiIGNsYXNzTmFtZT1cImNoZWNrYm94LWNvbnRyb2xcIiBjaGVja2VkPXt0aGlzLnN0YXRlLm1hdGNoUG9zID09PSAnc3RhcnQnfSBvbkNoYW5nZT17dGhpcy5vbkNoYW5nZU1hdGNoU3RhcnR9IC8+XG5cdFx0XHRcdFx0XHQ8c3BhbiBjbGFzc05hbWU9XCJjaGVja2JveC1sYWJlbFwiPk9ubHkgaW5jbHVkZSBtYXRjaGVzIGZyb20gdGhlIHN0YXJ0IG9mIHRoZSBzdHJpbmc8L3NwYW4+XG5cdFx0XHRcdFx0PC9sYWJlbD5cblx0XHRcdFx0PC9kaXY+XG5cdFx0XHRcdDxkaXYgY2xhc3NOYW1lPVwiaGludFwiPlRoaXMgZXhhbXBsZSB1c2VzIHNpbXBsZSBudW1lcmljIHZhbHVlczwvZGl2PlxuXHRcdFx0PC9kaXY+XG5cdFx0KTtcblx0fVxufSk7XG5cbm1vZHVsZS5leHBvcnRzID0gVmFsdWVzQXNOdW1iZXJzRmllbGQ7XG4iLCJpbXBvcnQgUmVhY3QgZnJvbSAncmVhY3QnO1xuaW1wb3J0IGNyZWF0ZUNsYXNzIGZyb20gJ2NyZWF0ZS1yZWFjdC1jbGFzcyc7XG5pbXBvcnQgUHJvcFR5cGVzIGZyb20gJ3Byb3AtdHlwZXMnO1xuaW1wb3J0IFNlbGVjdCBmcm9tICdyZWFjdC1zZWxlY3QnO1xuXG5jb25zdCBTVEFURVMgPSByZXF1aXJlKCcuLi9kYXRhL3N0YXRlcycpO1xuXG52YXIgU3RhdGVzRmllbGQgPSBjcmVhdGVDbGFzcyh7XG5cdGRpc3BsYXlOYW1lOiAnU3RhdGVzRmllbGQnLFxuXHRwcm9wVHlwZXM6IHtcblx0XHRsYWJlbDogUHJvcFR5cGVzLnN0cmluZyxcblx0XHRzZWFyY2hhYmxlOiBQcm9wVHlwZXMuYm9vbCxcblx0fSxcblx0Z2V0RGVmYXVsdFByb3BzICgpIHtcblx0XHRyZXR1cm4ge1xuXHRcdFx0bGFiZWw6ICdTdGF0ZXM6Jyxcblx0XHRcdHNlYXJjaGFibGU6IHRydWUsXG5cdFx0fTtcblx0fSxcblx0Z2V0SW5pdGlhbFN0YXRlICgpIHtcblx0XHRyZXR1cm4ge1xuXHRcdFx0Y291bnRyeTogJ0FVJyxcblx0XHRcdGRpc2FibGVkOiBmYWxzZSxcblx0XHRcdHNlYXJjaGFibGU6IHRoaXMucHJvcHMuc2VhcmNoYWJsZSxcblx0XHRcdHNlbGVjdFZhbHVlOiAnbmV3LXNvdXRoLXdhbGVzJyxcblx0XHRcdGNsZWFyYWJsZTogdHJ1ZSxcblx0XHR9O1xuXHR9LFxuXHRzd2l0Y2hDb3VudHJ5IChlKSB7XG5cdFx0dmFyIG5ld0NvdW50cnkgPSBlLnRhcmdldC52YWx1ZTtcblx0XHRjb25zb2xlLmxvZygnQ291bnRyeSBjaGFuZ2VkIHRvICcgKyBuZXdDb3VudHJ5KTtcblx0XHR0aGlzLnNldFN0YXRlKHtcblx0XHRcdGNvdW50cnk6IG5ld0NvdW50cnksXG5cdFx0XHRzZWxlY3RWYWx1ZTogbnVsbFxuXHRcdH0pO1xuXHR9LFxuXHR1cGRhdGVWYWx1ZSAobmV3VmFsdWUpIHtcblx0XHRjb25zb2xlLmxvZygnU3RhdGUgY2hhbmdlZCB0byAnICsgbmV3VmFsdWUpO1xuXHRcdHRoaXMuc2V0U3RhdGUoe1xuXHRcdFx0c2VsZWN0VmFsdWU6IG5ld1ZhbHVlXG5cdFx0fSk7XG5cdH0sXG5cdGZvY3VzU3RhdGVTZWxlY3QgKCkge1xuXHRcdHRoaXMucmVmcy5zdGF0ZVNlbGVjdC5mb2N1cygpO1xuXHR9LFxuXHR0b2dnbGVDaGVja2JveCAoZSkge1xuXHRcdGxldCBuZXdTdGF0ZSA9IHt9O1xuXHRcdG5ld1N0YXRlW2UudGFyZ2V0Lm5hbWVdID0gZS50YXJnZXQuY2hlY2tlZDtcblx0XHR0aGlzLnNldFN0YXRlKG5ld1N0YXRlKTtcblx0fSxcblx0cmVuZGVyICgpIHtcblx0XHR2YXIgb3B0aW9ucyA9IFNUQVRFU1t0aGlzLnN0YXRlLmNvdW50cnldO1xuXHRcdHJldHVybiAoXG5cdFx0XHQ8ZGl2IGNsYXNzTmFtZT1cInNlY3Rpb25cIj5cblx0XHRcdFx0PGgzIGNsYXNzTmFtZT1cInNlY3Rpb24taGVhZGluZ1wiPnt0aGlzLnByb3BzLmxhYmVsfTwvaDM+XG5cdFx0XHRcdDxTZWxlY3QgcmVmPVwic3RhdGVTZWxlY3RcIiBhdXRvZm9jdXMgb3B0aW9ucz17b3B0aW9uc30gc2ltcGxlVmFsdWUgY2xlYXJhYmxlPXt0aGlzLnN0YXRlLmNsZWFyYWJsZX0gbmFtZT1cInNlbGVjdGVkLXN0YXRlXCIgZGlzYWJsZWQ9e3RoaXMuc3RhdGUuZGlzYWJsZWR9IHZhbHVlPXt0aGlzLnN0YXRlLnNlbGVjdFZhbHVlfSBvbkNoYW5nZT17dGhpcy51cGRhdGVWYWx1ZX0gc2VhcmNoYWJsZT17dGhpcy5zdGF0ZS5zZWFyY2hhYmxlfSAvPlxuXG5cdFx0XHRcdDxkaXYgc3R5bGU9e3sgbWFyZ2luVG9wOiAxNCB9fT5cblx0XHRcdFx0XHQ8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBvbkNsaWNrPXt0aGlzLmZvY3VzU3RhdGVTZWxlY3R9PkZvY3VzIFNlbGVjdDwvYnV0dG9uPlxuXHRcdFx0XHRcdDxsYWJlbCBjbGFzc05hbWU9XCJjaGVja2JveFwiIHN0eWxlPXt7IG1hcmdpbkxlZnQ6IDEwIH19PlxuXHRcdFx0XHRcdFx0PGlucHV0IHR5cGU9XCJjaGVja2JveFwiIGNsYXNzTmFtZT1cImNoZWNrYm94LWNvbnRyb2xcIiBuYW1lPVwic2VhcmNoYWJsZVwiIGNoZWNrZWQ9e3RoaXMuc3RhdGUuc2VhcmNoYWJsZX0gb25DaGFuZ2U9e3RoaXMudG9nZ2xlQ2hlY2tib3h9Lz5cblx0XHRcdFx0XHRcdDxzcGFuIGNsYXNzTmFtZT1cImNoZWNrYm94LWxhYmVsXCI+U2VhcmNoYWJsZTwvc3Bhbj5cblx0XHRcdFx0XHQ8L2xhYmVsPlxuXHRcdFx0XHRcdDxsYWJlbCBjbGFzc05hbWU9XCJjaGVja2JveFwiIHN0eWxlPXt7IG1hcmdpbkxlZnQ6IDEwIH19PlxuXHRcdFx0XHRcdFx0PGlucHV0IHR5cGU9XCJjaGVja2JveFwiIGNsYXNzTmFtZT1cImNoZWNrYm94LWNvbnRyb2xcIiBuYW1lPVwiZGlzYWJsZWRcIiBjaGVja2VkPXt0aGlzLnN0YXRlLmRpc2FibGVkfSBvbkNoYW5nZT17dGhpcy50b2dnbGVDaGVja2JveH0vPlxuXHRcdFx0XHRcdFx0PHNwYW4gY2xhc3NOYW1lPVwiY2hlY2tib3gtbGFiZWxcIj5EaXNhYmxlZDwvc3Bhbj5cblx0XHRcdFx0XHQ8L2xhYmVsPlxuXHRcdFx0XHRcdDxsYWJlbCBjbGFzc05hbWU9XCJjaGVja2JveFwiIHN0eWxlPXt7IG1hcmdpbkxlZnQ6IDEwIH19PlxuXHRcdFx0XHRcdFx0PGlucHV0IHR5cGU9XCJjaGVja2JveFwiIGNsYXNzTmFtZT1cImNoZWNrYm94LWNvbnRyb2xcIiBuYW1lPVwiY2xlYXJhYmxlXCIgY2hlY2tlZD17dGhpcy5zdGF0ZS5jbGVhcmFibGV9IG9uQ2hhbmdlPXt0aGlzLnRvZ2dsZUNoZWNrYm94fS8+XG5cdFx0XHRcdFx0XHQ8c3BhbiBjbGFzc05hbWU9XCJjaGVja2JveC1sYWJlbFwiPkNsZWFyYWJsZTwvc3Bhbj5cblx0XHRcdFx0XHQ8L2xhYmVsPlxuXHRcdFx0XHQ8L2Rpdj5cblx0XHRcdFx0PGRpdiBjbGFzc05hbWU9XCJjaGVja2JveC1saXN0XCI+XG5cdFx0XHRcdFx0PGxhYmVsIGNsYXNzTmFtZT1cImNoZWNrYm94XCI+XG5cdFx0XHRcdFx0XHQ8aW5wdXQgdHlwZT1cInJhZGlvXCIgY2xhc3NOYW1lPVwiY2hlY2tib3gtY29udHJvbFwiIGNoZWNrZWQ9e3RoaXMuc3RhdGUuY291bnRyeSA9PT0gJ0FVJ30gdmFsdWU9XCJBVVwiIG9uQ2hhbmdlPXt0aGlzLnN3aXRjaENvdW50cnl9Lz5cblx0XHRcdFx0XHRcdDxzcGFuIGNsYXNzTmFtZT1cImNoZWNrYm94LWxhYmVsXCI+QXVzdHJhbGlhPC9zcGFuPlxuXHRcdFx0XHRcdDwvbGFiZWw+XG5cdFx0XHRcdFx0PGxhYmVsIGNsYXNzTmFtZT1cImNoZWNrYm94XCI+XG5cdFx0XHRcdFx0XHQ8aW5wdXQgdHlwZT1cInJhZGlvXCIgY2xhc3NOYW1lPVwiY2hlY2tib3gtY29udHJvbFwiIGNoZWNrZWQ9e3RoaXMuc3RhdGUuY291bnRyeSA9PT0gJ1VTJ30gdmFsdWU9XCJVU1wiIG9uQ2hhbmdlPXt0aGlzLnN3aXRjaENvdW50cnl9Lz5cblx0XHRcdFx0XHRcdDxzcGFuIGNsYXNzTmFtZT1cImNoZWNrYm94LWxhYmVsXCI+VW5pdGVkIFN0YXRlczwvc3Bhbj5cblx0XHRcdFx0XHQ8L2xhYmVsPlxuXHRcdFx0XHQ8L2Rpdj5cblx0XHRcdDwvZGl2PlxuXHRcdCk7XG5cdH1cbn0pO1xuXG5cbm1vZHVsZS5leHBvcnRzID0gU3RhdGVzRmllbGQ7XG4iLCJpbXBvcnQgUmVhY3QgZnJvbSAncmVhY3QnO1xuaW1wb3J0IGNyZWF0ZUNsYXNzIGZyb20gJ2NyZWF0ZS1yZWFjdC1jbGFzcyc7XG5pbXBvcnQgVmlydHVhbGl6ZWRTZWxlY3QgZnJvbSAncmVhY3QtdmlydHVhbGl6ZWQtc2VsZWN0JztcblxuY29uc3QgREFUQSA9IHJlcXVpcmUoJy4uL2RhdGEvY2l0aWVzJyk7XG5cbnZhciBDaXRpZXNGaWVsZCA9IGNyZWF0ZUNsYXNzKHtcblx0ZGlzcGxheU5hbWU6ICdDaXRpZXNGaWVsZCcsXG5cdGdldEluaXRpYWxTdGF0ZSAoKSB7XG5cdFx0cmV0dXJuIHt9O1xuXHR9LFxuXHR1cGRhdGVWYWx1ZSAobmV3VmFsdWUpIHtcblx0XHR0aGlzLnNldFN0YXRlKHtcblx0XHRcdHNlbGVjdFZhbHVlOiBuZXdWYWx1ZVxuXHRcdH0pO1xuXHR9LFxuXHRyZW5kZXIgKCkge1xuXHRcdHZhciBvcHRpb25zID0gREFUQS5DSVRJRVM7XG5cdFx0cmV0dXJuIChcblx0XHRcdDxkaXYgY2xhc3NOYW1lPVwic2VjdGlvblwiPlxuXHRcdFx0XHQ8aDMgY2xhc3NOYW1lPVwic2VjdGlvbi1oZWFkaW5nXCI+Q2l0aWVzIChMYXJnZSBEYXRhc2V0KTwvaDM+XG5cdFx0XHRcdDxWaXJ0dWFsaXplZFNlbGVjdCByZWY9XCJjaXR5U2VsZWN0XCJcblx0XHRcdFx0XHRvcHRpb25zPXtvcHRpb25zfVxuXHRcdFx0XHRcdHNpbXBsZVZhbHVlXG5cdFx0XHRcdFx0Y2xlYXJhYmxlXG5cdFx0XHRcdFx0bmFtZT1cInNlbGVjdC1jaXR5XCJcblx0XHRcdFx0XHR2YWx1ZT17dGhpcy5zdGF0ZS5zZWxlY3RWYWx1ZX1cblx0XHRcdFx0XHRvbkNoYW5nZT17dGhpcy51cGRhdGVWYWx1ZX1cblx0XHRcdFx0XHRzZWFyY2hhYmxlXG5cdFx0XHRcdFx0bGFiZWxLZXk9XCJuYW1lXCJcblx0XHRcdFx0XHR2YWx1ZUtleT1cIm5hbWVcIlxuXHRcdFx0XHQvPlxuXHRcdFx0XHQ8ZGl2IGNsYXNzTmFtZT1cImhpbnRcIj5cblx0XHRcdFx0XHRVc2VzIDxhIGhyZWY9XCJodHRwczovL2dpdGh1Yi5jb20vYnZhdWdobi9yZWFjdC12aXJ0dWFsaXplZFwiPnJlYWN0LXZpcnR1YWxpemVkPC9hPiBhbmQgPGEgaHJlZj1cImh0dHBzOi8vZ2l0aHViLmNvbS9idmF1Z2huL3JlYWN0LXZpcnR1YWxpemVkLXNlbGVjdC9cIj5yZWFjdC12aXJ0dWFsaXplZC1zZWxlY3Q8L2E+IHRvIGRpc3BsYXkgYSBsaXN0IG9mIHRoZSB3b3JsZCdzIDEsMDAwIGxhcmdlc3QgY2l0aWVzLlxuXHRcdFx0XHQ8L2Rpdj5cblx0XHRcdDwvZGl2PlxuXHRcdCk7XG5cdH1cbn0pO1xuXG5cbm1vZHVsZS5leHBvcnRzID0gQ2l0aWVzRmllbGQ7XG4iLCJleHBvcnRzLkNJVElFUyA9IFtcbiAgeyBuYW1lOiAnQWJpbGVuZScgfSxcbiAgeyBuYW1lOiAnQWRkaXNvbicgfSxcbiAgeyBuYW1lOiAnQWtyb24nIH0sXG4gIHsgbmFtZTogJ0FsYW1lZGEnIH0sXG4gIHsgbmFtZTogJ0FsYmFueScgfSxcbiAgeyBuYW1lOiAnQWxiYW55JyB9LFxuICB7IG5hbWU6ICdBbGJhbnknIH0sXG4gIHsgbmFtZTogJ0FsYnVxdWVycXVlJyB9LFxuICB7IG5hbWU6ICdBbGV4YW5kcmlhJyB9LFxuICB7IG5hbWU6ICdBbGV4YW5kcmlhJyB9LFxuICB7IG5hbWU6ICdBbGhhbWJyYScgfSxcbiAgeyBuYW1lOiAnQWxpc28gVmllam8nIH0sXG4gIHsgbmFtZTogJ0FsbGVuJyB9LFxuICB7IG5hbWU6ICdBbGxlbnRvd24nIH0sXG4gIHsgbmFtZTogJ0FscGhhcmV0dGEnIH0sXG4gIHsgbmFtZTogJ0FsdGFtb250ZSBTcHJpbmdzJyB9LFxuICB7IG5hbWU6ICdBbHRvb25hJyB9LFxuICB7IG5hbWU6ICdBbWFyaWxsbycgfSxcbiAgeyBuYW1lOiAnQW1lcycgfSxcbiAgeyBuYW1lOiAnQW5haGVpbScgfSxcbiAgeyBuYW1lOiAnQW5jaG9yYWdlJyB9LFxuICB7IG5hbWU6ICdBbmRlcnNvbicgfSxcbiAgeyBuYW1lOiAnQW5rZW55JyB9LFxuICB7IG5hbWU6ICdBbm4gQXJib3InIH0sXG4gIHsgbmFtZTogJ0FubmFwb2xpcycgfSxcbiAgeyBuYW1lOiAnQW50aW9jaCcgfSxcbiAgeyBuYW1lOiAnQXBhY2hlIEp1bmN0aW9uJyB9LFxuICB7IG5hbWU6ICdBcGV4JyB9LFxuICB7IG5hbWU6ICdBcG9wa2EnIH0sXG4gIHsgbmFtZTogJ0FwcGxlIFZhbGxleScgfSxcbiAgeyBuYW1lOiAnQXBwbGUgVmFsbGV5JyB9LFxuICB7IG5hbWU6ICdBcHBsZXRvbicgfSxcbiAgeyBuYW1lOiAnQXJjYWRpYScgfSxcbiAgeyBuYW1lOiAnQXJsaW5ndG9uJyB9LFxuICB7IG5hbWU6ICdBcmxpbmd0b24gSGVpZ2h0cycgfSxcbiAgeyBuYW1lOiAnQXJ2YWRhJyB9LFxuICB7IG5hbWU6ICdBc2hldmlsbGUnIH0sXG4gIHsgbmFtZTogJ0F0aGVucy1DbGFya2UgQ291bnR5JyB9LFxuICB7IG5hbWU6ICdBdGxhbnRhJyB9LFxuICB7IG5hbWU6ICdBdGxhbnRpYyBDaXR5JyB9LFxuICB7IG5hbWU6ICdBdHRsZWJvcm8nIH0sXG4gIHsgbmFtZTogJ0F1YnVybicgfSxcbiAgeyBuYW1lOiAnQXVidXJuJyB9LFxuICB7IG5hbWU6ICdBdWd1c3RhLVJpY2htb25kIENvdW50eScgfSxcbiAgeyBuYW1lOiAnQXVyb3JhJyB9LFxuICB7IG5hbWU6ICdBdXJvcmEnIH0sXG4gIHsgbmFtZTogJ0F1c3RpbicgfSxcbiAgeyBuYW1lOiAnQXZlbnR1cmEnIH0sXG4gIHsgbmFtZTogJ0F2b25kYWxlJyB9LFxuICB7IG5hbWU6ICdBenVzYScgfSxcbiAgeyBuYW1lOiAnQmFrZXJzZmllbGQnIH0sXG4gIHsgbmFtZTogJ0JhbGR3aW4gUGFyaycgfSxcbiAgeyBuYW1lOiAnQmFsdGltb3JlJyB9LFxuICB7IG5hbWU6ICdCYXJuc3RhYmxlIFRvd24nIH0sXG4gIHsgbmFtZTogJ0JhcnRsZXR0JyB9LFxuICB7IG5hbWU6ICdCYXJ0bGV0dCcgfSxcbiAgeyBuYW1lOiAnQmF0b24gUm91Z2UnIH0sXG4gIHsgbmFtZTogJ0JhdHRsZSBDcmVlaycgfSxcbiAgeyBuYW1lOiAnQmF5b25uZScgfSxcbiAgeyBuYW1lOiAnQmF5dG93bicgfSxcbiAgeyBuYW1lOiAnQmVhdW1vbnQnIH0sXG4gIHsgbmFtZTogJ0JlYXVtb250JyB9LFxuICB7IG5hbWU6ICdCZWF2ZXJjcmVlaycgfSxcbiAgeyBuYW1lOiAnQmVhdmVydG9uJyB9LFxuICB7IG5hbWU6ICdCZWRmb3JkJyB9LFxuICB7IG5hbWU6ICdCZWxsIEdhcmRlbnMnIH0sXG4gIHsgbmFtZTogJ0JlbGxldmlsbGUnIH0sXG4gIHsgbmFtZTogJ0JlbGxldnVlJyB9LFxuICB7IG5hbWU6ICdCZWxsZXZ1ZScgfSxcbiAgeyBuYW1lOiAnQmVsbGZsb3dlcicgfSxcbiAgeyBuYW1lOiAnQmVsbGluZ2hhbScgfSxcbiAgeyBuYW1lOiAnQmVsb2l0JyB9LFxuICB7IG5hbWU6ICdCZW5kJyB9LFxuICB7IG5hbWU6ICdCZW50b252aWxsZScgfSxcbiAgeyBuYW1lOiAnQmVya2VsZXknIH0sXG4gIHsgbmFtZTogJ0Jlcnd5bicgfSxcbiAgeyBuYW1lOiAnQmV0aGxlaGVtJyB9LFxuICB7IG5hbWU6ICdCZXZlcmx5JyB9LFxuICB7IG5hbWU6ICdCaWxsaW5ncycgfSxcbiAgeyBuYW1lOiAnQmlsb3hpJyB9LFxuICB7IG5hbWU6ICdCaW5naGFtdG9uJyB9LFxuICB7IG5hbWU6ICdCaXJtaW5naGFtJyB9LFxuICB7IG5hbWU6ICdCaXNtYXJjaycgfSxcbiAgeyBuYW1lOiAnQmxhY2tzYnVyZycgfSxcbiAgeyBuYW1lOiAnQmxhaW5lJyB9LFxuICB7IG5hbWU6ICdCbG9vbWluZ3RvbicgfSxcbiAgeyBuYW1lOiAnQmxvb21pbmd0b24nIH0sXG4gIHsgbmFtZTogJ0Jsb29taW5ndG9uJyB9LFxuICB7IG5hbWU6ICdCbHVlIFNwcmluZ3MnIH0sXG4gIHsgbmFtZTogJ0JvY2EgUmF0b24nIH0sXG4gIHsgbmFtZTogJ0JvaXNlIENpdHknIH0sXG4gIHsgbmFtZTogJ0JvbGluZ2Jyb29rJyB9LFxuICB7IG5hbWU6ICdCb25pdGEgU3ByaW5ncycgfSxcbiAgeyBuYW1lOiAnQm9zc2llciBDaXR5JyB9LFxuICB7IG5hbWU6ICdCb3N0b24nIH0sXG4gIHsgbmFtZTogJ0JvdWxkZXInIH0sXG4gIHsgbmFtZTogJ0JvdW50aWZ1bCcgfSxcbiAgeyBuYW1lOiAnQm93aWUnIH0sXG4gIHsgbmFtZTogJ0Jvd2xpbmcgR3JlZW4nIH0sXG4gIHsgbmFtZTogJ0JveW50b24gQmVhY2gnIH0sXG4gIHsgbmFtZTogJ0JvemVtYW4nIH0sXG4gIHsgbmFtZTogJ0JyYWRlbnRvbicgfSxcbiAgeyBuYW1lOiAnQnJlYScgfSxcbiAgeyBuYW1lOiAnQnJlbWVydG9uJyB9LFxuICB7IG5hbWU6ICdCcmVudHdvb2QnIH0sXG4gIHsgbmFtZTogJ0JyZW50d29vZCcgfSxcbiAgeyBuYW1lOiAnQnJpZGdlcG9ydCcgfSxcbiAgeyBuYW1lOiAnQnJpc3RvbCcgfSxcbiAgeyBuYW1lOiAnQnJvY2t0b24nIH0sXG4gIHsgbmFtZTogJ0Jyb2tlbiBBcnJvdycgfSxcbiAgeyBuYW1lOiAnQnJvb2tmaWVsZCcgfSxcbiAgeyBuYW1lOiAnQnJvb2toYXZlbicgfSxcbiAgeyBuYW1lOiAnQnJvb2tseW4gUGFyaycgfSxcbiAgeyBuYW1lOiAnQnJvb21maWVsZCcgfSxcbiAgeyBuYW1lOiAnQnJvd25zdmlsbGUnIH0sXG4gIHsgbmFtZTogJ0JyeWFuJyB9LFxuICB7IG5hbWU6ICdCdWNrZXllJyB9LFxuICB7IG5hbWU6ICdCdWVuYSBQYXJrJyB9LFxuICB7IG5hbWU6ICdCdWZmYWxvJyB9LFxuICB7IG5hbWU6ICdCdWZmYWxvIEdyb3ZlJyB9LFxuICB7IG5hbWU6ICdCdWxsaGVhZCBDaXR5JyB9LFxuICB7IG5hbWU6ICdCdXJiYW5rJyB9LFxuICB7IG5hbWU6ICdCdXJpZW4nIH0sXG4gIHsgbmFtZTogJ0J1cmxlc29uJyB9LFxuICB7IG5hbWU6ICdCdXJsaW5ndG9uJyB9LFxuICB7IG5hbWU6ICdCdXJsaW5ndG9uJyB9LFxuICB7IG5hbWU6ICdCdXJuc3ZpbGxlJyB9LFxuICB7IG5hbWU6ICdDYWxkd2VsbCcgfSxcbiAgeyBuYW1lOiAnQ2FsZXhpY28nIH0sXG4gIHsgbmFtZTogJ0NhbHVtZXQgQ2l0eScgfSxcbiAgeyBuYW1lOiAnQ2FtYXJpbGxvJyB9LFxuICB7IG5hbWU6ICdDYW1icmlkZ2UnIH0sXG4gIHsgbmFtZTogJ0NhbWRlbicgfSxcbiAgeyBuYW1lOiAnQ2FtcGJlbGwnIH0sXG4gIHsgbmFtZTogJ0NhbnRvbicgfSxcbiAgeyBuYW1lOiAnQ2FwZSBDb3JhbCcgfSxcbiAgeyBuYW1lOiAnQ2FwZSBHaXJhcmRlYXUnIH0sXG4gIHsgbmFtZTogJ0NhcmxzYmFkJyB9LFxuICB7IG5hbWU6ICdDYXJtZWwnIH0sXG4gIHsgbmFtZTogJ0Nhcm9sIFN0cmVhbScgfSxcbiAgeyBuYW1lOiAnQ2FycGVudGVyc3ZpbGxlJyB9LFxuICB7IG5hbWU6ICdDYXJyb2xsdG9uJyB9LFxuICB7IG5hbWU6ICdDYXJzb24nIH0sXG4gIHsgbmFtZTogJ0NhcnNvbiBDaXR5JyB9LFxuICB7IG5hbWU6ICdDYXJ5JyB9LFxuICB7IG5hbWU6ICdDYXNhIEdyYW5kZScgfSxcbiAgeyBuYW1lOiAnQ2FzcGVyJyB9LFxuICB7IG5hbWU6ICdDYXN0bGUgUm9jaycgfSxcbiAgeyBuYW1lOiAnQ2F0aGVkcmFsIENpdHknIH0sXG4gIHsgbmFtZTogJ0NlZGFyIEZhbGxzJyB9LFxuICB7IG5hbWU6ICdDZWRhciBIaWxsJyB9LFxuICB7IG5hbWU6ICdDZWRhciBQYXJrJyB9LFxuICB7IG5hbWU6ICdDZWRhciBSYXBpZHMnIH0sXG4gIHsgbmFtZTogJ0NlbnRlbm5pYWwnIH0sXG4gIHsgbmFtZTogJ0NlcmVzJyB9LFxuICB7IG5hbWU6ICdDZXJyaXRvcycgfSxcbiAgeyBuYW1lOiAnQ2hhbXBhaWduJyB9LFxuICB7IG5hbWU6ICdDaGFuZGxlcicgfSxcbiAgeyBuYW1lOiAnQ2hhcGVsIEhpbGwnIH0sXG4gIHsgbmFtZTogJ0NoYXJsZXN0b24nIH0sXG4gIHsgbmFtZTogJ0NoYXJsZXN0b24nIH0sXG4gIHsgbmFtZTogJ0NoYXJsb3R0ZScgfSxcbiAgeyBuYW1lOiAnQ2hhcmxvdHRlc3ZpbGxlJyB9LFxuICB7IG5hbWU6ICdDaGF0dGFub29nYScgfSxcbiAgeyBuYW1lOiAnQ2hlbHNlYScgfSxcbiAgeyBuYW1lOiAnQ2hlc2FwZWFrZScgfSxcbiAgeyBuYW1lOiAnQ2hlc3RlcmZpZWxkJyB9LFxuICB7IG5hbWU6ICdDaGV5ZW5uZScgfSxcbiAgeyBuYW1lOiAnQ2hpY2FnbycgfSxcbiAgeyBuYW1lOiAnQ2hpY28nIH0sXG4gIHsgbmFtZTogJ0NoaWNvcGVlJyB9LFxuICB7IG5hbWU6ICdDaGlubycgfSxcbiAgeyBuYW1lOiAnQ2hpbm8gSGlsbHMnIH0sXG4gIHsgbmFtZTogJ0NodWxhIFZpc3RhJyB9LFxuICB7IG5hbWU6ICdDaWNlcm8nIH0sXG4gIHsgbmFtZTogJ0NpbmNpbm5hdGknIH0sXG4gIHsgbmFtZTogJ0NpdHJ1cyBIZWlnaHRzJyB9LFxuICB7IG5hbWU6ICdDbGFya3N2aWxsZScgfSxcbiAgeyBuYW1lOiAnQ2xlYXJ3YXRlcicgfSxcbiAgeyBuYW1lOiAnQ2xldmVsYW5kJyB9LFxuICB7IG5hbWU6ICdDbGV2ZWxhbmQnIH0sXG4gIHsgbmFtZTogJ0NsZXZlbGFuZCBIZWlnaHRzJyB9LFxuICB7IG5hbWU6ICdDbGlmdG9uJyB9LFxuICB7IG5hbWU6ICdDbG92aXMnIH0sXG4gIHsgbmFtZTogJ0Nsb3ZpcycgfSxcbiAgeyBuYW1lOiAnQ29hY2hlbGxhJyB9LFxuICB7IG5hbWU6ICdDb2NvbnV0IENyZWVrJyB9LFxuICB7IG5hbWU6ICdDb2V1ciBkXFwnQWxlbmUnIH0sXG4gIHsgbmFtZTogJ0NvbGxlZ2UgU3RhdGlvbicgfSxcbiAgeyBuYW1lOiAnQ29sbGllcnZpbGxlJyB9LFxuICB7IG5hbWU6ICdDb2xvcmFkbyBTcHJpbmdzJyB9LFxuICB7IG5hbWU6ICdDb2x0b24nIH0sXG4gIHsgbmFtZTogJ0NvbHVtYmlhJyB9LFxuICB7IG5hbWU6ICdDb2x1bWJpYScgfSxcbiAgeyBuYW1lOiAnQ29sdW1idXMnIH0sXG4gIHsgbmFtZTogJ0NvbHVtYnVzJyB9LFxuICB7IG5hbWU6ICdDb2x1bWJ1cycgfSxcbiAgeyBuYW1lOiAnQ29tbWVyY2UgQ2l0eScgfSxcbiAgeyBuYW1lOiAnQ29tcHRvbicgfSxcbiAgeyBuYW1lOiAnQ29uY29yZCcgfSxcbiAgeyBuYW1lOiAnQ29uY29yZCcgfSxcbiAgeyBuYW1lOiAnQ29uY29yZCcgfSxcbiAgeyBuYW1lOiAnQ29ucm9lJyB9LFxuICB7IG5hbWU6ICdDb253YXknIH0sXG4gIHsgbmFtZTogJ0Nvb24gUmFwaWRzJyB9LFxuICB7IG5hbWU6ICdDb3BwZWxsJyB9LFxuICB7IG5hbWU6ICdDb3JhbCBHYWJsZXMnIH0sXG4gIHsgbmFtZTogJ0NvcmFsIFNwcmluZ3MnIH0sXG4gIHsgbmFtZTogJ0Nvcm9uYScgfSxcbiAgeyBuYW1lOiAnQ29ycHVzIENocmlzdGknIH0sXG4gIHsgbmFtZTogJ0NvcnZhbGxpcycgfSxcbiAgeyBuYW1lOiAnQ29zdGEgTWVzYScgfSxcbiAgeyBuYW1lOiAnQ291bmNpbCBCbHVmZnMnIH0sXG4gIHsgbmFtZTogJ0NvdmluYScgfSxcbiAgeyBuYW1lOiAnQ292aW5ndG9uJyB9LFxuICB7IG5hbWU6ICdDcmFuc3RvbicgfSxcbiAgeyBuYW1lOiAnQ3J5c3RhbCBMYWtlJyB9LFxuICB7IG5hbWU6ICdDdWx2ZXIgQ2l0eScgfSxcbiAgeyBuYW1lOiAnQ3VwZXJ0aW5vJyB9LFxuICB7IG5hbWU6ICdDdXRsZXIgQmF5JyB9LFxuICB7IG5hbWU6ICdDdXlhaG9nYSBGYWxscycgfSxcbiAgeyBuYW1lOiAnQ3lwcmVzcycgfSxcbiAgeyBuYW1lOiAnRGFsbGFzJyB9LFxuICB7IG5hbWU6ICdEYWx5IENpdHknIH0sXG4gIHsgbmFtZTogJ0RhbmJ1cnknIH0sXG4gIHsgbmFtZTogJ0RhbnZpbGxlJyB9LFxuICB7IG5hbWU6ICdEYW52aWxsZScgfSxcbiAgeyBuYW1lOiAnRGF2ZW5wb3J0JyB9LFxuICB7IG5hbWU6ICdEYXZpZScgfSxcbiAgeyBuYW1lOiAnRGF2aXMnIH0sXG4gIHsgbmFtZTogJ0RheXRvbicgfSxcbiAgeyBuYW1lOiAnRGF5dG9uYSBCZWFjaCcgfSxcbiAgeyBuYW1lOiAnRGVLYWxiJyB9LFxuICB7IG5hbWU6ICdEZVNvdG8nIH0sXG4gIHsgbmFtZTogJ0RlYXJib3JuJyB9LFxuICB7IG5hbWU6ICdEZWFyYm9ybiBIZWlnaHRzJyB9LFxuICB7IG5hbWU6ICdEZWNhdHVyJyB9LFxuICB7IG5hbWU6ICdEZWNhdHVyJyB9LFxuICB7IG5hbWU6ICdEZWVyZmllbGQgQmVhY2gnIH0sXG4gIHsgbmFtZTogJ0RlbGFubycgfSxcbiAgeyBuYW1lOiAnRGVscmF5IEJlYWNoJyB9LFxuICB7IG5hbWU6ICdEZWx0b25hJyB9LFxuICB7IG5hbWU6ICdEZW50b24nIH0sXG4gIHsgbmFtZTogJ0RlbnZlcicgfSxcbiAgeyBuYW1lOiAnRGVzIE1vaW5lcycgfSxcbiAgeyBuYW1lOiAnRGVzIFBsYWluZXMnIH0sXG4gIHsgbmFtZTogJ0RldHJvaXQnIH0sXG4gIHsgbmFtZTogJ0RpYW1vbmQgQmFyJyB9LFxuICB7IG5hbWU6ICdEb3JhbCcgfSxcbiAgeyBuYW1lOiAnRG90aGFuJyB9LFxuICB7IG5hbWU6ICdEb3ZlcicgfSxcbiAgeyBuYW1lOiAnRG93bmVycyBHcm92ZScgfSxcbiAgeyBuYW1lOiAnRG93bmV5JyB9LFxuICB7IG5hbWU6ICdEcmFwZXInIH0sXG4gIHsgbmFtZTogJ0R1YmxpbicgfSxcbiAgeyBuYW1lOiAnRHVibGluJyB9LFxuICB7IG5hbWU6ICdEdWJ1cXVlJyB9LFxuICB7IG5hbWU6ICdEdWx1dGgnIH0sXG4gIHsgbmFtZTogJ0R1bmNhbnZpbGxlJyB9LFxuICB7IG5hbWU6ICdEdW53b29keScgfSxcbiAgeyBuYW1lOiAnRHVyaGFtJyB9LFxuICB7IG5hbWU6ICdFYWdhbicgfSxcbiAgeyBuYW1lOiAnRWFzdCBMYW5zaW5nJyB9LFxuICB7IG5hbWU6ICdFYXN0IE9yYW5nZScgfSxcbiAgeyBuYW1lOiAnRWFzdCBQcm92aWRlbmNlJyB9LFxuICB7IG5hbWU6ICdFYXN0dmFsZScgfSxcbiAgeyBuYW1lOiAnRWF1IENsYWlyZScgfSxcbiAgeyBuYW1lOiAnRWRlbiBQcmFpcmllJyB9LFxuICB7IG5hbWU6ICdFZGluYScgfSxcbiAgeyBuYW1lOiAnRWRpbmJ1cmcnIH0sXG4gIHsgbmFtZTogJ0VkbW9uZCcgfSxcbiAgeyBuYW1lOiAnRWRtb25kcycgfSxcbiAgeyBuYW1lOiAnRWwgQ2Fqb24nIH0sXG4gIHsgbmFtZTogJ0VsIENlbnRybycgfSxcbiAgeyBuYW1lOiAnRWwgTW9udGUnIH0sXG4gIHsgbmFtZTogJ0VsIFBhc28nIH0sXG4gIHsgbmFtZTogJ0VsZ2luJyB9LFxuICB7IG5hbWU6ICdFbGl6YWJldGgnIH0sXG4gIHsgbmFtZTogJ0VsayBHcm92ZScgfSxcbiAgeyBuYW1lOiAnRWxraGFydCcgfSxcbiAgeyBuYW1lOiAnRWxtaHVyc3QnIH0sXG4gIHsgbmFtZTogJ0VseXJpYScgfSxcbiAgeyBuYW1lOiAnRW5jaW5pdGFzJyB9LFxuICB7IG5hbWU6ICdFbmlkJyB9LFxuICB7IG5hbWU6ICdFcmllJyB9LFxuICB7IG5hbWU6ICdFc2NvbmRpZG8nIH0sXG4gIHsgbmFtZTogJ0V1Y2xpZCcgfSxcbiAgeyBuYW1lOiAnRXVnZW5lJyB9LFxuICB7IG5hbWU6ICdFdWxlc3MnIH0sXG4gIHsgbmFtZTogJ0V2YW5zdG9uJyB9LFxuICB7IG5hbWU6ICdFdmFuc3ZpbGxlJyB9LFxuICB7IG5hbWU6ICdFdmVyZXR0JyB9LFxuICB7IG5hbWU6ICdFdmVyZXR0JyB9LFxuICB7IG5hbWU6ICdGYWlyZmllbGQnIH0sXG4gIHsgbmFtZTogJ0ZhaXJmaWVsZCcgfSxcbiAgeyBuYW1lOiAnRmFsbCBSaXZlcicgfSxcbiAgeyBuYW1lOiAnRmFyZ28nIH0sXG4gIHsgbmFtZTogJ0Zhcm1pbmd0b24nIH0sXG4gIHsgbmFtZTogJ0Zhcm1pbmd0b24gSGlsbHMnIH0sXG4gIHsgbmFtZTogJ0ZheWV0dGV2aWxsZScgfSxcbiAgeyBuYW1lOiAnRmF5ZXR0ZXZpbGxlJyB9LFxuICB7IG5hbWU6ICdGZWRlcmFsIFdheScgfSxcbiAgeyBuYW1lOiAnRmluZGxheScgfSxcbiAgeyBuYW1lOiAnRmlzaGVycycgfSxcbiAgeyBuYW1lOiAnRml0Y2hidXJnJyB9LFxuICB7IG5hbWU6ICdGbGFnc3RhZmYnIH0sXG4gIHsgbmFtZTogJ0ZsaW50JyB9LFxuICB7IG5hbWU6ICdGbG9yZW5jZScgfSxcbiAgeyBuYW1lOiAnRmxvcmVuY2UnIH0sXG4gIHsgbmFtZTogJ0Zsb3Jpc3NhbnQnIH0sXG4gIHsgbmFtZTogJ0Zsb3dlciBNb3VuZCcgfSxcbiAgeyBuYW1lOiAnRm9sc29tJyB9LFxuICB7IG5hbWU6ICdGb25kIGR1IExhYycgfSxcbiAgeyBuYW1lOiAnRm9udGFuYScgfSxcbiAgeyBuYW1lOiAnRm9ydCBDb2xsaW5zJyB9LFxuICB7IG5hbWU6ICdGb3J0IExhdWRlcmRhbGUnIH0sXG4gIHsgbmFtZTogJ0ZvcnQgTXllcnMnIH0sXG4gIHsgbmFtZTogJ0ZvcnQgUGllcmNlJyB9LFxuICB7IG5hbWU6ICdGb3J0IFNtaXRoJyB9LFxuICB7IG5hbWU6ICdGb3J0IFdheW5lJyB9LFxuICB7IG5hbWU6ICdGb3J0IFdvcnRoJyB9LFxuICB7IG5hbWU6ICdGb3VudGFpbiBWYWxsZXknIH0sXG4gIHsgbmFtZTogJ0ZyYW5rbGluJyB9LFxuICB7IG5hbWU6ICdGcmVkZXJpY2snIH0sXG4gIHsgbmFtZTogJ0ZyZWVwb3J0JyB9LFxuICB7IG5hbWU6ICdGcmVtb250JyB9LFxuICB7IG5hbWU6ICdGcmVzbm8nIH0sXG4gIHsgbmFtZTogJ0ZyaWVuZHN3b29kJyB9LFxuICB7IG5hbWU6ICdGcmlzY28nIH0sXG4gIHsgbmFtZTogJ0Z1bGxlcnRvbicgfSxcbiAgeyBuYW1lOiAnR2FpbmVzdmlsbGUnIH0sXG4gIHsgbmFtZTogJ0dhaXRoZXJzYnVyZycgfSxcbiAgeyBuYW1lOiAnR2FsdmVzdG9uJyB9LFxuICB7IG5hbWU6ICdHYXJkZW4gR3JvdmUnIH0sXG4gIHsgbmFtZTogJ0dhcmRlbmEnIH0sXG4gIHsgbmFtZTogJ0dhcmxhbmQnIH0sXG4gIHsgbmFtZTogJ0dhcnknIH0sXG4gIHsgbmFtZTogJ0dhc3RvbmlhJyB9LFxuICB7IG5hbWU6ICdHZW9yZ2V0b3duJyB9LFxuICB7IG5hbWU6ICdHZXJtYW50b3duJyB9LFxuICB7IG5hbWU6ICdHaWxiZXJ0JyB9LFxuICB7IG5hbWU6ICdHaWxyb3knIH0sXG4gIHsgbmFtZTogJ0dsZW5kYWxlJyB9LFxuICB7IG5hbWU6ICdHbGVuZGFsZScgfSxcbiAgeyBuYW1lOiAnR2xlbmRvcmEnIH0sXG4gIHsgbmFtZTogJ0dsZW52aWV3JyB9LFxuICB7IG5hbWU6ICdHb29keWVhcicgfSxcbiAgeyBuYW1lOiAnR29vc2UgQ3JlZWsnIH0sXG4gIHsgbmFtZTogJ0dyYW5kIEZvcmtzJyB9LFxuICB7IG5hbWU6ICdHcmFuZCBJc2xhbmQnIH0sXG4gIHsgbmFtZTogJ0dyYW5kIEp1bmN0aW9uJyB9LFxuICB7IG5hbWU6ICdHcmFuZCBQcmFpcmllJyB9LFxuICB7IG5hbWU6ICdHcmFuZCBSYXBpZHMnIH0sXG4gIHsgbmFtZTogJ0dyYXBldmluZScgfSxcbiAgeyBuYW1lOiAnR3JlYXQgRmFsbHMnIH0sXG4gIHsgbmFtZTogJ0dyZWVsZXknIH0sXG4gIHsgbmFtZTogJ0dyZWVuIEJheScgfSxcbiAgeyBuYW1lOiAnR3JlZW5hY3JlcycgfSxcbiAgeyBuYW1lOiAnR3JlZW5maWVsZCcgfSxcbiAgeyBuYW1lOiAnR3JlZW5zYm9ybycgfSxcbiAgeyBuYW1lOiAnR3JlZW52aWxsZScgfSxcbiAgeyBuYW1lOiAnR3JlZW52aWxsZScgfSxcbiAgeyBuYW1lOiAnR3JlZW53b29kJyB9LFxuICB7IG5hbWU6ICdHcmVzaGFtJyB9LFxuICB7IG5hbWU6ICdHcm92ZSBDaXR5JyB9LFxuICB7IG5hbWU6ICdHdWxmcG9ydCcgfSxcbiAgeyBuYW1lOiAnSGFja2Vuc2FjaycgfSxcbiAgeyBuYW1lOiAnSGFnZXJzdG93bicgfSxcbiAgeyBuYW1lOiAnSGFsbGFuZGFsZSBCZWFjaCcgfSxcbiAgeyBuYW1lOiAnSGFsdG9tIENpdHknIH0sXG4gIHsgbmFtZTogJ0hhbWlsdG9uJyB9LFxuICB7IG5hbWU6ICdIYW1tb25kJyB9LFxuICB7IG5hbWU6ICdIYW1wdG9uJyB9LFxuICB7IG5hbWU6ICdIYW5mb3JkJyB9LFxuICB7IG5hbWU6ICdIYW5vdmVyIFBhcmsnIH0sXG4gIHsgbmFtZTogJ0hhcmxpbmdlbicgfSxcbiAgeyBuYW1lOiAnSGFycmlzYnVyZycgfSxcbiAgeyBuYW1lOiAnSGFycmlzb25idXJnJyB9LFxuICB7IG5hbWU6ICdIYXJ0Zm9yZCcgfSxcbiAgeyBuYW1lOiAnSGF0dGllc2J1cmcnIH0sXG4gIHsgbmFtZTogJ0hhdmVyaGlsbCcgfSxcbiAgeyBuYW1lOiAnSGF3dGhvcm5lJyB9LFxuICB7IG5hbWU6ICdIYXl3YXJkJyB9LFxuICB7IG5hbWU6ICdIZW1ldCcgfSxcbiAgeyBuYW1lOiAnSGVtcHN0ZWFkJyB9LFxuICB7IG5hbWU6ICdIZW5kZXJzb24nIH0sXG4gIHsgbmFtZTogJ0hlbmRlcnNvbnZpbGxlJyB9LFxuICB7IG5hbWU6ICdIZXNwZXJpYScgfSxcbiAgeyBuYW1lOiAnSGlhbGVhaCcgfSxcbiAgeyBuYW1lOiAnSGlja29yeScgfSxcbiAgeyBuYW1lOiAnSGlnaCBQb2ludCcgfSxcbiAgeyBuYW1lOiAnSGlnaGxhbmQnIH0sXG4gIHsgbmFtZTogJ0hpbGxzYm9ybycgfSxcbiAgeyBuYW1lOiAnSGlsdG9uIEhlYWQgSXNsYW5kJyB9LFxuICB7IG5hbWU6ICdIb2Jva2VuJyB9LFxuICB7IG5hbWU6ICdIb2ZmbWFuIEVzdGF0ZXMnIH0sXG4gIHsgbmFtZTogJ0hvbGx5d29vZCcgfSxcbiAgeyBuYW1lOiAnSG9seW9rZScgfSxcbiAgeyBuYW1lOiAnSG9tZXN0ZWFkJyB9LFxuICB7IG5hbWU6ICdIb25vbHVsdScgfSxcbiAgeyBuYW1lOiAnSG9vdmVyJyB9LFxuICB7IG5hbWU6ICdIb3VzdG9uJyB9LFxuICB7IG5hbWU6ICdIdWJlciBIZWlnaHRzJyB9LFxuICB7IG5hbWU6ICdIdW50ZXJzdmlsbGUnIH0sXG4gIHsgbmFtZTogJ0h1bnRpbmd0b24nIH0sXG4gIHsgbmFtZTogJ0h1bnRpbmd0b24gQmVhY2gnIH0sXG4gIHsgbmFtZTogJ0h1bnRpbmd0b24gUGFyaycgfSxcbiAgeyBuYW1lOiAnSHVudHN2aWxsZScgfSxcbiAgeyBuYW1lOiAnSHVudHN2aWxsZScgfSxcbiAgeyBuYW1lOiAnSHVyc3QnIH0sXG4gIHsgbmFtZTogJ0h1dGNoaW5zb24nIH0sXG4gIHsgbmFtZTogJ0lkYWhvIEZhbGxzJyB9LFxuICB7IG5hbWU6ICdJbmRlcGVuZGVuY2UnIH0sXG4gIHsgbmFtZTogJ0luZGlhbmFwb2xpcycgfSxcbiAgeyBuYW1lOiAnSW5kaW8nIH0sXG4gIHsgbmFtZTogJ0luZ2xld29vZCcgfSxcbiAgeyBuYW1lOiAnSW93YSBDaXR5JyB9LFxuICB7IG5hbWU6ICdJcnZpbmUnIH0sXG4gIHsgbmFtZTogJ0lydmluZycgfSxcbiAgeyBuYW1lOiAnSmFja3NvbicgfSxcbiAgeyBuYW1lOiAnSmFja3NvbicgfSxcbiAgeyBuYW1lOiAnSmFja3NvbnZpbGxlJyB9LFxuICB7IG5hbWU6ICdKYWNrc29udmlsbGUnIH0sXG4gIHsgbmFtZTogJ0phbmVzdmlsbGUnIH0sXG4gIHsgbmFtZTogJ0plZmZlcnNvbiBDaXR5JyB9LFxuICB7IG5hbWU6ICdKZWZmZXJzb252aWxsZScgfSxcbiAgeyBuYW1lOiAnSmVyc2V5IENpdHknIH0sXG4gIHsgbmFtZTogJ0pvaG5zIENyZWVrJyB9LFxuICB7IG5hbWU6ICdKb2huc29uIENpdHknIH0sXG4gIHsgbmFtZTogJ0pvbGlldCcgfSxcbiAgeyBuYW1lOiAnSm9uZXNib3JvJyB9LFxuICB7IG5hbWU6ICdKb3BsaW4nIH0sXG4gIHsgbmFtZTogJ0p1cGl0ZXInIH0sXG4gIHsgbmFtZTogJ0p1cnVwYSBWYWxsZXknIH0sXG4gIHsgbmFtZTogJ0thbGFtYXpvbycgfSxcbiAgeyBuYW1lOiAnS2FubmFwb2xpcycgfSxcbiAgeyBuYW1lOiAnS2Fuc2FzIENpdHknIH0sXG4gIHsgbmFtZTogJ0thbnNhcyBDaXR5JyB9LFxuICB7IG5hbWU6ICdLZWFybnknIH0sXG4gIHsgbmFtZTogJ0tlaXplcicgfSxcbiAgeyBuYW1lOiAnS2VsbGVyJyB9LFxuICB7IG5hbWU6ICdLZW5uZXInIH0sXG4gIHsgbmFtZTogJ0tlbm5ld2ljaycgfSxcbiAgeyBuYW1lOiAnS2Vub3NoYScgfSxcbiAgeyBuYW1lOiAnS2VudCcgfSxcbiAgeyBuYW1lOiAnS2VudHdvb2QnIH0sXG4gIHsgbmFtZTogJ0tldHRlcmluZycgfSxcbiAgeyBuYW1lOiAnS2lsbGVlbicgfSxcbiAgeyBuYW1lOiAnS2luZ3Nwb3J0JyB9LFxuICB7IG5hbWU6ICdLaXJrbGFuZCcgfSxcbiAgeyBuYW1lOiAnS2lzc2ltbWVlJyB9LFxuICB7IG5hbWU6ICdLbm94dmlsbGUnIH0sXG4gIHsgbmFtZTogJ0tva29tbycgfSxcbiAgeyBuYW1lOiAnTGEgQ3Jvc3NlJyB9LFxuICB7IG5hbWU6ICdMYSBIYWJyYScgfSxcbiAgeyBuYW1lOiAnTGEgTWVzYScgfSxcbiAgeyBuYW1lOiAnTGEgTWlyYWRhJyB9LFxuICB7IG5hbWU6ICdMYSBQdWVudGUnIH0sXG4gIHsgbmFtZTogJ0xhIFF1aW50YScgfSxcbiAgeyBuYW1lOiAnTGFjZXknIH0sXG4gIHsgbmFtZTogJ0xhZmF5ZXR0ZScgfSxcbiAgeyBuYW1lOiAnTGFmYXlldHRlJyB9LFxuICB7IG5hbWU6ICdMYWd1bmEgTmlndWVsJyB9LFxuICB7IG5hbWU6ICdMYWtlIENoYXJsZXMnIH0sXG4gIHsgbmFtZTogJ0xha2UgRWxzaW5vcmUnIH0sXG4gIHsgbmFtZTogJ0xha2UgRm9yZXN0JyB9LFxuICB7IG5hbWU6ICdMYWtlIEhhdmFzdSBDaXR5JyB9LFxuICB7IG5hbWU6ICdMYWtlIE9zd2VnbycgfSxcbiAgeyBuYW1lOiAnTGFrZWxhbmQnIH0sXG4gIHsgbmFtZTogJ0xha2V2aWxsZScgfSxcbiAgeyBuYW1lOiAnTGFrZXdvb2QnIH0sXG4gIHsgbmFtZTogJ0xha2V3b29kJyB9LFxuICB7IG5hbWU6ICdMYWtld29vZCcgfSxcbiAgeyBuYW1lOiAnTGFrZXdvb2QnIH0sXG4gIHsgbmFtZTogJ0xhbmNhc3RlcicgfSxcbiAgeyBuYW1lOiAnTGFuY2FzdGVyJyB9LFxuICB7IG5hbWU6ICdMYW5jYXN0ZXInIH0sXG4gIHsgbmFtZTogJ0xhbmNhc3RlcicgfSxcbiAgeyBuYW1lOiAnTGFuc2luZycgfSxcbiAgeyBuYW1lOiAnTGFyZWRvJyB9LFxuICB7IG5hbWU6ICdMYXJnbycgfSxcbiAgeyBuYW1lOiAnTGFzIENydWNlcycgfSxcbiAgeyBuYW1lOiAnTGFzIFZlZ2FzJyB9LFxuICB7IG5hbWU6ICdMYXVkZXJoaWxsJyB9LFxuICB7IG5hbWU6ICdMYXdyZW5jZScgfSxcbiAgeyBuYW1lOiAnTGF3cmVuY2UnIH0sXG4gIHsgbmFtZTogJ0xhd3JlbmNlJyB9LFxuICB7IG5hbWU6ICdMYXd0b24nIH0sXG4gIHsgbmFtZTogJ0xheXRvbicgfSxcbiAgeyBuYW1lOiAnTGVhZ3VlIENpdHknIH0sXG4gIHsgbmFtZTogJ0xlZVxcJ3MgU3VtbWl0JyB9LFxuICB7IG5hbWU6ICdMZWVzYnVyZycgfSxcbiAgeyBuYW1lOiAnTGVoaScgfSxcbiAgeyBuYW1lOiAnTGVuZXhhJyB9LFxuICB7IG5hbWU6ICdMZW9taW5zdGVyJyB9LFxuICB7IG5hbWU6ICdMZXdpc3ZpbGxlJyB9LFxuICB7IG5hbWU6ICdMZXhpbmd0b24tRmF5ZXR0ZScgfSxcbiAgeyBuYW1lOiAnTGltYScgfSxcbiAgeyBuYW1lOiAnTGluY29sbicgfSxcbiAgeyBuYW1lOiAnTGluY29sbicgfSxcbiAgeyBuYW1lOiAnTGluY29sbiBQYXJrJyB9LFxuICB7IG5hbWU6ICdMaW5kZW4nIH0sXG4gIHsgbmFtZTogJ0xpdHRsZSBSb2NrJyB9LFxuICB7IG5hbWU6ICdMaXR0bGV0b24nIH0sXG4gIHsgbmFtZTogJ0xpdmVybW9yZScgfSxcbiAgeyBuYW1lOiAnTGl2b25pYScgfSxcbiAgeyBuYW1lOiAnTG9kaScgfSxcbiAgeyBuYW1lOiAnTG9nYW4nIH0sXG4gIHsgbmFtZTogJ0xvbWJhcmQnIH0sXG4gIHsgbmFtZTogJ0xvbXBvYycgfSxcbiAgeyBuYW1lOiAnTG9uZyBCZWFjaCcgfSxcbiAgeyBuYW1lOiAnTG9uZ21vbnQnIH0sXG4gIHsgbmFtZTogJ0xvbmd2aWV3JyB9LFxuICB7IG5hbWU6ICdMb3JhaW4nIH0sXG4gIHsgbmFtZTogJ0xvcyBBbmdlbGVzJyB9LFxuICB7IG5hbWU6ICdMb3Vpc3ZpbGxlL0plZmZlcnNvbiBDb3VudHknIH0sXG4gIHsgbmFtZTogJ0xvdmVsYW5kJyB9LFxuICB7IG5hbWU6ICdMb3dlbGwnIH0sXG4gIHsgbmFtZTogJ0x1YmJvY2snIH0sXG4gIHsgbmFtZTogJ0x5bmNoYnVyZycgfSxcbiAgeyBuYW1lOiAnTHlubicgfSxcbiAgeyBuYW1lOiAnTHlud29vZCcgfSxcbiAgeyBuYW1lOiAnTWFjb24nIH0sXG4gIHsgbmFtZTogJ01hZGVyYScgfSxcbiAgeyBuYW1lOiAnTWFkaXNvbicgfSxcbiAgeyBuYW1lOiAnTWFkaXNvbicgfSxcbiAgeyBuYW1lOiAnTWFsZGVuJyB9LFxuICB7IG5hbWU6ICdNYW5hc3NhcycgfSxcbiAgeyBuYW1lOiAnTWFuY2hlc3RlcicgfSxcbiAgeyBuYW1lOiAnTWFuaGF0dGFuJyB9LFxuICB7IG5hbWU6ICdNYW5rYXRvJyB9LFxuICB7IG5hbWU6ICdNYW5zZmllbGQnIH0sXG4gIHsgbmFtZTogJ01hbnNmaWVsZCcgfSxcbiAgeyBuYW1lOiAnTWFudGVjYScgfSxcbiAgeyBuYW1lOiAnTWFwbGUgR3JvdmUnIH0sXG4gIHsgbmFtZTogJ01hcGxld29vZCcgfSxcbiAgeyBuYW1lOiAnTWFyYW5hJyB9LFxuICB7IG5hbWU6ICdNYXJnYXRlJyB9LFxuICB7IG5hbWU6ICdNYXJpY29wYScgfSxcbiAgeyBuYW1lOiAnTWFyaWV0dGEnIH0sXG4gIHsgbmFtZTogJ01hcmxib3JvdWdoJyB9LFxuICB7IG5hbWU6ICdNYXJ0aW5leicgfSxcbiAgeyBuYW1lOiAnTWFyeXN2aWxsZScgfSxcbiAgeyBuYW1lOiAnTWNBbGxlbicgfSxcbiAgeyBuYW1lOiAnTWNLaW5uZXknIH0sXG4gIHsgbmFtZTogJ01lZGZvcmQnIH0sXG4gIHsgbmFtZTogJ01lZGZvcmQnIH0sXG4gIHsgbmFtZTogJ01lbGJvdXJuZScgfSxcbiAgeyBuYW1lOiAnTWVtcGhpcycgfSxcbiAgeyBuYW1lOiAnTWVuaWZlZScgfSxcbiAgeyBuYW1lOiAnTWVudG9yJyB9LFxuICB7IG5hbWU6ICdNZXJjZWQnIH0sXG4gIHsgbmFtZTogJ01lcmlkZW4nIH0sXG4gIHsgbmFtZTogJ01lcmlkaWFuJyB9LFxuICB7IG5hbWU6ICdNZXJpZGlhbicgfSxcbiAgeyBuYW1lOiAnTWVzYScgfSxcbiAgeyBuYW1lOiAnTWVzcXVpdGUnIH0sXG4gIHsgbmFtZTogJ01ldGh1ZW4nIH0sXG4gIHsgbmFtZTogJ01pYW1pJyB9LFxuICB7IG5hbWU6ICdNaWFtaSBCZWFjaCcgfSxcbiAgeyBuYW1lOiAnTWlhbWkgR2FyZGVucycgfSxcbiAgeyBuYW1lOiAnTWlkZGxldG93bicgfSxcbiAgeyBuYW1lOiAnTWlkZGxldG93bicgfSxcbiAgeyBuYW1lOiAnTWlkbGFuZCcgfSxcbiAgeyBuYW1lOiAnTWlkbGFuZCcgfSxcbiAgeyBuYW1lOiAnTWlkd2VzdCBDaXR5JyB9LFxuICB7IG5hbWU6ICdNaWxmb3JkJyB9LFxuICB7IG5hbWU6ICdNaWxwaXRhcycgfSxcbiAgeyBuYW1lOiAnTWlsd2F1a2VlJyB9LFxuICB7IG5hbWU6ICdNaW5uZWFwb2xpcycgfSxcbiAgeyBuYW1lOiAnTWlubmV0b25rYScgfSxcbiAgeyBuYW1lOiAnTWlub3QnIH0sXG4gIHsgbmFtZTogJ01pcmFtYXInIH0sXG4gIHsgbmFtZTogJ01pc2hhd2FrYScgfSxcbiAgeyBuYW1lOiAnTWlzc2lvbicgfSxcbiAgeyBuYW1lOiAnTWlzc2lvbiBWaWVqbycgfSxcbiAgeyBuYW1lOiAnTWlzc291bGEnIH0sXG4gIHsgbmFtZTogJ01pc3NvdXJpIENpdHknIH0sXG4gIHsgbmFtZTogJ01vYmlsZScgfSxcbiAgeyBuYW1lOiAnTW9kZXN0bycgfSxcbiAgeyBuYW1lOiAnTW9saW5lJyB9LFxuICB7IG5hbWU6ICdNb25yb2UnIH0sXG4gIHsgbmFtZTogJ01vbnJvdmlhJyB9LFxuICB7IG5hbWU6ICdNb250Y2xhaXInIH0sXG4gIHsgbmFtZTogJ01vbnRlYmVsbG8nIH0sXG4gIHsgbmFtZTogJ01vbnRlcmV5IFBhcmsnIH0sXG4gIHsgbmFtZTogJ01vbnRnb21lcnknIH0sXG4gIHsgbmFtZTogJ01vb3JlJyB9LFxuICB7IG5hbWU6ICdNb29yaGVhZCcgfSxcbiAgeyBuYW1lOiAnTW9yZW5vIFZhbGxleScgfSxcbiAgeyBuYW1lOiAnTW9yZ2FuIEhpbGwnIH0sXG4gIHsgbmFtZTogJ01vdW50IFBsZWFzYW50JyB9LFxuICB7IG5hbWU6ICdNb3VudCBQcm9zcGVjdCcgfSxcbiAgeyBuYW1lOiAnTW91bnQgVmVybm9uJyB9LFxuICB7IG5hbWU6ICdNb3VudGFpbiBWaWV3JyB9LFxuICB7IG5hbWU6ICdNdW5jaWUnIH0sXG4gIHsgbmFtZTogJ011cmZyZWVzYm9ybycgfSxcbiAgeyBuYW1lOiAnTXVycmF5JyB9LFxuICB7IG5hbWU6ICdNdXJyaWV0YScgfSxcbiAgeyBuYW1lOiAnTXVza2Vnb24nIH0sXG4gIHsgbmFtZTogJ011c2tvZ2VlJyB9LFxuICB7IG5hbWU6ICdOYW1wYScgfSxcbiAgeyBuYW1lOiAnTmFwYScgfSxcbiAgeyBuYW1lOiAnTmFwZXJ2aWxsZScgfSxcbiAgeyBuYW1lOiAnTmFzaHVhJyB9LFxuICB7IG5hbWU6ICdOYXNodmlsbGUtRGF2aWRzb24nIH0sXG4gIHsgbmFtZTogJ05hdGlvbmFsIENpdHknIH0sXG4gIHsgbmFtZTogJ05ldyBCZWRmb3JkJyB9LFxuICB7IG5hbWU6ICdOZXcgQmVybGluJyB9LFxuICB7IG5hbWU6ICdOZXcgQnJhdW5mZWxzJyB9LFxuICB7IG5hbWU6ICdOZXcgQnJpdGFpbicgfSxcbiAgeyBuYW1lOiAnTmV3IEJydW5zd2ljaycgfSxcbiAgeyBuYW1lOiAnTmV3IEhhdmVuJyB9LFxuICB7IG5hbWU6ICdOZXcgT3JsZWFucycgfSxcbiAgeyBuYW1lOiAnTmV3IFJvY2hlbGxlJyB9LFxuICB7IG5hbWU6ICdOZXcgWW9yaycgfSxcbiAgeyBuYW1lOiAnTmV3YXJrJyB9LFxuICB7IG5hbWU6ICdOZXdhcmsnIH0sXG4gIHsgbmFtZTogJ05ld2FyaycgfSxcbiAgeyBuYW1lOiAnTmV3cG9ydCBCZWFjaCcgfSxcbiAgeyBuYW1lOiAnTmV3cG9ydCBOZXdzJyB9LFxuICB7IG5hbWU6ICdOZXd0b24nIH0sXG4gIHsgbmFtZTogJ05pYWdhcmEgRmFsbHMnIH0sXG4gIHsgbmFtZTogJ05vYmxlc3ZpbGxlJyB9LFxuICB7IG5hbWU6ICdOb3Jmb2xrJyB9LFxuICB7IG5hbWU6ICdOb3JtYWwnIH0sXG4gIHsgbmFtZTogJ05vcm1hbicgfSxcbiAgeyBuYW1lOiAnTm9ydGggQ2hhcmxlc3RvbicgfSxcbiAgeyBuYW1lOiAnTm9ydGggTGFzIFZlZ2FzJyB9LFxuICB7IG5hbWU6ICdOb3J0aCBMYXVkZXJkYWxlJyB9LFxuICB7IG5hbWU6ICdOb3J0aCBMaXR0bGUgUm9jaycgfSxcbiAgeyBuYW1lOiAnTm9ydGggTWlhbWknIH0sXG4gIHsgbmFtZTogJ05vcnRoIE1pYW1pIEJlYWNoJyB9LFxuICB7IG5hbWU6ICdOb3J0aCBQb3J0JyB9LFxuICB7IG5hbWU6ICdOb3J0aCBSaWNobGFuZCBIaWxscycgfSxcbiAgeyBuYW1lOiAnTm9ydGhnbGVubicgfSxcbiAgeyBuYW1lOiAnTm9yd2FsaycgfSxcbiAgeyBuYW1lOiAnTm9yd2FsaycgfSxcbiAgeyBuYW1lOiAnTm9yd2ljaCcgfSxcbiAgeyBuYW1lOiAnTm92YXRvJyB9LFxuICB7IG5hbWU6ICdOb3ZpJyB9LFxuICB7IG5hbWU6ICdPXFwnRmFsbG9uJyB9LFxuICB7IG5hbWU6ICdPYWsgTGF3bicgfSxcbiAgeyBuYW1lOiAnT2FrIFBhcmsnIH0sXG4gIHsgbmFtZTogJ09ha2xhbmQnIH0sXG4gIHsgbmFtZTogJ09ha2xhbmQgUGFyaycgfSxcbiAgeyBuYW1lOiAnT2FrbGV5JyB9LFxuICB7IG5hbWU6ICdPY2FsYScgfSxcbiAgeyBuYW1lOiAnT2NlYW5zaWRlJyB9LFxuICB7IG5hbWU6ICdPY29lZScgfSxcbiAgeyBuYW1lOiAnT2Rlc3NhJyB9LFxuICB7IG5hbWU6ICdPZ2RlbicgfSxcbiAgeyBuYW1lOiAnT2tsYWhvbWEgQ2l0eScgfSxcbiAgeyBuYW1lOiAnT2xhdGhlJyB9LFxuICB7IG5hbWU6ICdPbHltcGlhJyB9LFxuICB7IG5hbWU6ICdPbWFoYScgfSxcbiAgeyBuYW1lOiAnT250YXJpbycgfSxcbiAgeyBuYW1lOiAnT3JhbmdlJyB9LFxuICB7IG5hbWU6ICdPcmVtJyB9LFxuICB7IG5hbWU6ICdPcmxhbmQgUGFyaycgfSxcbiAgeyBuYW1lOiAnT3JsYW5kbycgfSxcbiAgeyBuYW1lOiAnT3Jtb25kIEJlYWNoJyB9LFxuICB7IG5hbWU6ICdPcm8gVmFsbGV5JyB9LFxuICB7IG5hbWU6ICdPc2hrb3NoJyB9LFxuICB7IG5hbWU6ICdPdmVybGFuZCBQYXJrJyB9LFxuICB7IG5hbWU6ICdPd2Vuc2Jvcm8nIH0sXG4gIHsgbmFtZTogJ094bmFyZCcgfSxcbiAgeyBuYW1lOiAnUGFjaWZpY2EnIH0sXG4gIHsgbmFtZTogJ1BhbGF0aW5lJyB9LFxuICB7IG5hbWU6ICdQYWxtIEJheScgfSxcbiAgeyBuYW1lOiAnUGFsbSBCZWFjaCBHYXJkZW5zJyB9LFxuICB7IG5hbWU6ICdQYWxtIENvYXN0JyB9LFxuICB7IG5hbWU6ICdQYWxtIERlc2VydCcgfSxcbiAgeyBuYW1lOiAnUGFsbSBTcHJpbmdzJyB9LFxuICB7IG5hbWU6ICdQYWxtZGFsZScgfSxcbiAgeyBuYW1lOiAnUGFsbyBBbHRvJyB9LFxuICB7IG5hbWU6ICdQYW5hbWEgQ2l0eScgfSxcbiAgeyBuYW1lOiAnUGFyYW1vdW50JyB9LFxuICB7IG5hbWU6ICdQYXJrIFJpZGdlJyB9LFxuICB7IG5hbWU6ICdQYXJrZXInIH0sXG4gIHsgbmFtZTogJ1Bhcm1hJyB9LFxuICB7IG5hbWU6ICdQYXNhZGVuYScgfSxcbiAgeyBuYW1lOiAnUGFzYWRlbmEnIH0sXG4gIHsgbmFtZTogJ1Bhc2NvJyB9LFxuICB7IG5hbWU6ICdQYXNzYWljJyB9LFxuICB7IG5hbWU6ICdQYXRlcnNvbicgfSxcbiAgeyBuYW1lOiAnUGF3dHVja2V0JyB9LFxuICB7IG5hbWU6ICdQZWFib2R5JyB9LFxuICB7IG5hbWU6ICdQZWFjaHRyZWUgQ29ybmVycycgfSxcbiAgeyBuYW1lOiAnUGVhcmxhbmQnIH0sXG4gIHsgbmFtZTogJ1BlbWJyb2tlIFBpbmVzJyB9LFxuICB7IG5hbWU6ICdQZW5zYWNvbGEnIH0sXG4gIHsgbmFtZTogJ1Blb3JpYScgfSxcbiAgeyBuYW1lOiAnUGVvcmlhJyB9LFxuICB7IG5hbWU6ICdQZXJyaXMnIH0sXG4gIHsgbmFtZTogJ1BlcnRoIEFtYm95JyB9LFxuICB7IG5hbWU6ICdQZXRhbHVtYScgfSxcbiAgeyBuYW1lOiAnUGZsdWdlcnZpbGxlJyB9LFxuICB7IG5hbWU6ICdQaGFycicgfSxcbiAgeyBuYW1lOiAnUGhlbml4IENpdHknIH0sXG4gIHsgbmFtZTogJ1BoaWxhZGVscGhpYScgfSxcbiAgeyBuYW1lOiAnUGhvZW5peCcgfSxcbiAgeyBuYW1lOiAnUGljbyBSaXZlcmEnIH0sXG4gIHsgbmFtZTogJ1BpbmUgQmx1ZmYnIH0sXG4gIHsgbmFtZTogJ1BpbmVsbGFzIFBhcmsnIH0sXG4gIHsgbmFtZTogJ1BpdHRzYnVyZycgfSxcbiAgeyBuYW1lOiAnUGl0dHNidXJnaCcgfSxcbiAgeyBuYW1lOiAnUGl0dHNmaWVsZCcgfSxcbiAgeyBuYW1lOiAnUGxhY2VudGlhJyB9LFxuICB7IG5hbWU6ICdQbGFpbmZpZWxkJyB9LFxuICB7IG5hbWU6ICdQbGFpbmZpZWxkJyB9LFxuICB7IG5hbWU6ICdQbGFubycgfSxcbiAgeyBuYW1lOiAnUGxhbnRhdGlvbicgfSxcbiAgeyBuYW1lOiAnUGxlYXNhbnRvbicgfSxcbiAgeyBuYW1lOiAnUGx5bW91dGgnIH0sXG4gIHsgbmFtZTogJ1BvY2F0ZWxsbycgfSxcbiAgeyBuYW1lOiAnUG9tb25hJyB9LFxuICB7IG5hbWU6ICdQb21wYW5vIEJlYWNoJyB9LFxuICB7IG5hbWU6ICdQb250aWFjJyB9LFxuICB7IG5hbWU6ICdQb3J0IEFydGh1cicgfSxcbiAgeyBuYW1lOiAnUG9ydCBPcmFuZ2UnIH0sXG4gIHsgbmFtZTogJ1BvcnQgU3QuIEx1Y2llJyB9LFxuICB7IG5hbWU6ICdQb3J0YWdlJyB9LFxuICB7IG5hbWU6ICdQb3J0ZXJ2aWxsZScgfSxcbiAgeyBuYW1lOiAnUG9ydGxhbmQnIH0sXG4gIHsgbmFtZTogJ1BvcnRsYW5kJyB9LFxuICB7IG5hbWU6ICdQb3J0c21vdXRoJyB9LFxuICB7IG5hbWU6ICdQb3dheScgfSxcbiAgeyBuYW1lOiAnUHJlc2NvdHQnIH0sXG4gIHsgbmFtZTogJ1ByZXNjb3R0IFZhbGxleScgfSxcbiAgeyBuYW1lOiAnUHJvdmlkZW5jZScgfSxcbiAgeyBuYW1lOiAnUHJvdm8nIH0sXG4gIHsgbmFtZTogJ1B1ZWJsbycgfSxcbiAgeyBuYW1lOiAnUHV5YWxsdXAnIH0sXG4gIHsgbmFtZTogJ1F1aW5jeScgfSxcbiAgeyBuYW1lOiAnUXVpbmN5JyB9LFxuICB7IG5hbWU6ICdSYWNpbmUnIH0sXG4gIHsgbmFtZTogJ1JhbGVpZ2gnIH0sXG4gIHsgbmFtZTogJ1JhbmNobyBDb3Jkb3ZhJyB9LFxuICB7IG5hbWU6ICdSYW5jaG8gQ3VjYW1vbmdhJyB9LFxuICB7IG5hbWU6ICdSYW5jaG8gUGFsb3MgVmVyZGVzJyB9LFxuICB7IG5hbWU6ICdSYW5jaG8gU2FudGEgTWFyZ2FyaXRhJyB9LFxuICB7IG5hbWU6ICdSYXBpZCBDaXR5JyB9LFxuICB7IG5hbWU6ICdSZWFkaW5nJyB9LFxuICB7IG5hbWU6ICdSZWRkaW5nJyB9LFxuICB7IG5hbWU6ICdSZWRsYW5kcycgfSxcbiAgeyBuYW1lOiAnUmVkbW9uZCcgfSxcbiAgeyBuYW1lOiAnUmVkb25kbyBCZWFjaCcgfSxcbiAgeyBuYW1lOiAnUmVkd29vZCBDaXR5JyB9LFxuICB7IG5hbWU6ICdSZW5vJyB9LFxuICB7IG5hbWU6ICdSZW50b24nIH0sXG4gIHsgbmFtZTogJ1JldmVyZScgfSxcbiAgeyBuYW1lOiAnUmlhbHRvJyB9LFxuICB7IG5hbWU6ICdSaWNoYXJkc29uJyB9LFxuICB7IG5hbWU6ICdSaWNobGFuZCcgfSxcbiAgeyBuYW1lOiAnUmljaG1vbmQnIH0sXG4gIHsgbmFtZTogJ1JpY2htb25kJyB9LFxuICB7IG5hbWU6ICdSaW8gUmFuY2hvJyB9LFxuICB7IG5hbWU6ICdSaXZlcnNpZGUnIH0sXG4gIHsgbmFtZTogJ1JpdmVydG9uJyB9LFxuICB7IG5hbWU6ICdSb2Fub2tlJyB9LFxuICB7IG5hbWU6ICdSb2NoZXN0ZXInIH0sXG4gIHsgbmFtZTogJ1JvY2hlc3RlcicgfSxcbiAgeyBuYW1lOiAnUm9jaGVzdGVyIEhpbGxzJyB9LFxuICB7IG5hbWU6ICdSb2NrIEhpbGwnIH0sXG4gIHsgbmFtZTogJ1JvY2sgSXNsYW5kJyB9LFxuICB7IG5hbWU6ICdSb2NrZm9yZCcgfSxcbiAgeyBuYW1lOiAnUm9ja2xpbicgfSxcbiAgeyBuYW1lOiAnUm9ja3ZpbGxlJyB9LFxuICB7IG5hbWU6ICdSb2Nrd2FsbCcgfSxcbiAgeyBuYW1lOiAnUm9ja3kgTW91bnQnIH0sXG4gIHsgbmFtZTogJ1JvZ2VycycgfSxcbiAgeyBuYW1lOiAnUm9obmVydCBQYXJrJyB9LFxuICB7IG5hbWU6ICdSb21lb3ZpbGxlJyB9LFxuICB7IG5hbWU6ICdSb3NlbWVhZCcgfSxcbiAgeyBuYW1lOiAnUm9zZXZpbGxlJyB9LFxuICB7IG5hbWU6ICdSb3NldmlsbGUnIH0sXG4gIHsgbmFtZTogJ1Jvc3dlbGwnIH0sXG4gIHsgbmFtZTogJ1Jvc3dlbGwnIH0sXG4gIHsgbmFtZTogJ1JvdW5kIFJvY2snIH0sXG4gIHsgbmFtZTogJ1Jvd2xldHQnIH0sXG4gIHsgbmFtZTogJ1JveScgfSxcbiAgeyBuYW1lOiAnUm95YWwgT2FrJyB9LFxuICB7IG5hbWU6ICdTYWNyYW1lbnRvJyB9LFxuICB7IG5hbWU6ICdTYWdpbmF3JyB9LFxuICB7IG5hbWU6ICdTYWxlbScgfSxcbiAgeyBuYW1lOiAnU2FsZW0nIH0sXG4gIHsgbmFtZTogJ1NhbGluYScgfSxcbiAgeyBuYW1lOiAnU2FsaW5hcycgfSxcbiAgeyBuYW1lOiAnU2FsdCBMYWtlIENpdHknIH0sXG4gIHsgbmFtZTogJ1NhbW1hbWlzaCcgfSxcbiAgeyBuYW1lOiAnU2FuIEFuZ2VsbycgfSxcbiAgeyBuYW1lOiAnU2FuIEFudG9uaW8nIH0sXG4gIHsgbmFtZTogJ1NhbiBCZXJuYXJkaW5vJyB9LFxuICB7IG5hbWU6ICdTYW4gQnJ1bm8nIH0sXG4gIHsgbmFtZTogJ1NhbiBCdWVuYXZlbnR1cmEgKFZlbnR1cmEpJyB9LFxuICB7IG5hbWU6ICdTYW4gQ2xlbWVudGUnIH0sXG4gIHsgbmFtZTogJ1NhbiBEaWVnbycgfSxcbiAgeyBuYW1lOiAnU2FuIEZyYW5jaXNjbycgfSxcbiAgeyBuYW1lOiAnU2FuIEdhYnJpZWwnIH0sXG4gIHsgbmFtZTogJ1NhbiBKYWNpbnRvJyB9LFxuICB7IG5hbWU6ICdTYW4gSm9zZScgfSxcbiAgeyBuYW1lOiAnU2FuIExlYW5kcm8nIH0sXG4gIHsgbmFtZTogJ1NhbiBMdWlzIE9iaXNwbycgfSxcbiAgeyBuYW1lOiAnU2FuIE1hcmNvcycgfSxcbiAgeyBuYW1lOiAnU2FuIE1hcmNvcycgfSxcbiAgeyBuYW1lOiAnU2FuIE1hdGVvJyB9LFxuICB7IG5hbWU6ICdTYW4gUmFmYWVsJyB9LFxuICB7IG5hbWU6ICdTYW4gUmFtb24nIH0sXG4gIHsgbmFtZTogJ1NhbmR5JyB9LFxuICB7IG5hbWU6ICdTYW5keSBTcHJpbmdzJyB9LFxuICB7IG5hbWU6ICdTYW5mb3JkJyB9LFxuICB7IG5hbWU6ICdTYW50YSBBbmEnIH0sXG4gIHsgbmFtZTogJ1NhbnRhIEJhcmJhcmEnIH0sXG4gIHsgbmFtZTogJ1NhbnRhIENsYXJhJyB9LFxuICB7IG5hbWU6ICdTYW50YSBDbGFyaXRhJyB9LFxuICB7IG5hbWU6ICdTYW50YSBDcnV6JyB9LFxuICB7IG5hbWU6ICdTYW50YSBGZScgfSxcbiAgeyBuYW1lOiAnU2FudGEgTWFyaWEnIH0sXG4gIHsgbmFtZTogJ1NhbnRhIE1vbmljYScgfSxcbiAgeyBuYW1lOiAnU2FudGEgUm9zYScgfSxcbiAgeyBuYW1lOiAnU2FudGVlJyB9LFxuICB7IG5hbWU6ICdTYXJhc290YScgfSxcbiAgeyBuYW1lOiAnU2F2YW5uYWgnIH0sXG4gIHsgbmFtZTogJ1NheXJldmlsbGUnIH0sXG4gIHsgbmFtZTogJ1NjaGF1bWJ1cmcnIH0sXG4gIHsgbmFtZTogJ1NjaGVuZWN0YWR5JyB9LFxuICB7IG5hbWU6ICdTY290dHNkYWxlJyB9LFxuICB7IG5hbWU6ICdTY3JhbnRvbicgfSxcbiAgeyBuYW1lOiAnU2VhdHRsZScgfSxcbiAgeyBuYW1lOiAnU2hha29wZWUnIH0sXG4gIHsgbmFtZTogJ1NoYXduZWUnIH0sXG4gIHsgbmFtZTogJ1NoZWJveWdhbicgfSxcbiAgeyBuYW1lOiAnU2hlbHRvbicgfSxcbiAgeyBuYW1lOiAnU2hlcm1hbicgfSxcbiAgeyBuYW1lOiAnU2hvcmVsaW5lJyB9LFxuICB7IG5hbWU6ICdTaHJldmVwb3J0JyB9LFxuICB7IG5hbWU6ICdTaWVycmEgVmlzdGEnIH0sXG4gIHsgbmFtZTogJ1NpbWkgVmFsbGV5JyB9LFxuICB7IG5hbWU6ICdTaW91eCBDaXR5JyB9LFxuICB7IG5hbWU6ICdTaW91eCBGYWxscycgfSxcbiAgeyBuYW1lOiAnU2tva2llJyB9LFxuICB7IG5hbWU6ICdTbXlybmEnIH0sXG4gIHsgbmFtZTogJ1NteXJuYScgfSxcbiAgeyBuYW1lOiAnU29tZXJ2aWxsZScgfSxcbiAgeyBuYW1lOiAnU291dGggQmVuZCcgfSxcbiAgeyBuYW1lOiAnU291dGggR2F0ZScgfSxcbiAgeyBuYW1lOiAnU291dGggSm9yZGFuJyB9LFxuICB7IG5hbWU6ICdTb3V0aCBTYW4gRnJhbmNpc2NvJyB9LFxuICB7IG5hbWU6ICdTb3V0aGF2ZW4nIH0sXG4gIHsgbmFtZTogJ1NvdXRoZmllbGQnIH0sXG4gIHsgbmFtZTogJ1NwYW5pc2ggRm9yaycgfSxcbiAgeyBuYW1lOiAnU3BhcmtzJyB9LFxuICB7IG5hbWU6ICdTcGFydGFuYnVyZycgfSxcbiAgeyBuYW1lOiAnU3Bva2FuZScgfSxcbiAgeyBuYW1lOiAnU3Bva2FuZSBWYWxsZXknIH0sXG4gIHsgbmFtZTogJ1NwcmluZ2RhbGUnIH0sXG4gIHsgbmFtZTogJ1NwcmluZ2ZpZWxkJyB9LFxuICB7IG5hbWU6ICdTcHJpbmdmaWVsZCcgfSxcbiAgeyBuYW1lOiAnU3ByaW5nZmllbGQnIH0sXG4gIHsgbmFtZTogJ1NwcmluZ2ZpZWxkJyB9LFxuICB7IG5hbWU6ICdTcHJpbmdmaWVsZCcgfSxcbiAgeyBuYW1lOiAnU3QuIENoYXJsZXMnIH0sXG4gIHsgbmFtZTogJ1N0LiBDbGFpciBTaG9yZXMnIH0sXG4gIHsgbmFtZTogJ1N0LiBDbG91ZCcgfSxcbiAgeyBuYW1lOiAnU3QuIENsb3VkJyB9LFxuICB7IG5hbWU6ICdTdC4gR2VvcmdlJyB9LFxuICB7IG5hbWU6ICdTdC4gSm9zZXBoJyB9LFxuICB7IG5hbWU6ICdTdC4gTG91aXMnIH0sXG4gIHsgbmFtZTogJ1N0LiBMb3VpcyBQYXJrJyB9LFxuICB7IG5hbWU6ICdTdC4gUGF1bCcgfSxcbiAgeyBuYW1lOiAnU3QuIFBldGVycycgfSxcbiAgeyBuYW1lOiAnU3QuIFBldGVyc2J1cmcnIH0sXG4gIHsgbmFtZTogJ1N0YW1mb3JkJyB9LFxuICB7IG5hbWU6ICdTdGFudG9uJyB9LFxuICB7IG5hbWU6ICdTdGF0ZSBDb2xsZWdlJyB9LFxuICB7IG5hbWU6ICdTdGVybGluZyBIZWlnaHRzJyB9LFxuICB7IG5hbWU6ICdTdGlsbHdhdGVyJyB9LFxuICB7IG5hbWU6ICdTdG9ja3RvbicgfSxcbiAgeyBuYW1lOiAnU3RyZWFtd29vZCcgfSxcbiAgeyBuYW1lOiAnU3Ryb25nc3ZpbGxlJyB9LFxuICB7IG5hbWU6ICdTdWZmb2xrJyB9LFxuICB7IG5hbWU6ICdTdWdhciBMYW5kJyB9LFxuICB7IG5hbWU6ICdTdW1tZXJ2aWxsZScgfSxcbiAgeyBuYW1lOiAnU3VtdGVyJyB9LFxuICB7IG5hbWU6ICdTdW5ueXZhbGUnIH0sXG4gIHsgbmFtZTogJ1N1bnJpc2UnIH0sXG4gIHsgbmFtZTogJ1N1cnByaXNlJyB9LFxuICB7IG5hbWU6ICdTeXJhY3VzZScgfSxcbiAgeyBuYW1lOiAnVGFjb21hJyB9LFxuICB7IG5hbWU6ICdUYWxsYWhhc3NlZScgfSxcbiAgeyBuYW1lOiAnVGFtYXJhYycgfSxcbiAgeyBuYW1lOiAnVGFtcGEnIH0sXG4gIHsgbmFtZTogJ1RhdW50b24nIH0sXG4gIHsgbmFtZTogJ1RheWxvcicgfSxcbiAgeyBuYW1lOiAnVGF5bG9yc3ZpbGxlJyB9LFxuICB7IG5hbWU6ICdUZW1lY3VsYScgfSxcbiAgeyBuYW1lOiAnVGVtcGUnIH0sXG4gIHsgbmFtZTogJ1RlbXBsZScgfSxcbiAgeyBuYW1lOiAnVGVycmUgSGF1dGUnIH0sXG4gIHsgbmFtZTogJ1RleGFya2FuYScgfSxcbiAgeyBuYW1lOiAnVGV4YXMgQ2l0eScgfSxcbiAgeyBuYW1lOiAnVGhlIENvbG9ueScgfSxcbiAgeyBuYW1lOiAnVGhvcm50b24nIH0sXG4gIHsgbmFtZTogJ1Rob3VzYW5kIE9ha3MnIH0sXG4gIHsgbmFtZTogJ1RpZ2FyZCcgfSxcbiAgeyBuYW1lOiAnVGlubGV5IFBhcmsnIH0sXG4gIHsgbmFtZTogJ1RpdHVzdmlsbGUnIH0sXG4gIHsgbmFtZTogJ1RvbGVkbycgfSxcbiAgeyBuYW1lOiAnVG9wZWthJyB9LFxuICB7IG5hbWU6ICdUb3JyYW5jZScgfSxcbiAgeyBuYW1lOiAnVHJhY3knIH0sXG4gIHsgbmFtZTogJ1RyZW50b24nIH0sXG4gIHsgbmFtZTogJ1Ryb3knIH0sXG4gIHsgbmFtZTogJ1Ryb3knIH0sXG4gIHsgbmFtZTogJ1R1Y3NvbicgfSxcbiAgeyBuYW1lOiAnVHVsYXJlJyB9LFxuICB7IG5hbWU6ICdUdWxzYScgfSxcbiAgeyBuYW1lOiAnVHVybG9jaycgfSxcbiAgeyBuYW1lOiAnVHVzY2Fsb29zYScgfSxcbiAgeyBuYW1lOiAnVHVzdGluJyB9LFxuICB7IG5hbWU6ICdUd2luIEZhbGxzJyB9LFxuICB7IG5hbWU6ICdUeWxlcicgfSxcbiAgeyBuYW1lOiAnVW5pb24gQ2l0eScgfSxcbiAgeyBuYW1lOiAnVW5pb24gQ2l0eScgfSxcbiAgeyBuYW1lOiAnVXBsYW5kJyB9LFxuICB7IG5hbWU6ICdVcmJhbmEnIH0sXG4gIHsgbmFtZTogJ1VyYmFuZGFsZScgfSxcbiAgeyBuYW1lOiAnVXRpY2EnIH0sXG4gIHsgbmFtZTogJ1ZhY2F2aWxsZScgfSxcbiAgeyBuYW1lOiAnVmFsZG9zdGEnIH0sXG4gIHsgbmFtZTogJ1ZhbGxlam8nIH0sXG4gIHsgbmFtZTogJ1ZhbGxleSBTdHJlYW0nIH0sXG4gIHsgbmFtZTogJ1ZhbmNvdXZlcicgfSxcbiAgeyBuYW1lOiAnVmljdG9yaWEnIH0sXG4gIHsgbmFtZTogJ1ZpY3RvcnZpbGxlJyB9LFxuICB7IG5hbWU6ICdWaW5lbGFuZCcgfSxcbiAgeyBuYW1lOiAnVmlyZ2luaWEgQmVhY2gnIH0sXG4gIHsgbmFtZTogJ1Zpc2FsaWEnIH0sXG4gIHsgbmFtZTogJ1Zpc3RhJyB9LFxuICB7IG5hbWU6ICdXYWNvJyB9LFxuICB7IG5hbWU6ICdXYWxudXQgQ3JlZWsnIH0sXG4gIHsgbmFtZTogJ1dhbHRoYW0nIH0sXG4gIHsgbmFtZTogJ1dhcm5lciBSb2JpbnMnIH0sXG4gIHsgbmFtZTogJ1dhcnJlbicgfSxcbiAgeyBuYW1lOiAnV2FycmVuJyB9LFxuICB7IG5hbWU6ICdXYXJ3aWNrJyB9LFxuICB7IG5hbWU6ICdXYXNoaW5ndG9uJyB9LFxuICB7IG5hbWU6ICdXYXRlcmJ1cnknIH0sXG4gIHsgbmFtZTogJ1dhdGVybG9vJyB9LFxuICB7IG5hbWU6ICdXYXRzb252aWxsZScgfSxcbiAgeyBuYW1lOiAnV2F1a2VnYW4nIH0sXG4gIHsgbmFtZTogJ1dhdWtlc2hhJyB9LFxuICB7IG5hbWU6ICdXYXVzYXUnIH0sXG4gIHsgbmFtZTogJ1dhdXdhdG9zYScgfSxcbiAgeyBuYW1lOiAnV2VsbGluZ3RvbicgfSxcbiAgeyBuYW1lOiAnV2VzbGFjbycgfSxcbiAgeyBuYW1lOiAnV2VzdCBBbGxpcycgfSxcbiAgeyBuYW1lOiAnV2VzdCBDb3ZpbmEnIH0sXG4gIHsgbmFtZTogJ1dlc3QgRGVzIE1vaW5lcycgfSxcbiAgeyBuYW1lOiAnV2VzdCBIYXZlbicgfSxcbiAgeyBuYW1lOiAnV2VzdCBKb3JkYW4nIH0sXG4gIHsgbmFtZTogJ1dlc3QgTmV3IFlvcmsnIH0sXG4gIHsgbmFtZTogJ1dlc3QgUGFsbSBCZWFjaCcgfSxcbiAgeyBuYW1lOiAnV2VzdCBTYWNyYW1lbnRvJyB9LFxuICB7IG5hbWU6ICdXZXN0IFZhbGxleSBDaXR5JyB9LFxuICB7IG5hbWU6ICdXZXN0ZXJ2aWxsZScgfSxcbiAgeyBuYW1lOiAnV2VzdGZpZWxkJyB9LFxuICB7IG5hbWU6ICdXZXN0bGFuZCcgfSxcbiAgeyBuYW1lOiAnV2VzdG1pbnN0ZXInIH0sXG4gIHsgbmFtZTogJ1dlc3RtaW5zdGVyJyB9LFxuICB7IG5hbWU6ICdXZXN0b24nIH0sXG4gIHsgbmFtZTogJ1dleW1vdXRoIFRvd24nIH0sXG4gIHsgbmFtZTogJ1doZWF0b24nIH0sXG4gIHsgbmFtZTogJ1doZWVsaW5nJyB9LFxuICB7IG5hbWU6ICdXaGl0ZSBQbGFpbnMnIH0sXG4gIHsgbmFtZTogJ1doaXR0aWVyJyB9LFxuICB7IG5hbWU6ICdXaWNoaXRhJyB9LFxuICB7IG5hbWU6ICdXaWNoaXRhIEZhbGxzJyB9LFxuICB7IG5hbWU6ICdXaWxrZXMtQmFycmUnIH0sXG4gIHsgbmFtZTogJ1dpbG1pbmd0b24nIH0sXG4gIHsgbmFtZTogJ1dpbG1pbmd0b24nIH0sXG4gIHsgbmFtZTogJ1dpbHNvbicgfSxcbiAgeyBuYW1lOiAnV2luc3Rvbi1TYWxlbScgfSxcbiAgeyBuYW1lOiAnV2ludGVyIEdhcmRlbicgfSxcbiAgeyBuYW1lOiAnV29idXJuJyB9LFxuICB7IG5hbWU6ICdXb29kYnVyeScgfSxcbiAgeyBuYW1lOiAnV29vZGxhbmQnIH0sXG4gIHsgbmFtZTogJ1dvb25zb2NrZXQnIH0sXG4gIHsgbmFtZTogJ1dvcmNlc3RlcicgfSxcbiAgeyBuYW1lOiAnV3lsaWUnIH0sXG4gIHsgbmFtZTogJ1d5b21pbmcnIH0sXG4gIHsgbmFtZTogJ1lha2ltYScgfSxcbiAgeyBuYW1lOiAnWW9ua2VycycgfSxcbiAgeyBuYW1lOiAnWW9yYmEgTGluZGEnIH0sXG4gIHsgbmFtZTogJ1lvcmsnIH0sXG4gIHsgbmFtZTogJ1lvdW5nc3Rvd24nIH0sXG4gIHsgbmFtZTogJ1l1YmEgQ2l0eScgfSxcbiAgeyBuYW1lOiAnWXVjYWlwYScgfSxcbiAgeyBuYW1lOiAnWXVtYScgfVxuXTtcbiIsIm1vZHVsZS5leHBvcnRzID0gW1xuXHR7IGdpdGh1YjogJ2plZHdhdHNvbicsIG5hbWU6ICdKZWQgV2F0c29uJyB9LFxuXHR7IGdpdGh1YjogJ2JydWRlcnN0ZWluJywgbmFtZTogJ0RhdmUgQnJvdGhlcnN0b25lJyB9LFxuXHR7IGdpdGh1YjogJ2pvc3NtYWMnLCBuYW1lOiAnSm9zcyBNYWNraXNvbicgfSxcblx0eyBnaXRodWI6ICdqbmllY2hjaWFsJywgbmFtZTogJ0pha3ViIE5pZWNoY2lhxYInIH0sXG5cdHsgZ2l0aHViOiAnY3JhaWdkYWxsaW1vcmUnLCBuYW1lOiAnQ3JhaWcgRGFsbGltb3JlJyB9LFxuXHR7IGdpdGh1YjogJ2p1bGVuJywgbmFtZTogJ0p1bGVuIFJ1aXogQWl6cHVydScgfSxcblx0eyBnaXRodWI6ICdkY291c2VucycsIG5hbWU6ICdEYW5pZWwgQ291c2VucycgfSxcblx0eyBnaXRodWI6ICdqZ2F1dHNjaCcsIG5hbWU6ICdKb24gR2F1dHNjaCcgfSxcblx0eyBnaXRodWI6ICdkbWl0cnktc21pcm5vdicsIG5hbWU6ICdEbWl0cnkgU21pcm5vdicgfSxcbl07XG4iLCJleHBvcnRzLkFVID0gW1xuXHR7IHZhbHVlOiAnYXVzdHJhbGlhbi1jYXBpdGFsLXRlcnJpdG9yeScsIGxhYmVsOiAnQXVzdHJhbGlhbiBDYXBpdGFsIFRlcnJpdG9yeScsIGNsYXNzTmFtZTogJ1N0YXRlLUFDVCcgfSxcblx0eyB2YWx1ZTogJ25ldy1zb3V0aC13YWxlcycsIGxhYmVsOiAnTmV3IFNvdXRoIFdhbGVzJywgY2xhc3NOYW1lOiAnU3RhdGUtTlNXJyB9LFxuXHR7IHZhbHVlOiAndmljdG9yaWEnLCBsYWJlbDogJ1ZpY3RvcmlhJywgY2xhc3NOYW1lOiAnU3RhdGUtVmljJyB9LFxuXHR7IHZhbHVlOiAncXVlZW5zbGFuZCcsIGxhYmVsOiAnUXVlZW5zbGFuZCcsIGNsYXNzTmFtZTogJ1N0YXRlLVFsZCcgfSxcblx0eyB2YWx1ZTogJ3dlc3Rlcm4tYXVzdHJhbGlhJywgbGFiZWw6ICdXZXN0ZXJuIEF1c3RyYWxpYScsIGNsYXNzTmFtZTogJ1N0YXRlLVdBJyB9LFxuXHR7IHZhbHVlOiAnc291dGgtYXVzdHJhbGlhJywgbGFiZWw6ICdTb3V0aCBBdXN0cmFsaWEnLCBjbGFzc05hbWU6ICdTdGF0ZS1TQScgfSxcblx0eyB2YWx1ZTogJ3Rhc21hbmlhJywgbGFiZWw6ICdUYXNtYW5pYScsIGNsYXNzTmFtZTogJ1N0YXRlLVRhcycgfSxcblx0eyB2YWx1ZTogJ25vcnRoZXJuLXRlcnJpdG9yeScsIGxhYmVsOiAnTm9ydGhlcm4gVGVycml0b3J5JywgY2xhc3NOYW1lOiAnU3RhdGUtTlQnIH0sXG5dO1xuXG5leHBvcnRzLlVTID0gW1xuICAgIHsgdmFsdWU6ICdBTCcsIGxhYmVsOiAnQWxhYmFtYScsIGRpc2FibGVkOiB0cnVlIH0sXG4gICAgeyB2YWx1ZTogJ0FLJywgbGFiZWw6ICdBbGFza2EnIH0sXG4gICAgeyB2YWx1ZTogJ0FTJywgbGFiZWw6ICdBbWVyaWNhbiBTYW1vYScgfSxcbiAgICB7IHZhbHVlOiAnQVonLCBsYWJlbDogJ0FyaXpvbmEnIH0sXG4gICAgeyB2YWx1ZTogJ0FSJywgbGFiZWw6ICdBcmthbnNhcycgfSxcbiAgICB7IHZhbHVlOiAnQ0EnLCBsYWJlbDogJ0NhbGlmb3JuaWEnIH0sXG4gICAgeyB2YWx1ZTogJ0NPJywgbGFiZWw6ICdDb2xvcmFkbycgfSxcbiAgICB7IHZhbHVlOiAnQ1QnLCBsYWJlbDogJ0Nvbm5lY3RpY3V0JyB9LFxuICAgIHsgdmFsdWU6ICdERScsIGxhYmVsOiAnRGVsYXdhcmUnIH0sXG4gICAgeyB2YWx1ZTogJ0RDJywgbGFiZWw6ICdEaXN0cmljdCBPZiBDb2x1bWJpYScgfSxcbiAgICB7IHZhbHVlOiAnRk0nLCBsYWJlbDogJ0ZlZGVyYXRlZCBTdGF0ZXMgT2YgTWljcm9uZXNpYScgfSxcbiAgICB7IHZhbHVlOiAnRkwnLCBsYWJlbDogJ0Zsb3JpZGEnIH0sXG4gICAgeyB2YWx1ZTogJ0dBJywgbGFiZWw6ICdHZW9yZ2lhJyB9LFxuICAgIHsgdmFsdWU6ICdHVScsIGxhYmVsOiAnR3VhbScgfSxcbiAgICB7IHZhbHVlOiAnSEknLCBsYWJlbDogJ0hhd2FpaScgfSxcbiAgICB7IHZhbHVlOiAnSUQnLCBsYWJlbDogJ0lkYWhvJyB9LFxuICAgIHsgdmFsdWU6ICdJTCcsIGxhYmVsOiAnSWxsaW5vaXMnIH0sXG4gICAgeyB2YWx1ZTogJ0lOJywgbGFiZWw6ICdJbmRpYW5hJyB9LFxuICAgIHsgdmFsdWU6ICdJQScsIGxhYmVsOiAnSW93YScgfSxcbiAgICB7IHZhbHVlOiAnS1MnLCBsYWJlbDogJ0thbnNhcycgfSxcbiAgICB7IHZhbHVlOiAnS1knLCBsYWJlbDogJ0tlbnR1Y2t5JyB9LFxuICAgIHsgdmFsdWU6ICdMQScsIGxhYmVsOiAnTG91aXNpYW5hJyB9LFxuICAgIHsgdmFsdWU6ICdNRScsIGxhYmVsOiAnTWFpbmUnIH0sXG4gICAgeyB2YWx1ZTogJ01IJywgbGFiZWw6ICdNYXJzaGFsbCBJc2xhbmRzJyB9LFxuICAgIHsgdmFsdWU6ICdNRCcsIGxhYmVsOiAnTWFyeWxhbmQnIH0sXG4gICAgeyB2YWx1ZTogJ01BJywgbGFiZWw6ICdNYXNzYWNodXNldHRzJyB9LFxuICAgIHsgdmFsdWU6ICdNSScsIGxhYmVsOiAnTWljaGlnYW4nIH0sXG4gICAgeyB2YWx1ZTogJ01OJywgbGFiZWw6ICdNaW5uZXNvdGEnIH0sXG4gICAgeyB2YWx1ZTogJ01TJywgbGFiZWw6ICdNaXNzaXNzaXBwaScgfSxcbiAgICB7IHZhbHVlOiAnTU8nLCBsYWJlbDogJ01pc3NvdXJpJyB9LFxuICAgIHsgdmFsdWU6ICdNVCcsIGxhYmVsOiAnTW9udGFuYScgfSxcbiAgICB7IHZhbHVlOiAnTkUnLCBsYWJlbDogJ05lYnJhc2thJyB9LFxuICAgIHsgdmFsdWU6ICdOVicsIGxhYmVsOiAnTmV2YWRhJyB9LFxuICAgIHsgdmFsdWU6ICdOSCcsIGxhYmVsOiAnTmV3IEhhbXBzaGlyZScgfSxcbiAgICB7IHZhbHVlOiAnTkonLCBsYWJlbDogJ05ldyBKZXJzZXknIH0sXG4gICAgeyB2YWx1ZTogJ05NJywgbGFiZWw6ICdOZXcgTWV4aWNvJyB9LFxuICAgIHsgdmFsdWU6ICdOWScsIGxhYmVsOiAnTmV3IFlvcmsnIH0sXG4gICAgeyB2YWx1ZTogJ05DJywgbGFiZWw6ICdOb3J0aCBDYXJvbGluYScgfSxcbiAgICB7IHZhbHVlOiAnTkQnLCBsYWJlbDogJ05vcnRoIERha290YScgfSxcbiAgICB7IHZhbHVlOiAnTVAnLCBsYWJlbDogJ05vcnRoZXJuIE1hcmlhbmEgSXNsYW5kcycgfSxcbiAgICB7IHZhbHVlOiAnT0gnLCBsYWJlbDogJ09oaW8nIH0sXG4gICAgeyB2YWx1ZTogJ09LJywgbGFiZWw6ICdPa2xhaG9tYScgfSxcbiAgICB7IHZhbHVlOiAnT1InLCBsYWJlbDogJ09yZWdvbicgfSxcbiAgICB7IHZhbHVlOiAnUFcnLCBsYWJlbDogJ1BhbGF1JyB9LFxuICAgIHsgdmFsdWU6ICdQQScsIGxhYmVsOiAnUGVubnN5bHZhbmlhJyB9LFxuICAgIHsgdmFsdWU6ICdQUicsIGxhYmVsOiAnUHVlcnRvIFJpY28nIH0sXG4gICAgeyB2YWx1ZTogJ1JJJywgbGFiZWw6ICdSaG9kZSBJc2xhbmQnIH0sXG4gICAgeyB2YWx1ZTogJ1NDJywgbGFiZWw6ICdTb3V0aCBDYXJvbGluYScgfSxcbiAgICB7IHZhbHVlOiAnU0QnLCBsYWJlbDogJ1NvdXRoIERha290YScgfSxcbiAgICB7IHZhbHVlOiAnVE4nLCBsYWJlbDogJ1Rlbm5lc3NlZScgfSxcbiAgICB7IHZhbHVlOiAnVFgnLCBsYWJlbDogJ1RleGFzJyB9LFxuICAgIHsgdmFsdWU6ICdVVCcsIGxhYmVsOiAnVXRhaCcgfSxcbiAgICB7IHZhbHVlOiAnVlQnLCBsYWJlbDogJ1Zlcm1vbnQnIH0sXG4gICAgeyB2YWx1ZTogJ1ZJJywgbGFiZWw6ICdWaXJnaW4gSXNsYW5kcycgfSxcbiAgICB7IHZhbHVlOiAnVkEnLCBsYWJlbDogJ1ZpcmdpbmlhJyB9LFxuICAgIHsgdmFsdWU6ICdXQScsIGxhYmVsOiAnV2FzaGluZ3RvbicgfSxcbiAgICB7IHZhbHVlOiAnV1YnLCBsYWJlbDogJ1dlc3QgVmlyZ2luaWEnIH0sXG4gICAgeyB2YWx1ZTogJ1dJJywgbGFiZWw6ICdXaXNjb25zaW4nIH0sXG4gICAgeyB2YWx1ZTogJ1dZJywgbGFiZWw6ICdXeW9taW5nJyB9LFxuXTtcbiIsIm1vZHVsZS5leHBvcnRzID0gW1xuXHR7IHZhbHVlOiAnSm9obiBTbWl0aCcsIGxhYmVsOiAnSm9obiBTbWl0aCcsIGVtYWlsOiAnam9obkBzbWl0aC5jb20nIH0sXG5cdHsgdmFsdWU6ICdNZXJyeSBKYW5lJywgbGFiZWw6ICdNZXJyeSBKYW5lJywgZW1haWw6ICdtZXJyeUBqYW5lLmNvbScgfSxcblx0eyB2YWx1ZTogJ1N0YW4gSG9wZXInLCBsYWJlbDogJ1N0YW4gSG9wZXInLCBlbWFpbDogJ3N0YW5AaG9wZXIuY29tJyB9XG5dO1xuIiwiLy8gdGhlIHdoYXR3Zy1mZXRjaCBwb2x5ZmlsbCBpbnN0YWxscyB0aGUgZmV0Y2goKSBmdW5jdGlvblxuLy8gb24gdGhlIGdsb2JhbCBvYmplY3QgKHdpbmRvdyBvciBzZWxmKVxuLy9cbi8vIFJldHVybiB0aGF0IGFzIHRoZSBleHBvcnQgZm9yIHVzZSBpbiBXZWJwYWNrLCBCcm93c2VyaWZ5IGV0Yy5cbnJlcXVpcmUoJ3doYXR3Zy1mZXRjaCcpO1xubW9kdWxlLmV4cG9ydHMgPSBzZWxmLmZldGNoLmJpbmQoc2VsZik7XG4iLCIoZnVuY3Rpb24oc2VsZikge1xuICAndXNlIHN0cmljdCc7XG5cbiAgaWYgKHNlbGYuZmV0Y2gpIHtcbiAgICByZXR1cm5cbiAgfVxuXG4gIHZhciBzdXBwb3J0ID0ge1xuICAgIHNlYXJjaFBhcmFtczogJ1VSTFNlYXJjaFBhcmFtcycgaW4gc2VsZixcbiAgICBpdGVyYWJsZTogJ1N5bWJvbCcgaW4gc2VsZiAmJiAnaXRlcmF0b3InIGluIFN5bWJvbCxcbiAgICBibG9iOiAnRmlsZVJlYWRlcicgaW4gc2VsZiAmJiAnQmxvYicgaW4gc2VsZiAmJiAoZnVuY3Rpb24oKSB7XG4gICAgICB0cnkge1xuICAgICAgICBuZXcgQmxvYigpXG4gICAgICAgIHJldHVybiB0cnVlXG4gICAgICB9IGNhdGNoKGUpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlXG4gICAgICB9XG4gICAgfSkoKSxcbiAgICBmb3JtRGF0YTogJ0Zvcm1EYXRhJyBpbiBzZWxmLFxuICAgIGFycmF5QnVmZmVyOiAnQXJyYXlCdWZmZXInIGluIHNlbGZcbiAgfVxuXG4gIGlmIChzdXBwb3J0LmFycmF5QnVmZmVyKSB7XG4gICAgdmFyIHZpZXdDbGFzc2VzID0gW1xuICAgICAgJ1tvYmplY3QgSW50OEFycmF5XScsXG4gICAgICAnW29iamVjdCBVaW50OEFycmF5XScsXG4gICAgICAnW29iamVjdCBVaW50OENsYW1wZWRBcnJheV0nLFxuICAgICAgJ1tvYmplY3QgSW50MTZBcnJheV0nLFxuICAgICAgJ1tvYmplY3QgVWludDE2QXJyYXldJyxcbiAgICAgICdbb2JqZWN0IEludDMyQXJyYXldJyxcbiAgICAgICdbb2JqZWN0IFVpbnQzMkFycmF5XScsXG4gICAgICAnW29iamVjdCBGbG9hdDMyQXJyYXldJyxcbiAgICAgICdbb2JqZWN0IEZsb2F0NjRBcnJheV0nXG4gICAgXVxuXG4gICAgdmFyIGlzRGF0YVZpZXcgPSBmdW5jdGlvbihvYmopIHtcbiAgICAgIHJldHVybiBvYmogJiYgRGF0YVZpZXcucHJvdG90eXBlLmlzUHJvdG90eXBlT2Yob2JqKVxuICAgIH1cblxuICAgIHZhciBpc0FycmF5QnVmZmVyVmlldyA9IEFycmF5QnVmZmVyLmlzVmlldyB8fCBmdW5jdGlvbihvYmopIHtcbiAgICAgIHJldHVybiBvYmogJiYgdmlld0NsYXNzZXMuaW5kZXhPZihPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwob2JqKSkgPiAtMVxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIG5vcm1hbGl6ZU5hbWUobmFtZSkge1xuICAgIGlmICh0eXBlb2YgbmFtZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgIG5hbWUgPSBTdHJpbmcobmFtZSlcbiAgICB9XG4gICAgaWYgKC9bXmEtejAtOVxcLSMkJSYnKisuXFxeX2B8fl0vaS50ZXN0KG5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdJbnZhbGlkIGNoYXJhY3RlciBpbiBoZWFkZXIgZmllbGQgbmFtZScpXG4gICAgfVxuICAgIHJldHVybiBuYW1lLnRvTG93ZXJDYXNlKClcbiAgfVxuXG4gIGZ1bmN0aW9uIG5vcm1hbGl6ZVZhbHVlKHZhbHVlKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgIHZhbHVlID0gU3RyaW5nKHZhbHVlKVxuICAgIH1cbiAgICByZXR1cm4gdmFsdWVcbiAgfVxuXG4gIC8vIEJ1aWxkIGEgZGVzdHJ1Y3RpdmUgaXRlcmF0b3IgZm9yIHRoZSB2YWx1ZSBsaXN0XG4gIGZ1bmN0aW9uIGl0ZXJhdG9yRm9yKGl0ZW1zKSB7XG4gICAgdmFyIGl0ZXJhdG9yID0ge1xuICAgICAgbmV4dDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IGl0ZW1zLnNoaWZ0KClcbiAgICAgICAgcmV0dXJuIHtkb25lOiB2YWx1ZSA9PT0gdW5kZWZpbmVkLCB2YWx1ZTogdmFsdWV9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHN1cHBvcnQuaXRlcmFibGUpIHtcbiAgICAgIGl0ZXJhdG9yW1N5bWJvbC5pdGVyYXRvcl0gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIGl0ZXJhdG9yXG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGl0ZXJhdG9yXG4gIH1cblxuICBmdW5jdGlvbiBIZWFkZXJzKGhlYWRlcnMpIHtcbiAgICB0aGlzLm1hcCA9IHt9XG5cbiAgICBpZiAoaGVhZGVycyBpbnN0YW5jZW9mIEhlYWRlcnMpIHtcbiAgICAgIGhlYWRlcnMuZm9yRWFjaChmdW5jdGlvbih2YWx1ZSwgbmFtZSkge1xuICAgICAgICB0aGlzLmFwcGVuZChuYW1lLCB2YWx1ZSlcbiAgICAgIH0sIHRoaXMpXG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGhlYWRlcnMpKSB7XG4gICAgICBoZWFkZXJzLmZvckVhY2goZnVuY3Rpb24oaGVhZGVyKSB7XG4gICAgICAgIHRoaXMuYXBwZW5kKGhlYWRlclswXSwgaGVhZGVyWzFdKVxuICAgICAgfSwgdGhpcylcbiAgICB9IGVsc2UgaWYgKGhlYWRlcnMpIHtcbiAgICAgIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKGhlYWRlcnMpLmZvckVhY2goZnVuY3Rpb24obmFtZSkge1xuICAgICAgICB0aGlzLmFwcGVuZChuYW1lLCBoZWFkZXJzW25hbWVdKVxuICAgICAgfSwgdGhpcylcbiAgICB9XG4gIH1cblxuICBIZWFkZXJzLnByb3RvdHlwZS5hcHBlbmQgPSBmdW5jdGlvbihuYW1lLCB2YWx1ZSkge1xuICAgIG5hbWUgPSBub3JtYWxpemVOYW1lKG5hbWUpXG4gICAgdmFsdWUgPSBub3JtYWxpemVWYWx1ZSh2YWx1ZSlcbiAgICB2YXIgb2xkVmFsdWUgPSB0aGlzLm1hcFtuYW1lXVxuICAgIHRoaXMubWFwW25hbWVdID0gb2xkVmFsdWUgPyBvbGRWYWx1ZSsnLCcrdmFsdWUgOiB2YWx1ZVxuICB9XG5cbiAgSGVhZGVycy5wcm90b3R5cGVbJ2RlbGV0ZSddID0gZnVuY3Rpb24obmFtZSkge1xuICAgIGRlbGV0ZSB0aGlzLm1hcFtub3JtYWxpemVOYW1lKG5hbWUpXVxuICB9XG5cbiAgSGVhZGVycy5wcm90b3R5cGUuZ2V0ID0gZnVuY3Rpb24obmFtZSkge1xuICAgIG5hbWUgPSBub3JtYWxpemVOYW1lKG5hbWUpXG4gICAgcmV0dXJuIHRoaXMuaGFzKG5hbWUpID8gdGhpcy5tYXBbbmFtZV0gOiBudWxsXG4gIH1cblxuICBIZWFkZXJzLnByb3RvdHlwZS5oYXMgPSBmdW5jdGlvbihuYW1lKSB7XG4gICAgcmV0dXJuIHRoaXMubWFwLmhhc093blByb3BlcnR5KG5vcm1hbGl6ZU5hbWUobmFtZSkpXG4gIH1cblxuICBIZWFkZXJzLnByb3RvdHlwZS5zZXQgPSBmdW5jdGlvbihuYW1lLCB2YWx1ZSkge1xuICAgIHRoaXMubWFwW25vcm1hbGl6ZU5hbWUobmFtZSldID0gbm9ybWFsaXplVmFsdWUodmFsdWUpXG4gIH1cblxuICBIZWFkZXJzLnByb3RvdHlwZS5mb3JFYWNoID0gZnVuY3Rpb24oY2FsbGJhY2ssIHRoaXNBcmcpIHtcbiAgICBmb3IgKHZhciBuYW1lIGluIHRoaXMubWFwKSB7XG4gICAgICBpZiAodGhpcy5tYXAuaGFzT3duUHJvcGVydHkobmFtZSkpIHtcbiAgICAgICAgY2FsbGJhY2suY2FsbCh0aGlzQXJnLCB0aGlzLm1hcFtuYW1lXSwgbmFtZSwgdGhpcylcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBIZWFkZXJzLnByb3RvdHlwZS5rZXlzID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGl0ZW1zID0gW11cbiAgICB0aGlzLmZvckVhY2goZnVuY3Rpb24odmFsdWUsIG5hbWUpIHsgaXRlbXMucHVzaChuYW1lKSB9KVxuICAgIHJldHVybiBpdGVyYXRvckZvcihpdGVtcylcbiAgfVxuXG4gIEhlYWRlcnMucHJvdG90eXBlLnZhbHVlcyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBpdGVtcyA9IFtdXG4gICAgdGhpcy5mb3JFYWNoKGZ1bmN0aW9uKHZhbHVlKSB7IGl0ZW1zLnB1c2godmFsdWUpIH0pXG4gICAgcmV0dXJuIGl0ZXJhdG9yRm9yKGl0ZW1zKVxuICB9XG5cbiAgSGVhZGVycy5wcm90b3R5cGUuZW50cmllcyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBpdGVtcyA9IFtdXG4gICAgdGhpcy5mb3JFYWNoKGZ1bmN0aW9uKHZhbHVlLCBuYW1lKSB7IGl0ZW1zLnB1c2goW25hbWUsIHZhbHVlXSkgfSlcbiAgICByZXR1cm4gaXRlcmF0b3JGb3IoaXRlbXMpXG4gIH1cblxuICBpZiAoc3VwcG9ydC5pdGVyYWJsZSkge1xuICAgIEhlYWRlcnMucHJvdG90eXBlW1N5bWJvbC5pdGVyYXRvcl0gPSBIZWFkZXJzLnByb3RvdHlwZS5lbnRyaWVzXG4gIH1cblxuICBmdW5jdGlvbiBjb25zdW1lZChib2R5KSB7XG4gICAgaWYgKGJvZHkuYm9keVVzZWQpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgVHlwZUVycm9yKCdBbHJlYWR5IHJlYWQnKSlcbiAgICB9XG4gICAgYm9keS5ib2R5VXNlZCA9IHRydWVcbiAgfVxuXG4gIGZ1bmN0aW9uIGZpbGVSZWFkZXJSZWFkeShyZWFkZXIpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICByZWFkZXIub25sb2FkID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHJlc29sdmUocmVhZGVyLnJlc3VsdClcbiAgICAgIH1cbiAgICAgIHJlYWRlci5vbmVycm9yID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHJlamVjdChyZWFkZXIuZXJyb3IpXG4gICAgICB9XG4gICAgfSlcbiAgfVxuXG4gIGZ1bmN0aW9uIHJlYWRCbG9iQXNBcnJheUJ1ZmZlcihibG9iKSB7XG4gICAgdmFyIHJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKClcbiAgICB2YXIgcHJvbWlzZSA9IGZpbGVSZWFkZXJSZWFkeShyZWFkZXIpXG4gICAgcmVhZGVyLnJlYWRBc0FycmF5QnVmZmVyKGJsb2IpXG4gICAgcmV0dXJuIHByb21pc2VcbiAgfVxuXG4gIGZ1bmN0aW9uIHJlYWRCbG9iQXNUZXh0KGJsb2IpIHtcbiAgICB2YXIgcmVhZGVyID0gbmV3IEZpbGVSZWFkZXIoKVxuICAgIHZhciBwcm9taXNlID0gZmlsZVJlYWRlclJlYWR5KHJlYWRlcilcbiAgICByZWFkZXIucmVhZEFzVGV4dChibG9iKVxuICAgIHJldHVybiBwcm9taXNlXG4gIH1cblxuICBmdW5jdGlvbiByZWFkQXJyYXlCdWZmZXJBc1RleHQoYnVmKSB7XG4gICAgdmFyIHZpZXcgPSBuZXcgVWludDhBcnJheShidWYpXG4gICAgdmFyIGNoYXJzID0gbmV3IEFycmF5KHZpZXcubGVuZ3RoKVxuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB2aWV3Lmxlbmd0aDsgaSsrKSB7XG4gICAgICBjaGFyc1tpXSA9IFN0cmluZy5mcm9tQ2hhckNvZGUodmlld1tpXSlcbiAgICB9XG4gICAgcmV0dXJuIGNoYXJzLmpvaW4oJycpXG4gIH1cblxuICBmdW5jdGlvbiBidWZmZXJDbG9uZShidWYpIHtcbiAgICBpZiAoYnVmLnNsaWNlKSB7XG4gICAgICByZXR1cm4gYnVmLnNsaWNlKDApXG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciB2aWV3ID0gbmV3IFVpbnQ4QXJyYXkoYnVmLmJ5dGVMZW5ndGgpXG4gICAgICB2aWV3LnNldChuZXcgVWludDhBcnJheShidWYpKVxuICAgICAgcmV0dXJuIHZpZXcuYnVmZmVyXG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gQm9keSgpIHtcbiAgICB0aGlzLmJvZHlVc2VkID0gZmFsc2VcblxuICAgIHRoaXMuX2luaXRCb2R5ID0gZnVuY3Rpb24oYm9keSkge1xuICAgICAgdGhpcy5fYm9keUluaXQgPSBib2R5XG4gICAgICBpZiAoIWJvZHkpIHtcbiAgICAgICAgdGhpcy5fYm9keVRleHQgPSAnJ1xuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgYm9keSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgdGhpcy5fYm9keVRleHQgPSBib2R5XG4gICAgICB9IGVsc2UgaWYgKHN1cHBvcnQuYmxvYiAmJiBCbG9iLnByb3RvdHlwZS5pc1Byb3RvdHlwZU9mKGJvZHkpKSB7XG4gICAgICAgIHRoaXMuX2JvZHlCbG9iID0gYm9keVxuICAgICAgfSBlbHNlIGlmIChzdXBwb3J0LmZvcm1EYXRhICYmIEZvcm1EYXRhLnByb3RvdHlwZS5pc1Byb3RvdHlwZU9mKGJvZHkpKSB7XG4gICAgICAgIHRoaXMuX2JvZHlGb3JtRGF0YSA9IGJvZHlcbiAgICAgIH0gZWxzZSBpZiAoc3VwcG9ydC5zZWFyY2hQYXJhbXMgJiYgVVJMU2VhcmNoUGFyYW1zLnByb3RvdHlwZS5pc1Byb3RvdHlwZU9mKGJvZHkpKSB7XG4gICAgICAgIHRoaXMuX2JvZHlUZXh0ID0gYm9keS50b1N0cmluZygpXG4gICAgICB9IGVsc2UgaWYgKHN1cHBvcnQuYXJyYXlCdWZmZXIgJiYgc3VwcG9ydC5ibG9iICYmIGlzRGF0YVZpZXcoYm9keSkpIHtcbiAgICAgICAgdGhpcy5fYm9keUFycmF5QnVmZmVyID0gYnVmZmVyQ2xvbmUoYm9keS5idWZmZXIpXG4gICAgICAgIC8vIElFIDEwLTExIGNhbid0IGhhbmRsZSBhIERhdGFWaWV3IGJvZHkuXG4gICAgICAgIHRoaXMuX2JvZHlJbml0ID0gbmV3IEJsb2IoW3RoaXMuX2JvZHlBcnJheUJ1ZmZlcl0pXG4gICAgICB9IGVsc2UgaWYgKHN1cHBvcnQuYXJyYXlCdWZmZXIgJiYgKEFycmF5QnVmZmVyLnByb3RvdHlwZS5pc1Byb3RvdHlwZU9mKGJvZHkpIHx8IGlzQXJyYXlCdWZmZXJWaWV3KGJvZHkpKSkge1xuICAgICAgICB0aGlzLl9ib2R5QXJyYXlCdWZmZXIgPSBidWZmZXJDbG9uZShib2R5KVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCd1bnN1cHBvcnRlZCBCb2R5SW5pdCB0eXBlJylcbiAgICAgIH1cblxuICAgICAgaWYgKCF0aGlzLmhlYWRlcnMuZ2V0KCdjb250ZW50LXR5cGUnKSkge1xuICAgICAgICBpZiAodHlwZW9mIGJvZHkgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgdGhpcy5oZWFkZXJzLnNldCgnY29udGVudC10eXBlJywgJ3RleHQvcGxhaW47Y2hhcnNldD1VVEYtOCcpXG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5fYm9keUJsb2IgJiYgdGhpcy5fYm9keUJsb2IudHlwZSkge1xuICAgICAgICAgIHRoaXMuaGVhZGVycy5zZXQoJ2NvbnRlbnQtdHlwZScsIHRoaXMuX2JvZHlCbG9iLnR5cGUpXG4gICAgICAgIH0gZWxzZSBpZiAoc3VwcG9ydC5zZWFyY2hQYXJhbXMgJiYgVVJMU2VhcmNoUGFyYW1zLnByb3RvdHlwZS5pc1Byb3RvdHlwZU9mKGJvZHkpKSB7XG4gICAgICAgICAgdGhpcy5oZWFkZXJzLnNldCgnY29udGVudC10eXBlJywgJ2FwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZDtjaGFyc2V0PVVURi04JylcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChzdXBwb3J0LmJsb2IpIHtcbiAgICAgIHRoaXMuYmxvYiA9IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgcmVqZWN0ZWQgPSBjb25zdW1lZCh0aGlzKVxuICAgICAgICBpZiAocmVqZWN0ZWQpIHtcbiAgICAgICAgICByZXR1cm4gcmVqZWN0ZWRcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLl9ib2R5QmxvYikge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodGhpcy5fYm9keUJsb2IpXG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5fYm9keUFycmF5QnVmZmVyKSB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShuZXcgQmxvYihbdGhpcy5fYm9keUFycmF5QnVmZmVyXSkpXG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5fYm9keUZvcm1EYXRhKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdjb3VsZCBub3QgcmVhZCBGb3JtRGF0YSBib2R5IGFzIGJsb2InKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUobmV3IEJsb2IoW3RoaXMuX2JvZHlUZXh0XSkpXG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdGhpcy5hcnJheUJ1ZmZlciA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAodGhpcy5fYm9keUFycmF5QnVmZmVyKSB7XG4gICAgICAgICAgcmV0dXJuIGNvbnN1bWVkKHRoaXMpIHx8IFByb21pc2UucmVzb2x2ZSh0aGlzLl9ib2R5QXJyYXlCdWZmZXIpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMuYmxvYigpLnRoZW4ocmVhZEJsb2JBc0FycmF5QnVmZmVyKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy50ZXh0ID0gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgcmVqZWN0ZWQgPSBjb25zdW1lZCh0aGlzKVxuICAgICAgaWYgKHJlamVjdGVkKSB7XG4gICAgICAgIHJldHVybiByZWplY3RlZFxuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5fYm9keUJsb2IpIHtcbiAgICAgICAgcmV0dXJuIHJlYWRCbG9iQXNUZXh0KHRoaXMuX2JvZHlCbG9iKVxuICAgICAgfSBlbHNlIGlmICh0aGlzLl9ib2R5QXJyYXlCdWZmZXIpIHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShyZWFkQXJyYXlCdWZmZXJBc1RleHQodGhpcy5fYm9keUFycmF5QnVmZmVyKSlcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5fYm9keUZvcm1EYXRhKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignY291bGQgbm90IHJlYWQgRm9ybURhdGEgYm9keSBhcyB0ZXh0JylcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodGhpcy5fYm9keVRleHQpXG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHN1cHBvcnQuZm9ybURhdGEpIHtcbiAgICAgIHRoaXMuZm9ybURhdGEgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudGV4dCgpLnRoZW4oZGVjb2RlKVxuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuanNvbiA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHRoaXMudGV4dCgpLnRoZW4oSlNPTi5wYXJzZSlcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpc1xuICB9XG5cbiAgLy8gSFRUUCBtZXRob2RzIHdob3NlIGNhcGl0YWxpemF0aW9uIHNob3VsZCBiZSBub3JtYWxpemVkXG4gIHZhciBtZXRob2RzID0gWydERUxFVEUnLCAnR0VUJywgJ0hFQUQnLCAnT1BUSU9OUycsICdQT1NUJywgJ1BVVCddXG5cbiAgZnVuY3Rpb24gbm9ybWFsaXplTWV0aG9kKG1ldGhvZCkge1xuICAgIHZhciB1cGNhc2VkID0gbWV0aG9kLnRvVXBwZXJDYXNlKClcbiAgICByZXR1cm4gKG1ldGhvZHMuaW5kZXhPZih1cGNhc2VkKSA+IC0xKSA/IHVwY2FzZWQgOiBtZXRob2RcbiAgfVxuXG4gIGZ1bmN0aW9uIFJlcXVlc3QoaW5wdXQsIG9wdGlvbnMpIHtcbiAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fVxuICAgIHZhciBib2R5ID0gb3B0aW9ucy5ib2R5XG5cbiAgICBpZiAoaW5wdXQgaW5zdGFuY2VvZiBSZXF1ZXN0KSB7XG4gICAgICBpZiAoaW5wdXQuYm9keVVzZWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignQWxyZWFkeSByZWFkJylcbiAgICAgIH1cbiAgICAgIHRoaXMudXJsID0gaW5wdXQudXJsXG4gICAgICB0aGlzLmNyZWRlbnRpYWxzID0gaW5wdXQuY3JlZGVudGlhbHNcbiAgICAgIGlmICghb3B0aW9ucy5oZWFkZXJzKSB7XG4gICAgICAgIHRoaXMuaGVhZGVycyA9IG5ldyBIZWFkZXJzKGlucHV0LmhlYWRlcnMpXG4gICAgICB9XG4gICAgICB0aGlzLm1ldGhvZCA9IGlucHV0Lm1ldGhvZFxuICAgICAgdGhpcy5tb2RlID0gaW5wdXQubW9kZVxuICAgICAgaWYgKCFib2R5ICYmIGlucHV0Ll9ib2R5SW5pdCAhPSBudWxsKSB7XG4gICAgICAgIGJvZHkgPSBpbnB1dC5fYm9keUluaXRcbiAgICAgICAgaW5wdXQuYm9keVVzZWQgPSB0cnVlXG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMudXJsID0gU3RyaW5nKGlucHV0KVxuICAgIH1cblxuICAgIHRoaXMuY3JlZGVudGlhbHMgPSBvcHRpb25zLmNyZWRlbnRpYWxzIHx8IHRoaXMuY3JlZGVudGlhbHMgfHwgJ29taXQnXG4gICAgaWYgKG9wdGlvbnMuaGVhZGVycyB8fCAhdGhpcy5oZWFkZXJzKSB7XG4gICAgICB0aGlzLmhlYWRlcnMgPSBuZXcgSGVhZGVycyhvcHRpb25zLmhlYWRlcnMpXG4gICAgfVxuICAgIHRoaXMubWV0aG9kID0gbm9ybWFsaXplTWV0aG9kKG9wdGlvbnMubWV0aG9kIHx8IHRoaXMubWV0aG9kIHx8ICdHRVQnKVxuICAgIHRoaXMubW9kZSA9IG9wdGlvbnMubW9kZSB8fCB0aGlzLm1vZGUgfHwgbnVsbFxuICAgIHRoaXMucmVmZXJyZXIgPSBudWxsXG5cbiAgICBpZiAoKHRoaXMubWV0aG9kID09PSAnR0VUJyB8fCB0aGlzLm1ldGhvZCA9PT0gJ0hFQUQnKSAmJiBib2R5KSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdCb2R5IG5vdCBhbGxvd2VkIGZvciBHRVQgb3IgSEVBRCByZXF1ZXN0cycpXG4gICAgfVxuICAgIHRoaXMuX2luaXRCb2R5KGJvZHkpXG4gIH1cblxuICBSZXF1ZXN0LnByb3RvdHlwZS5jbG9uZSA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBuZXcgUmVxdWVzdCh0aGlzLCB7IGJvZHk6IHRoaXMuX2JvZHlJbml0IH0pXG4gIH1cblxuICBmdW5jdGlvbiBkZWNvZGUoYm9keSkge1xuICAgIHZhciBmb3JtID0gbmV3IEZvcm1EYXRhKClcbiAgICBib2R5LnRyaW0oKS5zcGxpdCgnJicpLmZvckVhY2goZnVuY3Rpb24oYnl0ZXMpIHtcbiAgICAgIGlmIChieXRlcykge1xuICAgICAgICB2YXIgc3BsaXQgPSBieXRlcy5zcGxpdCgnPScpXG4gICAgICAgIHZhciBuYW1lID0gc3BsaXQuc2hpZnQoKS5yZXBsYWNlKC9cXCsvZywgJyAnKVxuICAgICAgICB2YXIgdmFsdWUgPSBzcGxpdC5qb2luKCc9JykucmVwbGFjZSgvXFwrL2csICcgJylcbiAgICAgICAgZm9ybS5hcHBlbmQoZGVjb2RlVVJJQ29tcG9uZW50KG5hbWUpLCBkZWNvZGVVUklDb21wb25lbnQodmFsdWUpKVxuICAgICAgfVxuICAgIH0pXG4gICAgcmV0dXJuIGZvcm1cbiAgfVxuXG4gIGZ1bmN0aW9uIHBhcnNlSGVhZGVycyhyYXdIZWFkZXJzKSB7XG4gICAgdmFyIGhlYWRlcnMgPSBuZXcgSGVhZGVycygpXG4gICAgcmF3SGVhZGVycy5zcGxpdCgvXFxyP1xcbi8pLmZvckVhY2goZnVuY3Rpb24obGluZSkge1xuICAgICAgdmFyIHBhcnRzID0gbGluZS5zcGxpdCgnOicpXG4gICAgICB2YXIga2V5ID0gcGFydHMuc2hpZnQoKS50cmltKClcbiAgICAgIGlmIChrZXkpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gcGFydHMuam9pbignOicpLnRyaW0oKVxuICAgICAgICBoZWFkZXJzLmFwcGVuZChrZXksIHZhbHVlKVxuICAgICAgfVxuICAgIH0pXG4gICAgcmV0dXJuIGhlYWRlcnNcbiAgfVxuXG4gIEJvZHkuY2FsbChSZXF1ZXN0LnByb3RvdHlwZSlcblxuICBmdW5jdGlvbiBSZXNwb25zZShib2R5SW5pdCwgb3B0aW9ucykge1xuICAgIGlmICghb3B0aW9ucykge1xuICAgICAgb3B0aW9ucyA9IHt9XG4gICAgfVxuXG4gICAgdGhpcy50eXBlID0gJ2RlZmF1bHQnXG4gICAgdGhpcy5zdGF0dXMgPSAnc3RhdHVzJyBpbiBvcHRpb25zID8gb3B0aW9ucy5zdGF0dXMgOiAyMDBcbiAgICB0aGlzLm9rID0gdGhpcy5zdGF0dXMgPj0gMjAwICYmIHRoaXMuc3RhdHVzIDwgMzAwXG4gICAgdGhpcy5zdGF0dXNUZXh0ID0gJ3N0YXR1c1RleHQnIGluIG9wdGlvbnMgPyBvcHRpb25zLnN0YXR1c1RleHQgOiAnT0snXG4gICAgdGhpcy5oZWFkZXJzID0gbmV3IEhlYWRlcnMob3B0aW9ucy5oZWFkZXJzKVxuICAgIHRoaXMudXJsID0gb3B0aW9ucy51cmwgfHwgJydcbiAgICB0aGlzLl9pbml0Qm9keShib2R5SW5pdClcbiAgfVxuXG4gIEJvZHkuY2FsbChSZXNwb25zZS5wcm90b3R5cGUpXG5cbiAgUmVzcG9uc2UucHJvdG90eXBlLmNsb25lID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIG5ldyBSZXNwb25zZSh0aGlzLl9ib2R5SW5pdCwge1xuICAgICAgc3RhdHVzOiB0aGlzLnN0YXR1cyxcbiAgICAgIHN0YXR1c1RleHQ6IHRoaXMuc3RhdHVzVGV4dCxcbiAgICAgIGhlYWRlcnM6IG5ldyBIZWFkZXJzKHRoaXMuaGVhZGVycyksXG4gICAgICB1cmw6IHRoaXMudXJsXG4gICAgfSlcbiAgfVxuXG4gIFJlc3BvbnNlLmVycm9yID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHJlc3BvbnNlID0gbmV3IFJlc3BvbnNlKG51bGwsIHtzdGF0dXM6IDAsIHN0YXR1c1RleHQ6ICcnfSlcbiAgICByZXNwb25zZS50eXBlID0gJ2Vycm9yJ1xuICAgIHJldHVybiByZXNwb25zZVxuICB9XG5cbiAgdmFyIHJlZGlyZWN0U3RhdHVzZXMgPSBbMzAxLCAzMDIsIDMwMywgMzA3LCAzMDhdXG5cbiAgUmVzcG9uc2UucmVkaXJlY3QgPSBmdW5jdGlvbih1cmwsIHN0YXR1cykge1xuICAgIGlmIChyZWRpcmVjdFN0YXR1c2VzLmluZGV4T2Yoc3RhdHVzKSA9PT0gLTEpIHtcbiAgICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdJbnZhbGlkIHN0YXR1cyBjb2RlJylcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFJlc3BvbnNlKG51bGwsIHtzdGF0dXM6IHN0YXR1cywgaGVhZGVyczoge2xvY2F0aW9uOiB1cmx9fSlcbiAgfVxuXG4gIHNlbGYuSGVhZGVycyA9IEhlYWRlcnNcbiAgc2VsZi5SZXF1ZXN0ID0gUmVxdWVzdFxuICBzZWxmLlJlc3BvbnNlID0gUmVzcG9uc2VcblxuICBzZWxmLmZldGNoID0gZnVuY3Rpb24oaW5wdXQsIGluaXQpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICB2YXIgcmVxdWVzdCA9IG5ldyBSZXF1ZXN0KGlucHV0LCBpbml0KVxuICAgICAgdmFyIHhociA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpXG5cbiAgICAgIHhoci5vbmxvYWQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIG9wdGlvbnMgPSB7XG4gICAgICAgICAgc3RhdHVzOiB4aHIuc3RhdHVzLFxuICAgICAgICAgIHN0YXR1c1RleHQ6IHhoci5zdGF0dXNUZXh0LFxuICAgICAgICAgIGhlYWRlcnM6IHBhcnNlSGVhZGVycyh4aHIuZ2V0QWxsUmVzcG9uc2VIZWFkZXJzKCkgfHwgJycpXG4gICAgICAgIH1cbiAgICAgICAgb3B0aW9ucy51cmwgPSAncmVzcG9uc2VVUkwnIGluIHhociA/IHhoci5yZXNwb25zZVVSTCA6IG9wdGlvbnMuaGVhZGVycy5nZXQoJ1gtUmVxdWVzdC1VUkwnKVxuICAgICAgICB2YXIgYm9keSA9ICdyZXNwb25zZScgaW4geGhyID8geGhyLnJlc3BvbnNlIDogeGhyLnJlc3BvbnNlVGV4dFxuICAgICAgICByZXNvbHZlKG5ldyBSZXNwb25zZShib2R5LCBvcHRpb25zKSlcbiAgICAgIH1cblxuICAgICAgeGhyLm9uZXJyb3IgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgcmVqZWN0KG5ldyBUeXBlRXJyb3IoJ05ldHdvcmsgcmVxdWVzdCBmYWlsZWQnKSlcbiAgICAgIH1cblxuICAgICAgeGhyLm9udGltZW91dCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICByZWplY3QobmV3IFR5cGVFcnJvcignTmV0d29yayByZXF1ZXN0IGZhaWxlZCcpKVxuICAgICAgfVxuXG4gICAgICB4aHIub3BlbihyZXF1ZXN0Lm1ldGhvZCwgcmVxdWVzdC51cmwsIHRydWUpXG5cbiAgICAgIGlmIChyZXF1ZXN0LmNyZWRlbnRpYWxzID09PSAnaW5jbHVkZScpIHtcbiAgICAgICAgeGhyLndpdGhDcmVkZW50aWFscyA9IHRydWVcbiAgICAgIH1cblxuICAgICAgaWYgKCdyZXNwb25zZVR5cGUnIGluIHhociAmJiBzdXBwb3J0LmJsb2IpIHtcbiAgICAgICAgeGhyLnJlc3BvbnNlVHlwZSA9ICdibG9iJ1xuICAgICAgfVxuXG4gICAgICByZXF1ZXN0LmhlYWRlcnMuZm9yRWFjaChmdW5jdGlvbih2YWx1ZSwgbmFtZSkge1xuICAgICAgICB4aHIuc2V0UmVxdWVzdEhlYWRlcihuYW1lLCB2YWx1ZSlcbiAgICAgIH0pXG5cbiAgICAgIHhoci5zZW5kKHR5cGVvZiByZXF1ZXN0Ll9ib2R5SW5pdCA9PT0gJ3VuZGVmaW5lZCcgPyBudWxsIDogcmVxdWVzdC5fYm9keUluaXQpXG4gICAgfSlcbiAgfVxuICBzZWxmLmZldGNoLnBvbHlmaWxsID0gdHJ1ZVxufSkodHlwZW9mIHNlbGYgIT09ICd1bmRlZmluZWQnID8gc2VsZiA6IHRoaXMpO1xuIiwiLyoqXG4gKiBDb3B5cmlnaHQgMjAxMy1wcmVzZW50LCBGYWNlYm9vaywgSW5jLlxuICogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBCU0Qtc3R5bGUgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS4gQW4gYWRkaXRpb25hbCBncmFudFxuICogb2YgcGF0ZW50IHJpZ2h0cyBjYW4gYmUgZm91bmQgaW4gdGhlIFBBVEVOVFMgZmlsZSBpbiB0aGUgc2FtZSBkaXJlY3RvcnkuXG4gKlxuICogQHByb3ZpZGVzTW9kdWxlIHNoYWxsb3dDb21wYXJlXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgc2hhbGxvd0VxdWFsID0gcmVxdWlyZSgnZmJqcy9saWIvc2hhbGxvd0VxdWFsJyk7XG5cbi8qKlxuICogRG9lcyBhIHNoYWxsb3cgY29tcGFyaXNvbiBmb3IgcHJvcHMgYW5kIHN0YXRlLlxuICogU2VlIFJlYWN0Q29tcG9uZW50V2l0aFB1cmVSZW5kZXJNaXhpblxuICogU2VlIGFsc28gaHR0cHM6Ly9mYWNlYm9vay5naXRodWIuaW8vcmVhY3QvZG9jcy9zaGFsbG93LWNvbXBhcmUuaHRtbFxuICovXG5mdW5jdGlvbiBzaGFsbG93Q29tcGFyZShpbnN0YW5jZSwgbmV4dFByb3BzLCBuZXh0U3RhdGUpIHtcbiAgcmV0dXJuIChcbiAgICAhc2hhbGxvd0VxdWFsKGluc3RhbmNlLnByb3BzLCBuZXh0UHJvcHMpIHx8XG4gICAgIXNoYWxsb3dFcXVhbChpbnN0YW5jZS5zdGF0ZSwgbmV4dFN0YXRlKVxuICApO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHNoYWxsb3dDb21wYXJlO1xuIiwiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtcHJlc2VudCwgRmFjZWJvb2ssIEluYy5cbiAqIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gKlxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgQlNELXN0eWxlIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4gKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuIEFuIGFkZGl0aW9uYWwgZ3JhbnRcbiAqIG9mIHBhdGVudCByaWdodHMgY2FuIGJlIGZvdW5kIGluIHRoZSBQQVRFTlRTIGZpbGUgaW4gdGhlIHNhbWUgZGlyZWN0b3J5LlxuICpcbiAqIEB0eXBlY2hlY2tzXG4gKiBcbiAqL1xuXG4vKmVzbGludC1kaXNhYmxlIG5vLXNlbGYtY29tcGFyZSAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBoYXNPd25Qcm9wZXJ0eSA9IE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHk7XG5cbi8qKlxuICogaW5saW5lZCBPYmplY3QuaXMgcG9seWZpbGwgdG8gYXZvaWQgcmVxdWlyaW5nIGNvbnN1bWVycyBzaGlwIHRoZWlyIG93blxuICogaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvT2JqZWN0L2lzXG4gKi9cbmZ1bmN0aW9uIGlzKHgsIHkpIHtcbiAgLy8gU2FtZVZhbHVlIGFsZ29yaXRobVxuICBpZiAoeCA9PT0geSkge1xuICAgIC8vIFN0ZXBzIDEtNSwgNy0xMFxuICAgIC8vIFN0ZXBzIDYuYi02LmU6ICswICE9IC0wXG4gICAgLy8gQWRkZWQgdGhlIG5vbnplcm8geSBjaGVjayB0byBtYWtlIEZsb3cgaGFwcHksIGJ1dCBpdCBpcyByZWR1bmRhbnRcbiAgICByZXR1cm4geCAhPT0gMCB8fCB5ICE9PSAwIHx8IDEgLyB4ID09PSAxIC8geTtcbiAgfSBlbHNlIHtcbiAgICAvLyBTdGVwIDYuYTogTmFOID09IE5hTlxuICAgIHJldHVybiB4ICE9PSB4ICYmIHkgIT09IHk7XG4gIH1cbn1cblxuLyoqXG4gKiBQZXJmb3JtcyBlcXVhbGl0eSBieSBpdGVyYXRpbmcgdGhyb3VnaCBrZXlzIG9uIGFuIG9iamVjdCBhbmQgcmV0dXJuaW5nIGZhbHNlXG4gKiB3aGVuIGFueSBrZXkgaGFzIHZhbHVlcyB3aGljaCBhcmUgbm90IHN0cmljdGx5IGVxdWFsIGJldHdlZW4gdGhlIGFyZ3VtZW50cy5cbiAqIFJldHVybnMgdHJ1ZSB3aGVuIHRoZSB2YWx1ZXMgb2YgYWxsIGtleXMgYXJlIHN0cmljdGx5IGVxdWFsLlxuICovXG5mdW5jdGlvbiBzaGFsbG93RXF1YWwob2JqQSwgb2JqQikge1xuICBpZiAoaXMob2JqQSwgb2JqQikpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIGlmICh0eXBlb2Ygb2JqQSAhPT0gJ29iamVjdCcgfHwgb2JqQSA9PT0gbnVsbCB8fCB0eXBlb2Ygb2JqQiAhPT0gJ29iamVjdCcgfHwgb2JqQiA9PT0gbnVsbCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHZhciBrZXlzQSA9IE9iamVjdC5rZXlzKG9iakEpO1xuICB2YXIga2V5c0IgPSBPYmplY3Qua2V5cyhvYmpCKTtcblxuICBpZiAoa2V5c0EubGVuZ3RoICE9PSBrZXlzQi5sZW5ndGgpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvLyBUZXN0IGZvciBBJ3Mga2V5cyBkaWZmZXJlbnQgZnJvbSBCLlxuICBmb3IgKHZhciBpID0gMDsgaSA8IGtleXNBLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iakIsIGtleXNBW2ldKSB8fCAhaXMob2JqQVtrZXlzQVtpXV0sIG9iakJba2V5c0FbaV1dKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHNoYWxsb3dFcXVhbDsiLCIvLyBzaGltIGZvciB1c2luZyBwcm9jZXNzIGluIGJyb3dzZXJcbnZhciBwcm9jZXNzID0gbW9kdWxlLmV4cG9ydHMgPSB7fTtcblxuLy8gY2FjaGVkIGZyb20gd2hhdGV2ZXIgZ2xvYmFsIGlzIHByZXNlbnQgc28gdGhhdCB0ZXN0IHJ1bm5lcnMgdGhhdCBzdHViIGl0XG4vLyBkb24ndCBicmVhayB0aGluZ3MuICBCdXQgd2UgbmVlZCB0byB3cmFwIGl0IGluIGEgdHJ5IGNhdGNoIGluIGNhc2UgaXQgaXNcbi8vIHdyYXBwZWQgaW4gc3RyaWN0IG1vZGUgY29kZSB3aGljaCBkb2Vzbid0IGRlZmluZSBhbnkgZ2xvYmFscy4gIEl0J3MgaW5zaWRlIGFcbi8vIGZ1bmN0aW9uIGJlY2F1c2UgdHJ5L2NhdGNoZXMgZGVvcHRpbWl6ZSBpbiBjZXJ0YWluIGVuZ2luZXMuXG5cbnZhciBjYWNoZWRTZXRUaW1lb3V0O1xudmFyIGNhY2hlZENsZWFyVGltZW91dDtcblxuZnVuY3Rpb24gZGVmYXVsdFNldFRpbW91dCgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3NldFRpbWVvdXQgaGFzIG5vdCBiZWVuIGRlZmluZWQnKTtcbn1cbmZ1bmN0aW9uIGRlZmF1bHRDbGVhclRpbWVvdXQgKCkge1xuICAgIHRocm93IG5ldyBFcnJvcignY2xlYXJUaW1lb3V0IGhhcyBub3QgYmVlbiBkZWZpbmVkJyk7XG59XG4oZnVuY3Rpb24gKCkge1xuICAgIHRyeSB7XG4gICAgICAgIGlmICh0eXBlb2Ygc2V0VGltZW91dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgY2FjaGVkU2V0VGltZW91dCA9IHNldFRpbWVvdXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjYWNoZWRTZXRUaW1lb3V0ID0gZGVmYXVsdFNldFRpbW91dDtcbiAgICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY2FjaGVkU2V0VGltZW91dCA9IGRlZmF1bHRTZXRUaW1vdXQ7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICAgIGlmICh0eXBlb2YgY2xlYXJUaW1lb3V0ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICBjYWNoZWRDbGVhclRpbWVvdXQgPSBjbGVhclRpbWVvdXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjYWNoZWRDbGVhclRpbWVvdXQgPSBkZWZhdWx0Q2xlYXJUaW1lb3V0O1xuICAgICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjYWNoZWRDbGVhclRpbWVvdXQgPSBkZWZhdWx0Q2xlYXJUaW1lb3V0O1xuICAgIH1cbn0gKCkpXG5mdW5jdGlvbiBydW5UaW1lb3V0KGZ1bikge1xuICAgIGlmIChjYWNoZWRTZXRUaW1lb3V0ID09PSBzZXRUaW1lb3V0KSB7XG4gICAgICAgIC8vbm9ybWFsIGVudmlyb21lbnRzIGluIHNhbmUgc2l0dWF0aW9uc1xuICAgICAgICByZXR1cm4gc2V0VGltZW91dChmdW4sIDApO1xuICAgIH1cbiAgICAvLyBpZiBzZXRUaW1lb3V0IHdhc24ndCBhdmFpbGFibGUgYnV0IHdhcyBsYXR0ZXIgZGVmaW5lZFxuICAgIGlmICgoY2FjaGVkU2V0VGltZW91dCA9PT0gZGVmYXVsdFNldFRpbW91dCB8fCAhY2FjaGVkU2V0VGltZW91dCkgJiYgc2V0VGltZW91dCkge1xuICAgICAgICBjYWNoZWRTZXRUaW1lb3V0ID0gc2V0VGltZW91dDtcbiAgICAgICAgcmV0dXJuIHNldFRpbWVvdXQoZnVuLCAwKTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgICAgLy8gd2hlbiB3aGVuIHNvbWVib2R5IGhhcyBzY3Jld2VkIHdpdGggc2V0VGltZW91dCBidXQgbm8gSS5FLiBtYWRkbmVzc1xuICAgICAgICByZXR1cm4gY2FjaGVkU2V0VGltZW91dChmdW4sIDApO1xuICAgIH0gY2F0Y2goZSl7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICAvLyBXaGVuIHdlIGFyZSBpbiBJLkUuIGJ1dCB0aGUgc2NyaXB0IGhhcyBiZWVuIGV2YWxlZCBzbyBJLkUuIGRvZXNuJ3QgdHJ1c3QgdGhlIGdsb2JhbCBvYmplY3Qgd2hlbiBjYWxsZWQgbm9ybWFsbHlcbiAgICAgICAgICAgIHJldHVybiBjYWNoZWRTZXRUaW1lb3V0LmNhbGwobnVsbCwgZnVuLCAwKTtcbiAgICAgICAgfSBjYXRjaChlKXtcbiAgICAgICAgICAgIC8vIHNhbWUgYXMgYWJvdmUgYnV0IHdoZW4gaXQncyBhIHZlcnNpb24gb2YgSS5FLiB0aGF0IG11c3QgaGF2ZSB0aGUgZ2xvYmFsIG9iamVjdCBmb3IgJ3RoaXMnLCBob3BmdWxseSBvdXIgY29udGV4dCBjb3JyZWN0IG90aGVyd2lzZSBpdCB3aWxsIHRocm93IGEgZ2xvYmFsIGVycm9yXG4gICAgICAgICAgICByZXR1cm4gY2FjaGVkU2V0VGltZW91dC5jYWxsKHRoaXMsIGZ1biwgMCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxufVxuZnVuY3Rpb24gcnVuQ2xlYXJUaW1lb3V0KG1hcmtlcikge1xuICAgIGlmIChjYWNoZWRDbGVhclRpbWVvdXQgPT09IGNsZWFyVGltZW91dCkge1xuICAgICAgICAvL25vcm1hbCBlbnZpcm9tZW50cyBpbiBzYW5lIHNpdHVhdGlvbnNcbiAgICAgICAgcmV0dXJuIGNsZWFyVGltZW91dChtYXJrZXIpO1xuICAgIH1cbiAgICAvLyBpZiBjbGVhclRpbWVvdXQgd2Fzbid0IGF2YWlsYWJsZSBidXQgd2FzIGxhdHRlciBkZWZpbmVkXG4gICAgaWYgKChjYWNoZWRDbGVhclRpbWVvdXQgPT09IGRlZmF1bHRDbGVhclRpbWVvdXQgfHwgIWNhY2hlZENsZWFyVGltZW91dCkgJiYgY2xlYXJUaW1lb3V0KSB7XG4gICAgICAgIGNhY2hlZENsZWFyVGltZW91dCA9IGNsZWFyVGltZW91dDtcbiAgICAgICAgcmV0dXJuIGNsZWFyVGltZW91dChtYXJrZXIpO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgICAvLyB3aGVuIHdoZW4gc29tZWJvZHkgaGFzIHNjcmV3ZWQgd2l0aCBzZXRUaW1lb3V0IGJ1dCBubyBJLkUuIG1hZGRuZXNzXG4gICAgICAgIHJldHVybiBjYWNoZWRDbGVhclRpbWVvdXQobWFya2VyKTtcbiAgICB9IGNhdGNoIChlKXtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIC8vIFdoZW4gd2UgYXJlIGluIEkuRS4gYnV0IHRoZSBzY3JpcHQgaGFzIGJlZW4gZXZhbGVkIHNvIEkuRS4gZG9lc24ndCAgdHJ1c3QgdGhlIGdsb2JhbCBvYmplY3Qgd2hlbiBjYWxsZWQgbm9ybWFsbHlcbiAgICAgICAgICAgIHJldHVybiBjYWNoZWRDbGVhclRpbWVvdXQuY2FsbChudWxsLCBtYXJrZXIpO1xuICAgICAgICB9IGNhdGNoIChlKXtcbiAgICAgICAgICAgIC8vIHNhbWUgYXMgYWJvdmUgYnV0IHdoZW4gaXQncyBhIHZlcnNpb24gb2YgSS5FLiB0aGF0IG11c3QgaGF2ZSB0aGUgZ2xvYmFsIG9iamVjdCBmb3IgJ3RoaXMnLCBob3BmdWxseSBvdXIgY29udGV4dCBjb3JyZWN0IG90aGVyd2lzZSBpdCB3aWxsIHRocm93IGEgZ2xvYmFsIGVycm9yLlxuICAgICAgICAgICAgLy8gU29tZSB2ZXJzaW9ucyBvZiBJLkUuIGhhdmUgZGlmZmVyZW50IHJ1bGVzIGZvciBjbGVhclRpbWVvdXQgdnMgc2V0VGltZW91dFxuICAgICAgICAgICAgcmV0dXJuIGNhY2hlZENsZWFyVGltZW91dC5jYWxsKHRoaXMsIG1hcmtlcik7XG4gICAgICAgIH1cbiAgICB9XG5cblxuXG59XG52YXIgcXVldWUgPSBbXTtcbnZhciBkcmFpbmluZyA9IGZhbHNlO1xudmFyIGN1cnJlbnRRdWV1ZTtcbnZhciBxdWV1ZUluZGV4ID0gLTE7XG5cbmZ1bmN0aW9uIGNsZWFuVXBOZXh0VGljaygpIHtcbiAgICBpZiAoIWRyYWluaW5nIHx8ICFjdXJyZW50UXVldWUpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBkcmFpbmluZyA9IGZhbHNlO1xuICAgIGlmIChjdXJyZW50UXVldWUubGVuZ3RoKSB7XG4gICAgICAgIHF1ZXVlID0gY3VycmVudFF1ZXVlLmNvbmNhdChxdWV1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcXVldWVJbmRleCA9IC0xO1xuICAgIH1cbiAgICBpZiAocXVldWUubGVuZ3RoKSB7XG4gICAgICAgIGRyYWluUXVldWUoKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGRyYWluUXVldWUoKSB7XG4gICAgaWYgKGRyYWluaW5nKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIHRpbWVvdXQgPSBydW5UaW1lb3V0KGNsZWFuVXBOZXh0VGljayk7XG4gICAgZHJhaW5pbmcgPSB0cnVlO1xuXG4gICAgdmFyIGxlbiA9IHF1ZXVlLmxlbmd0aDtcbiAgICB3aGlsZShsZW4pIHtcbiAgICAgICAgY3VycmVudFF1ZXVlID0gcXVldWU7XG4gICAgICAgIHF1ZXVlID0gW107XG4gICAgICAgIHdoaWxlICgrK3F1ZXVlSW5kZXggPCBsZW4pIHtcbiAgICAgICAgICAgIGlmIChjdXJyZW50UXVldWUpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50UXVldWVbcXVldWVJbmRleF0ucnVuKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcXVldWVJbmRleCA9IC0xO1xuICAgICAgICBsZW4gPSBxdWV1ZS5sZW5ndGg7XG4gICAgfVxuICAgIGN1cnJlbnRRdWV1ZSA9IG51bGw7XG4gICAgZHJhaW5pbmcgPSBmYWxzZTtcbiAgICBydW5DbGVhclRpbWVvdXQodGltZW91dCk7XG59XG5cbnByb2Nlc3MubmV4dFRpY2sgPSBmdW5jdGlvbiAoZnVuKSB7XG4gICAgdmFyIGFyZ3MgPSBuZXcgQXJyYXkoYXJndW1lbnRzLmxlbmd0aCAtIDEpO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMSkge1xuICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgYXJnc1tpIC0gMV0gPSBhcmd1bWVudHNbaV07XG4gICAgICAgIH1cbiAgICB9XG4gICAgcXVldWUucHVzaChuZXcgSXRlbShmdW4sIGFyZ3MpKTtcbiAgICBpZiAocXVldWUubGVuZ3RoID09PSAxICYmICFkcmFpbmluZykge1xuICAgICAgICBydW5UaW1lb3V0KGRyYWluUXVldWUpO1xuICAgIH1cbn07XG5cbi8vIHY4IGxpa2VzIHByZWRpY3RpYmxlIG9iamVjdHNcbmZ1bmN0aW9uIEl0ZW0oZnVuLCBhcnJheSkge1xuICAgIHRoaXMuZnVuID0gZnVuO1xuICAgIHRoaXMuYXJyYXkgPSBhcnJheTtcbn1cbkl0ZW0ucHJvdG90eXBlLnJ1biA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmZ1bi5hcHBseShudWxsLCB0aGlzLmFycmF5KTtcbn07XG5wcm9jZXNzLnRpdGxlID0gJ2Jyb3dzZXInO1xucHJvY2Vzcy5icm93c2VyID0gdHJ1ZTtcbnByb2Nlc3MuZW52ID0ge307XG5wcm9jZXNzLmFyZ3YgPSBbXTtcbnByb2Nlc3MudmVyc2lvbiA9ICcnOyAvLyBlbXB0eSBzdHJpbmcgdG8gYXZvaWQgcmVnZXhwIGlzc3Vlc1xucHJvY2Vzcy52ZXJzaW9ucyA9IHt9O1xuXG5mdW5jdGlvbiBub29wKCkge31cblxucHJvY2Vzcy5vbiA9IG5vb3A7XG5wcm9jZXNzLmFkZExpc3RlbmVyID0gbm9vcDtcbnByb2Nlc3Mub25jZSA9IG5vb3A7XG5wcm9jZXNzLm9mZiA9IG5vb3A7XG5wcm9jZXNzLnJlbW92ZUxpc3RlbmVyID0gbm9vcDtcbnByb2Nlc3MucmVtb3ZlQWxsTGlzdGVuZXJzID0gbm9vcDtcbnByb2Nlc3MuZW1pdCA9IG5vb3A7XG5wcm9jZXNzLnByZXBlbmRMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLnByZXBlbmRPbmNlTGlzdGVuZXIgPSBub29wO1xuXG5wcm9jZXNzLmxpc3RlbmVycyA9IGZ1bmN0aW9uIChuYW1lKSB7IHJldHVybiBbXSB9XG5cbnByb2Nlc3MuYmluZGluZyA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmJpbmRpbmcgaXMgbm90IHN1cHBvcnRlZCcpO1xufTtcblxucHJvY2Vzcy5jd2QgPSBmdW5jdGlvbiAoKSB7IHJldHVybiAnLycgfTtcbnByb2Nlc3MuY2hkaXIgPSBmdW5jdGlvbiAoZGlyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmNoZGlyIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn07XG5wcm9jZXNzLnVtYXNrID0gZnVuY3Rpb24oKSB7IHJldHVybiAwOyB9O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgX2V4dGVuZHMgPSBPYmplY3QuYXNzaWduIHx8IGZ1bmN0aW9uICh0YXJnZXQpIHsgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHsgdmFyIHNvdXJjZSA9IGFyZ3VtZW50c1tpXTsgZm9yICh2YXIga2V5IGluIHNvdXJjZSkgeyBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHNvdXJjZSwga2V5KSkgeyB0YXJnZXRba2V5XSA9IHNvdXJjZVtrZXldOyB9IH0gfSByZXR1cm4gdGFyZ2V0OyB9O1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKFwidmFsdWVcIiBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSgpO1xuXG52YXIgX3JlYWN0ID0gcmVxdWlyZSgncmVhY3QnKTtcblxudmFyIF9yZWFjdDIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9yZWFjdCk7XG5cbnZhciBfbWQgPSByZXF1aXJlKCdtZDUnKTtcblxudmFyIF9tZDIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9tZCk7XG5cbnZhciBfcXVlcnlTdHJpbmcgPSByZXF1aXJlKCdxdWVyeS1zdHJpbmcnKTtcblxudmFyIF9xdWVyeVN0cmluZzIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9xdWVyeVN0cmluZyk7XG5cbnZhciBfaXNSZXRpbmEgPSByZXF1aXJlKCdpcy1yZXRpbmEnKTtcblxudmFyIF9pc1JldGluYTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9pc1JldGluYSk7XG5cbnZhciBfcHJvcFR5cGVzID0gcmVxdWlyZSgncHJvcC10eXBlcycpO1xuXG52YXIgX3Byb3BUeXBlczIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9wcm9wVHlwZXMpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyBkZWZhdWx0OiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfb2JqZWN0V2l0aG91dFByb3BlcnRpZXMob2JqLCBrZXlzKSB7IHZhciB0YXJnZXQgPSB7fTsgZm9yICh2YXIgaSBpbiBvYmopIHsgaWYgKGtleXMuaW5kZXhPZihpKSA+PSAwKSBjb250aW51ZTsgaWYgKCFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBpKSkgY29udGludWU7IHRhcmdldFtpXSA9IG9ialtpXTsgfSByZXR1cm4gdGFyZ2V0OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvblwiKTsgfSB9XG5cbmZ1bmN0aW9uIF9wb3NzaWJsZUNvbnN0cnVjdG9yUmV0dXJuKHNlbGYsIGNhbGwpIHsgaWYgKCFzZWxmKSB7IHRocm93IG5ldyBSZWZlcmVuY2VFcnJvcihcInRoaXMgaGFzbid0IGJlZW4gaW5pdGlhbGlzZWQgLSBzdXBlcigpIGhhc24ndCBiZWVuIGNhbGxlZFwiKTsgfSByZXR1cm4gY2FsbCAmJiAodHlwZW9mIGNhbGwgPT09IFwib2JqZWN0XCIgfHwgdHlwZW9mIGNhbGwgPT09IFwiZnVuY3Rpb25cIikgPyBjYWxsIDogc2VsZjsgfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSBcImZ1bmN0aW9uXCIgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCBcIiArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgT2JqZWN0LnNldFByb3RvdHlwZU9mID8gT2JqZWN0LnNldFByb3RvdHlwZU9mKHN1YkNsYXNzLCBzdXBlckNsYXNzKSA6IHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIEdyYXZhdGFyID0gZnVuY3Rpb24gKF9SZWFjdCRDb21wb25lbnQpIHtcbiAgX2luaGVyaXRzKEdyYXZhdGFyLCBfUmVhY3QkQ29tcG9uZW50KTtcblxuICBmdW5jdGlvbiBHcmF2YXRhcigpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgR3JhdmF0YXIpO1xuXG4gICAgcmV0dXJuIF9wb3NzaWJsZUNvbnN0cnVjdG9yUmV0dXJuKHRoaXMsIChHcmF2YXRhci5fX3Byb3RvX18gfHwgT2JqZWN0LmdldFByb3RvdHlwZU9mKEdyYXZhdGFyKSkuYXBwbHkodGhpcywgYXJndW1lbnRzKSk7XG4gIH1cblxuICBfY3JlYXRlQ2xhc3MoR3JhdmF0YXIsIFt7XG4gICAga2V5OiAncmVuZGVyJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVuZGVyKCkge1xuICAgICAgdmFyIGJhc2UgPSB0aGlzLnByb3BzLnByb3RvY29sICsgJ3d3dy5ncmF2YXRhci5jb20vYXZhdGFyLyc7XG5cbiAgICAgIHZhciBxdWVyeSA9IF9xdWVyeVN0cmluZzIuZGVmYXVsdC5zdHJpbmdpZnkoe1xuICAgICAgICBzOiB0aGlzLnByb3BzLnNpemUsXG4gICAgICAgIHI6IHRoaXMucHJvcHMucmF0aW5nLFxuICAgICAgICBkOiB0aGlzLnByb3BzLmRlZmF1bHRcbiAgICAgIH0pO1xuXG4gICAgICB2YXIgcmV0aW5hUXVlcnkgPSBfcXVlcnlTdHJpbmcyLmRlZmF1bHQuc3RyaW5naWZ5KHtcbiAgICAgICAgczogdGhpcy5wcm9wcy5zaXplICogMixcbiAgICAgICAgcjogdGhpcy5wcm9wcy5yYXRpbmcsXG4gICAgICAgIGQ6IHRoaXMucHJvcHMuZGVmYXVsdFxuICAgICAgfSk7XG5cbiAgICAgIC8vIEdyYXZhdGFyIHNlcnZpY2UgY3VycmVudGx5IHRyaW1zIGFuZCBsb3dlcmNhc2VzIGFsbCByZWdpc3RlcmVkIGVtYWlsc1xuICAgICAgdmFyIGZvcm1hdHRlZEVtYWlsID0gKCcnICsgdGhpcy5wcm9wcy5lbWFpbCkudHJpbSgpLnRvTG93ZXJDYXNlKCk7XG5cbiAgICAgIHZhciBoYXNoID0gdm9pZCAwO1xuICAgICAgaWYgKHRoaXMucHJvcHMubWQ1KSB7XG4gICAgICAgIGhhc2ggPSB0aGlzLnByb3BzLm1kNTtcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaXMucHJvcHMuZW1haWwgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGhhc2ggPSAoMCwgX21kMi5kZWZhdWx0KShmb3JtYXR0ZWRFbWFpbCwgeyBlbmNvZGluZzogXCJiaW5hcnlcIiB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUud2FybignR3JhdmF0YXIgaW1hZ2UgY2FuIG5vdCBiZSBmZXRjaGVkLiBFaXRoZXIgdGhlIFwiZW1haWxcIiBvciBcIm1kNVwiIHByb3AgbXVzdCBiZSBzcGVjaWZpZWQuJyk7XG4gICAgICAgIHJldHVybiBfcmVhY3QyLmRlZmF1bHQuY3JlYXRlRWxlbWVudCgnc2NyaXB0JywgbnVsbCk7XG4gICAgICB9XG5cbiAgICAgIHZhciBzcmMgPSAnJyArIGJhc2UgKyBoYXNoICsgJz8nICsgcXVlcnk7XG4gICAgICB2YXIgcmV0aW5hU3JjID0gJycgKyBiYXNlICsgaGFzaCArICc/JyArIHJldGluYVF1ZXJ5O1xuXG4gICAgICB2YXIgbW9kZXJuQnJvd3NlciA9IHRydWU7IC8vIHNlcnZlci1zaWRlLCB3ZSByZW5kZXIgZm9yIG1vZGVybiBicm93c2Vyc1xuXG4gICAgICBpZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgLy8gdGhpcyBpcyBub3QgTm9kZUpTXG4gICAgICAgIG1vZGVybkJyb3dzZXIgPSAnc3Jjc2V0JyBpbiBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpbWcnKTtcbiAgICAgIH1cblxuICAgICAgdmFyIGNsYXNzTmFtZSA9ICdyZWFjdC1ncmF2YXRhcic7XG4gICAgICBpZiAodGhpcy5wcm9wcy5jbGFzc05hbWUpIHtcbiAgICAgICAgY2xhc3NOYW1lID0gY2xhc3NOYW1lICsgJyAnICsgdGhpcy5wcm9wcy5jbGFzc05hbWU7XG4gICAgICB9XG5cbiAgICAgIC8vIENsb25lIHRoaXMucHJvcHMgYW5kIHRoZW4gZGVsZXRlIENvbXBvbmVudCBzcGVjaWZpYyBwcm9wcyBzbyB3ZSBjYW5cbiAgICAgIC8vIHNwcmVhZCB0aGUgcmVzdCBpbnRvIHRoZSBpbWcuXG5cbiAgICAgIHZhciByZXN0ID0gX29iamVjdFdpdGhvdXRQcm9wZXJ0aWVzKHRoaXMucHJvcHMsIFtdKTtcblxuICAgICAgZGVsZXRlIHJlc3QubWQ1O1xuICAgICAgZGVsZXRlIHJlc3QuZW1haWw7XG4gICAgICBkZWxldGUgcmVzdC5wcm90b2NvbDtcbiAgICAgIGRlbGV0ZSByZXN0LnJhdGluZztcbiAgICAgIGRlbGV0ZSByZXN0LnNpemU7XG4gICAgICBkZWxldGUgcmVzdC5zdHlsZTtcbiAgICAgIGRlbGV0ZSByZXN0LmNsYXNzTmFtZTtcbiAgICAgIGRlbGV0ZSByZXN0LmRlZmF1bHQ7XG4gICAgICBpZiAoIW1vZGVybkJyb3dzZXIgJiYgKDAsIF9pc1JldGluYTIuZGVmYXVsdCkoKSkge1xuICAgICAgICByZXR1cm4gX3JlYWN0Mi5kZWZhdWx0LmNyZWF0ZUVsZW1lbnQoJ2ltZycsIF9leHRlbmRzKHtcbiAgICAgICAgICBhbHQ6ICdHcmF2YXRhciBmb3IgJyArIGZvcm1hdHRlZEVtYWlsLFxuICAgICAgICAgIHN0eWxlOiB0aGlzLnByb3BzLnN0eWxlLFxuICAgICAgICAgIHNyYzogcmV0aW5hU3JjLFxuICAgICAgICAgIGhlaWdodDogdGhpcy5wcm9wcy5zaXplLFxuICAgICAgICAgIHdpZHRoOiB0aGlzLnByb3BzLnNpemVcbiAgICAgICAgfSwgcmVzdCwge1xuICAgICAgICAgIGNsYXNzTmFtZTogY2xhc3NOYW1lXG4gICAgICAgIH0pKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBfcmVhY3QyLmRlZmF1bHQuY3JlYXRlRWxlbWVudCgnaW1nJywgX2V4dGVuZHMoe1xuICAgICAgICBhbHQ6ICdHcmF2YXRhciBmb3IgJyArIGZvcm1hdHRlZEVtYWlsLFxuICAgICAgICBzdHlsZTogdGhpcy5wcm9wcy5zdHlsZSxcbiAgICAgICAgc3JjOiBzcmMsXG4gICAgICAgIHNyY1NldDogcmV0aW5hU3JjICsgJyAyeCcsXG4gICAgICAgIGhlaWdodDogdGhpcy5wcm9wcy5zaXplLFxuICAgICAgICB3aWR0aDogdGhpcy5wcm9wcy5zaXplXG4gICAgICB9LCByZXN0LCB7XG4gICAgICAgIGNsYXNzTmFtZTogY2xhc3NOYW1lXG4gICAgICB9KSk7XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIEdyYXZhdGFyO1xufShfcmVhY3QyLmRlZmF1bHQuQ29tcG9uZW50KTtcblxuR3JhdmF0YXIuZGlzcGxheU5hbWUgPSAnR3JhdmF0YXInO1xuR3JhdmF0YXIucHJvcFR5cGVzID0ge1xuICBlbWFpbDogX3Byb3BUeXBlczIuZGVmYXVsdC5zdHJpbmcsXG4gIG1kNTogX3Byb3BUeXBlczIuZGVmYXVsdC5zdHJpbmcsXG4gIHNpemU6IF9wcm9wVHlwZXMyLmRlZmF1bHQubnVtYmVyLFxuICByYXRpbmc6IF9wcm9wVHlwZXMyLmRlZmF1bHQuc3RyaW5nLFxuICBkZWZhdWx0OiBfcHJvcFR5cGVzMi5kZWZhdWx0LnN0cmluZyxcbiAgY2xhc3NOYW1lOiBfcHJvcFR5cGVzMi5kZWZhdWx0LnN0cmluZyxcbiAgcHJvdG9jb2w6IF9wcm9wVHlwZXMyLmRlZmF1bHQuc3RyaW5nLFxuICBzdHlsZTogX3Byb3BUeXBlczIuZGVmYXVsdC5vYmplY3Rcbn07XG5HcmF2YXRhci5kZWZhdWx0UHJvcHMgPSB7XG4gIHNpemU6IDUwLFxuICByYXRpbmc6ICdnJyxcbiAgZGVmYXVsdDogJ3JldHJvJyxcbiAgcHJvdG9jb2w6ICcvLydcbn07XG5cblxubW9kdWxlLmV4cG9ydHMgPSBHcmF2YXRhcjsiLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKCkge1xuICB2YXIgbWVkaWFRdWVyeTtcbiAgaWYgKHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgJiYgd2luZG93ICE9PSBudWxsKSB7XG4gICAgbWVkaWFRdWVyeSA9IFwiKC13ZWJraXQtbWluLWRldmljZS1waXhlbC1yYXRpbzogMS4yNSksIChtaW4tLW1vei1kZXZpY2UtcGl4ZWwtcmF0aW86IDEuMjUpLCAoLW8tbWluLWRldmljZS1waXhlbC1yYXRpbzogNS80KSwgKG1pbi1yZXNvbHV0aW9uOiAxLjI1ZHBweClcIjtcbiAgICBpZiAod2luZG93LmRldmljZVBpeGVsUmF0aW8gPiAxLjI1KSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKHdpbmRvdy5tYXRjaE1lZGlhICYmIHdpbmRvdy5tYXRjaE1lZGlhKG1lZGlhUXVlcnkpLm1hdGNoZXMpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuICByZXR1cm4gZmFsc2U7XG59O1xuIiwiKGZ1bmN0aW9uKCl7XHJcbiAgdmFyIGNyeXB0ID0gcmVxdWlyZSgnY3J5cHQnKSxcclxuICAgICAgdXRmOCA9IHJlcXVpcmUoJ2NoYXJlbmMnKS51dGY4LFxyXG4gICAgICBpc0J1ZmZlciA9IHJlcXVpcmUoJ2lzLWJ1ZmZlcicpLFxyXG4gICAgICBiaW4gPSByZXF1aXJlKCdjaGFyZW5jJykuYmluLFxyXG5cclxuICAvLyBUaGUgY29yZVxyXG4gIG1kNSA9IGZ1bmN0aW9uIChtZXNzYWdlLCBvcHRpb25zKSB7XHJcbiAgICAvLyBDb252ZXJ0IHRvIGJ5dGUgYXJyYXlcclxuICAgIGlmIChtZXNzYWdlLmNvbnN0cnVjdG9yID09IFN0cmluZylcclxuICAgICAgaWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5lbmNvZGluZyA9PT0gJ2JpbmFyeScpXHJcbiAgICAgICAgbWVzc2FnZSA9IGJpbi5zdHJpbmdUb0J5dGVzKG1lc3NhZ2UpO1xyXG4gICAgICBlbHNlXHJcbiAgICAgICAgbWVzc2FnZSA9IHV0Zjguc3RyaW5nVG9CeXRlcyhtZXNzYWdlKTtcclxuICAgIGVsc2UgaWYgKGlzQnVmZmVyKG1lc3NhZ2UpKVxyXG4gICAgICBtZXNzYWdlID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwobWVzc2FnZSwgMCk7XHJcbiAgICBlbHNlIGlmICghQXJyYXkuaXNBcnJheShtZXNzYWdlKSlcclxuICAgICAgbWVzc2FnZSA9IG1lc3NhZ2UudG9TdHJpbmcoKTtcclxuICAgIC8vIGVsc2UsIGFzc3VtZSBieXRlIGFycmF5IGFscmVhZHlcclxuXHJcbiAgICB2YXIgbSA9IGNyeXB0LmJ5dGVzVG9Xb3JkcyhtZXNzYWdlKSxcclxuICAgICAgICBsID0gbWVzc2FnZS5sZW5ndGggKiA4LFxyXG4gICAgICAgIGEgPSAgMTczMjU4NDE5MyxcclxuICAgICAgICBiID0gLTI3MTczMzg3OSxcclxuICAgICAgICBjID0gLTE3MzI1ODQxOTQsXHJcbiAgICAgICAgZCA9ICAyNzE3MzM4Nzg7XHJcblxyXG4gICAgLy8gU3dhcCBlbmRpYW5cclxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbS5sZW5ndGg7IGkrKykge1xyXG4gICAgICBtW2ldID0gKChtW2ldIDw8ICA4KSB8IChtW2ldID4+PiAyNCkpICYgMHgwMEZGMDBGRiB8XHJcbiAgICAgICAgICAgICAoKG1baV0gPDwgMjQpIHwgKG1baV0gPj4+ICA4KSkgJiAweEZGMDBGRjAwO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFBhZGRpbmdcclxuICAgIG1bbCA+Pj4gNV0gfD0gMHg4MCA8PCAobCAlIDMyKTtcclxuICAgIG1bKCgobCArIDY0KSA+Pj4gOSkgPDwgNCkgKyAxNF0gPSBsO1xyXG5cclxuICAgIC8vIE1ldGhvZCBzaG9ydGN1dHNcclxuICAgIHZhciBGRiA9IG1kNS5fZmYsXHJcbiAgICAgICAgR0cgPSBtZDUuX2dnLFxyXG4gICAgICAgIEhIID0gbWQ1Ll9oaCxcclxuICAgICAgICBJSSA9IG1kNS5faWk7XHJcblxyXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtLmxlbmd0aDsgaSArPSAxNikge1xyXG5cclxuICAgICAgdmFyIGFhID0gYSxcclxuICAgICAgICAgIGJiID0gYixcclxuICAgICAgICAgIGNjID0gYyxcclxuICAgICAgICAgIGRkID0gZDtcclxuXHJcbiAgICAgIGEgPSBGRihhLCBiLCBjLCBkLCBtW2krIDBdLCAgNywgLTY4MDg3NjkzNik7XHJcbiAgICAgIGQgPSBGRihkLCBhLCBiLCBjLCBtW2krIDFdLCAxMiwgLTM4OTU2NDU4Nik7XHJcbiAgICAgIGMgPSBGRihjLCBkLCBhLCBiLCBtW2krIDJdLCAxNywgIDYwNjEwNTgxOSk7XHJcbiAgICAgIGIgPSBGRihiLCBjLCBkLCBhLCBtW2krIDNdLCAyMiwgLTEwNDQ1MjUzMzApO1xyXG4gICAgICBhID0gRkYoYSwgYiwgYywgZCwgbVtpKyA0XSwgIDcsIC0xNzY0MTg4OTcpO1xyXG4gICAgICBkID0gRkYoZCwgYSwgYiwgYywgbVtpKyA1XSwgMTIsICAxMjAwMDgwNDI2KTtcclxuICAgICAgYyA9IEZGKGMsIGQsIGEsIGIsIG1baSsgNl0sIDE3LCAtMTQ3MzIzMTM0MSk7XHJcbiAgICAgIGIgPSBGRihiLCBjLCBkLCBhLCBtW2krIDddLCAyMiwgLTQ1NzA1OTgzKTtcclxuICAgICAgYSA9IEZGKGEsIGIsIGMsIGQsIG1baSsgOF0sICA3LCAgMTc3MDAzNTQxNik7XHJcbiAgICAgIGQgPSBGRihkLCBhLCBiLCBjLCBtW2krIDldLCAxMiwgLTE5NTg0MTQ0MTcpO1xyXG4gICAgICBjID0gRkYoYywgZCwgYSwgYiwgbVtpKzEwXSwgMTcsIC00MjA2Myk7XHJcbiAgICAgIGIgPSBGRihiLCBjLCBkLCBhLCBtW2krMTFdLCAyMiwgLTE5OTA0MDQxNjIpO1xyXG4gICAgICBhID0gRkYoYSwgYiwgYywgZCwgbVtpKzEyXSwgIDcsICAxODA0NjAzNjgyKTtcclxuICAgICAgZCA9IEZGKGQsIGEsIGIsIGMsIG1baSsxM10sIDEyLCAtNDAzNDExMDEpO1xyXG4gICAgICBjID0gRkYoYywgZCwgYSwgYiwgbVtpKzE0XSwgMTcsIC0xNTAyMDAyMjkwKTtcclxuICAgICAgYiA9IEZGKGIsIGMsIGQsIGEsIG1baSsxNV0sIDIyLCAgMTIzNjUzNTMyOSk7XHJcblxyXG4gICAgICBhID0gR0coYSwgYiwgYywgZCwgbVtpKyAxXSwgIDUsIC0xNjU3OTY1MTApO1xyXG4gICAgICBkID0gR0coZCwgYSwgYiwgYywgbVtpKyA2XSwgIDksIC0xMDY5NTAxNjMyKTtcclxuICAgICAgYyA9IEdHKGMsIGQsIGEsIGIsIG1baSsxMV0sIDE0LCAgNjQzNzE3NzEzKTtcclxuICAgICAgYiA9IEdHKGIsIGMsIGQsIGEsIG1baSsgMF0sIDIwLCAtMzczODk3MzAyKTtcclxuICAgICAgYSA9IEdHKGEsIGIsIGMsIGQsIG1baSsgNV0sICA1LCAtNzAxNTU4NjkxKTtcclxuICAgICAgZCA9IEdHKGQsIGEsIGIsIGMsIG1baSsxMF0sICA5LCAgMzgwMTYwODMpO1xyXG4gICAgICBjID0gR0coYywgZCwgYSwgYiwgbVtpKzE1XSwgMTQsIC02NjA0NzgzMzUpO1xyXG4gICAgICBiID0gR0coYiwgYywgZCwgYSwgbVtpKyA0XSwgMjAsIC00MDU1Mzc4NDgpO1xyXG4gICAgICBhID0gR0coYSwgYiwgYywgZCwgbVtpKyA5XSwgIDUsICA1Njg0NDY0MzgpO1xyXG4gICAgICBkID0gR0coZCwgYSwgYiwgYywgbVtpKzE0XSwgIDksIC0xMDE5ODAzNjkwKTtcclxuICAgICAgYyA9IEdHKGMsIGQsIGEsIGIsIG1baSsgM10sIDE0LCAtMTg3MzYzOTYxKTtcclxuICAgICAgYiA9IEdHKGIsIGMsIGQsIGEsIG1baSsgOF0sIDIwLCAgMTE2MzUzMTUwMSk7XHJcbiAgICAgIGEgPSBHRyhhLCBiLCBjLCBkLCBtW2krMTNdLCAgNSwgLTE0NDQ2ODE0NjcpO1xyXG4gICAgICBkID0gR0coZCwgYSwgYiwgYywgbVtpKyAyXSwgIDksIC01MTQwMzc4NCk7XHJcbiAgICAgIGMgPSBHRyhjLCBkLCBhLCBiLCBtW2krIDddLCAxNCwgIDE3MzUzMjg0NzMpO1xyXG4gICAgICBiID0gR0coYiwgYywgZCwgYSwgbVtpKzEyXSwgMjAsIC0xOTI2NjA3NzM0KTtcclxuXHJcbiAgICAgIGEgPSBISChhLCBiLCBjLCBkLCBtW2krIDVdLCAgNCwgLTM3ODU1OCk7XHJcbiAgICAgIGQgPSBISChkLCBhLCBiLCBjLCBtW2krIDhdLCAxMSwgLTIwMjI1NzQ0NjMpO1xyXG4gICAgICBjID0gSEgoYywgZCwgYSwgYiwgbVtpKzExXSwgMTYsICAxODM5MDMwNTYyKTtcclxuICAgICAgYiA9IEhIKGIsIGMsIGQsIGEsIG1baSsxNF0sIDIzLCAtMzUzMDk1NTYpO1xyXG4gICAgICBhID0gSEgoYSwgYiwgYywgZCwgbVtpKyAxXSwgIDQsIC0xNTMwOTkyMDYwKTtcclxuICAgICAgZCA9IEhIKGQsIGEsIGIsIGMsIG1baSsgNF0sIDExLCAgMTI3Mjg5MzM1Myk7XHJcbiAgICAgIGMgPSBISChjLCBkLCBhLCBiLCBtW2krIDddLCAxNiwgLTE1NTQ5NzYzMik7XHJcbiAgICAgIGIgPSBISChiLCBjLCBkLCBhLCBtW2krMTBdLCAyMywgLTEwOTQ3MzA2NDApO1xyXG4gICAgICBhID0gSEgoYSwgYiwgYywgZCwgbVtpKzEzXSwgIDQsICA2ODEyNzkxNzQpO1xyXG4gICAgICBkID0gSEgoZCwgYSwgYiwgYywgbVtpKyAwXSwgMTEsIC0zNTg1MzcyMjIpO1xyXG4gICAgICBjID0gSEgoYywgZCwgYSwgYiwgbVtpKyAzXSwgMTYsIC03MjI1MjE5NzkpO1xyXG4gICAgICBiID0gSEgoYiwgYywgZCwgYSwgbVtpKyA2XSwgMjMsICA3NjAyOTE4OSk7XHJcbiAgICAgIGEgPSBISChhLCBiLCBjLCBkLCBtW2krIDldLCAgNCwgLTY0MDM2NDQ4Nyk7XHJcbiAgICAgIGQgPSBISChkLCBhLCBiLCBjLCBtW2krMTJdLCAxMSwgLTQyMTgxNTgzNSk7XHJcbiAgICAgIGMgPSBISChjLCBkLCBhLCBiLCBtW2krMTVdLCAxNiwgIDUzMDc0MjUyMCk7XHJcbiAgICAgIGIgPSBISChiLCBjLCBkLCBhLCBtW2krIDJdLCAyMywgLTk5NTMzODY1MSk7XHJcblxyXG4gICAgICBhID0gSUkoYSwgYiwgYywgZCwgbVtpKyAwXSwgIDYsIC0xOTg2MzA4NDQpO1xyXG4gICAgICBkID0gSUkoZCwgYSwgYiwgYywgbVtpKyA3XSwgMTAsICAxMTI2ODkxNDE1KTtcclxuICAgICAgYyA9IElJKGMsIGQsIGEsIGIsIG1baSsxNF0sIDE1LCAtMTQxNjM1NDkwNSk7XHJcbiAgICAgIGIgPSBJSShiLCBjLCBkLCBhLCBtW2krIDVdLCAyMSwgLTU3NDM0MDU1KTtcclxuICAgICAgYSA9IElJKGEsIGIsIGMsIGQsIG1baSsxMl0sICA2LCAgMTcwMDQ4NTU3MSk7XHJcbiAgICAgIGQgPSBJSShkLCBhLCBiLCBjLCBtW2krIDNdLCAxMCwgLTE4OTQ5ODY2MDYpO1xyXG4gICAgICBjID0gSUkoYywgZCwgYSwgYiwgbVtpKzEwXSwgMTUsIC0xMDUxNTIzKTtcclxuICAgICAgYiA9IElJKGIsIGMsIGQsIGEsIG1baSsgMV0sIDIxLCAtMjA1NDkyMjc5OSk7XHJcbiAgICAgIGEgPSBJSShhLCBiLCBjLCBkLCBtW2krIDhdLCAgNiwgIDE4NzMzMTMzNTkpO1xyXG4gICAgICBkID0gSUkoZCwgYSwgYiwgYywgbVtpKzE1XSwgMTAsIC0zMDYxMTc0NCk7XHJcbiAgICAgIGMgPSBJSShjLCBkLCBhLCBiLCBtW2krIDZdLCAxNSwgLTE1NjAxOTgzODApO1xyXG4gICAgICBiID0gSUkoYiwgYywgZCwgYSwgbVtpKzEzXSwgMjEsICAxMzA5MTUxNjQ5KTtcclxuICAgICAgYSA9IElJKGEsIGIsIGMsIGQsIG1baSsgNF0sICA2LCAtMTQ1NTIzMDcwKTtcclxuICAgICAgZCA9IElJKGQsIGEsIGIsIGMsIG1baSsxMV0sIDEwLCAtMTEyMDIxMDM3OSk7XHJcbiAgICAgIGMgPSBJSShjLCBkLCBhLCBiLCBtW2krIDJdLCAxNSwgIDcxODc4NzI1OSk7XHJcbiAgICAgIGIgPSBJSShiLCBjLCBkLCBhLCBtW2krIDldLCAyMSwgLTM0MzQ4NTU1MSk7XHJcblxyXG4gICAgICBhID0gKGEgKyBhYSkgPj4+IDA7XHJcbiAgICAgIGIgPSAoYiArIGJiKSA+Pj4gMDtcclxuICAgICAgYyA9IChjICsgY2MpID4+PiAwO1xyXG4gICAgICBkID0gKGQgKyBkZCkgPj4+IDA7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIGNyeXB0LmVuZGlhbihbYSwgYiwgYywgZF0pO1xyXG4gIH07XHJcblxyXG4gIC8vIEF1eGlsaWFyeSBmdW5jdGlvbnNcclxuICBtZDUuX2ZmICA9IGZ1bmN0aW9uIChhLCBiLCBjLCBkLCB4LCBzLCB0KSB7XHJcbiAgICB2YXIgbiA9IGEgKyAoYiAmIGMgfCB+YiAmIGQpICsgKHggPj4+IDApICsgdDtcclxuICAgIHJldHVybiAoKG4gPDwgcykgfCAobiA+Pj4gKDMyIC0gcykpKSArIGI7XHJcbiAgfTtcclxuICBtZDUuX2dnICA9IGZ1bmN0aW9uIChhLCBiLCBjLCBkLCB4LCBzLCB0KSB7XHJcbiAgICB2YXIgbiA9IGEgKyAoYiAmIGQgfCBjICYgfmQpICsgKHggPj4+IDApICsgdDtcclxuICAgIHJldHVybiAoKG4gPDwgcykgfCAobiA+Pj4gKDMyIC0gcykpKSArIGI7XHJcbiAgfTtcclxuICBtZDUuX2hoICA9IGZ1bmN0aW9uIChhLCBiLCBjLCBkLCB4LCBzLCB0KSB7XHJcbiAgICB2YXIgbiA9IGEgKyAoYiBeIGMgXiBkKSArICh4ID4+PiAwKSArIHQ7XHJcbiAgICByZXR1cm4gKChuIDw8IHMpIHwgKG4gPj4+ICgzMiAtIHMpKSkgKyBiO1xyXG4gIH07XHJcbiAgbWQ1Ll9paSAgPSBmdW5jdGlvbiAoYSwgYiwgYywgZCwgeCwgcywgdCkge1xyXG4gICAgdmFyIG4gPSBhICsgKGMgXiAoYiB8IH5kKSkgKyAoeCA+Pj4gMCkgKyB0O1xyXG4gICAgcmV0dXJuICgobiA8PCBzKSB8IChuID4+PiAoMzIgLSBzKSkpICsgYjtcclxuICB9O1xyXG5cclxuICAvLyBQYWNrYWdlIHByaXZhdGUgYmxvY2tzaXplXHJcbiAgbWQ1Ll9ibG9ja3NpemUgPSAxNjtcclxuICBtZDUuX2RpZ2VzdHNpemUgPSAxNjtcclxuXHJcbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAobWVzc2FnZSwgb3B0aW9ucykge1xyXG4gICAgaWYgKG1lc3NhZ2UgPT09IHVuZGVmaW5lZCB8fCBtZXNzYWdlID09PSBudWxsKVxyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0lsbGVnYWwgYXJndW1lbnQgJyArIG1lc3NhZ2UpO1xyXG5cclxuICAgIHZhciBkaWdlc3RieXRlcyA9IGNyeXB0LndvcmRzVG9CeXRlcyhtZDUobWVzc2FnZSwgb3B0aW9ucykpO1xyXG4gICAgcmV0dXJuIG9wdGlvbnMgJiYgb3B0aW9ucy5hc0J5dGVzID8gZGlnZXN0Ynl0ZXMgOlxyXG4gICAgICAgIG9wdGlvbnMgJiYgb3B0aW9ucy5hc1N0cmluZyA/IGJpbi5ieXRlc1RvU3RyaW5nKGRpZ2VzdGJ5dGVzKSA6XHJcbiAgICAgICAgY3J5cHQuYnl0ZXNUb0hleChkaWdlc3RieXRlcyk7XHJcbiAgfTtcclxuXHJcbn0pKCk7XHJcbiIsInZhciBjaGFyZW5jID0ge1xuICAvLyBVVEYtOCBlbmNvZGluZ1xuICB1dGY4OiB7XG4gICAgLy8gQ29udmVydCBhIHN0cmluZyB0byBhIGJ5dGUgYXJyYXlcbiAgICBzdHJpbmdUb0J5dGVzOiBmdW5jdGlvbihzdHIpIHtcbiAgICAgIHJldHVybiBjaGFyZW5jLmJpbi5zdHJpbmdUb0J5dGVzKHVuZXNjYXBlKGVuY29kZVVSSUNvbXBvbmVudChzdHIpKSk7XG4gICAgfSxcblxuICAgIC8vIENvbnZlcnQgYSBieXRlIGFycmF5IHRvIGEgc3RyaW5nXG4gICAgYnl0ZXNUb1N0cmluZzogZnVuY3Rpb24oYnl0ZXMpIHtcbiAgICAgIHJldHVybiBkZWNvZGVVUklDb21wb25lbnQoZXNjYXBlKGNoYXJlbmMuYmluLmJ5dGVzVG9TdHJpbmcoYnl0ZXMpKSk7XG4gICAgfVxuICB9LFxuXG4gIC8vIEJpbmFyeSBlbmNvZGluZ1xuICBiaW46IHtcbiAgICAvLyBDb252ZXJ0IGEgc3RyaW5nIHRvIGEgYnl0ZSBhcnJheVxuICAgIHN0cmluZ1RvQnl0ZXM6IGZ1bmN0aW9uKHN0cikge1xuICAgICAgZm9yICh2YXIgYnl0ZXMgPSBbXSwgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspXG4gICAgICAgIGJ5dGVzLnB1c2goc3RyLmNoYXJDb2RlQXQoaSkgJiAweEZGKTtcbiAgICAgIHJldHVybiBieXRlcztcbiAgICB9LFxuXG4gICAgLy8gQ29udmVydCBhIGJ5dGUgYXJyYXkgdG8gYSBzdHJpbmdcbiAgICBieXRlc1RvU3RyaW5nOiBmdW5jdGlvbihieXRlcykge1xuICAgICAgZm9yICh2YXIgc3RyID0gW10sIGkgPSAwOyBpIDwgYnl0ZXMubGVuZ3RoOyBpKyspXG4gICAgICAgIHN0ci5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUoYnl0ZXNbaV0pKTtcbiAgICAgIHJldHVybiBzdHIuam9pbignJyk7XG4gICAgfVxuICB9XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNoYXJlbmM7XG4iLCIoZnVuY3Rpb24oKSB7XG4gIHZhciBiYXNlNjRtYXBcbiAgICAgID0gJ0FCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5Ky8nLFxuXG4gIGNyeXB0ID0ge1xuICAgIC8vIEJpdC13aXNlIHJvdGF0aW9uIGxlZnRcbiAgICByb3RsOiBmdW5jdGlvbihuLCBiKSB7XG4gICAgICByZXR1cm4gKG4gPDwgYikgfCAobiA+Pj4gKDMyIC0gYikpO1xuICAgIH0sXG5cbiAgICAvLyBCaXQtd2lzZSByb3RhdGlvbiByaWdodFxuICAgIHJvdHI6IGZ1bmN0aW9uKG4sIGIpIHtcbiAgICAgIHJldHVybiAobiA8PCAoMzIgLSBiKSkgfCAobiA+Pj4gYik7XG4gICAgfSxcblxuICAgIC8vIFN3YXAgYmlnLWVuZGlhbiB0byBsaXR0bGUtZW5kaWFuIGFuZCB2aWNlIHZlcnNhXG4gICAgZW5kaWFuOiBmdW5jdGlvbihuKSB7XG4gICAgICAvLyBJZiBudW1iZXIgZ2l2ZW4sIHN3YXAgZW5kaWFuXG4gICAgICBpZiAobi5jb25zdHJ1Y3RvciA9PSBOdW1iZXIpIHtcbiAgICAgICAgcmV0dXJuIGNyeXB0LnJvdGwobiwgOCkgJiAweDAwRkYwMEZGIHwgY3J5cHQucm90bChuLCAyNCkgJiAweEZGMDBGRjAwO1xuICAgICAgfVxuXG4gICAgICAvLyBFbHNlLCBhc3N1bWUgYXJyYXkgYW5kIHN3YXAgYWxsIGl0ZW1zXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG4ubGVuZ3RoOyBpKyspXG4gICAgICAgIG5baV0gPSBjcnlwdC5lbmRpYW4obltpXSk7XG4gICAgICByZXR1cm4gbjtcbiAgICB9LFxuXG4gICAgLy8gR2VuZXJhdGUgYW4gYXJyYXkgb2YgYW55IGxlbmd0aCBvZiByYW5kb20gYnl0ZXNcbiAgICByYW5kb21CeXRlczogZnVuY3Rpb24obikge1xuICAgICAgZm9yICh2YXIgYnl0ZXMgPSBbXTsgbiA+IDA7IG4tLSlcbiAgICAgICAgYnl0ZXMucHVzaChNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiAyNTYpKTtcbiAgICAgIHJldHVybiBieXRlcztcbiAgICB9LFxuXG4gICAgLy8gQ29udmVydCBhIGJ5dGUgYXJyYXkgdG8gYmlnLWVuZGlhbiAzMi1iaXQgd29yZHNcbiAgICBieXRlc1RvV29yZHM6IGZ1bmN0aW9uKGJ5dGVzKSB7XG4gICAgICBmb3IgKHZhciB3b3JkcyA9IFtdLCBpID0gMCwgYiA9IDA7IGkgPCBieXRlcy5sZW5ndGg7IGkrKywgYiArPSA4KVxuICAgICAgICB3b3Jkc1tiID4+PiA1XSB8PSBieXRlc1tpXSA8PCAoMjQgLSBiICUgMzIpO1xuICAgICAgcmV0dXJuIHdvcmRzO1xuICAgIH0sXG5cbiAgICAvLyBDb252ZXJ0IGJpZy1lbmRpYW4gMzItYml0IHdvcmRzIHRvIGEgYnl0ZSBhcnJheVxuICAgIHdvcmRzVG9CeXRlczogZnVuY3Rpb24od29yZHMpIHtcbiAgICAgIGZvciAodmFyIGJ5dGVzID0gW10sIGIgPSAwOyBiIDwgd29yZHMubGVuZ3RoICogMzI7IGIgKz0gOClcbiAgICAgICAgYnl0ZXMucHVzaCgod29yZHNbYiA+Pj4gNV0gPj4+ICgyNCAtIGIgJSAzMikpICYgMHhGRik7XG4gICAgICByZXR1cm4gYnl0ZXM7XG4gICAgfSxcblxuICAgIC8vIENvbnZlcnQgYSBieXRlIGFycmF5IHRvIGEgaGV4IHN0cmluZ1xuICAgIGJ5dGVzVG9IZXg6IGZ1bmN0aW9uKGJ5dGVzKSB7XG4gICAgICBmb3IgKHZhciBoZXggPSBbXSwgaSA9IDA7IGkgPCBieXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBoZXgucHVzaCgoYnl0ZXNbaV0gPj4+IDQpLnRvU3RyaW5nKDE2KSk7XG4gICAgICAgIGhleC5wdXNoKChieXRlc1tpXSAmIDB4RikudG9TdHJpbmcoMTYpKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBoZXguam9pbignJyk7XG4gICAgfSxcblxuICAgIC8vIENvbnZlcnQgYSBoZXggc3RyaW5nIHRvIGEgYnl0ZSBhcnJheVxuICAgIGhleFRvQnl0ZXM6IGZ1bmN0aW9uKGhleCkge1xuICAgICAgZm9yICh2YXIgYnl0ZXMgPSBbXSwgYyA9IDA7IGMgPCBoZXgubGVuZ3RoOyBjICs9IDIpXG4gICAgICAgIGJ5dGVzLnB1c2gocGFyc2VJbnQoaGV4LnN1YnN0cihjLCAyKSwgMTYpKTtcbiAgICAgIHJldHVybiBieXRlcztcbiAgICB9LFxuXG4gICAgLy8gQ29udmVydCBhIGJ5dGUgYXJyYXkgdG8gYSBiYXNlLTY0IHN0cmluZ1xuICAgIGJ5dGVzVG9CYXNlNjQ6IGZ1bmN0aW9uKGJ5dGVzKSB7XG4gICAgICBmb3IgKHZhciBiYXNlNjQgPSBbXSwgaSA9IDA7IGkgPCBieXRlcy5sZW5ndGg7IGkgKz0gMykge1xuICAgICAgICB2YXIgdHJpcGxldCA9IChieXRlc1tpXSA8PCAxNikgfCAoYnl0ZXNbaSArIDFdIDw8IDgpIHwgYnl0ZXNbaSArIDJdO1xuICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IDQ7IGorKylcbiAgICAgICAgICBpZiAoaSAqIDggKyBqICogNiA8PSBieXRlcy5sZW5ndGggKiA4KVxuICAgICAgICAgICAgYmFzZTY0LnB1c2goYmFzZTY0bWFwLmNoYXJBdCgodHJpcGxldCA+Pj4gNiAqICgzIC0gaikpICYgMHgzRikpO1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIGJhc2U2NC5wdXNoKCc9Jyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYmFzZTY0LmpvaW4oJycpO1xuICAgIH0sXG5cbiAgICAvLyBDb252ZXJ0IGEgYmFzZS02NCBzdHJpbmcgdG8gYSBieXRlIGFycmF5XG4gICAgYmFzZTY0VG9CeXRlczogZnVuY3Rpb24oYmFzZTY0KSB7XG4gICAgICAvLyBSZW1vdmUgbm9uLWJhc2UtNjQgY2hhcmFjdGVyc1xuICAgICAgYmFzZTY0ID0gYmFzZTY0LnJlcGxhY2UoL1teQS1aMC05K1xcL10vaWcsICcnKTtcblxuICAgICAgZm9yICh2YXIgYnl0ZXMgPSBbXSwgaSA9IDAsIGltb2Q0ID0gMDsgaSA8IGJhc2U2NC5sZW5ndGg7XG4gICAgICAgICAgaW1vZDQgPSArK2kgJSA0KSB7XG4gICAgICAgIGlmIChpbW9kNCA9PSAwKSBjb250aW51ZTtcbiAgICAgICAgYnl0ZXMucHVzaCgoKGJhc2U2NG1hcC5pbmRleE9mKGJhc2U2NC5jaGFyQXQoaSAtIDEpKVxuICAgICAgICAgICAgJiAoTWF0aC5wb3coMiwgLTIgKiBpbW9kNCArIDgpIC0gMSkpIDw8IChpbW9kNCAqIDIpKVxuICAgICAgICAgICAgfCAoYmFzZTY0bWFwLmluZGV4T2YoYmFzZTY0LmNoYXJBdChpKSkgPj4+ICg2IC0gaW1vZDQgKiAyKSkpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJ5dGVzO1xuICAgIH1cbiAgfTtcblxuICBtb2R1bGUuZXhwb3J0cyA9IGNyeXB0O1xufSkoKTtcbiIsIi8qIVxuICogRGV0ZXJtaW5lIGlmIGFuIG9iamVjdCBpcyBhIEJ1ZmZlclxuICpcbiAqIEBhdXRob3IgICBGZXJvc3MgQWJvdWtoYWRpamVoIDxmZXJvc3NAZmVyb3NzLm9yZz4gPGh0dHA6Ly9mZXJvc3Mub3JnPlxuICogQGxpY2Vuc2UgIE1JVFxuICovXG5cbi8vIFRoZSBfaXNCdWZmZXIgY2hlY2sgaXMgZm9yIFNhZmFyaSA1LTcgc3VwcG9ydCwgYmVjYXVzZSBpdCdzIG1pc3Npbmdcbi8vIE9iamVjdC5wcm90b3R5cGUuY29uc3RydWN0b3IuIFJlbW92ZSB0aGlzIGV2ZW50dWFsbHlcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKG9iaikge1xuICByZXR1cm4gb2JqICE9IG51bGwgJiYgKGlzQnVmZmVyKG9iaikgfHwgaXNTbG93QnVmZmVyKG9iaikgfHwgISFvYmouX2lzQnVmZmVyKVxufVxuXG5mdW5jdGlvbiBpc0J1ZmZlciAob2JqKSB7XG4gIHJldHVybiAhIW9iai5jb25zdHJ1Y3RvciAmJiB0eXBlb2Ygb2JqLmNvbnN0cnVjdG9yLmlzQnVmZmVyID09PSAnZnVuY3Rpb24nICYmIG9iai5jb25zdHJ1Y3Rvci5pc0J1ZmZlcihvYmopXG59XG5cbi8vIEZvciBOb2RlIHYwLjEwIHN1cHBvcnQuIFJlbW92ZSB0aGlzIGV2ZW50dWFsbHkuXG5mdW5jdGlvbiBpc1Nsb3dCdWZmZXIgKG9iaikge1xuICByZXR1cm4gdHlwZW9mIG9iai5yZWFkRmxvYXRMRSA9PT0gJ2Z1bmN0aW9uJyAmJiB0eXBlb2Ygb2JqLnNsaWNlID09PSAnZnVuY3Rpb24nICYmIGlzQnVmZmVyKG9iai5zbGljZSgwLCAwKSlcbn1cbiIsIid1c2Ugc3RyaWN0JztcbnZhciBzdHJpY3RVcmlFbmNvZGUgPSByZXF1aXJlKCdzdHJpY3QtdXJpLWVuY29kZScpO1xudmFyIG9iamVjdEFzc2lnbiA9IHJlcXVpcmUoJ29iamVjdC1hc3NpZ24nKTtcblxuZnVuY3Rpb24gZW5jb2RlckZvckFycmF5Rm9ybWF0KG9wdHMpIHtcblx0c3dpdGNoIChvcHRzLmFycmF5Rm9ybWF0KSB7XG5cdFx0Y2FzZSAnaW5kZXgnOlxuXHRcdFx0cmV0dXJuIGZ1bmN0aW9uIChrZXksIHZhbHVlLCBpbmRleCkge1xuXHRcdFx0XHRyZXR1cm4gdmFsdWUgPT09IG51bGwgPyBbXG5cdFx0XHRcdFx0ZW5jb2RlKGtleSwgb3B0cyksXG5cdFx0XHRcdFx0J1snLFxuXHRcdFx0XHRcdGluZGV4LFxuXHRcdFx0XHRcdCddJ1xuXHRcdFx0XHRdLmpvaW4oJycpIDogW1xuXHRcdFx0XHRcdGVuY29kZShrZXksIG9wdHMpLFxuXHRcdFx0XHRcdCdbJyxcblx0XHRcdFx0XHRlbmNvZGUoaW5kZXgsIG9wdHMpLFxuXHRcdFx0XHRcdCddPScsXG5cdFx0XHRcdFx0ZW5jb2RlKHZhbHVlLCBvcHRzKVxuXHRcdFx0XHRdLmpvaW4oJycpO1xuXHRcdFx0fTtcblxuXHRcdGNhc2UgJ2JyYWNrZXQnOlxuXHRcdFx0cmV0dXJuIGZ1bmN0aW9uIChrZXksIHZhbHVlKSB7XG5cdFx0XHRcdHJldHVybiB2YWx1ZSA9PT0gbnVsbCA/IGVuY29kZShrZXksIG9wdHMpIDogW1xuXHRcdFx0XHRcdGVuY29kZShrZXksIG9wdHMpLFxuXHRcdFx0XHRcdCdbXT0nLFxuXHRcdFx0XHRcdGVuY29kZSh2YWx1ZSwgb3B0cylcblx0XHRcdFx0XS5qb2luKCcnKTtcblx0XHRcdH07XG5cblx0XHRkZWZhdWx0OlxuXHRcdFx0cmV0dXJuIGZ1bmN0aW9uIChrZXksIHZhbHVlKSB7XG5cdFx0XHRcdHJldHVybiB2YWx1ZSA9PT0gbnVsbCA/IGVuY29kZShrZXksIG9wdHMpIDogW1xuXHRcdFx0XHRcdGVuY29kZShrZXksIG9wdHMpLFxuXHRcdFx0XHRcdCc9Jyxcblx0XHRcdFx0XHRlbmNvZGUodmFsdWUsIG9wdHMpXG5cdFx0XHRcdF0uam9pbignJyk7XG5cdFx0XHR9O1xuXHR9XG59XG5cbmZ1bmN0aW9uIHBhcnNlckZvckFycmF5Rm9ybWF0KG9wdHMpIHtcblx0dmFyIHJlc3VsdDtcblxuXHRzd2l0Y2ggKG9wdHMuYXJyYXlGb3JtYXQpIHtcblx0XHRjYXNlICdpbmRleCc6XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24gKGtleSwgdmFsdWUsIGFjY3VtdWxhdG9yKSB7XG5cdFx0XHRcdHJlc3VsdCA9IC9cXFsoXFxkKilcXF0kLy5leGVjKGtleSk7XG5cblx0XHRcdFx0a2V5ID0ga2V5LnJlcGxhY2UoL1xcW1xcZCpcXF0kLywgJycpO1xuXG5cdFx0XHRcdGlmICghcmVzdWx0KSB7XG5cdFx0XHRcdFx0YWNjdW11bGF0b3Jba2V5XSA9IHZhbHVlO1xuXHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmIChhY2N1bXVsYXRvcltrZXldID09PSB1bmRlZmluZWQpIHtcblx0XHRcdFx0XHRhY2N1bXVsYXRvcltrZXldID0ge307XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRhY2N1bXVsYXRvcltrZXldW3Jlc3VsdFsxXV0gPSB2YWx1ZTtcblx0XHRcdH07XG5cblx0XHRjYXNlICdicmFja2V0Jzpcblx0XHRcdHJldHVybiBmdW5jdGlvbiAoa2V5LCB2YWx1ZSwgYWNjdW11bGF0b3IpIHtcblx0XHRcdFx0cmVzdWx0ID0gLyhcXFtcXF0pJC8uZXhlYyhrZXkpO1xuXHRcdFx0XHRrZXkgPSBrZXkucmVwbGFjZSgvXFxbXFxdJC8sICcnKTtcblxuXHRcdFx0XHRpZiAoIXJlc3VsdCkge1xuXHRcdFx0XHRcdGFjY3VtdWxhdG9yW2tleV0gPSB2YWx1ZTtcblx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdH0gZWxzZSBpZiAoYWNjdW11bGF0b3Jba2V5XSA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdFx0YWNjdW11bGF0b3Jba2V5XSA9IFt2YWx1ZV07XG5cdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0YWNjdW11bGF0b3Jba2V5XSA9IFtdLmNvbmNhdChhY2N1bXVsYXRvcltrZXldLCB2YWx1ZSk7XG5cdFx0XHR9O1xuXG5cdFx0ZGVmYXVsdDpcblx0XHRcdHJldHVybiBmdW5jdGlvbiAoa2V5LCB2YWx1ZSwgYWNjdW11bGF0b3IpIHtcblx0XHRcdFx0aWYgKGFjY3VtdWxhdG9yW2tleV0gPT09IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRcdGFjY3VtdWxhdG9yW2tleV0gPSB2YWx1ZTtcblx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRhY2N1bXVsYXRvcltrZXldID0gW10uY29uY2F0KGFjY3VtdWxhdG9yW2tleV0sIHZhbHVlKTtcblx0XHRcdH07XG5cdH1cbn1cblxuZnVuY3Rpb24gZW5jb2RlKHZhbHVlLCBvcHRzKSB7XG5cdGlmIChvcHRzLmVuY29kZSkge1xuXHRcdHJldHVybiBvcHRzLnN0cmljdCA/IHN0cmljdFVyaUVuY29kZSh2YWx1ZSkgOiBlbmNvZGVVUklDb21wb25lbnQodmFsdWUpO1xuXHR9XG5cblx0cmV0dXJuIHZhbHVlO1xufVxuXG5mdW5jdGlvbiBrZXlzU29ydGVyKGlucHV0KSB7XG5cdGlmIChBcnJheS5pc0FycmF5KGlucHV0KSkge1xuXHRcdHJldHVybiBpbnB1dC5zb3J0KCk7XG5cdH0gZWxzZSBpZiAodHlwZW9mIGlucHV0ID09PSAnb2JqZWN0Jykge1xuXHRcdHJldHVybiBrZXlzU29ydGVyKE9iamVjdC5rZXlzKGlucHV0KSkuc29ydChmdW5jdGlvbiAoYSwgYikge1xuXHRcdFx0cmV0dXJuIE51bWJlcihhKSAtIE51bWJlcihiKTtcblx0XHR9KS5tYXAoZnVuY3Rpb24gKGtleSkge1xuXHRcdFx0cmV0dXJuIGlucHV0W2tleV07XG5cdFx0fSk7XG5cdH1cblxuXHRyZXR1cm4gaW5wdXQ7XG59XG5cbmV4cG9ydHMuZXh0cmFjdCA9IGZ1bmN0aW9uIChzdHIpIHtcblx0cmV0dXJuIHN0ci5zcGxpdCgnPycpWzFdIHx8ICcnO1xufTtcblxuZXhwb3J0cy5wYXJzZSA9IGZ1bmN0aW9uIChzdHIsIG9wdHMpIHtcblx0b3B0cyA9IG9iamVjdEFzc2lnbih7YXJyYXlGb3JtYXQ6ICdub25lJ30sIG9wdHMpO1xuXG5cdHZhciBmb3JtYXR0ZXIgPSBwYXJzZXJGb3JBcnJheUZvcm1hdChvcHRzKTtcblxuXHQvLyBDcmVhdGUgYW4gb2JqZWN0IHdpdGggbm8gcHJvdG90eXBlXG5cdC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9zaW5kcmVzb3JodXMvcXVlcnktc3RyaW5nL2lzc3Vlcy80N1xuXHR2YXIgcmV0ID0gT2JqZWN0LmNyZWF0ZShudWxsKTtcblxuXHRpZiAodHlwZW9mIHN0ciAhPT0gJ3N0cmluZycpIHtcblx0XHRyZXR1cm4gcmV0O1xuXHR9XG5cblx0c3RyID0gc3RyLnRyaW0oKS5yZXBsYWNlKC9eKFxcP3wjfCYpLywgJycpO1xuXG5cdGlmICghc3RyKSB7XG5cdFx0cmV0dXJuIHJldDtcblx0fVxuXG5cdHN0ci5zcGxpdCgnJicpLmZvckVhY2goZnVuY3Rpb24gKHBhcmFtKSB7XG5cdFx0dmFyIHBhcnRzID0gcGFyYW0ucmVwbGFjZSgvXFwrL2csICcgJykuc3BsaXQoJz0nKTtcblx0XHQvLyBGaXJlZm94IChwcmUgNDApIGRlY29kZXMgYCUzRGAgdG8gYD1gXG5cdFx0Ly8gaHR0cHM6Ly9naXRodWIuY29tL3NpbmRyZXNvcmh1cy9xdWVyeS1zdHJpbmcvcHVsbC8zN1xuXHRcdHZhciBrZXkgPSBwYXJ0cy5zaGlmdCgpO1xuXHRcdHZhciB2YWwgPSBwYXJ0cy5sZW5ndGggPiAwID8gcGFydHMuam9pbignPScpIDogdW5kZWZpbmVkO1xuXG5cdFx0Ly8gbWlzc2luZyBgPWAgc2hvdWxkIGJlIGBudWxsYDpcblx0XHQvLyBodHRwOi8vdzMub3JnL1RSLzIwMTIvV0QtdXJsLTIwMTIwNTI0LyNjb2xsZWN0LXVybC1wYXJhbWV0ZXJzXG5cdFx0dmFsID0gdmFsID09PSB1bmRlZmluZWQgPyBudWxsIDogZGVjb2RlVVJJQ29tcG9uZW50KHZhbCk7XG5cblx0XHRmb3JtYXR0ZXIoZGVjb2RlVVJJQ29tcG9uZW50KGtleSksIHZhbCwgcmV0KTtcblx0fSk7XG5cblx0cmV0dXJuIE9iamVjdC5rZXlzKHJldCkuc29ydCgpLnJlZHVjZShmdW5jdGlvbiAocmVzdWx0LCBrZXkpIHtcblx0XHR2YXIgdmFsID0gcmV0W2tleV07XG5cdFx0aWYgKEJvb2xlYW4odmFsKSAmJiB0eXBlb2YgdmFsID09PSAnb2JqZWN0JyAmJiAhQXJyYXkuaXNBcnJheSh2YWwpKSB7XG5cdFx0XHQvLyBTb3J0IG9iamVjdCBrZXlzLCBub3QgdmFsdWVzXG5cdFx0XHRyZXN1bHRba2V5XSA9IGtleXNTb3J0ZXIodmFsKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cmVzdWx0W2tleV0gPSB2YWw7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHJlc3VsdDtcblx0fSwgT2JqZWN0LmNyZWF0ZShudWxsKSk7XG59O1xuXG5leHBvcnRzLnN0cmluZ2lmeSA9IGZ1bmN0aW9uIChvYmosIG9wdHMpIHtcblx0dmFyIGRlZmF1bHRzID0ge1xuXHRcdGVuY29kZTogdHJ1ZSxcblx0XHRzdHJpY3Q6IHRydWUsXG5cdFx0YXJyYXlGb3JtYXQ6ICdub25lJ1xuXHR9O1xuXG5cdG9wdHMgPSBvYmplY3RBc3NpZ24oZGVmYXVsdHMsIG9wdHMpO1xuXG5cdHZhciBmb3JtYXR0ZXIgPSBlbmNvZGVyRm9yQXJyYXlGb3JtYXQob3B0cyk7XG5cblx0cmV0dXJuIG9iaiA/IE9iamVjdC5rZXlzKG9iaikuc29ydCgpLm1hcChmdW5jdGlvbiAoa2V5KSB7XG5cdFx0dmFyIHZhbCA9IG9ialtrZXldO1xuXG5cdFx0aWYgKHZhbCA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRyZXR1cm4gJyc7XG5cdFx0fVxuXG5cdFx0aWYgKHZhbCA9PT0gbnVsbCkge1xuXHRcdFx0cmV0dXJuIGVuY29kZShrZXksIG9wdHMpO1xuXHRcdH1cblxuXHRcdGlmIChBcnJheS5pc0FycmF5KHZhbCkpIHtcblx0XHRcdHZhciByZXN1bHQgPSBbXTtcblxuXHRcdFx0dmFsLnNsaWNlKCkuZm9yRWFjaChmdW5jdGlvbiAodmFsMikge1xuXHRcdFx0XHRpZiAodmFsMiA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0cmVzdWx0LnB1c2goZm9ybWF0dGVyKGtleSwgdmFsMiwgcmVzdWx0Lmxlbmd0aCkpO1xuXHRcdFx0fSk7XG5cblx0XHRcdHJldHVybiByZXN1bHQuam9pbignJicpO1xuXHRcdH1cblxuXHRcdHJldHVybiBlbmNvZGUoa2V5LCBvcHRzKSArICc9JyArIGVuY29kZSh2YWwsIG9wdHMpO1xuXHR9KS5maWx0ZXIoZnVuY3Rpb24gKHgpIHtcblx0XHRyZXR1cm4geC5sZW5ndGggPiAwO1xuXHR9KS5qb2luKCcmJykgOiAnJztcbn07XG4iLCIvKlxub2JqZWN0LWFzc2lnblxuKGMpIFNpbmRyZSBTb3JodXNcbkBsaWNlbnNlIE1JVFxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuLyogZXNsaW50LWRpc2FibGUgbm8tdW51c2VkLXZhcnMgKi9cbnZhciBnZXRPd25Qcm9wZXJ0eVN5bWJvbHMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzO1xudmFyIGhhc093blByb3BlcnR5ID0gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eTtcbnZhciBwcm9wSXNFbnVtZXJhYmxlID0gT2JqZWN0LnByb3RvdHlwZS5wcm9wZXJ0eUlzRW51bWVyYWJsZTtcblxuZnVuY3Rpb24gdG9PYmplY3QodmFsKSB7XG5cdGlmICh2YWwgPT09IG51bGwgfHwgdmFsID09PSB1bmRlZmluZWQpIHtcblx0XHR0aHJvdyBuZXcgVHlwZUVycm9yKCdPYmplY3QuYXNzaWduIGNhbm5vdCBiZSBjYWxsZWQgd2l0aCBudWxsIG9yIHVuZGVmaW5lZCcpO1xuXHR9XG5cblx0cmV0dXJuIE9iamVjdCh2YWwpO1xufVxuXG5mdW5jdGlvbiBzaG91bGRVc2VOYXRpdmUoKSB7XG5cdHRyeSB7XG5cdFx0aWYgKCFPYmplY3QuYXNzaWduKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXG5cdFx0Ly8gRGV0ZWN0IGJ1Z2d5IHByb3BlcnR5IGVudW1lcmF0aW9uIG9yZGVyIGluIG9sZGVyIFY4IHZlcnNpb25zLlxuXG5cdFx0Ly8gaHR0cHM6Ly9idWdzLmNocm9taXVtLm9yZy9wL3Y4L2lzc3Vlcy9kZXRhaWw/aWQ9NDExOFxuXHRcdHZhciB0ZXN0MSA9IG5ldyBTdHJpbmcoJ2FiYycpOyAgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1uZXctd3JhcHBlcnNcblx0XHR0ZXN0MVs1XSA9ICdkZSc7XG5cdFx0aWYgKE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHRlc3QxKVswXSA9PT0gJzUnKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXG5cdFx0Ly8gaHR0cHM6Ly9idWdzLmNocm9taXVtLm9yZy9wL3Y4L2lzc3Vlcy9kZXRhaWw/aWQ9MzA1NlxuXHRcdHZhciB0ZXN0MiA9IHt9O1xuXHRcdGZvciAodmFyIGkgPSAwOyBpIDwgMTA7IGkrKykge1xuXHRcdFx0dGVzdDJbJ18nICsgU3RyaW5nLmZyb21DaGFyQ29kZShpKV0gPSBpO1xuXHRcdH1cblx0XHR2YXIgb3JkZXIyID0gT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXModGVzdDIpLm1hcChmdW5jdGlvbiAobikge1xuXHRcdFx0cmV0dXJuIHRlc3QyW25dO1xuXHRcdH0pO1xuXHRcdGlmIChvcmRlcjIuam9pbignJykgIT09ICcwMTIzNDU2Nzg5Jykge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblxuXHRcdC8vIGh0dHBzOi8vYnVncy5jaHJvbWl1bS5vcmcvcC92OC9pc3N1ZXMvZGV0YWlsP2lkPTMwNTZcblx0XHR2YXIgdGVzdDMgPSB7fTtcblx0XHQnYWJjZGVmZ2hpamtsbW5vcHFyc3QnLnNwbGl0KCcnKS5mb3JFYWNoKGZ1bmN0aW9uIChsZXR0ZXIpIHtcblx0XHRcdHRlc3QzW2xldHRlcl0gPSBsZXR0ZXI7XG5cdFx0fSk7XG5cdFx0aWYgKE9iamVjdC5rZXlzKE9iamVjdC5hc3NpZ24oe30sIHRlc3QzKSkuam9pbignJykgIT09XG5cdFx0XHRcdCdhYmNkZWZnaGlqa2xtbm9wcXJzdCcpIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cblx0XHRyZXR1cm4gdHJ1ZTtcblx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0Ly8gV2UgZG9uJ3QgZXhwZWN0IGFueSBvZiB0aGUgYWJvdmUgdG8gdGhyb3csIGJ1dCBiZXR0ZXIgdG8gYmUgc2FmZS5cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSBzaG91bGRVc2VOYXRpdmUoKSA/IE9iamVjdC5hc3NpZ24gOiBmdW5jdGlvbiAodGFyZ2V0LCBzb3VyY2UpIHtcblx0dmFyIGZyb207XG5cdHZhciB0byA9IHRvT2JqZWN0KHRhcmdldCk7XG5cdHZhciBzeW1ib2xzO1xuXG5cdGZvciAodmFyIHMgPSAxOyBzIDwgYXJndW1lbnRzLmxlbmd0aDsgcysrKSB7XG5cdFx0ZnJvbSA9IE9iamVjdChhcmd1bWVudHNbc10pO1xuXG5cdFx0Zm9yICh2YXIga2V5IGluIGZyb20pIHtcblx0XHRcdGlmIChoYXNPd25Qcm9wZXJ0eS5jYWxsKGZyb20sIGtleSkpIHtcblx0XHRcdFx0dG9ba2V5XSA9IGZyb21ba2V5XTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAoZ2V0T3duUHJvcGVydHlTeW1ib2xzKSB7XG5cdFx0XHRzeW1ib2xzID0gZ2V0T3duUHJvcGVydHlTeW1ib2xzKGZyb20pO1xuXHRcdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBzeW1ib2xzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdGlmIChwcm9wSXNFbnVtZXJhYmxlLmNhbGwoZnJvbSwgc3ltYm9sc1tpXSkpIHtcblx0XHRcdFx0XHR0b1tzeW1ib2xzW2ldXSA9IGZyb21bc3ltYm9sc1tpXV07XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRyZXR1cm4gdG87XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoc3RyKSB7XG5cdHJldHVybiBlbmNvZGVVUklDb21wb25lbnQoc3RyKS5yZXBsYWNlKC9bIScoKSpdL2csIGZ1bmN0aW9uIChjKSB7XG5cdFx0cmV0dXJuICclJyArIGMuY2hhckNvZGVBdCgwKS50b1N0cmluZygxNikudG9VcHBlckNhc2UoKTtcblx0fSk7XG59O1xuIiwibW9kdWxlLmV4cG9ydHMgPVxuLyoqKioqKi8gKGZ1bmN0aW9uKG1vZHVsZXMpIHsgLy8gd2VicGFja0Jvb3RzdHJhcFxuLyoqKioqKi8gXHQvLyBUaGUgbW9kdWxlIGNhY2hlXG4vKioqKioqLyBcdHZhciBpbnN0YWxsZWRNb2R1bGVzID0ge307XG4vKioqKioqL1xuLyoqKioqKi8gXHQvLyBUaGUgcmVxdWlyZSBmdW5jdGlvblxuLyoqKioqKi8gXHRmdW5jdGlvbiBfX3dlYnBhY2tfcmVxdWlyZV9fKG1vZHVsZUlkKSB7XG4vKioqKioqL1xuLyoqKioqKi8gXHRcdC8vIENoZWNrIGlmIG1vZHVsZSBpcyBpbiBjYWNoZVxuLyoqKioqKi8gXHRcdGlmKGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdKVxuLyoqKioqKi8gXHRcdFx0cmV0dXJuIGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdLmV4cG9ydHM7XG4vKioqKioqL1xuLyoqKioqKi8gXHRcdC8vIENyZWF0ZSBhIG5ldyBtb2R1bGUgKGFuZCBwdXQgaXQgaW50byB0aGUgY2FjaGUpXG4vKioqKioqLyBcdFx0dmFyIG1vZHVsZSA9IGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdID0ge1xuLyoqKioqKi8gXHRcdFx0ZXhwb3J0czoge30sXG4vKioqKioqLyBcdFx0XHRpZDogbW9kdWxlSWQsXG4vKioqKioqLyBcdFx0XHRsb2FkZWQ6IGZhbHNlXG4vKioqKioqLyBcdFx0fTtcbi8qKioqKiovXG4vKioqKioqLyBcdFx0Ly8gRXhlY3V0ZSB0aGUgbW9kdWxlIGZ1bmN0aW9uXG4vKioqKioqLyBcdFx0bW9kdWxlc1ttb2R1bGVJZF0uY2FsbChtb2R1bGUuZXhwb3J0cywgbW9kdWxlLCBtb2R1bGUuZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXyk7XG4vKioqKioqL1xuLyoqKioqKi8gXHRcdC8vIEZsYWcgdGhlIG1vZHVsZSBhcyBsb2FkZWRcbi8qKioqKiovIFx0XHRtb2R1bGUubG9hZGVkID0gdHJ1ZTtcbi8qKioqKiovXG4vKioqKioqLyBcdFx0Ly8gUmV0dXJuIHRoZSBleHBvcnRzIG9mIHRoZSBtb2R1bGVcbi8qKioqKiovIFx0XHRyZXR1cm4gbW9kdWxlLmV4cG9ydHM7XG4vKioqKioqLyBcdH1cbi8qKioqKiovXG4vKioqKioqL1xuLyoqKioqKi8gXHQvLyBleHBvc2UgdGhlIG1vZHVsZXMgb2JqZWN0IChfX3dlYnBhY2tfbW9kdWxlc19fKVxuLyoqKioqKi8gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm0gPSBtb2R1bGVzO1xuLyoqKioqKi9cbi8qKioqKiovIFx0Ly8gZXhwb3NlIHRoZSBtb2R1bGUgY2FjaGVcbi8qKioqKiovIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5jID0gaW5zdGFsbGVkTW9kdWxlcztcbi8qKioqKiovXG4vKioqKioqLyBcdC8vIF9fd2VicGFja19wdWJsaWNfcGF0aF9fXG4vKioqKioqLyBcdF9fd2VicGFja19yZXF1aXJlX18ucCA9IFwiXCI7XG4vKioqKioqL1xuLyoqKioqKi8gXHQvLyBMb2FkIGVudHJ5IG1vZHVsZSBhbmQgcmV0dXJuIGV4cG9ydHNcbi8qKioqKiovIFx0cmV0dXJuIF9fd2VicGFja19yZXF1aXJlX18oMCk7XG4vKioqKioqLyB9KVxuLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cbi8qKioqKiovIChbXG4vKiAwICovXG4vKioqLyBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcblxuXHRtb2R1bGUuZXhwb3J0cyA9IF9fd2VicGFja19yZXF1aXJlX18oMSk7XG5cblxuLyoqKi8gfSxcbi8qIDEgKi9cbi8qKiovIGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykge1xuXG5cdCd1c2Ugc3RyaWN0Jztcblx0XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcblx0ICB2YWx1ZTogdHJ1ZVxuXHR9KTtcblx0XG5cdGZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblx0XG5cdHZhciBfSGlnaGxpZ2h0ZXIgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDIpO1xuXHRcblx0dmFyIF9IaWdobGlnaHRlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9IaWdobGlnaHRlcik7XG5cdFxuXHR2YXIgX3V0aWxzID0gX193ZWJwYWNrX3JlcXVpcmVfXyg0KTtcblx0XG5cdGV4cG9ydHNbJ2RlZmF1bHQnXSA9IF9IaWdobGlnaHRlcjJbJ2RlZmF1bHQnXTtcblx0ZXhwb3J0cy5jb21iaW5lQ2h1bmtzID0gX3V0aWxzLmNvbWJpbmVDaHVua3M7XG5cdGV4cG9ydHMuZmlsbEluQ2h1bmtzID0gX3V0aWxzLmZpbGxJbkNodW5rcztcblx0ZXhwb3J0cy5maW5kQWxsID0gX3V0aWxzLmZpbmRBbGw7XG5cdGV4cG9ydHMuZmluZENodW5rcyA9IF91dGlscy5maW5kQ2h1bmtzO1xuXG4vKioqLyB9LFxuLyogMiAqL1xuLyoqKi8gZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG5cblx0J3VzZSBzdHJpY3QnO1xuXHRcblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywge1xuXHQgIHZhbHVlOiB0cnVlXG5cdH0pO1xuXHRleHBvcnRzWydkZWZhdWx0J10gPSBIaWdobGlnaHRlcjtcblx0XG5cdGZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZVdpbGRjYXJkKG9iaikgeyBpZiAob2JqICYmIG9iai5fX2VzTW9kdWxlKSB7IHJldHVybiBvYmo7IH0gZWxzZSB7IHZhciBuZXdPYmogPSB7fTsgaWYgKG9iaiAhPSBudWxsKSB7IGZvciAodmFyIGtleSBpbiBvYmopIHsgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmosIGtleSkpIG5ld09ialtrZXldID0gb2JqW2tleV07IH0gfSBuZXdPYmpbJ2RlZmF1bHQnXSA9IG9iajsgcmV0dXJuIG5ld09iajsgfSB9XG5cdFxuXHRmdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cdFxuXHR2YXIgX3JlYWN0ID0gX193ZWJwYWNrX3JlcXVpcmVfXygzKTtcblx0XG5cdHZhciBfcmVhY3QyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfcmVhY3QpO1xuXHRcblx0dmFyIF91dGlsc0pzID0gX193ZWJwYWNrX3JlcXVpcmVfXyg0KTtcblx0XG5cdHZhciBDaHVua3MgPSBfaW50ZXJvcFJlcXVpcmVXaWxkY2FyZChfdXRpbHNKcyk7XG5cdFxuXHRIaWdobGlnaHRlci5wcm9wVHlwZXMgPSB7XG5cdCAgaGlnaGxpZ2h0Q2xhc3NOYW1lOiBfcmVhY3QuUHJvcFR5cGVzLnN0cmluZyxcblx0ICBoaWdobGlnaHRTdHlsZTogX3JlYWN0LlByb3BUeXBlcy5vYmplY3QsXG5cdCAgc2VhcmNoV29yZHM6IF9yZWFjdC5Qcm9wVHlwZXMuYXJyYXlPZihfcmVhY3QuUHJvcFR5cGVzLnN0cmluZykuaXNSZXF1aXJlZCxcblx0ICB0ZXh0VG9IaWdobGlnaHQ6IF9yZWFjdC5Qcm9wVHlwZXMuc3RyaW5nLmlzUmVxdWlyZWQsXG5cdCAgc2FuaXRpemU6IF9yZWFjdC5Qcm9wVHlwZXMuZnVuY1xuXHR9O1xuXHRcblx0LyoqXG5cdCAqIEhpZ2hsaWdodHMgYWxsIG9jY3VycmVuY2VzIG9mIHNlYXJjaCB0ZXJtcyAoc2VhcmNoVGV4dCkgd2l0aGluIGEgc3RyaW5nICh0ZXh0VG9IaWdobGlnaHQpLlxuXHQgKiBUaGlzIGZ1bmN0aW9uIHJldHVybnMgYW4gYXJyYXkgb2Ygc3RyaW5ncyBhbmQgPHNwYW4+cyAod3JhcHBpbmcgaGlnaGxpZ2h0ZWQgd29yZHMpLlxuXHQgKi9cblx0XG5cdGZ1bmN0aW9uIEhpZ2hsaWdodGVyKF9yZWYpIHtcblx0ICB2YXIgX3JlZiRoaWdobGlnaHRDbGFzc05hbWUgPSBfcmVmLmhpZ2hsaWdodENsYXNzTmFtZTtcblx0ICB2YXIgaGlnaGxpZ2h0Q2xhc3NOYW1lID0gX3JlZiRoaWdobGlnaHRDbGFzc05hbWUgPT09IHVuZGVmaW5lZCA/ICcnIDogX3JlZiRoaWdobGlnaHRDbGFzc05hbWU7XG5cdCAgdmFyIF9yZWYkaGlnaGxpZ2h0U3R5bGUgPSBfcmVmLmhpZ2hsaWdodFN0eWxlO1xuXHQgIHZhciBoaWdobGlnaHRTdHlsZSA9IF9yZWYkaGlnaGxpZ2h0U3R5bGUgPT09IHVuZGVmaW5lZCA/IHt9IDogX3JlZiRoaWdobGlnaHRTdHlsZTtcblx0ICB2YXIgc2VhcmNoV29yZHMgPSBfcmVmLnNlYXJjaFdvcmRzO1xuXHQgIHZhciB0ZXh0VG9IaWdobGlnaHQgPSBfcmVmLnRleHRUb0hpZ2hsaWdodDtcblx0ICB2YXIgc2FuaXRpemUgPSBfcmVmLnNhbml0aXplO1xuXHRcblx0ICB2YXIgY2h1bmtzID0gQ2h1bmtzLmZpbmRBbGwodGV4dFRvSGlnaGxpZ2h0LCBzZWFyY2hXb3Jkcywgc2FuaXRpemUpO1xuXHRcblx0ICByZXR1cm4gX3JlYWN0MlsnZGVmYXVsdCddLmNyZWF0ZUVsZW1lbnQoXG5cdCAgICAnc3BhbicsXG5cdCAgICBudWxsLFxuXHQgICAgY2h1bmtzLm1hcChmdW5jdGlvbiAoY2h1bmssIGluZGV4KSB7XG5cdCAgICAgIHZhciB0ZXh0ID0gdGV4dFRvSGlnaGxpZ2h0LnN1YnN0cihjaHVuay5zdGFydCwgY2h1bmsuZW5kIC0gY2h1bmsuc3RhcnQpO1xuXHRcblx0ICAgICAgaWYgKGNodW5rLmhpZ2hsaWdodCkge1xuXHQgICAgICAgIHJldHVybiBfcmVhY3QyWydkZWZhdWx0J10uY3JlYXRlRWxlbWVudChcblx0ICAgICAgICAgICdtYXJrJyxcblx0ICAgICAgICAgIHtcblx0ICAgICAgICAgICAgY2xhc3NOYW1lOiBoaWdobGlnaHRDbGFzc05hbWUsXG5cdCAgICAgICAgICAgIGtleTogaW5kZXgsXG5cdCAgICAgICAgICAgIHN0eWxlOiBoaWdobGlnaHRTdHlsZVxuXHQgICAgICAgICAgfSxcblx0ICAgICAgICAgIHRleHRcblx0ICAgICAgICApO1xuXHQgICAgICB9IGVsc2Uge1xuXHQgICAgICAgIHJldHVybiBfcmVhY3QyWydkZWZhdWx0J10uY3JlYXRlRWxlbWVudChcblx0ICAgICAgICAgICdzcGFuJyxcblx0ICAgICAgICAgIHsga2V5OiBpbmRleCB9LFxuXHQgICAgICAgICAgdGV4dFxuXHQgICAgICAgICk7XG5cdCAgICAgIH1cblx0ICAgIH0pXG5cdCAgKTtcblx0fVxuXHRcblx0bW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG5cbi8qKiovIH0sXG4vKiAzICovXG4vKioqLyBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMpIHtcblxuXHRtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoXCJyZWFjdFwiKTtcblxuLyoqKi8gfSxcbi8qIDQgKi9cbi8qKiovIGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cykge1xuXG5cdC8qKlxuXHQgKiBDcmVhdGVzIGFuIGFycmF5IG9mIGNodW5rIG9iamVjdHMgcmVwcmVzZW50aW5nIGJvdGggaGlnbGlnaHRhYmxlIGFuZCBub24gaGlnaGxpZ2h0YWJsZSBwaWVjZXMgb2YgdGV4dCB0aGF0IG1hdGNoIGVhY2ggc2VhcmNoIHdvcmQuXG5cdCAqIEBwYXJhbSBzZWFyY2hXb3JkcyBzdHJpbmdbXVxuXHQgKiBAcGFyYW0gdGV4dFRvU2VhcmNoIHN0cmluZ1xuXHQgKiBAcmV0dXJuIHtzdGFydDpudW1iZXIsIGVuZDpudW1iZXIsIGhpZ2hsaWdodDpib29sZWFufVtdXG5cdCAqL1xuXHQndXNlIHN0cmljdCc7XG5cdFxuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7XG5cdCAgdmFsdWU6IHRydWVcblx0fSk7XG5cdHZhciBmaW5kQWxsID0gZnVuY3Rpb24gZmluZEFsbCh0ZXh0VG9TZWFyY2gsIHdvcmRzVG9GaW5kLCBzYW5pdGl6ZSkge1xuXHQgIHJldHVybiBmaWxsSW5DaHVua3MoY29tYmluZUNodW5rcyhmaW5kQ2h1bmtzKHRleHRUb1NlYXJjaCwgd29yZHNUb0ZpbmQsIHNhbml0aXplKSksIHRleHRUb1NlYXJjaC5sZW5ndGgpO1xuXHR9O1xuXHRcblx0ZXhwb3J0cy5maW5kQWxsID0gZmluZEFsbDtcblx0LyoqXG5cdCAqIFRha2VzIGFuIGFycmF5IG9mIHtzdGFydDpudW1iZXIsIGVuZDpudW1iZXJ9IG9iamVjdHMgYW5kIGNvbWJpbmVzIGNodW5rcyB0aGF0IG92ZXJsYXAgaW50byBzaW5nbGUgY2h1bmtzLlxuXHQgKiBAcGFyYW0gY2h1bmtzIHtzdGFydDpudW1iZXIsIGVuZDpudW1iZXJ9W11cblx0ICogQHJldHVybiB7c3RhcnQ6bnVtYmVyLCBlbmQ6bnVtYmVyfVtdXG5cdCAqL1xuXHR2YXIgY29tYmluZUNodW5rcyA9IGZ1bmN0aW9uIGNvbWJpbmVDaHVua3MoY2h1bmtzKSB7XG5cdCAgY2h1bmtzID0gY2h1bmtzLnNvcnQoZnVuY3Rpb24gKGZpcnN0LCBzZWNvbmQpIHtcblx0ICAgIHJldHVybiBmaXJzdC5zdGFydCAtIHNlY29uZC5zdGFydDtcblx0ICB9KS5yZWR1Y2UoZnVuY3Rpb24gKHByb2Nlc3NlZENodW5rcywgbmV4dENodW5rKSB7XG5cdCAgICAvLyBGaXJzdCBjaHVuayBqdXN0IGdvZXMgc3RyYWlnaHQgaW4gdGhlIGFycmF5Li4uXG5cdCAgICBpZiAocHJvY2Vzc2VkQ2h1bmtzLmxlbmd0aCA9PT0gMCkge1xuXHQgICAgICByZXR1cm4gW25leHRDaHVua107XG5cdCAgICB9IGVsc2Uge1xuXHQgICAgICAvLyAuLi4gc3Vic2VxdWVudCBjaHVua3MgZ2V0IGNoZWNrZWQgdG8gc2VlIGlmIHRoZXkgb3ZlcmxhcC4uLlxuXHQgICAgICB2YXIgcHJldkNodW5rID0gcHJvY2Vzc2VkQ2h1bmtzLnBvcCgpO1xuXHQgICAgICBpZiAobmV4dENodW5rLnN0YXJ0IDw9IHByZXZDaHVuay5lbmQpIHtcblx0ICAgICAgICAvLyBJdCBtYXkgYmUgdGhlIGNhc2UgdGhhdCBwcmV2Q2h1bmsgY29tcGxldGVseSBzdXJyb3VuZHMgbmV4dENodW5rLCBzbyB0YWtlIHRoZVxuXHQgICAgICAgIC8vIGxhcmdlc3Qgb2YgdGhlIGVuZCBpbmRlY2VzLlxuXHQgICAgICAgIHZhciBlbmRJbmRleCA9IE1hdGgubWF4KHByZXZDaHVuay5lbmQsIG5leHRDaHVuay5lbmQpO1xuXHQgICAgICAgIHByb2Nlc3NlZENodW5rcy5wdXNoKHsgc3RhcnQ6IHByZXZDaHVuay5zdGFydCwgZW5kOiBlbmRJbmRleCB9KTtcblx0ICAgICAgfSBlbHNlIHtcblx0ICAgICAgICBwcm9jZXNzZWRDaHVua3MucHVzaChwcmV2Q2h1bmssIG5leHRDaHVuayk7XG5cdCAgICAgIH1cblx0ICAgICAgcmV0dXJuIHByb2Nlc3NlZENodW5rcztcblx0ICAgIH1cblx0ICB9LCBbXSk7XG5cdFxuXHQgIHJldHVybiBjaHVua3M7XG5cdH07XG5cdFxuXHRleHBvcnRzLmNvbWJpbmVDaHVua3MgPSBjb21iaW5lQ2h1bmtzO1xuXHQvKipcblx0ICogRXhhbWluZSB0ZXh0VG9TZWFyY2ggZm9yIGFueSBtYXRjaGVzLlxuXHQgKiBJZiB3ZSBmaW5kIG1hdGNoZXMsIGFkZCB0aGVtIHRvIHRoZSByZXR1cm5lZCBhcnJheSBhcyBhIFwiY2h1bmtcIiBvYmplY3QgKHtzdGFydDpudW1iZXIsIGVuZDpudW1iZXJ9KS5cblx0ICogQHBhcmFtIHRleHRUb1NlYXJjaCBzdHJpbmdcblx0ICogQHBhcmFtIHdvcmRzVG9GaW5kIHN0cmluZ1tdXG5cdCAqIEBwYXJhbSBzYW5pdGl6ZSBQcm9jZXNzIGFuZCBvcHRpb25hbGx5IG1vZGlmeSB0ZXh0VG9TZWFyY2ggYW5kIHdvcmRzVG9GaW5kIGJlZm9yZSBjb21wYXJpc29uOyB0aGlzIGNhbiBiZSB1c2VkIHRvIGVnLiByZW1vdmUgYWNjZW50c1xuXHQgKiBAcmV0dXJuIHtzdGFydDpudW1iZXIsIGVuZDpudW1iZXJ9W11cblx0ICovXG5cdHZhciBmaW5kQ2h1bmtzID0gZnVuY3Rpb24gZmluZENodW5rcyh0ZXh0VG9TZWFyY2gsIHdvcmRzVG9GaW5kKSB7XG5cdCAgdmFyIHNhbml0aXplID0gYXJndW1lbnRzLmxlbmd0aCA8PSAyIHx8IGFyZ3VtZW50c1syXSA9PT0gdW5kZWZpbmVkID8gaWRlbnRpdHkgOiBhcmd1bWVudHNbMl07XG5cdCAgcmV0dXJuIHdvcmRzVG9GaW5kLmZpbHRlcihmdW5jdGlvbiAoc2VhcmNoV29yZCkge1xuXHQgICAgcmV0dXJuIHNlYXJjaFdvcmQ7XG5cdCAgfSkgLy8gUmVtb3ZlIGVtcHR5IHdvcmRzXG5cdCAgLnJlZHVjZShmdW5jdGlvbiAoY2h1bmtzLCBzZWFyY2hXb3JkKSB7XG5cdCAgICB2YXIgbm9ybWFsaXplZFdvcmQgPSBzYW5pdGl6ZShzZWFyY2hXb3JkKTtcblx0ICAgIHZhciBub3JtYWxpemVkVGV4dCA9IHNhbml0aXplKHRleHRUb1NlYXJjaCk7XG5cdCAgICB2YXIgcmVnZXggPSBuZXcgUmVnRXhwKG5vcm1hbGl6ZWRXb3JkLCAnZ2knKTtcblx0ICAgIHZhciBtYXRjaCA9IHVuZGVmaW5lZDtcblx0ICAgIHdoaWxlICgobWF0Y2ggPSByZWdleC5leGVjKG5vcm1hbGl6ZWRUZXh0KSkgIT0gbnVsbCkge1xuXHQgICAgICBjaHVua3MucHVzaCh7IHN0YXJ0OiBtYXRjaC5pbmRleCwgZW5kOiByZWdleC5sYXN0SW5kZXggfSk7XG5cdCAgICB9XG5cdCAgICByZXR1cm4gY2h1bmtzO1xuXHQgIH0sIFtdKTtcblx0fTtcblx0XG5cdGV4cG9ydHMuZmluZENodW5rcyA9IGZpbmRDaHVua3M7XG5cdC8qKlxuXHQgKiBHaXZlbiBhIHNldCBvZiBjaHVua3MgdG8gaGlnaGxpZ2h0LCBjcmVhdGUgYW4gYWRkaXRpb25hbCBzZXQgb2YgY2h1bmtzXG5cdCAqIHRvIHJlcHJlc2VudCB0aGUgYml0cyBvZiB0ZXh0IGJldHdlZW4gdGhlIGhpZ2hsaWdodGVkIHRleHQuXG5cdCAqIEBwYXJhbSBjaHVua3NUb0hpZ2hsaWdodCB7c3RhcnQ6bnVtYmVyLCBlbmQ6bnVtYmVyfVtdXG5cdCAqIEBwYXJhbSB0b3RhbExlbmd0aCBudW1iZXJcblx0ICogQHJldHVybiB7c3RhcnQ6bnVtYmVyLCBlbmQ6bnVtYmVyLCBoaWdobGlnaHQ6Ym9vbGVhbn1bXVxuXHQgKi9cblx0dmFyIGZpbGxJbkNodW5rcyA9IGZ1bmN0aW9uIGZpbGxJbkNodW5rcyhjaHVua3NUb0hpZ2hsaWdodCwgdG90YWxMZW5ndGgpIHtcblx0ICB2YXIgYWxsQ2h1bmtzID0gW107XG5cdCAgdmFyIGFwcGVuZCA9IGZ1bmN0aW9uIGFwcGVuZChzdGFydCwgZW5kLCBoaWdobGlnaHQpIHtcblx0ICAgIGlmIChlbmQgLSBzdGFydCA+IDApIHtcblx0ICAgICAgYWxsQ2h1bmtzLnB1c2goeyBzdGFydDogc3RhcnQsIGVuZDogZW5kLCBoaWdobGlnaHQ6IGhpZ2hsaWdodCB9KTtcblx0ICAgIH1cblx0ICB9O1xuXHRcblx0ICBpZiAoY2h1bmtzVG9IaWdobGlnaHQubGVuZ3RoID09PSAwKSB7XG5cdCAgICBhcHBlbmQoMCwgdG90YWxMZW5ndGgsIGZhbHNlKTtcblx0ICB9IGVsc2Uge1xuXHQgICAgKGZ1bmN0aW9uICgpIHtcblx0ICAgICAgdmFyIGxhc3RJbmRleCA9IDA7XG5cdCAgICAgIGNodW5rc1RvSGlnaGxpZ2h0LmZvckVhY2goZnVuY3Rpb24gKGNodW5rKSB7XG5cdCAgICAgICAgYXBwZW5kKGxhc3RJbmRleCwgY2h1bmsuc3RhcnQsIGZhbHNlKTtcblx0ICAgICAgICBhcHBlbmQoY2h1bmsuc3RhcnQsIGNodW5rLmVuZCwgdHJ1ZSk7XG5cdCAgICAgICAgbGFzdEluZGV4ID0gY2h1bmsuZW5kO1xuXHQgICAgICB9KTtcblx0ICAgICAgYXBwZW5kKGxhc3RJbmRleCwgdG90YWxMZW5ndGgsIGZhbHNlKTtcblx0ICAgIH0pKCk7XG5cdCAgfVxuXHQgIHJldHVybiBhbGxDaHVua3M7XG5cdH07XG5cdFxuXHRleHBvcnRzLmZpbGxJbkNodW5rcyA9IGZpbGxJbkNodW5rcztcblx0ZnVuY3Rpb24gaWRlbnRpdHkodmFsdWUpIHtcblx0ICByZXR1cm4gdmFsdWU7XG5cdH1cblxuLyoqKi8gfVxuLyoqKioqKi8gXSk7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1tYWluLmpzLm1hcCIsIid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9leHRlbmRzID0gT2JqZWN0LmFzc2lnbiB8fCBmdW5jdGlvbiAodGFyZ2V0KSB7IGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7IHZhciBzb3VyY2UgPSBhcmd1bWVudHNbaV07IGZvciAodmFyIGtleSBpbiBzb3VyY2UpIHsgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzb3VyY2UsIGtleSkpIHsgdGFyZ2V0W2tleV0gPSBzb3VyY2Vba2V5XTsgfSB9IH0gcmV0dXJuIHRhcmdldDsgfTtcblxudmFyIF9jcmVhdGVDbGFzcyA9IGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmIChcInZhbHVlXCIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0oKTtcblxudmFyIF9yZWFjdCA9IHJlcXVpcmUoJ3JlYWN0Jyk7XG5cbnZhciBfcmVhY3QyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfcmVhY3QpO1xuXG52YXIgX3JlYWN0U2VsZWN0ID0gcmVxdWlyZSgncmVhY3Qtc2VsZWN0Jyk7XG5cbnZhciBfcmVhY3RTZWxlY3QyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfcmVhY3RTZWxlY3QpO1xuXG52YXIgX3JlYWN0VmlydHVhbGl6ZWQgPSByZXF1aXJlKCdyZWFjdC12aXJ0dWFsaXplZCcpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyBkZWZhdWx0OiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb25cIik7IH0gfVxuXG5mdW5jdGlvbiBfcG9zc2libGVDb25zdHJ1Y3RvclJldHVybihzZWxmLCBjYWxsKSB7IGlmICghc2VsZikgeyB0aHJvdyBuZXcgUmVmZXJlbmNlRXJyb3IoXCJ0aGlzIGhhc24ndCBiZWVuIGluaXRpYWxpc2VkIC0gc3VwZXIoKSBoYXNuJ3QgYmVlbiBjYWxsZWRcIik7IH0gcmV0dXJuIGNhbGwgJiYgKHR5cGVvZiBjYWxsID09PSBcIm9iamVjdFwiIHx8IHR5cGVvZiBjYWxsID09PSBcImZ1bmN0aW9uXCIpID8gY2FsbCA6IHNlbGY7IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gXCJmdW5jdGlvblwiICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgXCIgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIE9iamVjdC5zZXRQcm90b3R5cGVPZiA/IE9iamVjdC5zZXRQcm90b3R5cGVPZihzdWJDbGFzcywgc3VwZXJDbGFzcykgOiBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBWaXJ0dWFsaXplZFNlbGVjdCA9IGZ1bmN0aW9uIChfQ29tcG9uZW50KSB7XG4gIF9pbmhlcml0cyhWaXJ0dWFsaXplZFNlbGVjdCwgX0NvbXBvbmVudCk7XG5cbiAgZnVuY3Rpb24gVmlydHVhbGl6ZWRTZWxlY3QocHJvcHMsIGNvbnRleHQpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgVmlydHVhbGl6ZWRTZWxlY3QpO1xuXG4gICAgdmFyIF90aGlzID0gX3Bvc3NpYmxlQ29uc3RydWN0b3JSZXR1cm4odGhpcywgT2JqZWN0LmdldFByb3RvdHlwZU9mKFZpcnR1YWxpemVkU2VsZWN0KS5jYWxsKHRoaXMsIHByb3BzLCBjb250ZXh0KSk7XG5cbiAgICBfdGhpcy5fcmVuZGVyTWVudSA9IF90aGlzLl9yZW5kZXJNZW51LmJpbmQoX3RoaXMpO1xuICAgIF90aGlzLl9vcHRpb25SZW5kZXJlciA9IF90aGlzLl9vcHRpb25SZW5kZXJlci5iaW5kKF90aGlzKTtcbiAgICByZXR1cm4gX3RoaXM7XG4gIH1cblxuICAvKiogU2VlIFZpcnR1YWxTY3JvbGwjcmVjb21wdXRlUm93SGVpZ2h0cyAqL1xuXG5cbiAgX2NyZWF0ZUNsYXNzKFZpcnR1YWxpemVkU2VsZWN0LCBbe1xuICAgIGtleTogJ3JlY29tcHV0ZU9wdGlvbkhlaWdodHMnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiByZWNvbXB1dGVPcHRpb25IZWlnaHRzKCkge1xuICAgICAgdmFyIGluZGV4ID0gYXJndW1lbnRzLmxlbmd0aCA8PSAwIHx8IGFyZ3VtZW50c1swXSA9PT0gdW5kZWZpbmVkID8gMCA6IGFyZ3VtZW50c1swXTtcblxuICAgICAgaWYgKHRoaXMuX3ZpcnR1YWxTY3JvbGwpIHtcbiAgICAgICAgdGhpcy5fdmlydHVhbFNjcm9sbC5yZWNvbXB1dGVSb3dIZWlnaHRzKGluZGV4KTtcbiAgICAgIH1cbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdyZW5kZXInLFxuICAgIHZhbHVlOiBmdW5jdGlvbiByZW5kZXIoKSB7XG4gICAgICB2YXIgU2VsZWN0Q29tcG9uZW50ID0gdGhpcy5fZ2V0U2VsZWN0Q29tcG9uZW50KCk7XG5cbiAgICAgIHJldHVybiBfcmVhY3QyLmRlZmF1bHQuY3JlYXRlRWxlbWVudChTZWxlY3RDb21wb25lbnQsIF9leHRlbmRzKHt9LCB0aGlzLnByb3BzLCB7XG4gICAgICAgIG1lbnVSZW5kZXJlcjogdGhpcy5fcmVuZGVyTWVudSxcbiAgICAgICAgbWVudVN0eWxlOiB7IG92ZXJmbG93OiAnaGlkZGVuJyB9XG4gICAgICB9KSk7XG4gICAgfVxuXG4gICAgLy8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9KZWRXYXRzb24vcmVhY3Qtc2VsZWN0LyNlZmZlY2llbnRseS1yZW5kZXJpbmctbGFyZ2UtbGlzdHMtd2l0aC13aW5kb3dpbmdcblxuICB9LCB7XG4gICAga2V5OiAnX3JlbmRlck1lbnUnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBfcmVuZGVyTWVudShfcmVmKSB7XG4gICAgICB2YXIgX3RoaXMyID0gdGhpcztcblxuICAgICAgdmFyIGZvY3VzZWRPcHRpb24gPSBfcmVmLmZvY3VzZWRPcHRpb247XG4gICAgICB2YXIgZm9jdXNPcHRpb24gPSBfcmVmLmZvY3VzT3B0aW9uO1xuICAgICAgdmFyIGxhYmVsS2V5ID0gX3JlZi5sYWJlbEtleTtcbiAgICAgIHZhciBvcHRpb25zID0gX3JlZi5vcHRpb25zO1xuICAgICAgdmFyIHNlbGVjdFZhbHVlID0gX3JlZi5zZWxlY3RWYWx1ZTtcbiAgICAgIHZhciB2YWx1ZUFycmF5ID0gX3JlZi52YWx1ZUFycmF5O1xuICAgICAgdmFyIG9wdGlvblJlbmRlcmVyID0gdGhpcy5wcm9wcy5vcHRpb25SZW5kZXJlcjtcblxuICAgICAgdmFyIGZvY3VzZWRPcHRpb25JbmRleCA9IG9wdGlvbnMuaW5kZXhPZihmb2N1c2VkT3B0aW9uKTtcbiAgICAgIHZhciBoZWlnaHQgPSB0aGlzLl9jYWxjdWxhdGVWaXJ0dWFsU2Nyb2xsSGVpZ2h0KHsgb3B0aW9uczogb3B0aW9ucyB9KTtcbiAgICAgIHZhciBpbm5lclJvd1JlbmRlcmVyID0gb3B0aW9uUmVuZGVyZXIgfHwgdGhpcy5fb3B0aW9uUmVuZGVyZXI7XG5cbiAgICAgIGZ1bmN0aW9uIHdyYXBwZWRSb3dSZW5kZXJlcihfcmVmMikge1xuICAgICAgICB2YXIgaW5kZXggPSBfcmVmMi5pbmRleDtcblxuICAgICAgICB2YXIgb3B0aW9uID0gb3B0aW9uc1tpbmRleF07XG5cbiAgICAgICAgcmV0dXJuIGlubmVyUm93UmVuZGVyZXIoe1xuICAgICAgICAgIGZvY3VzZWRPcHRpb246IGZvY3VzZWRPcHRpb24sXG4gICAgICAgICAgZm9jdXNlZE9wdGlvbkluZGV4OiBmb2N1c2VkT3B0aW9uSW5kZXgsXG4gICAgICAgICAgZm9jdXNPcHRpb246IGZvY3VzT3B0aW9uLFxuICAgICAgICAgIGxhYmVsS2V5OiBsYWJlbEtleSxcbiAgICAgICAgICBvcHRpb246IG9wdGlvbixcbiAgICAgICAgICBvcHRpb25JbmRleDogaW5kZXgsXG4gICAgICAgICAgb3B0aW9uczogb3B0aW9ucyxcbiAgICAgICAgICBzZWxlY3RWYWx1ZTogc2VsZWN0VmFsdWUsXG4gICAgICAgICAgdmFsdWVBcnJheTogdmFsdWVBcnJheVxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIF9yZWFjdDIuZGVmYXVsdC5jcmVhdGVFbGVtZW50KFxuICAgICAgICBfcmVhY3RWaXJ0dWFsaXplZC5BdXRvU2l6ZXIsXG4gICAgICAgIHsgZGlzYWJsZUhlaWdodDogdHJ1ZSB9LFxuICAgICAgICBmdW5jdGlvbiAoX3JlZjMpIHtcbiAgICAgICAgICB2YXIgd2lkdGggPSBfcmVmMy53aWR0aDtcbiAgICAgICAgICByZXR1cm4gX3JlYWN0Mi5kZWZhdWx0LmNyZWF0ZUVsZW1lbnQoX3JlYWN0VmlydHVhbGl6ZWQuVmlydHVhbFNjcm9sbCwge1xuICAgICAgICAgICAgY2xhc3NOYW1lOiAnVmlydHVhbFNlbGVjdEdyaWQnLFxuICAgICAgICAgICAgaGVpZ2h0OiBoZWlnaHQsXG4gICAgICAgICAgICByZWY6IGZ1bmN0aW9uIHJlZihfcmVmNSkge1xuICAgICAgICAgICAgICByZXR1cm4gX3RoaXMyLl92aXJ0dWFsU2Nyb2xsID0gX3JlZjU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcm93Q291bnQ6IG9wdGlvbnMubGVuZ3RoLFxuICAgICAgICAgICAgcm93SGVpZ2h0OiBmdW5jdGlvbiByb3dIZWlnaHQoX3JlZjQpIHtcbiAgICAgICAgICAgICAgdmFyIGluZGV4ID0gX3JlZjQuaW5kZXg7XG4gICAgICAgICAgICAgIHJldHVybiBfdGhpczIuX2dldE9wdGlvbkhlaWdodCh7XG4gICAgICAgICAgICAgICAgb3B0aW9uOiBvcHRpb25zW2luZGV4XVxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICByb3dSZW5kZXJlcjogd3JhcHBlZFJvd1JlbmRlcmVyLFxuICAgICAgICAgICAgc2Nyb2xsVG9JbmRleDogZm9jdXNlZE9wdGlvbkluZGV4LFxuICAgICAgICAgICAgd2lkdGg6IHdpZHRoXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX2NhbGN1bGF0ZVZpcnR1YWxTY3JvbGxIZWlnaHQnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBfY2FsY3VsYXRlVmlydHVhbFNjcm9sbEhlaWdodChfcmVmNikge1xuICAgICAgdmFyIG9wdGlvbnMgPSBfcmVmNi5vcHRpb25zO1xuICAgICAgdmFyIG1heEhlaWdodCA9IHRoaXMucHJvcHMubWF4SGVpZ2h0O1xuXG5cbiAgICAgIHZhciBoZWlnaHQgPSAwO1xuXG4gICAgICBmb3IgKHZhciBvcHRpb25JbmRleCA9IDA7IG9wdGlvbkluZGV4IDwgb3B0aW9ucy5sZW5ndGg7IG9wdGlvbkluZGV4KyspIHtcbiAgICAgICAgdmFyIG9wdGlvbiA9IG9wdGlvbnNbb3B0aW9uSW5kZXhdO1xuXG4gICAgICAgIGhlaWdodCArPSB0aGlzLl9nZXRPcHRpb25IZWlnaHQoeyBvcHRpb246IG9wdGlvbiB9KTtcblxuICAgICAgICBpZiAoaGVpZ2h0ID4gbWF4SGVpZ2h0KSB7XG4gICAgICAgICAgcmV0dXJuIG1heEhlaWdodDtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gaGVpZ2h0O1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19nZXRPcHRpb25IZWlnaHQnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBfZ2V0T3B0aW9uSGVpZ2h0KF9yZWY3KSB7XG4gICAgICB2YXIgb3B0aW9uID0gX3JlZjcub3B0aW9uO1xuICAgICAgdmFyIG9wdGlvbkhlaWdodCA9IHRoaXMucHJvcHMub3B0aW9uSGVpZ2h0O1xuXG5cbiAgICAgIHJldHVybiBvcHRpb25IZWlnaHQgaW5zdGFuY2VvZiBGdW5jdGlvbiA/IG9wdGlvbkhlaWdodCh7IG9wdGlvbjogb3B0aW9uIH0pIDogb3B0aW9uSGVpZ2h0O1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19nZXRTZWxlY3RDb21wb25lbnQnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBfZ2V0U2VsZWN0Q29tcG9uZW50KCkge1xuICAgICAgdmFyIF9wcm9wcyA9IHRoaXMucHJvcHM7XG4gICAgICB2YXIgYXN5bmMgPSBfcHJvcHMuYXN5bmM7XG4gICAgICB2YXIgc2VsZWN0Q29tcG9uZW50ID0gX3Byb3BzLnNlbGVjdENvbXBvbmVudDtcblxuXG4gICAgICBpZiAoc2VsZWN0Q29tcG9uZW50KSB7XG4gICAgICAgIHJldHVybiBzZWxlY3RDb21wb25lbnQ7XG4gICAgICB9IGVsc2UgaWYgKGFzeW5jKSB7XG4gICAgICAgIHJldHVybiBfcmVhY3RTZWxlY3QyLmRlZmF1bHQuQXN5bmM7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gX3JlYWN0U2VsZWN0Mi5kZWZhdWx0O1xuICAgICAgfVxuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vcHRpb25SZW5kZXJlcicsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vcHRpb25SZW5kZXJlcihfcmVmOCkge1xuICAgICAgdmFyIGZvY3VzZWRPcHRpb24gPSBfcmVmOC5mb2N1c2VkT3B0aW9uO1xuICAgICAgdmFyIGZvY3VzT3B0aW9uID0gX3JlZjguZm9jdXNPcHRpb247XG4gICAgICB2YXIgbGFiZWxLZXkgPSBfcmVmOC5sYWJlbEtleTtcbiAgICAgIHZhciBvcHRpb24gPSBfcmVmOC5vcHRpb247XG4gICAgICB2YXIgc2VsZWN0VmFsdWUgPSBfcmVmOC5zZWxlY3RWYWx1ZTtcblxuICAgICAgdmFyIGhlaWdodCA9IHRoaXMuX2dldE9wdGlvbkhlaWdodCh7IG9wdGlvbjogb3B0aW9uIH0pO1xuXG4gICAgICB2YXIgY2xhc3NOYW1lID0gWydWaXJ0dWFsaXplZFNlbGVjdE9wdGlvbiddO1xuXG4gICAgICBpZiAob3B0aW9uID09PSBmb2N1c2VkT3B0aW9uKSB7XG4gICAgICAgIGNsYXNzTmFtZS5wdXNoKCdWaXJ0dWFsaXplZFNlbGVjdEZvY3VzZWRPcHRpb24nKTtcbiAgICAgIH1cblxuICAgICAgaWYgKG9wdGlvbi5kaXNhYmxlZCkge1xuICAgICAgICBjbGFzc05hbWUucHVzaCgnVmlydHVhbGl6ZWRTZWxlY3REaXNhYmxlZE9wdGlvbicpO1xuICAgICAgfVxuXG4gICAgICB2YXIgZXZlbnRzID0gb3B0aW9uLmRpc2FibGVkID8ge30gOiB7XG4gICAgICAgIG9uQ2xpY2s6IGZ1bmN0aW9uIG9uQ2xpY2soKSB7XG4gICAgICAgICAgcmV0dXJuIHNlbGVjdFZhbHVlKG9wdGlvbik7XG4gICAgICAgIH0sXG4gICAgICAgIG9uTW91c2VPdmVyOiBmdW5jdGlvbiBvbk1vdXNlT3ZlcigpIHtcbiAgICAgICAgICByZXR1cm4gZm9jdXNPcHRpb24ob3B0aW9uKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgcmV0dXJuIF9yZWFjdDIuZGVmYXVsdC5jcmVhdGVFbGVtZW50KFxuICAgICAgICAnZGl2JyxcbiAgICAgICAgX2V4dGVuZHMoe1xuICAgICAgICAgIGNsYXNzTmFtZTogY2xhc3NOYW1lLmpvaW4oJyAnKSxcbiAgICAgICAgICBzdHlsZTogeyBoZWlnaHQ6IGhlaWdodCB9XG4gICAgICAgIH0sIGV2ZW50cyksXG4gICAgICAgIG9wdGlvbltsYWJlbEtleV1cbiAgICAgICk7XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIFZpcnR1YWxpemVkU2VsZWN0O1xufShfcmVhY3QuQ29tcG9uZW50KTtcblxuVmlydHVhbGl6ZWRTZWxlY3QucHJvcFR5cGVzID0ge1xuICBhc3luYzogX3JlYWN0LlByb3BUeXBlcy5ib29sLFxuICBtYXhIZWlnaHQ6IF9yZWFjdC5Qcm9wVHlwZXMubnVtYmVyLmlzUmVxdWlyZWQsXG4gIG9wdGlvbkhlaWdodDogX3JlYWN0LlByb3BUeXBlcy5vbmVPZlR5cGUoW19yZWFjdC5Qcm9wVHlwZXMubnVtYmVyLCBfcmVhY3QuUHJvcFR5cGVzLmZ1bmNdKS5pc1JlcXVpcmVkLFxuICBvcHRpb25SZW5kZXJlcjogX3JlYWN0LlByb3BUeXBlcy5mdW5jLFxuICBzZWxlY3RDb21wb25lbnQ6IF9yZWFjdC5Qcm9wVHlwZXMuZnVuY1xufTtcblZpcnR1YWxpemVkU2VsZWN0LmRlZmF1bHRQcm9wcyA9IHtcbiAgYXN5bmM6IGZhbHNlLFxuICBtYXhIZWlnaHQ6IDIwMCxcbiAgb3B0aW9uSGVpZ2h0OiAzNVxufTtcbmV4cG9ydHMuZGVmYXVsdCA9IFZpcnR1YWxpemVkU2VsZWN0OyIsIid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcbmV4cG9ydHMuZGVmYXVsdCA9IHVuZGVmaW5lZDtcblxudmFyIF9WaXJ0dWFsaXplZFNlbGVjdCA9IHJlcXVpcmUoJy4vVmlydHVhbGl6ZWRTZWxlY3QnKTtcblxudmFyIF9WaXJ0dWFsaXplZFNlbGVjdDIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9WaXJ0dWFsaXplZFNlbGVjdCk7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7IGRlZmF1bHQ6IG9iaiB9OyB9XG5cbmV4cG9ydHMuZGVmYXVsdCA9IF9WaXJ0dWFsaXplZFNlbGVjdDIuZGVmYXVsdDsiLCIndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSBmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoXCJ2YWx1ZVwiIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KCk7XG5cbnZhciBfcmVhY3QgPSByZXF1aXJlKCdyZWFjdCcpO1xuXG52YXIgX3JlYWN0MiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3JlYWN0KTtcblxudmFyIF9yZWFjdEFkZG9uc1NoYWxsb3dDb21wYXJlID0gcmVxdWlyZSgncmVhY3QtYWRkb25zLXNoYWxsb3ctY29tcGFyZScpO1xuXG52YXIgX3JlYWN0QWRkb25zU2hhbGxvd0NvbXBhcmUyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfcmVhY3RBZGRvbnNTaGFsbG93Q29tcGFyZSk7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7IGRlZmF1bHQ6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvblwiKTsgfSB9XG5cbmZ1bmN0aW9uIF9wb3NzaWJsZUNvbnN0cnVjdG9yUmV0dXJuKHNlbGYsIGNhbGwpIHsgaWYgKCFzZWxmKSB7IHRocm93IG5ldyBSZWZlcmVuY2VFcnJvcihcInRoaXMgaGFzbid0IGJlZW4gaW5pdGlhbGlzZWQgLSBzdXBlcigpIGhhc24ndCBiZWVuIGNhbGxlZFwiKTsgfSByZXR1cm4gY2FsbCAmJiAodHlwZW9mIGNhbGwgPT09IFwib2JqZWN0XCIgfHwgdHlwZW9mIGNhbGwgPT09IFwiZnVuY3Rpb25cIikgPyBjYWxsIDogc2VsZjsgfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSBcImZ1bmN0aW9uXCIgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCBcIiArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgT2JqZWN0LnNldFByb3RvdHlwZU9mID8gT2JqZWN0LnNldFByb3RvdHlwZU9mKHN1YkNsYXNzLCBzdXBlckNsYXNzKSA6IHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxuLyoqXG4gKiBUaGlzIEhPQyBkZWNvcmF0ZXMgYSB2aXJ0dWFsaXplZCBjb21wb25lbnQgYW5kIHJlc3BvbmRzIHRvIGFycm93LWtleSBldmVudHMgYnkgc2Nyb2xsaW5nIG9uZSByb3cgb3IgY29sdW1uIGF0IGEgdGltZS5cbiAqL1xudmFyIEFycm93S2V5U3RlcHBlciA9IGZ1bmN0aW9uIChfQ29tcG9uZW50KSB7XG4gIF9pbmhlcml0cyhBcnJvd0tleVN0ZXBwZXIsIF9Db21wb25lbnQpO1xuXG4gIGZ1bmN0aW9uIEFycm93S2V5U3RlcHBlcihwcm9wcywgY29udGV4dCkge1xuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBBcnJvd0tleVN0ZXBwZXIpO1xuXG4gICAgdmFyIF90aGlzID0gX3Bvc3NpYmxlQ29uc3RydWN0b3JSZXR1cm4odGhpcywgKEFycm93S2V5U3RlcHBlci5fX3Byb3RvX18gfHwgT2JqZWN0LmdldFByb3RvdHlwZU9mKEFycm93S2V5U3RlcHBlcikpLmNhbGwodGhpcywgcHJvcHMsIGNvbnRleHQpKTtcblxuICAgIF90aGlzLnN0YXRlID0ge1xuICAgICAgc2Nyb2xsVG9Db2x1bW46IDAsXG4gICAgICBzY3JvbGxUb1JvdzogMFxuICAgIH07XG5cbiAgICBfdGhpcy5fY29sdW1uU3RhcnRJbmRleCA9IDA7XG4gICAgX3RoaXMuX2NvbHVtblN0b3BJbmRleCA9IDA7XG4gICAgX3RoaXMuX3Jvd1N0YXJ0SW5kZXggPSAwO1xuICAgIF90aGlzLl9yb3dTdG9wSW5kZXggPSAwO1xuXG4gICAgX3RoaXMuX29uS2V5RG93biA9IF90aGlzLl9vbktleURvd24uYmluZChfdGhpcyk7XG4gICAgX3RoaXMuX29uU2VjdGlvblJlbmRlcmVkID0gX3RoaXMuX29uU2VjdGlvblJlbmRlcmVkLmJpbmQoX3RoaXMpO1xuICAgIHJldHVybiBfdGhpcztcbiAgfVxuXG4gIF9jcmVhdGVDbGFzcyhBcnJvd0tleVN0ZXBwZXIsIFt7XG4gICAga2V5OiAncmVuZGVyJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVuZGVyKCkge1xuICAgICAgdmFyIF9wcm9wcyA9IHRoaXMucHJvcHM7XG4gICAgICB2YXIgY2xhc3NOYW1lID0gX3Byb3BzLmNsYXNzTmFtZTtcbiAgICAgIHZhciBjaGlsZHJlbiA9IF9wcm9wcy5jaGlsZHJlbjtcbiAgICAgIHZhciBfc3RhdGUgPSB0aGlzLnN0YXRlO1xuICAgICAgdmFyIHNjcm9sbFRvQ29sdW1uID0gX3N0YXRlLnNjcm9sbFRvQ29sdW1uO1xuICAgICAgdmFyIHNjcm9sbFRvUm93ID0gX3N0YXRlLnNjcm9sbFRvUm93O1xuXG5cbiAgICAgIHJldHVybiBfcmVhY3QyLmRlZmF1bHQuY3JlYXRlRWxlbWVudChcbiAgICAgICAgJ2RpdicsXG4gICAgICAgIHtcbiAgICAgICAgICBjbGFzc05hbWU6IGNsYXNzTmFtZSxcbiAgICAgICAgICBvbktleURvd246IHRoaXMuX29uS2V5RG93blxuICAgICAgICB9LFxuICAgICAgICBjaGlsZHJlbih7XG4gICAgICAgICAgb25TZWN0aW9uUmVuZGVyZWQ6IHRoaXMuX29uU2VjdGlvblJlbmRlcmVkLFxuICAgICAgICAgIHNjcm9sbFRvQ29sdW1uOiBzY3JvbGxUb0NvbHVtbixcbiAgICAgICAgICBzY3JvbGxUb1Jvdzogc2Nyb2xsVG9Sb3dcbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnc2hvdWxkQ29tcG9uZW50VXBkYXRlJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gc2hvdWxkQ29tcG9uZW50VXBkYXRlKG5leHRQcm9wcywgbmV4dFN0YXRlKSB7XG4gICAgICByZXR1cm4gKDAsIF9yZWFjdEFkZG9uc1NoYWxsb3dDb21wYXJlMi5kZWZhdWx0KSh0aGlzLCBuZXh0UHJvcHMsIG5leHRTdGF0ZSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uS2V5RG93bicsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vbktleURvd24oZXZlbnQpIHtcbiAgICAgIHZhciBfcHJvcHMyID0gdGhpcy5wcm9wcztcbiAgICAgIHZhciBjb2x1bW5Db3VudCA9IF9wcm9wczIuY29sdW1uQ291bnQ7XG4gICAgICB2YXIgcm93Q291bnQgPSBfcHJvcHMyLnJvd0NvdW50O1xuXG4gICAgICAvLyBUaGUgYWJvdmUgY2FzZXMgYWxsIHByZXZlbnQgZGVmYXVsdCBldmVudCBldmVudCBiZWhhdmlvci5cbiAgICAgIC8vIFRoaXMgaXMgdG8ga2VlcCB0aGUgZ3JpZCBmcm9tIHNjcm9sbGluZyBhZnRlciB0aGUgc25hcC10byB1cGRhdGUuXG5cbiAgICAgIHN3aXRjaCAoZXZlbnQua2V5KSB7XG4gICAgICAgIGNhc2UgJ0Fycm93RG93bic6XG4gICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgIHNjcm9sbFRvUm93OiBNYXRoLm1pbih0aGlzLl9yb3dTdG9wSW5kZXggKyAxLCByb3dDb3VudCAtIDEpXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ0Fycm93TGVmdCc6XG4gICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgIHNjcm9sbFRvQ29sdW1uOiBNYXRoLm1heCh0aGlzLl9jb2x1bW5TdGFydEluZGV4IC0gMSwgMClcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnQXJyb3dSaWdodCc6XG4gICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgIHNjcm9sbFRvQ29sdW1uOiBNYXRoLm1pbih0aGlzLl9jb2x1bW5TdG9wSW5kZXggKyAxLCBjb2x1bW5Db3VudCAtIDEpXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ0Fycm93VXAnOlxuICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBzY3JvbGxUb1JvdzogTWF0aC5tYXgodGhpcy5fcm93U3RhcnRJbmRleCAtIDEsIDApXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uU2VjdGlvblJlbmRlcmVkJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uU2VjdGlvblJlbmRlcmVkKF9yZWYpIHtcbiAgICAgIHZhciBjb2x1bW5TdGFydEluZGV4ID0gX3JlZi5jb2x1bW5TdGFydEluZGV4O1xuICAgICAgdmFyIGNvbHVtblN0b3BJbmRleCA9IF9yZWYuY29sdW1uU3RvcEluZGV4O1xuICAgICAgdmFyIHJvd1N0YXJ0SW5kZXggPSBfcmVmLnJvd1N0YXJ0SW5kZXg7XG4gICAgICB2YXIgcm93U3RvcEluZGV4ID0gX3JlZi5yb3dTdG9wSW5kZXg7XG5cbiAgICAgIHRoaXMuX2NvbHVtblN0YXJ0SW5kZXggPSBjb2x1bW5TdGFydEluZGV4O1xuICAgICAgdGhpcy5fY29sdW1uU3RvcEluZGV4ID0gY29sdW1uU3RvcEluZGV4O1xuICAgICAgdGhpcy5fcm93U3RhcnRJbmRleCA9IHJvd1N0YXJ0SW5kZXg7XG4gICAgICB0aGlzLl9yb3dTdG9wSW5kZXggPSByb3dTdG9wSW5kZXg7XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIEFycm93S2V5U3RlcHBlcjtcbn0oX3JlYWN0LkNvbXBvbmVudCk7XG5cbkFycm93S2V5U3RlcHBlci5wcm9wVHlwZXMgPSB7XG4gIGNoaWxkcmVuOiBfcmVhY3QuUHJvcFR5cGVzLmZ1bmMuaXNSZXF1aXJlZCxcbiAgY2xhc3NOYW1lOiBfcmVhY3QuUHJvcFR5cGVzLnN0cmluZyxcbiAgY29sdW1uQ291bnQ6IF9yZWFjdC5Qcm9wVHlwZXMubnVtYmVyLmlzUmVxdWlyZWQsXG4gIHJvd0NvdW50OiBfcmVhY3QuUHJvcFR5cGVzLm51bWJlci5pc1JlcXVpcmVkXG59O1xuZXhwb3J0cy5kZWZhdWx0ID0gQXJyb3dLZXlTdGVwcGVyOyIsIid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcbmV4cG9ydHMuQXJyb3dLZXlTdGVwcGVyID0gZXhwb3J0cy5kZWZhdWx0ID0gdW5kZWZpbmVkO1xuXG52YXIgX0Fycm93S2V5U3RlcHBlcjIgPSByZXF1aXJlKCcuL0Fycm93S2V5U3RlcHBlcicpO1xuXG52YXIgX0Fycm93S2V5U3RlcHBlcjMgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9BcnJvd0tleVN0ZXBwZXIyKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgZGVmYXVsdDogb2JqIH07IH1cblxuZXhwb3J0cy5kZWZhdWx0ID0gX0Fycm93S2V5U3RlcHBlcjMuZGVmYXVsdDtcbmV4cG9ydHMuQXJyb3dLZXlTdGVwcGVyID0gX0Fycm93S2V5U3RlcHBlcjMuZGVmYXVsdDsiLCIndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSBmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoXCJ2YWx1ZVwiIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KCk7XG5cbnZhciBfcmVhY3QgPSByZXF1aXJlKCdyZWFjdCcpO1xuXG52YXIgX3JlYWN0MiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3JlYWN0KTtcblxudmFyIF9yZWFjdEFkZG9uc1NoYWxsb3dDb21wYXJlID0gcmVxdWlyZSgncmVhY3QtYWRkb25zLXNoYWxsb3ctY29tcGFyZScpO1xuXG52YXIgX3JlYWN0QWRkb25zU2hhbGxvd0NvbXBhcmUyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfcmVhY3RBZGRvbnNTaGFsbG93Q29tcGFyZSk7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7IGRlZmF1bHQ6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvblwiKTsgfSB9XG5cbmZ1bmN0aW9uIF9wb3NzaWJsZUNvbnN0cnVjdG9yUmV0dXJuKHNlbGYsIGNhbGwpIHsgaWYgKCFzZWxmKSB7IHRocm93IG5ldyBSZWZlcmVuY2VFcnJvcihcInRoaXMgaGFzbid0IGJlZW4gaW5pdGlhbGlzZWQgLSBzdXBlcigpIGhhc24ndCBiZWVuIGNhbGxlZFwiKTsgfSByZXR1cm4gY2FsbCAmJiAodHlwZW9mIGNhbGwgPT09IFwib2JqZWN0XCIgfHwgdHlwZW9mIGNhbGwgPT09IFwiZnVuY3Rpb25cIikgPyBjYWxsIDogc2VsZjsgfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSBcImZ1bmN0aW9uXCIgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCBcIiArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgT2JqZWN0LnNldFByb3RvdHlwZU9mID8gT2JqZWN0LnNldFByb3RvdHlwZU9mKHN1YkNsYXNzLCBzdXBlckNsYXNzKSA6IHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxuLyoqXG4gKiBEZWNvcmF0b3IgY29tcG9uZW50IHRoYXQgYXV0b21hdGljYWxseSBhZGp1c3RzIHRoZSB3aWR0aCBhbmQgaGVpZ2h0IG9mIGEgc2luZ2xlIGNoaWxkLlxuICogQ2hpbGQgY29tcG9uZW50IHNob3VsZCBub3QgYmUgZGVjbGFyZWQgYXMgYSBjaGlsZCBidXQgc2hvdWxkIHJhdGhlciBiZSBzcGVjaWZpZWQgYnkgYSBgQ2hpbGRDb21wb25lbnRgIHByb3BlcnR5LlxuICogQWxsIG90aGVyIHByb3BlcnRpZXMgd2lsbCBiZSBwYXNzZWQgdGhyb3VnaCB0byB0aGUgY2hpbGQgY29tcG9uZW50LlxuICovXG52YXIgQXV0b1NpemVyID0gZnVuY3Rpb24gKF9Db21wb25lbnQpIHtcbiAgX2luaGVyaXRzKEF1dG9TaXplciwgX0NvbXBvbmVudCk7XG5cbiAgZnVuY3Rpb24gQXV0b1NpemVyKHByb3BzKSB7XG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIEF1dG9TaXplcik7XG5cbiAgICB2YXIgX3RoaXMgPSBfcG9zc2libGVDb25zdHJ1Y3RvclJldHVybih0aGlzLCAoQXV0b1NpemVyLl9fcHJvdG9fXyB8fCBPYmplY3QuZ2V0UHJvdG90eXBlT2YoQXV0b1NpemVyKSkuY2FsbCh0aGlzLCBwcm9wcykpO1xuXG4gICAgX3RoaXMuc3RhdGUgPSB7XG4gICAgICBoZWlnaHQ6IDAsXG4gICAgICB3aWR0aDogMFxuICAgIH07XG5cbiAgICBfdGhpcy5fb25SZXNpemUgPSBfdGhpcy5fb25SZXNpemUuYmluZChfdGhpcyk7XG4gICAgX3RoaXMuX29uU2Nyb2xsID0gX3RoaXMuX29uU2Nyb2xsLmJpbmQoX3RoaXMpO1xuICAgIF90aGlzLl9zZXRSZWYgPSBfdGhpcy5fc2V0UmVmLmJpbmQoX3RoaXMpO1xuICAgIHJldHVybiBfdGhpcztcbiAgfVxuXG4gIF9jcmVhdGVDbGFzcyhBdXRvU2l6ZXIsIFt7XG4gICAga2V5OiAnY29tcG9uZW50RGlkTW91bnQnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBjb21wb25lbnREaWRNb3VudCgpIHtcbiAgICAgIC8vIERlbGF5IGFjY2VzcyBvZiBwYXJlbnROb2RlIHVudGlsIG1vdW50LlxuICAgICAgLy8gVGhpcyBoYW5kbGVzIGVkZ2UtY2FzZXMgd2hlcmUgdGhlIGNvbXBvbmVudCBoYXMgYWxyZWFkeSBiZWVuIHVubW91bnRlZCBiZWZvcmUgaXRzIHJlZiBoYXMgYmVlbiBzZXQsXG4gICAgICAvLyBBcyB3ZWxsIGFzIGxpYnJhcmllcyBsaWtlIHJlYWN0LWxpdGUgd2hpY2ggaGF2ZSBhIHNsaWdodGx5IGRpZmZlcmVudCBsaWZlY3ljbGUuXG4gICAgICB0aGlzLl9wYXJlbnROb2RlID0gdGhpcy5fYXV0b1NpemVyLnBhcmVudE5vZGU7XG5cbiAgICAgIC8vIERlZmVyIHJlcXVpcmluZyByZXNpemUgaGFuZGxlciBpbiBvcmRlciB0byBzdXBwb3J0IHNlcnZlci1zaWRlIHJlbmRlcmluZy5cbiAgICAgIC8vIFNlZSBpc3N1ZSAjNDFcbiAgICAgIHRoaXMuX2RldGVjdEVsZW1lbnRSZXNpemUgPSByZXF1aXJlKCcuLi92ZW5kb3IvZGV0ZWN0RWxlbWVudFJlc2l6ZScpO1xuICAgICAgdGhpcy5fZGV0ZWN0RWxlbWVudFJlc2l6ZS5hZGRSZXNpemVMaXN0ZW5lcih0aGlzLl9wYXJlbnROb2RlLCB0aGlzLl9vblJlc2l6ZSk7XG5cbiAgICAgIHRoaXMuX29uUmVzaXplKCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnY29tcG9uZW50V2lsbFVubW91bnQnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBjb21wb25lbnRXaWxsVW5tb3VudCgpIHtcbiAgICAgIGlmICh0aGlzLl9kZXRlY3RFbGVtZW50UmVzaXplKSB7XG4gICAgICAgIHRoaXMuX2RldGVjdEVsZW1lbnRSZXNpemUucmVtb3ZlUmVzaXplTGlzdGVuZXIodGhpcy5fcGFyZW50Tm9kZSwgdGhpcy5fb25SZXNpemUpO1xuICAgICAgfVxuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ3JlbmRlcicsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJlbmRlcigpIHtcbiAgICAgIHZhciBfcHJvcHMgPSB0aGlzLnByb3BzO1xuICAgICAgdmFyIGNoaWxkcmVuID0gX3Byb3BzLmNoaWxkcmVuO1xuICAgICAgdmFyIGRpc2FibGVIZWlnaHQgPSBfcHJvcHMuZGlzYWJsZUhlaWdodDtcbiAgICAgIHZhciBkaXNhYmxlV2lkdGggPSBfcHJvcHMuZGlzYWJsZVdpZHRoO1xuICAgICAgdmFyIF9zdGF0ZSA9IHRoaXMuc3RhdGU7XG4gICAgICB2YXIgaGVpZ2h0ID0gX3N0YXRlLmhlaWdodDtcbiAgICAgIHZhciB3aWR0aCA9IF9zdGF0ZS53aWR0aDtcblxuICAgICAgLy8gT3V0ZXIgZGl2IHNob3VsZCBub3QgZm9yY2Ugd2lkdGgvaGVpZ2h0IHNpbmNlIHRoYXQgbWF5IHByZXZlbnQgY29udGFpbmVycyBmcm9tIHNocmlua2luZy5cbiAgICAgIC8vIElubmVyIGNvbXBvbmVudCBzaG91bGQgb3ZlcmZsb3cgYW5kIHVzZSBjYWxjdWxhdGVkIHdpZHRoL2hlaWdodC5cbiAgICAgIC8vIFNlZSBpc3N1ZSAjNjggZm9yIG1vcmUgaW5mb3JtYXRpb24uXG5cbiAgICAgIHZhciBvdXRlclN0eWxlID0geyBvdmVyZmxvdzogJ3Zpc2libGUnIH07XG5cbiAgICAgIGlmICghZGlzYWJsZUhlaWdodCkge1xuICAgICAgICBvdXRlclN0eWxlLmhlaWdodCA9IDA7XG4gICAgICB9XG5cbiAgICAgIGlmICghZGlzYWJsZVdpZHRoKSB7XG4gICAgICAgIG91dGVyU3R5bGUud2lkdGggPSAwO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gX3JlYWN0Mi5kZWZhdWx0LmNyZWF0ZUVsZW1lbnQoXG4gICAgICAgICdkaXYnLFxuICAgICAgICB7XG4gICAgICAgICAgcmVmOiB0aGlzLl9zZXRSZWYsXG4gICAgICAgICAgb25TY3JvbGw6IHRoaXMuX29uU2Nyb2xsLFxuICAgICAgICAgIHN0eWxlOiBvdXRlclN0eWxlXG4gICAgICAgIH0sXG4gICAgICAgIGNoaWxkcmVuKHsgaGVpZ2h0OiBoZWlnaHQsIHdpZHRoOiB3aWR0aCB9KVxuICAgICAgKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdzaG91bGRDb21wb25lbnRVcGRhdGUnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBzaG91bGRDb21wb25lbnRVcGRhdGUobmV4dFByb3BzLCBuZXh0U3RhdGUpIHtcbiAgICAgIHJldHVybiAoMCwgX3JlYWN0QWRkb25zU2hhbGxvd0NvbXBhcmUyLmRlZmF1bHQpKHRoaXMsIG5leHRQcm9wcywgbmV4dFN0YXRlKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25SZXNpemUnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBfb25SZXNpemUoKSB7XG4gICAgICB2YXIgb25SZXNpemUgPSB0aGlzLnByb3BzLm9uUmVzaXplO1xuXG4gICAgICAvLyBHYXVyZCBhZ2FpbnN0IEF1dG9TaXplciBjb21wb25lbnQgYmVpbmcgcmVtb3ZlZCBmcm9tIHRoZSBET00gaW1tZWRpYXRlbHkgYWZ0ZXIgYmVpbmcgYWRkZWQuXG4gICAgICAvLyBUaGlzIGNhbiByZXN1bHQgaW4gaW52YWxpZCBzdHlsZSB2YWx1ZXMgd2hpY2ggY2FuIHJlc3VsdCBpbiBOYU4gdmFsdWVzIGlmIHdlIGRvbid0IGhhbmRsZSB0aGVtLlxuICAgICAgLy8gU2VlIGlzc3VlICMxNTAgZm9yIG1vcmUgY29udGV4dC5cblxuICAgICAgdmFyIGJvdW5kaW5nUmVjdCA9IHRoaXMuX3BhcmVudE5vZGUuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICB2YXIgaGVpZ2h0ID0gYm91bmRpbmdSZWN0LmhlaWdodCB8fCAwO1xuICAgICAgdmFyIHdpZHRoID0gYm91bmRpbmdSZWN0LndpZHRoIHx8IDA7XG5cbiAgICAgIHZhciBzdHlsZSA9IGdldENvbXB1dGVkU3R5bGUodGhpcy5fcGFyZW50Tm9kZSk7XG4gICAgICB2YXIgcGFkZGluZ0xlZnQgPSBwYXJzZUludChzdHlsZS5wYWRkaW5nTGVmdCwgMTApIHx8IDA7XG4gICAgICB2YXIgcGFkZGluZ1JpZ2h0ID0gcGFyc2VJbnQoc3R5bGUucGFkZGluZ1JpZ2h0LCAxMCkgfHwgMDtcbiAgICAgIHZhciBwYWRkaW5nVG9wID0gcGFyc2VJbnQoc3R5bGUucGFkZGluZ1RvcCwgMTApIHx8IDA7XG4gICAgICB2YXIgcGFkZGluZ0JvdHRvbSA9IHBhcnNlSW50KHN0eWxlLnBhZGRpbmdCb3R0b20sIDEwKSB8fCAwO1xuXG4gICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgaGVpZ2h0OiBoZWlnaHQgLSBwYWRkaW5nVG9wIC0gcGFkZGluZ0JvdHRvbSxcbiAgICAgICAgd2lkdGg6IHdpZHRoIC0gcGFkZGluZ0xlZnQgLSBwYWRkaW5nUmlnaHRcbiAgICAgIH0pO1xuXG4gICAgICBvblJlc2l6ZSh7IGhlaWdodDogaGVpZ2h0LCB3aWR0aDogd2lkdGggfSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uU2Nyb2xsJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uU2Nyb2xsKGV2ZW50KSB7XG4gICAgICAvLyBQcmV2ZW50IGRldGVjdEVsZW1lbnRSZXNpemUgbGlicmFyeSBmcm9tIGJlaW5nIHRyaWdnZXJlZCBieSB0aGlzIHNjcm9sbCBldmVudC5cbiAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19zZXRSZWYnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBfc2V0UmVmKGF1dG9TaXplcikge1xuICAgICAgdGhpcy5fYXV0b1NpemVyID0gYXV0b1NpemVyO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBBdXRvU2l6ZXI7XG59KF9yZWFjdC5Db21wb25lbnQpO1xuXG5BdXRvU2l6ZXIucHJvcFR5cGVzID0ge1xuICAvKipcbiAgICogRnVuY3Rpb24gcmVzcG9uZGlibGUgZm9yIHJlbmRlcmluZyBjaGlsZHJlbi5cbiAgICogVGhpcyBmdW5jdGlvbiBzaG91bGQgaW1wbGVtZW50IHRoZSBmb2xsb3dpbmcgc2lnbmF0dXJlOlxuICAgKiAoeyBoZWlnaHQsIHdpZHRoIH0pID0+IFByb3BUeXBlcy5lbGVtZW50XG4gICAqL1xuICBjaGlsZHJlbjogX3JlYWN0LlByb3BUeXBlcy5mdW5jLmlzUmVxdWlyZWQsXG5cbiAgLyoqIERpc2FibGUgZHluYW1pYyA6aGVpZ2h0IHByb3BlcnR5ICovXG4gIGRpc2FibGVIZWlnaHQ6IF9yZWFjdC5Qcm9wVHlwZXMuYm9vbCxcblxuICAvKiogRGlzYWJsZSBkeW5hbWljIDp3aWR0aCBwcm9wZXJ0eSAqL1xuICBkaXNhYmxlV2lkdGg6IF9yZWFjdC5Qcm9wVHlwZXMuYm9vbCxcblxuICAvKiogQ2FsbGJhY2sgdG8gYmUgaW52b2tlZCBvbi1yZXNpemU6ICh7IGhlaWdodCwgd2lkdGggfSkgKi9cbiAgb25SZXNpemU6IF9yZWFjdC5Qcm9wVHlwZXMuZnVuYy5pc1JlcXVpcmVkXG59O1xuQXV0b1NpemVyLmRlZmF1bHRQcm9wcyA9IHtcbiAgb25SZXNpemU6IGZ1bmN0aW9uIG9uUmVzaXplKCkge31cbn07XG5leHBvcnRzLmRlZmF1bHQgPSBBdXRvU2l6ZXI7IiwiJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0cy5BdXRvU2l6ZXIgPSBleHBvcnRzLmRlZmF1bHQgPSB1bmRlZmluZWQ7XG5cbnZhciBfQXV0b1NpemVyMiA9IHJlcXVpcmUoJy4vQXV0b1NpemVyJyk7XG5cbnZhciBfQXV0b1NpemVyMyA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX0F1dG9TaXplcjIpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyBkZWZhdWx0OiBvYmogfTsgfVxuXG5leHBvcnRzLmRlZmF1bHQgPSBfQXV0b1NpemVyMy5kZWZhdWx0O1xuZXhwb3J0cy5BdXRvU2l6ZXIgPSBfQXV0b1NpemVyMy5kZWZhdWx0OyIsIid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9jcmVhdGVDbGFzcyA9IGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmIChcInZhbHVlXCIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0oKTtcblxudmFyIF9yZWFjdCA9IHJlcXVpcmUoJ3JlYWN0Jyk7XG5cbnZhciBfcmVhY3QyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfcmVhY3QpO1xuXG52YXIgX3JlYWN0QWRkb25zU2hhbGxvd0NvbXBhcmUgPSByZXF1aXJlKCdyZWFjdC1hZGRvbnMtc2hhbGxvdy1jb21wYXJlJyk7XG5cbnZhciBfcmVhY3RBZGRvbnNTaGFsbG93Q29tcGFyZTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9yZWFjdEFkZG9uc1NoYWxsb3dDb21wYXJlKTtcblxudmFyIF9yZWFjdERvbSA9IHJlcXVpcmUoJ3JlYWN0LWRvbScpO1xuXG52YXIgX3JlYWN0RG9tMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3JlYWN0RG9tKTtcblxudmFyIF9kZWZhdWx0Q2VsbFNpemVDYWNoZSA9IHJlcXVpcmUoJy4vZGVmYXVsdENlbGxTaXplQ2FjaGUnKTtcblxudmFyIF9kZWZhdWx0Q2VsbFNpemVDYWNoZTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9kZWZhdWx0Q2VsbFNpemVDYWNoZSk7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7IGRlZmF1bHQ6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvblwiKTsgfSB9XG5cbmZ1bmN0aW9uIF9wb3NzaWJsZUNvbnN0cnVjdG9yUmV0dXJuKHNlbGYsIGNhbGwpIHsgaWYgKCFzZWxmKSB7IHRocm93IG5ldyBSZWZlcmVuY2VFcnJvcihcInRoaXMgaGFzbid0IGJlZW4gaW5pdGlhbGlzZWQgLSBzdXBlcigpIGhhc24ndCBiZWVuIGNhbGxlZFwiKTsgfSByZXR1cm4gY2FsbCAmJiAodHlwZW9mIGNhbGwgPT09IFwib2JqZWN0XCIgfHwgdHlwZW9mIGNhbGwgPT09IFwiZnVuY3Rpb25cIikgPyBjYWxsIDogc2VsZjsgfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSBcImZ1bmN0aW9uXCIgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCBcIiArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgT2JqZWN0LnNldFByb3RvdHlwZU9mID8gT2JqZWN0LnNldFByb3RvdHlwZU9mKHN1YkNsYXNzLCBzdXBlckNsYXNzKSA6IHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxuLyoqXG4gKiBNZWFzdXJlcyBhIEdyaWQgY2VsbCdzIGNvbnRlbnRzIGJ5IHJlbmRlcmluZyB0aGVtIGluIGEgd2F5IHRoYXQgaXMgbm90IHZpc2libGUgdG8gdGhlIHVzZXIuXG4gKiBFaXRoZXIgYSBmaXhlZCB3aWR0aCBvciBoZWlnaHQgbWF5IGJlIHByb3ZpZGVkIGlmIGl0IGlzIGRlc2lyYWJsZSB0byBtZWFzdXJlIG9ubHkgaW4gb25lIGRpcmVjdGlvbi5cbiAqL1xudmFyIENlbGxNZWFzdXJlciA9IGZ1bmN0aW9uIChfQ29tcG9uZW50KSB7XG4gIF9pbmhlcml0cyhDZWxsTWVhc3VyZXIsIF9Db21wb25lbnQpO1xuXG4gIGZ1bmN0aW9uIENlbGxNZWFzdXJlcihwcm9wcywgc3RhdGUpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgQ2VsbE1lYXN1cmVyKTtcblxuICAgIHZhciBfdGhpcyA9IF9wb3NzaWJsZUNvbnN0cnVjdG9yUmV0dXJuKHRoaXMsIChDZWxsTWVhc3VyZXIuX19wcm90b19fIHx8IE9iamVjdC5nZXRQcm90b3R5cGVPZihDZWxsTWVhc3VyZXIpKS5jYWxsKHRoaXMsIHByb3BzLCBzdGF0ZSkpO1xuXG4gICAgX3RoaXMuX2NlbGxTaXplQ2FjaGUgPSBwcm9wcy5jZWxsU2l6ZUNhY2hlIHx8IG5ldyBfZGVmYXVsdENlbGxTaXplQ2FjaGUyLmRlZmF1bHQoKTtcblxuICAgIF90aGlzLmdldENvbHVtbldpZHRoID0gX3RoaXMuZ2V0Q29sdW1uV2lkdGguYmluZChfdGhpcyk7XG4gICAgX3RoaXMuZ2V0Um93SGVpZ2h0ID0gX3RoaXMuZ2V0Um93SGVpZ2h0LmJpbmQoX3RoaXMpO1xuICAgIF90aGlzLnJlc2V0TWVhc3VyZW1lbnRzID0gX3RoaXMucmVzZXRNZWFzdXJlbWVudHMuYmluZChfdGhpcyk7XG4gICAgX3RoaXMucmVzZXRNZWFzdXJlbWVudEZvckNvbHVtbiA9IF90aGlzLnJlc2V0TWVhc3VyZW1lbnRGb3JDb2x1bW4uYmluZChfdGhpcyk7XG4gICAgX3RoaXMucmVzZXRNZWFzdXJlbWVudEZvclJvdyA9IF90aGlzLnJlc2V0TWVhc3VyZW1lbnRGb3JSb3cuYmluZChfdGhpcyk7XG4gICAgcmV0dXJuIF90aGlzO1xuICB9XG5cbiAgX2NyZWF0ZUNsYXNzKENlbGxNZWFzdXJlciwgW3tcbiAgICBrZXk6ICdnZXRDb2x1bW5XaWR0aCcsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGdldENvbHVtbldpZHRoKF9yZWYpIHtcbiAgICAgIHZhciBpbmRleCA9IF9yZWYuaW5kZXg7XG5cbiAgICAgIGlmICh0aGlzLl9jZWxsU2l6ZUNhY2hlLmhhc0NvbHVtbldpZHRoKGluZGV4KSkge1xuICAgICAgICByZXR1cm4gdGhpcy5fY2VsbFNpemVDYWNoZS5nZXRDb2x1bW5XaWR0aChpbmRleCk7XG4gICAgICB9XG5cbiAgICAgIHZhciByb3dDb3VudCA9IHRoaXMucHJvcHMucm93Q291bnQ7XG5cblxuICAgICAgdmFyIG1heFdpZHRoID0gMDtcblxuICAgICAgZm9yICh2YXIgcm93SW5kZXggPSAwOyByb3dJbmRleCA8IHJvd0NvdW50OyByb3dJbmRleCsrKSB7XG4gICAgICAgIHZhciBfbWVhc3VyZUNlbGwyID0gdGhpcy5fbWVhc3VyZUNlbGwoe1xuICAgICAgICAgIGNsaWVudFdpZHRoOiB0cnVlLFxuICAgICAgICAgIGNvbHVtbkluZGV4OiBpbmRleCxcbiAgICAgICAgICByb3dJbmRleDogcm93SW5kZXhcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdmFyIHdpZHRoID0gX21lYXN1cmVDZWxsMi53aWR0aDtcblxuXG4gICAgICAgIG1heFdpZHRoID0gTWF0aC5tYXgobWF4V2lkdGgsIHdpZHRoKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fY2VsbFNpemVDYWNoZS5zZXRDb2x1bW5XaWR0aChpbmRleCwgbWF4V2lkdGgpO1xuXG4gICAgICByZXR1cm4gbWF4V2lkdGg7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnZ2V0Um93SGVpZ2h0JyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gZ2V0Um93SGVpZ2h0KF9yZWYyKSB7XG4gICAgICB2YXIgaW5kZXggPSBfcmVmMi5pbmRleDtcblxuICAgICAgaWYgKHRoaXMuX2NlbGxTaXplQ2FjaGUuaGFzUm93SGVpZ2h0KGluZGV4KSkge1xuICAgICAgICByZXR1cm4gdGhpcy5fY2VsbFNpemVDYWNoZS5nZXRSb3dIZWlnaHQoaW5kZXgpO1xuICAgICAgfVxuXG4gICAgICB2YXIgY29sdW1uQ291bnQgPSB0aGlzLnByb3BzLmNvbHVtbkNvdW50O1xuXG5cbiAgICAgIHZhciBtYXhIZWlnaHQgPSAwO1xuXG4gICAgICBmb3IgKHZhciBjb2x1bW5JbmRleCA9IDA7IGNvbHVtbkluZGV4IDwgY29sdW1uQ291bnQ7IGNvbHVtbkluZGV4KyspIHtcbiAgICAgICAgdmFyIF9tZWFzdXJlQ2VsbDMgPSB0aGlzLl9tZWFzdXJlQ2VsbCh7XG4gICAgICAgICAgY2xpZW50SGVpZ2h0OiB0cnVlLFxuICAgICAgICAgIGNvbHVtbkluZGV4OiBjb2x1bW5JbmRleCxcbiAgICAgICAgICByb3dJbmRleDogaW5kZXhcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdmFyIGhlaWdodCA9IF9tZWFzdXJlQ2VsbDMuaGVpZ2h0O1xuXG5cbiAgICAgICAgbWF4SGVpZ2h0ID0gTWF0aC5tYXgobWF4SGVpZ2h0LCBoZWlnaHQpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9jZWxsU2l6ZUNhY2hlLnNldFJvd0hlaWdodChpbmRleCwgbWF4SGVpZ2h0KTtcblxuICAgICAgcmV0dXJuIG1heEhlaWdodDtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdyZXNldE1lYXN1cmVtZW50Rm9yQ29sdW1uJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVzZXRNZWFzdXJlbWVudEZvckNvbHVtbihjb2x1bW5JbmRleCkge1xuICAgICAgdGhpcy5fY2VsbFNpemVDYWNoZS5jbGVhckNvbHVtbldpZHRoKGNvbHVtbkluZGV4KTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdyZXNldE1lYXN1cmVtZW50Rm9yUm93JyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVzZXRNZWFzdXJlbWVudEZvclJvdyhyb3dJbmRleCkge1xuICAgICAgdGhpcy5fY2VsbFNpemVDYWNoZS5jbGVhclJvd0hlaWdodChyb3dJbmRleCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAncmVzZXRNZWFzdXJlbWVudHMnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiByZXNldE1lYXN1cmVtZW50cygpIHtcbiAgICAgIHRoaXMuX2NlbGxTaXplQ2FjaGUuY2xlYXJBbGxDb2x1bW5XaWR0aHMoKTtcbiAgICAgIHRoaXMuX2NlbGxTaXplQ2FjaGUuY2xlYXJBbGxSb3dIZWlnaHRzKCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnY29tcG9uZW50RGlkTW91bnQnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBjb21wb25lbnREaWRNb3VudCgpIHtcbiAgICAgIHRoaXMuX3JlbmRlckFuZE1vdW50KCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnY29tcG9uZW50V2lsbFJlY2VpdmVQcm9wcycsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGNvbXBvbmVudFdpbGxSZWNlaXZlUHJvcHMobmV4dFByb3BzKSB7XG4gICAgICB2YXIgY2VsbFNpemVDYWNoZSA9IHRoaXMucHJvcHMuY2VsbFNpemVDYWNoZTtcblxuXG4gICAgICBpZiAoY2VsbFNpemVDYWNoZSAhPT0gbmV4dFByb3BzLmNlbGxTaXplQ2FjaGUpIHtcbiAgICAgICAgdGhpcy5fY2VsbFNpemVDYWNoZSA9IG5leHRQcm9wcy5jZWxsU2l6ZUNhY2hlO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl91cGRhdGVEaXZEaW1lbnNpb25zKG5leHRQcm9wcyk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnY29tcG9uZW50V2lsbFVubW91bnQnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBjb21wb25lbnRXaWxsVW5tb3VudCgpIHtcbiAgICAgIHRoaXMuX3VubW91bnRDb250YWluZXIoKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdyZW5kZXInLFxuICAgIHZhbHVlOiBmdW5jdGlvbiByZW5kZXIoKSB7XG4gICAgICB2YXIgY2hpbGRyZW4gPSB0aGlzLnByb3BzLmNoaWxkcmVuO1xuXG5cbiAgICAgIHJldHVybiBjaGlsZHJlbih7XG4gICAgICAgIGdldENvbHVtbldpZHRoOiB0aGlzLmdldENvbHVtbldpZHRoLFxuICAgICAgICBnZXRSb3dIZWlnaHQ6IHRoaXMuZ2V0Um93SGVpZ2h0LFxuICAgICAgICByZXNldE1lYXN1cmVtZW50czogdGhpcy5yZXNldE1lYXN1cmVtZW50cyxcbiAgICAgICAgcmVzZXRNZWFzdXJlbWVudEZvckNvbHVtbjogdGhpcy5yZXNldE1lYXN1cmVtZW50Rm9yQ29sdW1uLFxuICAgICAgICByZXNldE1lYXN1cmVtZW50Rm9yUm93OiB0aGlzLnJlc2V0TWVhc3VyZW1lbnRGb3JSb3dcbiAgICAgIH0pO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ3Nob3VsZENvbXBvbmVudFVwZGF0ZScsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHNob3VsZENvbXBvbmVudFVwZGF0ZShuZXh0UHJvcHMsIG5leHRTdGF0ZSkge1xuICAgICAgcmV0dXJuICgwLCBfcmVhY3RBZGRvbnNTaGFsbG93Q29tcGFyZTIuZGVmYXVsdCkodGhpcywgbmV4dFByb3BzLCBuZXh0U3RhdGUpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19nZXRDb250YWluZXJOb2RlJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gX2dldENvbnRhaW5lck5vZGUocHJvcHMpIHtcbiAgICAgIHZhciBjb250YWluZXIgPSBwcm9wcy5jb250YWluZXI7XG5cblxuICAgICAgaWYgKGNvbnRhaW5lcikge1xuICAgICAgICByZXR1cm4gX3JlYWN0RG9tMi5kZWZhdWx0LmZpbmRET01Ob2RlKHR5cGVvZiBjb250YWluZXIgPT09ICdmdW5jdGlvbicgPyBjb250YWluZXIoKSA6IGNvbnRhaW5lcik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gZG9jdW1lbnQuYm9keTtcbiAgICAgIH1cbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfbWVhc3VyZUNlbGwnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBfbWVhc3VyZUNlbGwoX3JlZjMpIHtcbiAgICAgIHZhciBfcmVmMyRjbGllbnRIZWlnaHQgPSBfcmVmMy5jbGllbnRIZWlnaHQ7XG4gICAgICB2YXIgY2xpZW50SGVpZ2h0ID0gX3JlZjMkY2xpZW50SGVpZ2h0ID09PSB1bmRlZmluZWQgPyBmYWxzZSA6IF9yZWYzJGNsaWVudEhlaWdodDtcbiAgICAgIHZhciBfcmVmMyRjbGllbnRXaWR0aCA9IF9yZWYzLmNsaWVudFdpZHRoO1xuICAgICAgdmFyIGNsaWVudFdpZHRoID0gX3JlZjMkY2xpZW50V2lkdGggPT09IHVuZGVmaW5lZCA/IHRydWUgOiBfcmVmMyRjbGllbnRXaWR0aDtcbiAgICAgIHZhciBjb2x1bW5JbmRleCA9IF9yZWYzLmNvbHVtbkluZGV4O1xuICAgICAgdmFyIHJvd0luZGV4ID0gX3JlZjMucm93SW5kZXg7XG4gICAgICB2YXIgY2VsbFJlbmRlcmVyID0gdGhpcy5wcm9wcy5jZWxsUmVuZGVyZXI7XG5cblxuICAgICAgdmFyIHJlbmRlcmVkID0gY2VsbFJlbmRlcmVyKHtcbiAgICAgICAgY29sdW1uSW5kZXg6IGNvbHVtbkluZGV4LFxuICAgICAgICByb3dJbmRleDogcm93SW5kZXhcbiAgICAgIH0pO1xuXG4gICAgICAvLyBIYW5kbGUgZWRnZSBjYXNlIHdoZXJlIHRoaXMgbWV0aG9kIGlzIGNhbGxlZCBiZWZvcmUgdGhlIENlbGxNZWFzdXJlciBoYXMgY29tcGxldGVkIGl0cyBpbml0aWFsIHJlbmRlciAoYW5kIG1vdW50ZWQpLlxuICAgICAgdGhpcy5fcmVuZGVyQW5kTW91bnQoKTtcblxuICAgICAgLy8gQFRPRE8gS2VlcCBhbiBleWUgb24gdGhpcyBmb3IgZnV0dXJlIFJlYWN0IHVwZGF0ZXMgYXMgdGhlIGludGVyZmFjZSBtYXkgY2hhbmdlOlxuICAgICAgLy8gaHR0cHM6Ly90d2l0dGVyLmNvbS9zb3ByYW5vL3N0YXR1cy83MzczMTYzNzk3MTIzMzE3NzZcbiAgICAgIF9yZWFjdERvbTIuZGVmYXVsdC51bnN0YWJsZV9yZW5kZXJTdWJ0cmVlSW50b0NvbnRhaW5lcih0aGlzLCByZW5kZXJlZCwgdGhpcy5fZGl2KTtcblxuICAgICAgdmFyIG1lYXN1cmVtZW50cyA9IHtcbiAgICAgICAgaGVpZ2h0OiBjbGllbnRIZWlnaHQgJiYgdGhpcy5fZGl2LmNsaWVudEhlaWdodCxcbiAgICAgICAgd2lkdGg6IGNsaWVudFdpZHRoICYmIHRoaXMuX2Rpdi5jbGllbnRXaWR0aFxuICAgICAgfTtcblxuICAgICAgX3JlYWN0RG9tMi5kZWZhdWx0LnVubW91bnRDb21wb25lbnRBdE5vZGUodGhpcy5fZGl2KTtcblxuICAgICAgcmV0dXJuIG1lYXN1cmVtZW50cztcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfcmVuZGVyQW5kTW91bnQnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBfcmVuZGVyQW5kTW91bnQoKSB7XG4gICAgICBpZiAoIXRoaXMuX2Rpdikge1xuICAgICAgICB0aGlzLl9kaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgdGhpcy5fZGl2LnN0eWxlLmRpc3BsYXkgPSAnaW5saW5lLWJsb2NrJztcbiAgICAgICAgdGhpcy5fZGl2LnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICAgICAgdGhpcy5fZGl2LnN0eWxlLnZpc2liaWxpdHkgPSAnaGlkZGVuJztcbiAgICAgICAgdGhpcy5fZGl2LnN0eWxlLnpJbmRleCA9IC0xO1xuXG4gICAgICAgIHRoaXMuX3VwZGF0ZURpdkRpbWVuc2lvbnModGhpcy5wcm9wcyk7XG5cbiAgICAgICAgdGhpcy5fY29udGFpbmVyTm9kZSA9IHRoaXMuX2dldENvbnRhaW5lck5vZGUodGhpcy5wcm9wcyk7XG4gICAgICAgIHRoaXMuX2NvbnRhaW5lck5vZGUuYXBwZW5kQ2hpbGQodGhpcy5fZGl2KTtcbiAgICAgIH1cbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfdW5tb3VudENvbnRhaW5lcicsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF91bm1vdW50Q29udGFpbmVyKCkge1xuICAgICAgaWYgKHRoaXMuX2Rpdikge1xuICAgICAgICB0aGlzLl9jb250YWluZXJOb2RlLnJlbW92ZUNoaWxkKHRoaXMuX2Rpdik7XG5cbiAgICAgICAgdGhpcy5fZGl2ID0gbnVsbDtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fY29udGFpbmVyTm9kZSA9IG51bGw7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX3VwZGF0ZURpdkRpbWVuc2lvbnMnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBfdXBkYXRlRGl2RGltZW5zaW9ucyhwcm9wcykge1xuICAgICAgdmFyIGhlaWdodCA9IHByb3BzLmhlaWdodDtcbiAgICAgIHZhciB3aWR0aCA9IHByb3BzLndpZHRoO1xuXG5cbiAgICAgIGlmIChoZWlnaHQgJiYgaGVpZ2h0ICE9PSB0aGlzLl9kaXZIZWlnaHQpIHtcbiAgICAgICAgdGhpcy5fZGl2SGVpZ2h0ID0gaGVpZ2h0O1xuICAgICAgICB0aGlzLl9kaXYuc3R5bGUuaGVpZ2h0ID0gaGVpZ2h0ICsgJ3B4JztcbiAgICAgIH1cblxuICAgICAgaWYgKHdpZHRoICYmIHdpZHRoICE9PSB0aGlzLl9kaXZXaWR0aCkge1xuICAgICAgICB0aGlzLl9kaXZXaWR0aCA9IHdpZHRoO1xuICAgICAgICB0aGlzLl9kaXYuc3R5bGUud2lkdGggPSB3aWR0aCArICdweCc7XG4gICAgICB9XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIENlbGxNZWFzdXJlcjtcbn0oX3JlYWN0LkNvbXBvbmVudCk7XG5cbkNlbGxNZWFzdXJlci5wcm9wVHlwZXMgPSB7XG4gIC8qKlxuICAgKiBSZW5kZXJzIGEgY2VsbCBnaXZlbiBpdHMgaW5kaWNlcy5cbiAgICogU2hvdWxkIGltcGxlbWVudCB0aGUgZm9sbG93aW5nIGludGVyZmFjZTogKHsgY29sdW1uSW5kZXg6IG51bWJlciwgcm93SW5kZXg6IG51bWJlciB9KTogUHJvcFR5cGVzLm5vZGVcbiAgICovXG4gIGNlbGxSZW5kZXJlcjogX3JlYWN0LlByb3BUeXBlcy5mdW5jLmlzUmVxdWlyZWQsXG5cbiAgLyoqXG4gICAqIE9wdGlvbmFsLCBjdXN0b20gY2FjaGluZyBzdHJhdGVneSBmb3IgY2VsbCBzaXplcy5cbiAgICovXG4gIGNlbGxTaXplQ2FjaGU6IF9yZWFjdC5Qcm9wVHlwZXMub2JqZWN0LFxuXG4gIC8qKlxuICAgKiBGdW5jdGlvbiByZXNwb25kaWJsZSBmb3IgcmVuZGVyaW5nIGEgdmlydHVhbGl6ZWQgY29tcG9uZW50LlxuICAgKiBUaGlzIGZ1bmN0aW9uIHNob3VsZCBpbXBsZW1lbnQgdGhlIGZvbGxvd2luZyBzaWduYXR1cmU6XG4gICAqICh7IGdldENvbHVtbldpZHRoLCBnZXRSb3dIZWlnaHQsIHJlc2V0TWVhc3VyZW1lbnRzIH0pID0+IFByb3BUeXBlcy5lbGVtZW50XG4gICAqL1xuICBjaGlsZHJlbjogX3JlYWN0LlByb3BUeXBlcy5mdW5jLmlzUmVxdWlyZWQsXG5cbiAgLyoqXG4gICAqIE51bWJlciBvZiBjb2x1bW5zIGluIGdyaWQuXG4gICAqL1xuICBjb2x1bW5Db3VudDogX3JlYWN0LlByb3BUeXBlcy5udW1iZXIuaXNSZXF1aXJlZCxcblxuICAvKipcbiAgICogQSBOb2RlLCBDb21wb25lbnQgaW5zdGFuY2UsIG9yIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyBlaXRoZXIuXG4gICAqIElmIHRoaXMgcHJvcGVydHkgaXMgbm90IHNwZWNpZmllZCB0aGUgZG9jdW1lbnQgYm9keSB3aWxsIGJlIHVzZWQuXG4gICAqL1xuICBjb250YWluZXI6IF9yZWFjdDIuZGVmYXVsdC5Qcm9wVHlwZXMub25lT2ZUeXBlKFtfcmVhY3QyLmRlZmF1bHQuUHJvcFR5cGVzLmZ1bmMsIF9yZWFjdDIuZGVmYXVsdC5Qcm9wVHlwZXMubm9kZV0pLFxuXG4gIC8qKlxuICAgKiBBc3NpZ24gYSBmaXhlZCA6aGVpZ2h0IGluIG9yZGVyIHRvIG1lYXN1cmUgZHluYW1pYyB0ZXh0IDp3aWR0aCBvbmx5LlxuICAgKi9cbiAgaGVpZ2h0OiBfcmVhY3QuUHJvcFR5cGVzLm51bWJlcixcblxuICAvKipcbiAgICogTnVtYmVyIG9mIHJvd3MgaW4gZ3JpZC5cbiAgICovXG4gIHJvd0NvdW50OiBfcmVhY3QuUHJvcFR5cGVzLm51bWJlci5pc1JlcXVpcmVkLFxuXG4gIC8qKlxuICAgKiBBc3NpZ24gYSBmaXhlZCA6d2lkdGggaW4gb3JkZXIgdG8gbWVhc3VyZSBkeW5hbWljIHRleHQgOmhlaWdodCBvbmx5LlxuICAgKi9cbiAgd2lkdGg6IF9yZWFjdC5Qcm9wVHlwZXMubnVtYmVyXG59O1xuZXhwb3J0cy5kZWZhdWx0ID0gQ2VsbE1lYXN1cmVyOyIsIlwidXNlIHN0cmljdFwiO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKFwidmFsdWVcIiBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSgpO1xuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb25cIik7IH0gfVxuXG4vKipcbiAqIERlZmF1bHQgQ2VsbE1lYXN1cmVyIGBjZWxsU2l6ZUNhY2hlYCBpbXBsZW1lbnRhdGlvbi5cbiAqIFBlcm1hbmVudGx5IGNhY2hlcyBhbGwgY2VsbCBzaXplcyAoaWRlbnRpZmllZCBieSBjb2x1bW4gYW5kIHJvdyBpbmRleCkgdW5sZXNzIGV4cGxpY2l0bHkgY2xlYXJlZC5cbiAqIENhbiBiZSBjb25maWd1cmVkIHRvIGhhbmRsZSB1bmlmb3JtIGNlbGwgd2lkdGhzIGFuZC9vciBoZWlnaHRzIGFzIGEgd2F5IG9mIG9wdGltaXppbmcgY2VydGFpbiB1c2UgY2FzZXMuXG4gKi9cbnZhciBDZWxsU2l6ZUNhY2hlID0gZnVuY3Rpb24gKCkge1xuICBmdW5jdGlvbiBDZWxsU2l6ZUNhY2hlKCkge1xuICAgIHZhciBfcmVmID0gYXJndW1lbnRzLmxlbmd0aCA8PSAwIHx8IGFyZ3VtZW50c1swXSA9PT0gdW5kZWZpbmVkID8ge30gOiBhcmd1bWVudHNbMF07XG5cbiAgICB2YXIgX3JlZiR1bmlmb3JtUm93SGVpZ2h0ID0gX3JlZi51bmlmb3JtUm93SGVpZ2h0O1xuICAgIHZhciB1bmlmb3JtUm93SGVpZ2h0ID0gX3JlZiR1bmlmb3JtUm93SGVpZ2h0ID09PSB1bmRlZmluZWQgPyBmYWxzZSA6IF9yZWYkdW5pZm9ybVJvd0hlaWdodDtcbiAgICB2YXIgX3JlZiR1bmlmb3JtQ29sdW1uV2lkID0gX3JlZi51bmlmb3JtQ29sdW1uV2lkdGg7XG4gICAgdmFyIHVuaWZvcm1Db2x1bW5XaWR0aCA9IF9yZWYkdW5pZm9ybUNvbHVtbldpZCA9PT0gdW5kZWZpbmVkID8gZmFsc2UgOiBfcmVmJHVuaWZvcm1Db2x1bW5XaWQ7XG5cbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgQ2VsbFNpemVDYWNoZSk7XG5cbiAgICB0aGlzLl91bmlmb3JtUm93SGVpZ2h0ID0gdW5pZm9ybVJvd0hlaWdodDtcbiAgICB0aGlzLl91bmlmb3JtQ29sdW1uV2lkdGggPSB1bmlmb3JtQ29sdW1uV2lkdGg7XG5cbiAgICB0aGlzLl9jYWNoZWRDb2x1bW5XaWR0aHMgPSB7fTtcbiAgICB0aGlzLl9jYWNoZWRSb3dIZWlnaHRzID0ge307XG4gIH1cblxuICBfY3JlYXRlQ2xhc3MoQ2VsbFNpemVDYWNoZSwgW3tcbiAgICBrZXk6IFwiY2xlYXJBbGxDb2x1bW5XaWR0aHNcIixcbiAgICB2YWx1ZTogZnVuY3Rpb24gY2xlYXJBbGxDb2x1bW5XaWR0aHMoKSB7XG4gICAgICB0aGlzLl9jYWNoZWRDb2x1bW5XaWR0aCA9IHVuZGVmaW5lZDtcbiAgICAgIHRoaXMuX2NhY2hlZENvbHVtbldpZHRocyA9IHt9O1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogXCJjbGVhckFsbFJvd0hlaWdodHNcIixcbiAgICB2YWx1ZTogZnVuY3Rpb24gY2xlYXJBbGxSb3dIZWlnaHRzKCkge1xuICAgICAgdGhpcy5fY2FjaGVkUm93SGVpZ2h0ID0gdW5kZWZpbmVkO1xuICAgICAgdGhpcy5fY2FjaGVkUm93SGVpZ2h0cyA9IHt9O1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogXCJjbGVhckNvbHVtbldpZHRoXCIsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGNsZWFyQ29sdW1uV2lkdGgoaW5kZXgpIHtcbiAgICAgIHRoaXMuX2NhY2hlZENvbHVtbldpZHRoID0gdW5kZWZpbmVkO1xuXG4gICAgICBkZWxldGUgdGhpcy5fY2FjaGVkQ29sdW1uV2lkdGhzW2luZGV4XTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6IFwiY2xlYXJSb3dIZWlnaHRcIixcbiAgICB2YWx1ZTogZnVuY3Rpb24gY2xlYXJSb3dIZWlnaHQoaW5kZXgpIHtcbiAgICAgIHRoaXMuX2NhY2hlZFJvd0hlaWdodCA9IHVuZGVmaW5lZDtcblxuICAgICAgZGVsZXRlIHRoaXMuX2NhY2hlZFJvd0hlaWdodHNbaW5kZXhdO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogXCJnZXRDb2x1bW5XaWR0aFwiLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBnZXRDb2x1bW5XaWR0aChpbmRleCkge1xuICAgICAgcmV0dXJuIHRoaXMuX3VuaWZvcm1Db2x1bW5XaWR0aCA/IHRoaXMuX2NhY2hlZENvbHVtbldpZHRoIDogdGhpcy5fY2FjaGVkQ29sdW1uV2lkdGhzW2luZGV4XTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6IFwiZ2V0Um93SGVpZ2h0XCIsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGdldFJvd0hlaWdodChpbmRleCkge1xuICAgICAgcmV0dXJuIHRoaXMuX3VuaWZvcm1Sb3dIZWlnaHQgPyB0aGlzLl9jYWNoZWRSb3dIZWlnaHQgOiB0aGlzLl9jYWNoZWRSb3dIZWlnaHRzW2luZGV4XTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6IFwiaGFzQ29sdW1uV2lkdGhcIixcbiAgICB2YWx1ZTogZnVuY3Rpb24gaGFzQ29sdW1uV2lkdGgoaW5kZXgpIHtcbiAgICAgIHJldHVybiB0aGlzLl91bmlmb3JtQ29sdW1uV2lkdGggPyAhIXRoaXMuX2NhY2hlZENvbHVtbldpZHRoIDogISF0aGlzLl9jYWNoZWRDb2x1bW5XaWR0aHNbaW5kZXhdO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogXCJoYXNSb3dIZWlnaHRcIixcbiAgICB2YWx1ZTogZnVuY3Rpb24gaGFzUm93SGVpZ2h0KGluZGV4KSB7XG4gICAgICByZXR1cm4gdGhpcy5fdW5pZm9ybVJvd0hlaWdodCA/ICEhdGhpcy5fY2FjaGVkUm93SGVpZ2h0IDogISF0aGlzLl9jYWNoZWRSb3dIZWlnaHRzW2luZGV4XTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6IFwic2V0Q29sdW1uV2lkdGhcIixcbiAgICB2YWx1ZTogZnVuY3Rpb24gc2V0Q29sdW1uV2lkdGgoaW5kZXgsIHdpZHRoKSB7XG4gICAgICB0aGlzLl9jYWNoZWRDb2x1bW5XaWR0aCA9IHdpZHRoO1xuICAgICAgdGhpcy5fY2FjaGVkQ29sdW1uV2lkdGhzW2luZGV4XSA9IHdpZHRoO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogXCJzZXRSb3dIZWlnaHRcIixcbiAgICB2YWx1ZTogZnVuY3Rpb24gc2V0Um93SGVpZ2h0KGluZGV4LCBoZWlnaHQpIHtcbiAgICAgIHRoaXMuX2NhY2hlZFJvd0hlaWdodCA9IGhlaWdodDtcbiAgICAgIHRoaXMuX2NhY2hlZFJvd0hlaWdodHNbaW5kZXhdID0gaGVpZ2h0O1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBDZWxsU2l6ZUNhY2hlO1xufSgpO1xuXG5leHBvcnRzLmRlZmF1bHQgPSBDZWxsU2l6ZUNhY2hlOyIsIid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcbmV4cG9ydHMuZGVmYXVsdENlbGxTaXplQ2FjaGUgPSBleHBvcnRzLkNlbGxNZWFzdXJlciA9IGV4cG9ydHMuZGVmYXVsdCA9IHVuZGVmaW5lZDtcblxudmFyIF9DZWxsTWVhc3VyZXIyID0gcmVxdWlyZSgnLi9DZWxsTWVhc3VyZXInKTtcblxudmFyIF9DZWxsTWVhc3VyZXIzID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfQ2VsbE1lYXN1cmVyMik7XG5cbnZhciBfZGVmYXVsdENlbGxTaXplQ2FjaGUyID0gcmVxdWlyZSgnLi9kZWZhdWx0Q2VsbFNpemVDYWNoZScpO1xuXG52YXIgX2RlZmF1bHRDZWxsU2l6ZUNhY2hlMyA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2RlZmF1bHRDZWxsU2l6ZUNhY2hlMik7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7IGRlZmF1bHQ6IG9iaiB9OyB9XG5cbmV4cG9ydHMuZGVmYXVsdCA9IF9DZWxsTWVhc3VyZXIzLmRlZmF1bHQ7XG5leHBvcnRzLkNlbGxNZWFzdXJlciA9IF9DZWxsTWVhc3VyZXIzLmRlZmF1bHQ7XG5leHBvcnRzLmRlZmF1bHRDZWxsU2l6ZUNhY2hlID0gX2RlZmF1bHRDZWxsU2l6ZUNhY2hlMy5kZWZhdWx0OyIsIid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9leHRlbmRzID0gT2JqZWN0LmFzc2lnbiB8fCBmdW5jdGlvbiAodGFyZ2V0KSB7IGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7IHZhciBzb3VyY2UgPSBhcmd1bWVudHNbaV07IGZvciAodmFyIGtleSBpbiBzb3VyY2UpIHsgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzb3VyY2UsIGtleSkpIHsgdGFyZ2V0W2tleV0gPSBzb3VyY2Vba2V5XTsgfSB9IH0gcmV0dXJuIHRhcmdldDsgfTtcblxudmFyIF9jcmVhdGVDbGFzcyA9IGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmIChcInZhbHVlXCIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0oKTtcblxudmFyIF9yZWFjdCA9IHJlcXVpcmUoJ3JlYWN0Jyk7XG5cbnZhciBfcmVhY3QyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfcmVhY3QpO1xuXG52YXIgX0NvbGxlY3Rpb25WaWV3ID0gcmVxdWlyZSgnLi9Db2xsZWN0aW9uVmlldycpO1xuXG52YXIgX0NvbGxlY3Rpb25WaWV3MiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX0NvbGxlY3Rpb25WaWV3KTtcblxudmFyIF9jYWxjdWxhdGVTaXplQW5kUG9zaXRpb25EYXRhMiA9IHJlcXVpcmUoJy4vdXRpbHMvY2FsY3VsYXRlU2l6ZUFuZFBvc2l0aW9uRGF0YScpO1xuXG52YXIgX2NhbGN1bGF0ZVNpemVBbmRQb3NpdGlvbkRhdGEzID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfY2FsY3VsYXRlU2l6ZUFuZFBvc2l0aW9uRGF0YTIpO1xuXG52YXIgX2dldFVwZGF0ZWRPZmZzZXRGb3JJbmRleCA9IHJlcXVpcmUoJy4uL3V0aWxzL2dldFVwZGF0ZWRPZmZzZXRGb3JJbmRleCcpO1xuXG52YXIgX2dldFVwZGF0ZWRPZmZzZXRGb3JJbmRleDIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9nZXRVcGRhdGVkT2Zmc2V0Rm9ySW5kZXgpO1xuXG52YXIgX3JlYWN0QWRkb25zU2hhbGxvd0NvbXBhcmUgPSByZXF1aXJlKCdyZWFjdC1hZGRvbnMtc2hhbGxvdy1jb21wYXJlJyk7XG5cbnZhciBfcmVhY3RBZGRvbnNTaGFsbG93Q29tcGFyZTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9yZWFjdEFkZG9uc1NoYWxsb3dDb21wYXJlKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgZGVmYXVsdDogb2JqIH07IH1cblxuZnVuY3Rpb24gX29iamVjdFdpdGhvdXRQcm9wZXJ0aWVzKG9iaiwga2V5cykgeyB2YXIgdGFyZ2V0ID0ge307IGZvciAodmFyIGkgaW4gb2JqKSB7IGlmIChrZXlzLmluZGV4T2YoaSkgPj0gMCkgY29udGludWU7IGlmICghT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgaSkpIGNvbnRpbnVlOyB0YXJnZXRbaV0gPSBvYmpbaV07IH0gcmV0dXJuIHRhcmdldDsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb25cIik7IH0gfVxuXG5mdW5jdGlvbiBfcG9zc2libGVDb25zdHJ1Y3RvclJldHVybihzZWxmLCBjYWxsKSB7IGlmICghc2VsZikgeyB0aHJvdyBuZXcgUmVmZXJlbmNlRXJyb3IoXCJ0aGlzIGhhc24ndCBiZWVuIGluaXRpYWxpc2VkIC0gc3VwZXIoKSBoYXNuJ3QgYmVlbiBjYWxsZWRcIik7IH0gcmV0dXJuIGNhbGwgJiYgKHR5cGVvZiBjYWxsID09PSBcIm9iamVjdFwiIHx8IHR5cGVvZiBjYWxsID09PSBcImZ1bmN0aW9uXCIpID8gY2FsbCA6IHNlbGY7IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gXCJmdW5jdGlvblwiICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgXCIgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIE9iamVjdC5zZXRQcm90b3R5cGVPZiA/IE9iamVjdC5zZXRQcm90b3R5cGVPZihzdWJDbGFzcywgc3VwZXJDbGFzcykgOiBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbi8qKlxuICogUmVuZGVycyBzY2F0dGVyZWQgb3Igbm9uLWxpbmVhciBkYXRhLlxuICogVW5saWtlIEdyaWQsIHdoaWNoIHJlbmRlcnMgY2hlY2tlcmJvYXJkIGRhdGEsIENvbGxlY3Rpb24gY2FuIHJlbmRlciBhcmJpdHJhcmlseSBwb3NpdGlvbmVkLSBldmVuIG92ZXJsYXBwaW5nLSBkYXRhLlxuICovXG52YXIgQ29sbGVjdGlvbiA9IGZ1bmN0aW9uIChfQ29tcG9uZW50KSB7XG4gIF9pbmhlcml0cyhDb2xsZWN0aW9uLCBfQ29tcG9uZW50KTtcblxuICBmdW5jdGlvbiBDb2xsZWN0aW9uKHByb3BzLCBjb250ZXh0KSB7XG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIENvbGxlY3Rpb24pO1xuXG4gICAgdmFyIF90aGlzID0gX3Bvc3NpYmxlQ29uc3RydWN0b3JSZXR1cm4odGhpcywgKENvbGxlY3Rpb24uX19wcm90b19fIHx8IE9iamVjdC5nZXRQcm90b3R5cGVPZihDb2xsZWN0aW9uKSkuY2FsbCh0aGlzLCBwcm9wcywgY29udGV4dCkpO1xuXG4gICAgX3RoaXMuX2NlbGxNZXRhZGF0YSA9IFtdO1xuICAgIF90aGlzLl9sYXN0UmVuZGVyZWRDZWxsSW5kaWNlcyA9IFtdO1xuXG4gICAgLy8gQ2VsbCBjYWNoZSBkdXJpbmcgc2Nyb2xsIChmb3IgcGVyZm9yYW1uY2UpXG4gICAgX3RoaXMuX2NlbGxDYWNoZSA9IFtdO1xuXG4gICAgX3RoaXMuX2lzU2Nyb2xsaW5nQ2hhbmdlID0gX3RoaXMuX2lzU2Nyb2xsaW5nQ2hhbmdlLmJpbmQoX3RoaXMpO1xuICAgIHJldHVybiBfdGhpcztcbiAgfVxuXG4gIC8qKiBTZWUgQ29sbGVjdGlvbiNyZWNvbXB1dGVDZWxsU2l6ZXNBbmRQb3NpdGlvbnMgKi9cblxuXG4gIF9jcmVhdGVDbGFzcyhDb2xsZWN0aW9uLCBbe1xuICAgIGtleTogJ3JlY29tcHV0ZUNlbGxTaXplc0FuZFBvc2l0aW9ucycsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJlY29tcHV0ZUNlbGxTaXplc0FuZFBvc2l0aW9ucygpIHtcbiAgICAgIHRoaXMuX2NlbGxDYWNoZSA9IFtdO1xuICAgICAgdGhpcy5fY29sbGVjdGlvblZpZXcucmVjb21wdXRlQ2VsbFNpemVzQW5kUG9zaXRpb25zKCk7XG4gICAgfVxuXG4gICAgLyoqIFJlYWN0IGxpZmVjeWNsZSBtZXRob2RzICovXG5cbiAgfSwge1xuICAgIGtleTogJ3JlbmRlcicsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJlbmRlcigpIHtcbiAgICAgIHZhciBfdGhpczIgPSB0aGlzO1xuXG4gICAgICB2YXIgcHJvcHMgPSBfb2JqZWN0V2l0aG91dFByb3BlcnRpZXModGhpcy5wcm9wcywgW10pO1xuXG4gICAgICByZXR1cm4gX3JlYWN0Mi5kZWZhdWx0LmNyZWF0ZUVsZW1lbnQoX0NvbGxlY3Rpb25WaWV3Mi5kZWZhdWx0LCBfZXh0ZW5kcyh7XG4gICAgICAgIGNlbGxMYXlvdXRNYW5hZ2VyOiB0aGlzLFxuICAgICAgICBpc1Njcm9sbGluZ0NoYW5nZTogdGhpcy5faXNTY3JvbGxpbmdDaGFuZ2UsXG4gICAgICAgIHJlZjogZnVuY3Rpb24gcmVmKF9yZWYpIHtcbiAgICAgICAgICBfdGhpczIuX2NvbGxlY3Rpb25WaWV3ID0gX3JlZjtcbiAgICAgICAgfVxuICAgICAgfSwgcHJvcHMpKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdzaG91bGRDb21wb25lbnRVcGRhdGUnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBzaG91bGRDb21wb25lbnRVcGRhdGUobmV4dFByb3BzLCBuZXh0U3RhdGUpIHtcbiAgICAgIHJldHVybiAoMCwgX3JlYWN0QWRkb25zU2hhbGxvd0NvbXBhcmUyLmRlZmF1bHQpKHRoaXMsIG5leHRQcm9wcywgbmV4dFN0YXRlKTtcbiAgICB9XG5cbiAgICAvKiogQ2VsbExheW91dE1hbmFnZXIgaW50ZXJmYWNlICovXG5cbiAgfSwge1xuICAgIGtleTogJ2NhbGN1bGF0ZVNpemVBbmRQb3NpdGlvbkRhdGEnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBjYWxjdWxhdGVTaXplQW5kUG9zaXRpb25EYXRhKCkge1xuICAgICAgdmFyIF9wcm9wcyA9IHRoaXMucHJvcHM7XG4gICAgICB2YXIgY2VsbENvdW50ID0gX3Byb3BzLmNlbGxDb3VudDtcbiAgICAgIHZhciBjZWxsU2l6ZUFuZFBvc2l0aW9uR2V0dGVyID0gX3Byb3BzLmNlbGxTaXplQW5kUG9zaXRpb25HZXR0ZXI7XG4gICAgICB2YXIgc2VjdGlvblNpemUgPSBfcHJvcHMuc2VjdGlvblNpemU7XG5cblxuICAgICAgdmFyIGRhdGEgPSAoMCwgX2NhbGN1bGF0ZVNpemVBbmRQb3NpdGlvbkRhdGEzLmRlZmF1bHQpKHtcbiAgICAgICAgY2VsbENvdW50OiBjZWxsQ291bnQsXG4gICAgICAgIGNlbGxTaXplQW5kUG9zaXRpb25HZXR0ZXI6IGNlbGxTaXplQW5kUG9zaXRpb25HZXR0ZXIsXG4gICAgICAgIHNlY3Rpb25TaXplOiBzZWN0aW9uU2l6ZVxuICAgICAgfSk7XG5cbiAgICAgIHRoaXMuX2NlbGxNZXRhZGF0YSA9IGRhdGEuY2VsbE1ldGFkYXRhO1xuICAgICAgdGhpcy5fc2VjdGlvbk1hbmFnZXIgPSBkYXRhLnNlY3Rpb25NYW5hZ2VyO1xuICAgICAgdGhpcy5faGVpZ2h0ID0gZGF0YS5oZWlnaHQ7XG4gICAgICB0aGlzLl93aWR0aCA9IGRhdGEud2lkdGg7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgbW9zdCByZWNlbnRseSByZW5kZXJlZCBzZXQgb2YgY2VsbCBpbmRpY2VzLlxuICAgICAqL1xuXG4gIH0sIHtcbiAgICBrZXk6ICdnZXRMYXN0UmVuZGVyZWRJbmRpY2VzJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gZ2V0TGFzdFJlbmRlcmVkSW5kaWNlcygpIHtcbiAgICAgIHJldHVybiB0aGlzLl9sYXN0UmVuZGVyZWRDZWxsSW5kaWNlcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDYWxjdWxhdGVzIHRoZSBtaW5pbXVtIGFtb3VudCBvZiBjaGFuZ2UgZnJvbSB0aGUgY3VycmVudCBzY3JvbGwgcG9zaXRpb24gdG8gZW5zdXJlIHRoZSBzcGVjaWZpZWQgY2VsbCBpcyAoZnVsbHkpIHZpc2libGUuXG4gICAgICovXG5cbiAgfSwge1xuICAgIGtleTogJ2dldFNjcm9sbFBvc2l0aW9uRm9yQ2VsbCcsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGdldFNjcm9sbFBvc2l0aW9uRm9yQ2VsbChfcmVmMikge1xuICAgICAgdmFyIGFsaWduID0gX3JlZjIuYWxpZ247XG4gICAgICB2YXIgY2VsbEluZGV4ID0gX3JlZjIuY2VsbEluZGV4O1xuICAgICAgdmFyIGhlaWdodCA9IF9yZWYyLmhlaWdodDtcbiAgICAgIHZhciBzY3JvbGxMZWZ0ID0gX3JlZjIuc2Nyb2xsTGVmdDtcbiAgICAgIHZhciBzY3JvbGxUb3AgPSBfcmVmMi5zY3JvbGxUb3A7XG4gICAgICB2YXIgd2lkdGggPSBfcmVmMi53aWR0aDtcbiAgICAgIHZhciBjZWxsQ291bnQgPSB0aGlzLnByb3BzLmNlbGxDb3VudDtcblxuXG4gICAgICBpZiAoY2VsbEluZGV4ID49IDAgJiYgY2VsbEluZGV4IDwgY2VsbENvdW50KSB7XG4gICAgICAgIHZhciBjZWxsTWV0YWRhdGEgPSB0aGlzLl9jZWxsTWV0YWRhdGFbY2VsbEluZGV4XTtcblxuICAgICAgICBzY3JvbGxMZWZ0ID0gKDAsIF9nZXRVcGRhdGVkT2Zmc2V0Rm9ySW5kZXgyLmRlZmF1bHQpKHtcbiAgICAgICAgICBhbGlnbjogYWxpZ24sXG4gICAgICAgICAgY2VsbE9mZnNldDogY2VsbE1ldGFkYXRhLngsXG4gICAgICAgICAgY2VsbFNpemU6IGNlbGxNZXRhZGF0YS53aWR0aCxcbiAgICAgICAgICBjb250YWluZXJTaXplOiB3aWR0aCxcbiAgICAgICAgICBjdXJyZW50T2Zmc2V0OiBzY3JvbGxMZWZ0LFxuICAgICAgICAgIHRhcmdldEluZGV4OiBjZWxsSW5kZXhcbiAgICAgICAgfSk7XG5cbiAgICAgICAgc2Nyb2xsVG9wID0gKDAsIF9nZXRVcGRhdGVkT2Zmc2V0Rm9ySW5kZXgyLmRlZmF1bHQpKHtcbiAgICAgICAgICBhbGlnbjogYWxpZ24sXG4gICAgICAgICAgY2VsbE9mZnNldDogY2VsbE1ldGFkYXRhLnksXG4gICAgICAgICAgY2VsbFNpemU6IGNlbGxNZXRhZGF0YS5oZWlnaHQsXG4gICAgICAgICAgY29udGFpbmVyU2l6ZTogaGVpZ2h0LFxuICAgICAgICAgIGN1cnJlbnRPZmZzZXQ6IHNjcm9sbFRvcCxcbiAgICAgICAgICB0YXJnZXRJbmRleDogY2VsbEluZGV4XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBzY3JvbGxMZWZ0OiBzY3JvbGxMZWZ0LFxuICAgICAgICBzY3JvbGxUb3A6IHNjcm9sbFRvcFxuICAgICAgfTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdnZXRUb3RhbFNpemUnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBnZXRUb3RhbFNpemUoKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBoZWlnaHQ6IHRoaXMuX2hlaWdodCxcbiAgICAgICAgd2lkdGg6IHRoaXMuX3dpZHRoXG4gICAgICB9O1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ2NlbGxSZW5kZXJlcnMnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBjZWxsUmVuZGVyZXJzKF9yZWYzKSB7XG4gICAgICB2YXIgX3RoaXMzID0gdGhpcztcblxuICAgICAgdmFyIGhlaWdodCA9IF9yZWYzLmhlaWdodDtcbiAgICAgIHZhciBpc1Njcm9sbGluZyA9IF9yZWYzLmlzU2Nyb2xsaW5nO1xuICAgICAgdmFyIHdpZHRoID0gX3JlZjMud2lkdGg7XG4gICAgICB2YXIgeCA9IF9yZWYzLng7XG4gICAgICB2YXIgeSA9IF9yZWYzLnk7XG4gICAgICB2YXIgX3Byb3BzMiA9IHRoaXMucHJvcHM7XG4gICAgICB2YXIgY2VsbEdyb3VwUmVuZGVyZXIgPSBfcHJvcHMyLmNlbGxHcm91cFJlbmRlcmVyO1xuICAgICAgdmFyIGNlbGxSZW5kZXJlciA9IF9wcm9wczIuY2VsbFJlbmRlcmVyO1xuXG4gICAgICAvLyBTdG9yZSBmb3IgbGF0ZXIgY2FsbHMgdG8gZ2V0TGFzdFJlbmRlcmVkSW5kaWNlcygpXG5cbiAgICAgIHRoaXMuX2xhc3RSZW5kZXJlZENlbGxJbmRpY2VzID0gdGhpcy5fc2VjdGlvbk1hbmFnZXIuZ2V0Q2VsbEluZGljZXMoe1xuICAgICAgICBoZWlnaHQ6IGhlaWdodCxcbiAgICAgICAgd2lkdGg6IHdpZHRoLFxuICAgICAgICB4OiB4LFxuICAgICAgICB5OiB5XG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIGNlbGxHcm91cFJlbmRlcmVyKHtcbiAgICAgICAgY2VsbENhY2hlOiB0aGlzLl9jZWxsQ2FjaGUsXG4gICAgICAgIGNlbGxSZW5kZXJlcjogY2VsbFJlbmRlcmVyLFxuICAgICAgICBjZWxsU2l6ZUFuZFBvc2l0aW9uR2V0dGVyOiBmdW5jdGlvbiBjZWxsU2l6ZUFuZFBvc2l0aW9uR2V0dGVyKF9yZWY0KSB7XG4gICAgICAgICAgdmFyIGluZGV4ID0gX3JlZjQuaW5kZXg7XG4gICAgICAgICAgcmV0dXJuIF90aGlzMy5fc2VjdGlvbk1hbmFnZXIuZ2V0Q2VsbE1ldGFkYXRhKHsgaW5kZXg6IGluZGV4IH0pO1xuICAgICAgICB9LFxuICAgICAgICBpbmRpY2VzOiB0aGlzLl9sYXN0UmVuZGVyZWRDZWxsSW5kaWNlcyxcbiAgICAgICAgaXNTY3JvbGxpbmc6IGlzU2Nyb2xsaW5nXG4gICAgICB9KTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfaXNTY3JvbGxpbmdDaGFuZ2UnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBfaXNTY3JvbGxpbmdDaGFuZ2UoaXNTY3JvbGxpbmcpIHtcbiAgICAgIGlmICghaXNTY3JvbGxpbmcpIHtcbiAgICAgICAgdGhpcy5fY2VsbENhY2hlID0gW107XG4gICAgICB9XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIENvbGxlY3Rpb247XG59KF9yZWFjdC5Db21wb25lbnQpO1xuXG5Db2xsZWN0aW9uLnByb3BUeXBlcyA9IHtcbiAgJ2FyaWEtbGFiZWwnOiBfcmVhY3QuUHJvcFR5cGVzLnN0cmluZyxcblxuICAvKipcbiAgICogTnVtYmVyIG9mIGNlbGxzIGluIENvbGxlY3Rpb24uXG4gICAqL1xuICBjZWxsQ291bnQ6IF9yZWFjdC5Qcm9wVHlwZXMubnVtYmVyLmlzUmVxdWlyZWQsXG5cbiAgLyoqXG4gICAqIFJlc3BvbnNpYmxlIGZvciByZW5kZXJpbmcgYSBncm91cCBvZiBjZWxscyBnaXZlbiB0aGVpciBpbmRpY2VzLlxuICAgKiBTaG91bGQgaW1wbGVtZW50IHRoZSBmb2xsb3dpbmcgaW50ZXJmYWNlOiAoe1xuICAgKiAgIGNlbGxTaXplQW5kUG9zaXRpb25HZXR0ZXI6RnVuY3Rpb24sXG4gICAqICAgaW5kaWNlczogQXJyYXk8bnVtYmVyPixcbiAgICogICBjZWxsUmVuZGVyZXI6IEZ1bmN0aW9uXG4gICAqIH0pOiBBcnJheTxQcm9wVHlwZXMubm9kZT5cbiAgICovXG4gIGNlbGxHcm91cFJlbmRlcmVyOiBfcmVhY3QuUHJvcFR5cGVzLmZ1bmMuaXNSZXF1aXJlZCxcblxuICAvKipcbiAgICogUmVzcG9uc2libGUgZm9yIHJlbmRlcmluZyBhIGNlbGwgZ2l2ZW4gYW4gcm93IGFuZCBjb2x1bW4gaW5kZXguXG4gICAqIFNob3VsZCBpbXBsZW1lbnQgdGhlIGZvbGxvd2luZyBpbnRlcmZhY2U6ICh7IGluZGV4OiBudW1iZXIgfSk6IFByb3BUeXBlcy5lbGVtZW50XG4gICAqL1xuICBjZWxsUmVuZGVyZXI6IF9yZWFjdC5Qcm9wVHlwZXMuZnVuYy5pc1JlcXVpcmVkLFxuXG4gIC8qKlxuICAgKiBDYWxsYmFjayByZXNwb25zaWJsZSBmb3IgcmV0dXJuaW5nIHNpemUgYW5kIG9mZnNldC9wb3NpdGlvbiBpbmZvcm1hdGlvbiBmb3IgYSBnaXZlbiBjZWxsIChpbmRleCkuXG4gICAqICh7IGluZGV4OiBudW1iZXIgfSk6IHsgaGVpZ2h0OiBudW1iZXIsIHdpZHRoOiBudW1iZXIsIHg6IG51bWJlciwgeTogbnVtYmVyIH1cbiAgICovXG4gIGNlbGxTaXplQW5kUG9zaXRpb25HZXR0ZXI6IF9yZWFjdC5Qcm9wVHlwZXMuZnVuYy5pc1JlcXVpcmVkLFxuXG4gIC8qKlxuICAgKiBPcHRpb25hbGx5IG92ZXJyaWRlIHRoZSBzaXplIG9mIHRoZSBzZWN0aW9ucyBhIENvbGxlY3Rpb24ncyBjZWxscyBhcmUgc3BsaXQgaW50by5cbiAgICovXG4gIHNlY3Rpb25TaXplOiBfcmVhY3QuUHJvcFR5cGVzLm51bWJlclxufTtcbkNvbGxlY3Rpb24uZGVmYXVsdFByb3BzID0ge1xuICAnYXJpYS1sYWJlbCc6ICdncmlkJyxcbiAgY2VsbEdyb3VwUmVuZGVyZXI6IGRlZmF1bHRDZWxsR3JvdXBSZW5kZXJlclxufTtcbmV4cG9ydHMuZGVmYXVsdCA9IENvbGxlY3Rpb247XG5cblxuZnVuY3Rpb24gZGVmYXVsdENlbGxHcm91cFJlbmRlcmVyKF9yZWY1KSB7XG4gIHZhciBjZWxsQ2FjaGUgPSBfcmVmNS5jZWxsQ2FjaGU7XG4gIHZhciBjZWxsUmVuZGVyZXIgPSBfcmVmNS5jZWxsUmVuZGVyZXI7XG4gIHZhciBjZWxsU2l6ZUFuZFBvc2l0aW9uR2V0dGVyID0gX3JlZjUuY2VsbFNpemVBbmRQb3NpdGlvbkdldHRlcjtcbiAgdmFyIGluZGljZXMgPSBfcmVmNS5pbmRpY2VzO1xuICB2YXIgaXNTY3JvbGxpbmcgPSBfcmVmNS5pc1Njcm9sbGluZztcblxuICByZXR1cm4gaW5kaWNlcy5tYXAoZnVuY3Rpb24gKGluZGV4KSB7XG4gICAgdmFyIGNlbGxNZXRhZGF0YSA9IGNlbGxTaXplQW5kUG9zaXRpb25HZXR0ZXIoeyBpbmRleDogaW5kZXggfSk7XG5cbiAgICAvLyBBdm9pZCByZS1jcmVhdGluZyBjZWxscyB3aGlsZSBzY3JvbGxpbmcuXG4gICAgLy8gVGhpcyBjYW4gbGVhZCB0byB0aGUgc2FtZSBjZWxsIGJlaW5nIGNyZWF0ZWQgbWFueSB0aW1lcyBhbmQgY2FuIGNhdXNlIHBlcmZvcm1hbmNlIGlzc3VlcyBmb3IgXCJoZWF2eVwiIGNlbGxzLlxuICAgIC8vIElmIGEgc2Nyb2xsIGlzIGluIHByb2dyZXNzLSBjYWNoZSBhbmQgcmV1c2UgY2VsbHMuXG4gICAgLy8gVGhpcyBjYWNoZSB3aWxsIGJlIHRocm93biBhd2F5IG9uY2Ugc2Nyb2xsaW5nIGNvbXBsZXRzLlxuICAgIHZhciByZW5kZXJlZENlbGwgPSB2b2lkIDA7XG5cbiAgICBpZiAoaXNTY3JvbGxpbmcpIHtcbiAgICAgIGlmICghKGluZGV4IGluIGNlbGxDYWNoZSkpIHtcbiAgICAgICAgY2VsbENhY2hlW2luZGV4XSA9IGNlbGxSZW5kZXJlcih7XG4gICAgICAgICAgaW5kZXg6IGluZGV4LFxuICAgICAgICAgIGlzU2Nyb2xsaW5nOiBpc1Njcm9sbGluZ1xuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgcmVuZGVyZWRDZWxsID0gY2VsbENhY2hlW2luZGV4XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmVuZGVyZWRDZWxsID0gY2VsbFJlbmRlcmVyKHtcbiAgICAgICAgaW5kZXg6IGluZGV4LFxuICAgICAgICBpc1Njcm9sbGluZzogaXNTY3JvbGxpbmdcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmIChyZW5kZXJlZENlbGwgPT0gbnVsbCB8fCByZW5kZXJlZENlbGwgPT09IGZhbHNlKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICByZXR1cm4gX3JlYWN0Mi5kZWZhdWx0LmNyZWF0ZUVsZW1lbnQoXG4gICAgICAnZGl2JyxcbiAgICAgIHtcbiAgICAgICAgY2xhc3NOYW1lOiAnQ29sbGVjdGlvbl9fY2VsbCcsXG4gICAgICAgIGtleTogaW5kZXgsXG4gICAgICAgIHN0eWxlOiB7XG4gICAgICAgICAgaGVpZ2h0OiBjZWxsTWV0YWRhdGEuaGVpZ2h0LFxuICAgICAgICAgIGxlZnQ6IGNlbGxNZXRhZGF0YS54LFxuICAgICAgICAgIHRvcDogY2VsbE1ldGFkYXRhLnksXG4gICAgICAgICAgd2lkdGg6IGNlbGxNZXRhZGF0YS53aWR0aFxuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgcmVuZGVyZWRDZWxsXG4gICAgKTtcbiAgfSkuZmlsdGVyKGZ1bmN0aW9uIChyZW5kZXJlZENlbGwpIHtcbiAgICByZXR1cm4gISFyZW5kZXJlZENlbGw7XG4gIH0pO1xufSIsIid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9leHRlbmRzID0gT2JqZWN0LmFzc2lnbiB8fCBmdW5jdGlvbiAodGFyZ2V0KSB7IGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7IHZhciBzb3VyY2UgPSBhcmd1bWVudHNbaV07IGZvciAodmFyIGtleSBpbiBzb3VyY2UpIHsgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzb3VyY2UsIGtleSkpIHsgdGFyZ2V0W2tleV0gPSBzb3VyY2Vba2V5XTsgfSB9IH0gcmV0dXJuIHRhcmdldDsgfTtcblxudmFyIF9jcmVhdGVDbGFzcyA9IGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmIChcInZhbHVlXCIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0oKTtcblxudmFyIF9yZWFjdCA9IHJlcXVpcmUoJ3JlYWN0Jyk7XG5cbnZhciBfcmVhY3QyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfcmVhY3QpO1xuXG52YXIgX2NsYXNzbmFtZXMgPSByZXF1aXJlKCdjbGFzc25hbWVzJyk7XG5cbnZhciBfY2xhc3NuYW1lczIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9jbGFzc25hbWVzKTtcblxudmFyIF9jcmVhdGVDYWxsYmFja01lbW9pemVyID0gcmVxdWlyZSgnLi4vdXRpbHMvY3JlYXRlQ2FsbGJhY2tNZW1vaXplcicpO1xuXG52YXIgX2NyZWF0ZUNhbGxiYWNrTWVtb2l6ZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfY3JlYXRlQ2FsbGJhY2tNZW1vaXplcik7XG5cbnZhciBfc2Nyb2xsYmFyU2l6ZSA9IHJlcXVpcmUoJ2RvbS1oZWxwZXJzL3V0aWwvc2Nyb2xsYmFyU2l6ZScpO1xuXG52YXIgX3Njcm9sbGJhclNpemUyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfc2Nyb2xsYmFyU2l6ZSk7XG5cbnZhciBfcmFmID0gcmVxdWlyZSgncmFmJyk7XG5cbnZhciBfcmFmMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3JhZik7XG5cbnZhciBfcmVhY3RBZGRvbnNTaGFsbG93Q29tcGFyZSA9IHJlcXVpcmUoJ3JlYWN0LWFkZG9ucy1zaGFsbG93LWNvbXBhcmUnKTtcblxudmFyIF9yZWFjdEFkZG9uc1NoYWxsb3dDb21wYXJlMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3JlYWN0QWRkb25zU2hhbGxvd0NvbXBhcmUpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyBkZWZhdWx0OiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb25cIik7IH0gfVxuXG5mdW5jdGlvbiBfcG9zc2libGVDb25zdHJ1Y3RvclJldHVybihzZWxmLCBjYWxsKSB7IGlmICghc2VsZikgeyB0aHJvdyBuZXcgUmVmZXJlbmNlRXJyb3IoXCJ0aGlzIGhhc24ndCBiZWVuIGluaXRpYWxpc2VkIC0gc3VwZXIoKSBoYXNuJ3QgYmVlbiBjYWxsZWRcIik7IH0gcmV0dXJuIGNhbGwgJiYgKHR5cGVvZiBjYWxsID09PSBcIm9iamVjdFwiIHx8IHR5cGVvZiBjYWxsID09PSBcImZ1bmN0aW9uXCIpID8gY2FsbCA6IHNlbGY7IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gXCJmdW5jdGlvblwiICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgXCIgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIE9iamVjdC5zZXRQcm90b3R5cGVPZiA/IE9iamVjdC5zZXRQcm90b3R5cGVPZihzdWJDbGFzcywgc3VwZXJDbGFzcykgOiBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbi8vIEBUT0RPIEl0IHdvdWxkIGJlIG5pY2UgdG8gcmVmYWN0b3IgR3JpZCB0byB1c2UgdGhpcyBjb2RlIGFzIHdlbGwuXG5cbi8qKlxuICogU3BlY2lmaWVzIHRoZSBudW1iZXIgb2YgbWlsaXNlY29uZHMgZHVyaW5nIHdoaWNoIHRvIGRpc2FibGUgcG9pbnRlciBldmVudHMgd2hpbGUgYSBzY3JvbGwgaXMgaW4gcHJvZ3Jlc3MuXG4gKiBUaGlzIGltcHJvdmVzIHBlcmZvcm1hbmNlIGFuZCBtYWtlcyBzY3JvbGxpbmcgc21vb3RoZXIuXG4gKi9cbnZhciBJU19TQ1JPTExJTkdfVElNRU9VVCA9IDE1MDtcblxuLyoqXG4gKiBDb250cm9scyB3aGV0aGVyIHRoZSBHcmlkIHVwZGF0ZXMgdGhlIERPTSBlbGVtZW50J3Mgc2Nyb2xsTGVmdC9zY3JvbGxUb3AgYmFzZWQgb24gdGhlIGN1cnJlbnQgc3RhdGUgb3IganVzdCBvYnNlcnZlcyBpdC5cbiAqIFRoaXMgcHJldmVudHMgR3JpZCBmcm9tIGludGVycnVwdGluZyBtb3VzZS13aGVlbCBhbmltYXRpb25zIChzZWUgaXNzdWUgIzIpLlxuICovXG52YXIgU0NST0xMX1BPU0lUSU9OX0NIQU5HRV9SRUFTT05TID0ge1xuICBPQlNFUlZFRDogJ29ic2VydmVkJyxcbiAgUkVRVUVTVEVEOiAncmVxdWVzdGVkJ1xufTtcblxuLyoqXG4gKiBNb25pdG9ycyBjaGFuZ2VzIGluIHByb3BlcnRpZXMgKGVnLiBjZWxsQ291bnQpIGFuZCBzdGF0ZSAoZWcuIHNjcm9sbCBvZmZzZXRzKSB0byBkZXRlcm1pbmUgd2hlbiByZW5kZXJpbmcgbmVlZHMgdG8gb2NjdXIuXG4gKiBUaGlzIGNvbXBvbmVudCBkb2VzIG5vdCByZW5kZXIgYW55IHZpc2libGUgY29udGVudCBpdHNlbGY7IGl0IGRlZmVycyB0byB0aGUgc3BlY2lmaWVkIDpjZWxsTGF5b3V0TWFuYWdlci5cbiAqL1xuXG52YXIgQ29sbGVjdGlvblZpZXcgPSBmdW5jdGlvbiAoX0NvbXBvbmVudCkge1xuICBfaW5oZXJpdHMoQ29sbGVjdGlvblZpZXcsIF9Db21wb25lbnQpO1xuXG4gIGZ1bmN0aW9uIENvbGxlY3Rpb25WaWV3KHByb3BzLCBjb250ZXh0KSB7XG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIENvbGxlY3Rpb25WaWV3KTtcblxuICAgIHZhciBfdGhpcyA9IF9wb3NzaWJsZUNvbnN0cnVjdG9yUmV0dXJuKHRoaXMsIChDb2xsZWN0aW9uVmlldy5fX3Byb3RvX18gfHwgT2JqZWN0LmdldFByb3RvdHlwZU9mKENvbGxlY3Rpb25WaWV3KSkuY2FsbCh0aGlzLCBwcm9wcywgY29udGV4dCkpO1xuXG4gICAgX3RoaXMuc3RhdGUgPSB7XG4gICAgICBjYWxjdWxhdGVTaXplQW5kUG9zaXRpb25EYXRhT25OZXh0VXBkYXRlOiBmYWxzZSxcbiAgICAgIGlzU2Nyb2xsaW5nOiBmYWxzZSxcbiAgICAgIHNjcm9sbExlZnQ6IDAsXG4gICAgICBzY3JvbGxUb3A6IDBcbiAgICB9O1xuXG4gICAgLy8gSW52b2tlcyBjYWxsYmFja3Mgb25seSB3aGVuIHRoZWlyIHZhbHVlcyBoYXZlIGNoYW5nZWQuXG4gICAgX3RoaXMuX29uU2VjdGlvblJlbmRlcmVkTWVtb2l6ZXIgPSAoMCwgX2NyZWF0ZUNhbGxiYWNrTWVtb2l6ZXIyLmRlZmF1bHQpKCk7XG4gICAgX3RoaXMuX29uU2Nyb2xsTWVtb2l6ZXIgPSAoMCwgX2NyZWF0ZUNhbGxiYWNrTWVtb2l6ZXIyLmRlZmF1bHQpKGZhbHNlKTtcblxuICAgIC8vIEJpbmQgZnVuY3Rpb25zIHRvIGluc3RhbmNlIHNvIHRoZXkgZG9uJ3QgbG9zZSBjb250ZXh0IHdoZW4gcGFzc2VkIGFyb3VuZC5cbiAgICBfdGhpcy5faW52b2tlT25TZWN0aW9uUmVuZGVyZWRIZWxwZXIgPSBfdGhpcy5faW52b2tlT25TZWN0aW9uUmVuZGVyZWRIZWxwZXIuYmluZChfdGhpcyk7XG4gICAgX3RoaXMuX29uU2Nyb2xsID0gX3RoaXMuX29uU2Nyb2xsLmJpbmQoX3RoaXMpO1xuICAgIF90aGlzLl91cGRhdGVTY3JvbGxQb3NpdGlvbkZvclNjcm9sbFRvQ2VsbCA9IF90aGlzLl91cGRhdGVTY3JvbGxQb3NpdGlvbkZvclNjcm9sbFRvQ2VsbC5iaW5kKF90aGlzKTtcbiAgICByZXR1cm4gX3RoaXM7XG4gIH1cblxuICAvKipcbiAgICogRm9yY2VkIHJlY29tcHV0ZSBvZiBjZWxsIHNpemVzIGFuZCBwb3NpdGlvbnMuXG4gICAqIFRoaXMgZnVuY3Rpb24gc2hvdWxkIGJlIGNhbGxlZCBpZiBjZWxsIHNpemVzIGhhdmUgY2hhbmdlZCBidXQgbm90aGluZyBlbHNlIGhhcy5cbiAgICogU2luY2UgY2VsbCBwb3NpdGlvbnMgYXJlIGNhbGN1bGF0ZWQgYnkgY2FsbGJhY2tzLCB0aGUgY29sbGVjdGlvbiB2aWV3IGhhcyBubyB3YXkgb2YgZGV0ZWN0aW5nIHdoZW4gdGhlIHVuZGVybHlpbmcgZGF0YSBoYXMgY2hhbmdlZC5cbiAgICovXG5cblxuICBfY3JlYXRlQ2xhc3MoQ29sbGVjdGlvblZpZXcsIFt7XG4gICAga2V5OiAncmVjb21wdXRlQ2VsbFNpemVzQW5kUG9zaXRpb25zJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVjb21wdXRlQ2VsbFNpemVzQW5kUG9zaXRpb25zKCkge1xuICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgIGNhbGN1bGF0ZVNpemVBbmRQb3NpdGlvbkRhdGFPbk5leHRVcGRhdGU6IHRydWVcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gQ29tcG9uZW50IGxpZmVjeWNsZSBtZXRob2RzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cblxuICB9LCB7XG4gICAga2V5OiAnY29tcG9uZW50RGlkTW91bnQnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBjb21wb25lbnREaWRNb3VudCgpIHtcbiAgICAgIHZhciBfcHJvcHMgPSB0aGlzLnByb3BzO1xuICAgICAgdmFyIGNlbGxMYXlvdXRNYW5hZ2VyID0gX3Byb3BzLmNlbGxMYXlvdXRNYW5hZ2VyO1xuICAgICAgdmFyIHNjcm9sbExlZnQgPSBfcHJvcHMuc2Nyb2xsTGVmdDtcbiAgICAgIHZhciBzY3JvbGxUb0NlbGwgPSBfcHJvcHMuc2Nyb2xsVG9DZWxsO1xuICAgICAgdmFyIHNjcm9sbFRvcCA9IF9wcm9wcy5zY3JvbGxUb3A7XG5cbiAgICAgIC8vIElmIHRoaXMgY29tcG9uZW50IHdhcyBmaXJzdCByZW5kZXJlZCBzZXJ2ZXItc2lkZSwgc2Nyb2xsYmFyIHNpemUgd2lsbCBiZSB1bmRlZmluZWQuXG4gICAgICAvLyBJbiB0aGF0IGV2ZW50IHdlIG5lZWQgdG8gcmVtZWFzdXJlLlxuXG4gICAgICBpZiAoIXRoaXMuX3Njcm9sbGJhclNpemVNZWFzdXJlZCkge1xuICAgICAgICB0aGlzLl9zY3JvbGxiYXJTaXplID0gKDAsIF9zY3JvbGxiYXJTaXplMi5kZWZhdWx0KSgpO1xuICAgICAgICB0aGlzLl9zY3JvbGxiYXJTaXplTWVhc3VyZWQgPSB0cnVlO1xuICAgICAgICB0aGlzLnNldFN0YXRlKHt9KTtcbiAgICAgIH1cblxuICAgICAgaWYgKHNjcm9sbFRvQ2VsbCA+PSAwKSB7XG4gICAgICAgIHRoaXMuX3VwZGF0ZVNjcm9sbFBvc2l0aW9uRm9yU2Nyb2xsVG9DZWxsKCk7XG4gICAgICB9IGVsc2UgaWYgKHNjcm9sbExlZnQgPj0gMCB8fCBzY3JvbGxUb3AgPj0gMCkge1xuICAgICAgICB0aGlzLl9zZXRTY3JvbGxQb3NpdGlvbih7IHNjcm9sbExlZnQ6IHNjcm9sbExlZnQsIHNjcm9sbFRvcDogc2Nyb2xsVG9wIH0pO1xuICAgICAgfVxuXG4gICAgICAvLyBVcGRhdGUgb25TZWN0aW9uUmVuZGVyZWQgY2FsbGJhY2suXG4gICAgICB0aGlzLl9pbnZva2VPblNlY3Rpb25SZW5kZXJlZEhlbHBlcigpO1xuXG4gICAgICB2YXIgX2NlbGxMYXlvdXRNYW5hZ2VyJGdlID0gY2VsbExheW91dE1hbmFnZXIuZ2V0VG90YWxTaXplKCk7XG5cbiAgICAgIHZhciB0b3RhbEhlaWdodCA9IF9jZWxsTGF5b3V0TWFuYWdlciRnZS5oZWlnaHQ7XG4gICAgICB2YXIgdG90YWxXaWR0aCA9IF9jZWxsTGF5b3V0TWFuYWdlciRnZS53aWR0aDtcblxuICAgICAgLy8gSW5pdGlhbGl6ZSBvblNjcm9sbCBjYWxsYmFjay5cblxuICAgICAgdGhpcy5faW52b2tlT25TY3JvbGxNZW1vaXplcih7XG4gICAgICAgIHNjcm9sbExlZnQ6IHNjcm9sbExlZnQgfHwgMCxcbiAgICAgICAgc2Nyb2xsVG9wOiBzY3JvbGxUb3AgfHwgMCxcbiAgICAgICAgdG90YWxIZWlnaHQ6IHRvdGFsSGVpZ2h0LFxuICAgICAgICB0b3RhbFdpZHRoOiB0b3RhbFdpZHRoXG4gICAgICB9KTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdjb21wb25lbnREaWRVcGRhdGUnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBjb21wb25lbnREaWRVcGRhdGUocHJldlByb3BzLCBwcmV2U3RhdGUpIHtcbiAgICAgIHZhciBfcHJvcHMyID0gdGhpcy5wcm9wcztcbiAgICAgIHZhciBoZWlnaHQgPSBfcHJvcHMyLmhlaWdodDtcbiAgICAgIHZhciBzY3JvbGxUb0NlbGwgPSBfcHJvcHMyLnNjcm9sbFRvQ2VsbDtcbiAgICAgIHZhciB3aWR0aCA9IF9wcm9wczIud2lkdGg7XG4gICAgICB2YXIgX3N0YXRlID0gdGhpcy5zdGF0ZTtcbiAgICAgIHZhciBzY3JvbGxMZWZ0ID0gX3N0YXRlLnNjcm9sbExlZnQ7XG4gICAgICB2YXIgc2Nyb2xsUG9zaXRpb25DaGFuZ2VSZWFzb24gPSBfc3RhdGUuc2Nyb2xsUG9zaXRpb25DaGFuZ2VSZWFzb247XG4gICAgICB2YXIgc2Nyb2xsVG9BbGlnbm1lbnQgPSBfc3RhdGUuc2Nyb2xsVG9BbGlnbm1lbnQ7XG4gICAgICB2YXIgc2Nyb2xsVG9wID0gX3N0YXRlLnNjcm9sbFRvcDtcblxuICAgICAgLy8gTWFrZSBzdXJlIHJlcXVlc3RlZCBjaGFuZ2VzIHRvIDpzY3JvbGxMZWZ0IG9yIDpzY3JvbGxUb3AgZ2V0IGFwcGxpZWQuXG4gICAgICAvLyBBc3NpZ25pbmcgdG8gc2Nyb2xsTGVmdC9zY3JvbGxUb3AgdGVsbHMgdGhlIGJyb3dzZXIgdG8gaW50ZXJydXB0IGFueSBydW5uaW5nIHNjcm9sbCBhbmltYXRpb25zLFxuICAgICAgLy8gQW5kIHRvIGRpc2NhcmQgYW55IHBlbmRpbmcgYXN5bmMgY2hhbmdlcyB0byB0aGUgc2Nyb2xsIHBvc2l0aW9uIHRoYXQgbWF5IGhhdmUgaGFwcGVuZWQgaW4gdGhlIG1lYW50aW1lIChlLmcuIG9uIGEgc2VwYXJhdGUgc2Nyb2xsaW5nIHRocmVhZCkuXG4gICAgICAvLyBTbyB3ZSBvbmx5IHNldCB0aGVzZSB3aGVuIHdlIHJlcXVpcmUgYW4gYWRqdXN0bWVudCBvZiB0aGUgc2Nyb2xsIHBvc2l0aW9uLlxuICAgICAgLy8gU2VlIGlzc3VlICMyIGZvciBtb3JlIGluZm9ybWF0aW9uLlxuXG4gICAgICBpZiAoc2Nyb2xsUG9zaXRpb25DaGFuZ2VSZWFzb24gPT09IFNDUk9MTF9QT1NJVElPTl9DSEFOR0VfUkVBU09OUy5SRVFVRVNURUQpIHtcbiAgICAgICAgaWYgKHNjcm9sbExlZnQgPj0gMCAmJiBzY3JvbGxMZWZ0ICE9PSBwcmV2U3RhdGUuc2Nyb2xsTGVmdCAmJiBzY3JvbGxMZWZ0ICE9PSB0aGlzLl9zY3JvbGxpbmdDb250YWluZXIuc2Nyb2xsTGVmdCkge1xuICAgICAgICAgIHRoaXMuX3Njcm9sbGluZ0NvbnRhaW5lci5zY3JvbGxMZWZ0ID0gc2Nyb2xsTGVmdDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoc2Nyb2xsVG9wID49IDAgJiYgc2Nyb2xsVG9wICE9PSBwcmV2U3RhdGUuc2Nyb2xsVG9wICYmIHNjcm9sbFRvcCAhPT0gdGhpcy5fc2Nyb2xsaW5nQ29udGFpbmVyLnNjcm9sbFRvcCkge1xuICAgICAgICAgIHRoaXMuX3Njcm9sbGluZ0NvbnRhaW5lci5zY3JvbGxUb3AgPSBzY3JvbGxUb3A7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gVXBkYXRlIHNjcm9sbCBvZmZzZXRzIGlmIHRoZSBjdXJyZW50IDpzY3JvbGxUb0NlbGwgdmFsdWVzIHJlcXVpcmVzIGl0XG4gICAgICBpZiAoaGVpZ2h0ICE9PSBwcmV2UHJvcHMuaGVpZ2h0IHx8IHNjcm9sbFRvQWxpZ25tZW50ICE9PSBwcmV2UHJvcHMuc2Nyb2xsVG9BbGlnbm1lbnQgfHwgc2Nyb2xsVG9DZWxsICE9PSBwcmV2UHJvcHMuc2Nyb2xsVG9DZWxsIHx8IHdpZHRoICE9PSBwcmV2UHJvcHMud2lkdGgpIHtcbiAgICAgICAgdGhpcy5fdXBkYXRlU2Nyb2xsUG9zaXRpb25Gb3JTY3JvbGxUb0NlbGwoKTtcbiAgICAgIH1cblxuICAgICAgLy8gVXBkYXRlIG9uUm93c1JlbmRlcmVkIGNhbGxiYWNrIGlmIHN0YXJ0L3N0b3AgaW5kaWNlcyBoYXZlIGNoYW5nZWRcbiAgICAgIHRoaXMuX2ludm9rZU9uU2VjdGlvblJlbmRlcmVkSGVscGVyKCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnY29tcG9uZW50V2lsbE1vdW50JyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gY29tcG9uZW50V2lsbE1vdW50KCkge1xuICAgICAgdmFyIGNlbGxMYXlvdXRNYW5hZ2VyID0gdGhpcy5wcm9wcy5jZWxsTGF5b3V0TWFuYWdlcjtcblxuXG4gICAgICBjZWxsTGF5b3V0TWFuYWdlci5jYWxjdWxhdGVTaXplQW5kUG9zaXRpb25EYXRhKCk7XG5cbiAgICAgIC8vIElmIHRoaXMgY29tcG9uZW50IGlzIGJlaW5nIHJlbmRlcmVkIHNlcnZlci1zaWRlLCBnZXRTY3JvbGxiYXJTaXplKCkgd2lsbCByZXR1cm4gdW5kZWZpbmVkLlxuICAgICAgLy8gV2UgaGFuZGxlIHRoaXMgY2FzZSBpbiBjb21wb25lbnREaWRNb3VudCgpXG4gICAgICB0aGlzLl9zY3JvbGxiYXJTaXplID0gKDAsIF9zY3JvbGxiYXJTaXplMi5kZWZhdWx0KSgpO1xuICAgICAgaWYgKHRoaXMuX3Njcm9sbGJhclNpemUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aGlzLl9zY3JvbGxiYXJTaXplTWVhc3VyZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5fc2Nyb2xsYmFyU2l6ZSA9IDA7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLl9zY3JvbGxiYXJTaXplTWVhc3VyZWQgPSB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ2NvbXBvbmVudFdpbGxVbm1vdW50JyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gY29tcG9uZW50V2lsbFVubW91bnQoKSB7XG4gICAgICBpZiAodGhpcy5fZGlzYWJsZVBvaW50ZXJFdmVudHNUaW1lb3V0SWQpIHtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMuX2Rpc2FibGVQb2ludGVyRXZlbnRzVGltZW91dElkKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuX3NldE5leHRTdGF0ZUFuaW1hdGlvbkZyYW1lSWQpIHtcbiAgICAgICAgX3JhZjIuZGVmYXVsdC5jYW5jZWwodGhpcy5fc2V0TmV4dFN0YXRlQW5pbWF0aW9uRnJhbWVJZCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBUaGlzIG1ldGhvZCB1cGRhdGVzIHNjcm9sbExlZnQvc2Nyb2xsVG9wIGluIHN0YXRlIGZvciB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4gICAgICogMSkgRW1wdHkgY29udGVudCAoMCByb3dzIG9yIGNvbHVtbnMpXG4gICAgICogMikgTmV3IHNjcm9sbCBwcm9wcyBvdmVycmlkaW5nIHRoZSBjdXJyZW50IHN0YXRlXG4gICAgICogMykgQ2VsbHMtY291bnQgb3IgY2VsbHMtc2l6ZSBoYXMgY2hhbmdlZCwgbWFraW5nIHByZXZpb3VzIHNjcm9sbCBvZmZzZXRzIGludmFsaWRcbiAgICAgKi9cblxuICB9LCB7XG4gICAga2V5OiAnY29tcG9uZW50V2lsbFVwZGF0ZScsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGNvbXBvbmVudFdpbGxVcGRhdGUobmV4dFByb3BzLCBuZXh0U3RhdGUpIHtcbiAgICAgIGlmIChuZXh0UHJvcHMuY2VsbENvdW50ID09PSAwICYmIChuZXh0U3RhdGUuc2Nyb2xsTGVmdCAhPT0gMCB8fCBuZXh0U3RhdGUuc2Nyb2xsVG9wICE9PSAwKSkge1xuICAgICAgICB0aGlzLl9zZXRTY3JvbGxQb3NpdGlvbih7XG4gICAgICAgICAgc2Nyb2xsTGVmdDogMCxcbiAgICAgICAgICBzY3JvbGxUb3A6IDBcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2UgaWYgKG5leHRQcm9wcy5zY3JvbGxMZWZ0ICE9PSB0aGlzLnByb3BzLnNjcm9sbExlZnQgfHwgbmV4dFByb3BzLnNjcm9sbFRvcCAhPT0gdGhpcy5wcm9wcy5zY3JvbGxUb3ApIHtcbiAgICAgICAgdGhpcy5fc2V0U2Nyb2xsUG9zaXRpb24oe1xuICAgICAgICAgIHNjcm9sbExlZnQ6IG5leHRQcm9wcy5zY3JvbGxMZWZ0LFxuICAgICAgICAgIHNjcm9sbFRvcDogbmV4dFByb3BzLnNjcm9sbFRvcFxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgaWYgKG5leHRQcm9wcy5jZWxsQ291bnQgIT09IHRoaXMucHJvcHMuY2VsbENvdW50IHx8IG5leHRQcm9wcy5jZWxsTGF5b3V0TWFuYWdlciAhPT0gdGhpcy5wcm9wcy5jZWxsTGF5b3V0TWFuYWdlciB8fCBuZXh0U3RhdGUuY2FsY3VsYXRlU2l6ZUFuZFBvc2l0aW9uRGF0YU9uTmV4dFVwZGF0ZSkge1xuICAgICAgICBuZXh0UHJvcHMuY2VsbExheW91dE1hbmFnZXIuY2FsY3VsYXRlU2l6ZUFuZFBvc2l0aW9uRGF0YSgpO1xuICAgICAgfVxuXG4gICAgICBpZiAobmV4dFN0YXRlLmNhbGN1bGF0ZVNpemVBbmRQb3NpdGlvbkRhdGFPbk5leHRVcGRhdGUpIHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgY2FsY3VsYXRlU2l6ZUFuZFBvc2l0aW9uRGF0YU9uTmV4dFVwZGF0ZTogZmFsc2VcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAncmVuZGVyJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVuZGVyKCkge1xuICAgICAgdmFyIF90aGlzMiA9IHRoaXM7XG5cbiAgICAgIHZhciBfcHJvcHMzID0gdGhpcy5wcm9wcztcbiAgICAgIHZhciBhdXRvSGVpZ2h0ID0gX3Byb3BzMy5hdXRvSGVpZ2h0O1xuICAgICAgdmFyIGNlbGxDb3VudCA9IF9wcm9wczMuY2VsbENvdW50O1xuICAgICAgdmFyIGNlbGxMYXlvdXRNYW5hZ2VyID0gX3Byb3BzMy5jZWxsTGF5b3V0TWFuYWdlcjtcbiAgICAgIHZhciBjbGFzc05hbWUgPSBfcHJvcHMzLmNsYXNzTmFtZTtcbiAgICAgIHZhciBoZWlnaHQgPSBfcHJvcHMzLmhlaWdodDtcbiAgICAgIHZhciBob3Jpem9udGFsT3ZlcnNjYW5TaXplID0gX3Byb3BzMy5ob3Jpem9udGFsT3ZlcnNjYW5TaXplO1xuICAgICAgdmFyIG5vQ29udGVudFJlbmRlcmVyID0gX3Byb3BzMy5ub0NvbnRlbnRSZW5kZXJlcjtcbiAgICAgIHZhciBzdHlsZSA9IF9wcm9wczMuc3R5bGU7XG4gICAgICB2YXIgdmVydGljYWxPdmVyc2NhblNpemUgPSBfcHJvcHMzLnZlcnRpY2FsT3ZlcnNjYW5TaXplO1xuICAgICAgdmFyIHdpZHRoID0gX3Byb3BzMy53aWR0aDtcbiAgICAgIHZhciBfc3RhdGUyID0gdGhpcy5zdGF0ZTtcbiAgICAgIHZhciBpc1Njcm9sbGluZyA9IF9zdGF0ZTIuaXNTY3JvbGxpbmc7XG4gICAgICB2YXIgc2Nyb2xsTGVmdCA9IF9zdGF0ZTIuc2Nyb2xsTGVmdDtcbiAgICAgIHZhciBzY3JvbGxUb3AgPSBfc3RhdGUyLnNjcm9sbFRvcDtcblxuICAgICAgdmFyIF9jZWxsTGF5b3V0TWFuYWdlciRnZTIgPSBjZWxsTGF5b3V0TWFuYWdlci5nZXRUb3RhbFNpemUoKTtcblxuICAgICAgdmFyIHRvdGFsSGVpZ2h0ID0gX2NlbGxMYXlvdXRNYW5hZ2VyJGdlMi5oZWlnaHQ7XG4gICAgICB2YXIgdG90YWxXaWR0aCA9IF9jZWxsTGF5b3V0TWFuYWdlciRnZTIud2lkdGg7XG5cbiAgICAgIC8vIFNhZmVseSBleHBhbmQgdGhlIHJlbmRlcmVkIGFyZWEgYnkgdGhlIHNwZWNpZmllZCBvdmVyc2NhbiBhbW91bnRcblxuICAgICAgdmFyIGxlZnQgPSBNYXRoLm1heCgwLCBzY3JvbGxMZWZ0IC0gaG9yaXpvbnRhbE92ZXJzY2FuU2l6ZSk7XG4gICAgICB2YXIgdG9wID0gTWF0aC5tYXgoMCwgc2Nyb2xsVG9wIC0gdmVydGljYWxPdmVyc2NhblNpemUpO1xuICAgICAgdmFyIHJpZ2h0ID0gTWF0aC5taW4odG90YWxXaWR0aCwgc2Nyb2xsTGVmdCArIHdpZHRoICsgaG9yaXpvbnRhbE92ZXJzY2FuU2l6ZSk7XG4gICAgICB2YXIgYm90dG9tID0gTWF0aC5taW4odG90YWxIZWlnaHQsIHNjcm9sbFRvcCArIGhlaWdodCArIHZlcnRpY2FsT3ZlcnNjYW5TaXplKTtcblxuICAgICAgdmFyIGNoaWxkcmVuVG9EaXNwbGF5ID0gaGVpZ2h0ID4gMCAmJiB3aWR0aCA+IDAgPyBjZWxsTGF5b3V0TWFuYWdlci5jZWxsUmVuZGVyZXJzKHtcbiAgICAgICAgaGVpZ2h0OiBib3R0b20gLSB0b3AsXG4gICAgICAgIGlzU2Nyb2xsaW5nOiBpc1Njcm9sbGluZyxcbiAgICAgICAgd2lkdGg6IHJpZ2h0IC0gbGVmdCxcbiAgICAgICAgeDogbGVmdCxcbiAgICAgICAgeTogdG9wXG4gICAgICB9KSA6IFtdO1xuXG4gICAgICB2YXIgY29sbGVjdGlvblN0eWxlID0ge1xuICAgICAgICBoZWlnaHQ6IGF1dG9IZWlnaHQgPyAnYXV0bycgOiBoZWlnaHQsXG4gICAgICAgIHdpZHRoOiB3aWR0aFxuICAgICAgfTtcblxuICAgICAgLy8gRm9yY2UgYnJvd3NlciB0byBoaWRlIHNjcm9sbGJhcnMgd2hlbiB3ZSBrbm93IHRoZXkgYXJlbid0IG5lY2Vzc2FyeS5cbiAgICAgIC8vIE90aGVyd2lzZSBvbmNlIHNjcm9sbGJhcnMgYXBwZWFyIHRoZXkgbWF5IG5vdCBkaXNhcHBlYXIgYWdhaW4uXG4gICAgICAvLyBGb3IgbW9yZSBpbmZvIHNlZSBpc3N1ZSAjMTE2XG4gICAgICB2YXIgdmVydGljYWxTY3JvbGxCYXJTaXplID0gdG90YWxIZWlnaHQgPiBoZWlnaHQgPyB0aGlzLl9zY3JvbGxiYXJTaXplIDogMDtcbiAgICAgIHZhciBob3Jpem9udGFsU2Nyb2xsQmFyU2l6ZSA9IHRvdGFsV2lkdGggPiB3aWR0aCA/IHRoaXMuX3Njcm9sbGJhclNpemUgOiAwO1xuICAgICAgaWYgKHRvdGFsV2lkdGggKyB2ZXJ0aWNhbFNjcm9sbEJhclNpemUgPD0gd2lkdGgpIHtcbiAgICAgICAgY29sbGVjdGlvblN0eWxlLm92ZXJmbG93WCA9ICdoaWRkZW4nO1xuICAgICAgfVxuICAgICAgaWYgKHRvdGFsSGVpZ2h0ICsgaG9yaXpvbnRhbFNjcm9sbEJhclNpemUgPD0gaGVpZ2h0KSB7XG4gICAgICAgIGNvbGxlY3Rpb25TdHlsZS5vdmVyZmxvd1kgPSAnaGlkZGVuJztcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIF9yZWFjdDIuZGVmYXVsdC5jcmVhdGVFbGVtZW50KFxuICAgICAgICAnZGl2JyxcbiAgICAgICAge1xuICAgICAgICAgIHJlZjogZnVuY3Rpb24gcmVmKF9yZWYpIHtcbiAgICAgICAgICAgIF90aGlzMi5fc2Nyb2xsaW5nQ29udGFpbmVyID0gX3JlZjtcbiAgICAgICAgICB9LFxuICAgICAgICAgICdhcmlhLWxhYmVsJzogdGhpcy5wcm9wc1snYXJpYS1sYWJlbCddLFxuICAgICAgICAgIGNsYXNzTmFtZTogKDAsIF9jbGFzc25hbWVzMi5kZWZhdWx0KSgnQ29sbGVjdGlvbicsIGNsYXNzTmFtZSksXG4gICAgICAgICAgb25TY3JvbGw6IHRoaXMuX29uU2Nyb2xsLFxuICAgICAgICAgIHJvbGU6ICdncmlkJyxcbiAgICAgICAgICBzdHlsZTogX2V4dGVuZHMoe30sIGNvbGxlY3Rpb25TdHlsZSwgc3R5bGUpLFxuICAgICAgICAgIHRhYkluZGV4OiAwXG4gICAgICAgIH0sXG4gICAgICAgIGNlbGxDb3VudCA+IDAgJiYgX3JlYWN0Mi5kZWZhdWx0LmNyZWF0ZUVsZW1lbnQoXG4gICAgICAgICAgJ2RpdicsXG4gICAgICAgICAge1xuICAgICAgICAgICAgY2xhc3NOYW1lOiAnQ29sbGVjdGlvbl9faW5uZXJTY3JvbGxDb250YWluZXInLFxuICAgICAgICAgICAgc3R5bGU6IHtcbiAgICAgICAgICAgICAgaGVpZ2h0OiB0b3RhbEhlaWdodCxcbiAgICAgICAgICAgICAgbWF4SGVpZ2h0OiB0b3RhbEhlaWdodCxcbiAgICAgICAgICAgICAgbWF4V2lkdGg6IHRvdGFsV2lkdGgsXG4gICAgICAgICAgICAgIHBvaW50ZXJFdmVudHM6IGlzU2Nyb2xsaW5nID8gJ25vbmUnIDogJycsXG4gICAgICAgICAgICAgIHdpZHRoOiB0b3RhbFdpZHRoXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgICBjaGlsZHJlblRvRGlzcGxheVxuICAgICAgICApLFxuICAgICAgICBjZWxsQ291bnQgPT09IDAgJiYgbm9Db250ZW50UmVuZGVyZXIoKVxuICAgICAgKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdzaG91bGRDb21wb25lbnRVcGRhdGUnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBzaG91bGRDb21wb25lbnRVcGRhdGUobmV4dFByb3BzLCBuZXh0U3RhdGUpIHtcbiAgICAgIHJldHVybiAoMCwgX3JlYWN0QWRkb25zU2hhbGxvd0NvbXBhcmUyLmRlZmF1bHQpKHRoaXMsIG5leHRQcm9wcywgbmV4dFN0YXRlKTtcbiAgICB9XG5cbiAgICAvKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIEhlbHBlciBtZXRob2RzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cblxuICAgIC8qKlxuICAgICAqIFNldHMgYW4gOmlzU2Nyb2xsaW5nIGZsYWcgZm9yIGEgc21hbGwgd2luZG93IG9mIHRpbWUuXG4gICAgICogVGhpcyBmbGFnIGlzIHVzZWQgdG8gZGlzYWJsZSBwb2ludGVyIGV2ZW50cyBvbiB0aGUgc2Nyb2xsYWJsZSBwb3J0aW9uIG9mIHRoZSBDb2xsZWN0aW9uLlxuICAgICAqIFRoaXMgcHJldmVudHMgamVya3kvc3R1dHRlcnkgbW91c2Utd2hlZWwgc2Nyb2xsaW5nLlxuICAgICAqL1xuXG4gIH0sIHtcbiAgICBrZXk6ICdfZW5hYmxlUG9pbnRlckV2ZW50c0FmdGVyRGVsYXknLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBfZW5hYmxlUG9pbnRlckV2ZW50c0FmdGVyRGVsYXkoKSB7XG4gICAgICB2YXIgX3RoaXMzID0gdGhpcztcblxuICAgICAgaWYgKHRoaXMuX2Rpc2FibGVQb2ludGVyRXZlbnRzVGltZW91dElkKSB7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aGlzLl9kaXNhYmxlUG9pbnRlckV2ZW50c1RpbWVvdXRJZCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX2Rpc2FibGVQb2ludGVyRXZlbnRzVGltZW91dElkID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBpc1Njcm9sbGluZ0NoYW5nZSA9IF90aGlzMy5wcm9wcy5pc1Njcm9sbGluZ0NoYW5nZTtcblxuXG4gICAgICAgIGlzU2Nyb2xsaW5nQ2hhbmdlKGZhbHNlKTtcblxuICAgICAgICBfdGhpczMuX2Rpc2FibGVQb2ludGVyRXZlbnRzVGltZW91dElkID0gbnVsbDtcbiAgICAgICAgX3RoaXMzLnNldFN0YXRlKHtcbiAgICAgICAgICBpc1Njcm9sbGluZzogZmFsc2VcbiAgICAgICAgfSk7XG4gICAgICB9LCBJU19TQ1JPTExJTkdfVElNRU9VVCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX2ludm9rZU9uU2VjdGlvblJlbmRlcmVkSGVscGVyJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gX2ludm9rZU9uU2VjdGlvblJlbmRlcmVkSGVscGVyKCkge1xuICAgICAgdmFyIF9wcm9wczQgPSB0aGlzLnByb3BzO1xuICAgICAgdmFyIGNlbGxMYXlvdXRNYW5hZ2VyID0gX3Byb3BzNC5jZWxsTGF5b3V0TWFuYWdlcjtcbiAgICAgIHZhciBvblNlY3Rpb25SZW5kZXJlZCA9IF9wcm9wczQub25TZWN0aW9uUmVuZGVyZWQ7XG5cblxuICAgICAgdGhpcy5fb25TZWN0aW9uUmVuZGVyZWRNZW1vaXplcih7XG4gICAgICAgIGNhbGxiYWNrOiBvblNlY3Rpb25SZW5kZXJlZCxcbiAgICAgICAgaW5kaWNlczoge1xuICAgICAgICAgIGluZGljZXM6IGNlbGxMYXlvdXRNYW5hZ2VyLmdldExhc3RSZW5kZXJlZEluZGljZXMoKVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfaW52b2tlT25TY3JvbGxNZW1vaXplcicsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9pbnZva2VPblNjcm9sbE1lbW9pemVyKF9yZWYyKSB7XG4gICAgICB2YXIgX3RoaXM0ID0gdGhpcztcblxuICAgICAgdmFyIHNjcm9sbExlZnQgPSBfcmVmMi5zY3JvbGxMZWZ0O1xuICAgICAgdmFyIHNjcm9sbFRvcCA9IF9yZWYyLnNjcm9sbFRvcDtcbiAgICAgIHZhciB0b3RhbEhlaWdodCA9IF9yZWYyLnRvdGFsSGVpZ2h0O1xuICAgICAgdmFyIHRvdGFsV2lkdGggPSBfcmVmMi50b3RhbFdpZHRoO1xuXG4gICAgICB0aGlzLl9vblNjcm9sbE1lbW9pemVyKHtcbiAgICAgICAgY2FsbGJhY2s6IGZ1bmN0aW9uIGNhbGxiYWNrKF9yZWYzKSB7XG4gICAgICAgICAgdmFyIHNjcm9sbExlZnQgPSBfcmVmMy5zY3JvbGxMZWZ0O1xuICAgICAgICAgIHZhciBzY3JvbGxUb3AgPSBfcmVmMy5zY3JvbGxUb3A7XG4gICAgICAgICAgdmFyIF9wcm9wczUgPSBfdGhpczQucHJvcHM7XG4gICAgICAgICAgdmFyIGhlaWdodCA9IF9wcm9wczUuaGVpZ2h0O1xuICAgICAgICAgIHZhciBvblNjcm9sbCA9IF9wcm9wczUub25TY3JvbGw7XG4gICAgICAgICAgdmFyIHdpZHRoID0gX3Byb3BzNS53aWR0aDtcblxuXG4gICAgICAgICAgb25TY3JvbGwoe1xuICAgICAgICAgICAgY2xpZW50SGVpZ2h0OiBoZWlnaHQsXG4gICAgICAgICAgICBjbGllbnRXaWR0aDogd2lkdGgsXG4gICAgICAgICAgICBzY3JvbGxIZWlnaHQ6IHRvdGFsSGVpZ2h0LFxuICAgICAgICAgICAgc2Nyb2xsTGVmdDogc2Nyb2xsTGVmdCxcbiAgICAgICAgICAgIHNjcm9sbFRvcDogc2Nyb2xsVG9wLFxuICAgICAgICAgICAgc2Nyb2xsV2lkdGg6IHRvdGFsV2lkdGhcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgaW5kaWNlczoge1xuICAgICAgICAgIHNjcm9sbExlZnQ6IHNjcm9sbExlZnQsXG4gICAgICAgICAgc2Nyb2xsVG9wOiBzY3JvbGxUb3BcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXBkYXRlcyB0aGUgc3RhdGUgZHVyaW5nIHRoZSBuZXh0IGFuaW1hdGlvbiBmcmFtZS5cbiAgICAgKiBVc2UgdGhpcyBtZXRob2QgdG8gYXZvaWQgbXVsdGlwbGUgcmVuZGVycyBpbiBhIHNtYWxsIHNwYW4gb2YgdGltZS5cbiAgICAgKiBUaGlzIGhlbHBzIHBlcmZvcm1hbmNlIGZvciBidXJzdHkgZXZlbnRzIChsaWtlIG9uU2Nyb2xsKS5cbiAgICAgKi9cblxuICB9LCB7XG4gICAga2V5OiAnX3NldE5leHRTdGF0ZScsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9zZXROZXh0U3RhdGUoc3RhdGUpIHtcbiAgICAgIHZhciBfdGhpczUgPSB0aGlzO1xuXG4gICAgICBpZiAodGhpcy5fc2V0TmV4dFN0YXRlQW5pbWF0aW9uRnJhbWVJZCkge1xuICAgICAgICBfcmFmMi5kZWZhdWx0LmNhbmNlbCh0aGlzLl9zZXROZXh0U3RhdGVBbmltYXRpb25GcmFtZUlkKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fc2V0TmV4dFN0YXRlQW5pbWF0aW9uRnJhbWVJZCA9ICgwLCBfcmFmMi5kZWZhdWx0KShmdW5jdGlvbiAoKSB7XG4gICAgICAgIF90aGlzNS5fc2V0TmV4dFN0YXRlQW5pbWF0aW9uRnJhbWVJZCA9IG51bGw7XG4gICAgICAgIF90aGlzNS5zZXRTdGF0ZShzdGF0ZSk7XG4gICAgICB9KTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfc2V0U2Nyb2xsUG9zaXRpb24nLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBfc2V0U2Nyb2xsUG9zaXRpb24oX3JlZjQpIHtcbiAgICAgIHZhciBzY3JvbGxMZWZ0ID0gX3JlZjQuc2Nyb2xsTGVmdDtcbiAgICAgIHZhciBzY3JvbGxUb3AgPSBfcmVmNC5zY3JvbGxUb3A7XG5cbiAgICAgIHZhciBuZXdTdGF0ZSA9IHtcbiAgICAgICAgc2Nyb2xsUG9zaXRpb25DaGFuZ2VSZWFzb246IFNDUk9MTF9QT1NJVElPTl9DSEFOR0VfUkVBU09OUy5SRVFVRVNURURcbiAgICAgIH07XG5cbiAgICAgIGlmIChzY3JvbGxMZWZ0ID49IDApIHtcbiAgICAgICAgbmV3U3RhdGUuc2Nyb2xsTGVmdCA9IHNjcm9sbExlZnQ7XG4gICAgICB9XG5cbiAgICAgIGlmIChzY3JvbGxUb3AgPj0gMCkge1xuICAgICAgICBuZXdTdGF0ZS5zY3JvbGxUb3AgPSBzY3JvbGxUb3A7XG4gICAgICB9XG5cbiAgICAgIGlmIChzY3JvbGxMZWZ0ID49IDAgJiYgc2Nyb2xsTGVmdCAhPT0gdGhpcy5zdGF0ZS5zY3JvbGxMZWZ0IHx8IHNjcm9sbFRvcCA+PSAwICYmIHNjcm9sbFRvcCAhPT0gdGhpcy5zdGF0ZS5zY3JvbGxUb3ApIHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZShuZXdTdGF0ZSk7XG4gICAgICB9XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX3VwZGF0ZVNjcm9sbFBvc2l0aW9uRm9yU2Nyb2xsVG9DZWxsJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gX3VwZGF0ZVNjcm9sbFBvc2l0aW9uRm9yU2Nyb2xsVG9DZWxsKCkge1xuICAgICAgdmFyIF9wcm9wczYgPSB0aGlzLnByb3BzO1xuICAgICAgdmFyIGNlbGxMYXlvdXRNYW5hZ2VyID0gX3Byb3BzNi5jZWxsTGF5b3V0TWFuYWdlcjtcbiAgICAgIHZhciBoZWlnaHQgPSBfcHJvcHM2LmhlaWdodDtcbiAgICAgIHZhciBzY3JvbGxUb0FsaWdubWVudCA9IF9wcm9wczYuc2Nyb2xsVG9BbGlnbm1lbnQ7XG4gICAgICB2YXIgc2Nyb2xsVG9DZWxsID0gX3Byb3BzNi5zY3JvbGxUb0NlbGw7XG4gICAgICB2YXIgd2lkdGggPSBfcHJvcHM2LndpZHRoO1xuICAgICAgdmFyIF9zdGF0ZTMgPSB0aGlzLnN0YXRlO1xuICAgICAgdmFyIHNjcm9sbExlZnQgPSBfc3RhdGUzLnNjcm9sbExlZnQ7XG4gICAgICB2YXIgc2Nyb2xsVG9wID0gX3N0YXRlMy5zY3JvbGxUb3A7XG5cblxuICAgICAgaWYgKHNjcm9sbFRvQ2VsbCA+PSAwKSB7XG4gICAgICAgIHZhciBzY3JvbGxQb3NpdGlvbiA9IGNlbGxMYXlvdXRNYW5hZ2VyLmdldFNjcm9sbFBvc2l0aW9uRm9yQ2VsbCh7XG4gICAgICAgICAgYWxpZ246IHNjcm9sbFRvQWxpZ25tZW50LFxuICAgICAgICAgIGNlbGxJbmRleDogc2Nyb2xsVG9DZWxsLFxuICAgICAgICAgIGhlaWdodDogaGVpZ2h0LFxuICAgICAgICAgIHNjcm9sbExlZnQ6IHNjcm9sbExlZnQsXG4gICAgICAgICAgc2Nyb2xsVG9wOiBzY3JvbGxUb3AsXG4gICAgICAgICAgd2lkdGg6IHdpZHRoXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChzY3JvbGxQb3NpdGlvbi5zY3JvbGxMZWZ0ICE9PSBzY3JvbGxMZWZ0IHx8IHNjcm9sbFBvc2l0aW9uLnNjcm9sbFRvcCAhPT0gc2Nyb2xsVG9wKSB7XG4gICAgICAgICAgdGhpcy5fc2V0U2Nyb2xsUG9zaXRpb24oc2Nyb2xsUG9zaXRpb24pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uU2Nyb2xsJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uU2Nyb2xsKGV2ZW50KSB7XG4gICAgICAvLyBJbiBjZXJ0YWluIGVkZ2UtY2FzZXMgUmVhY3QgZGlzcGF0Y2hlcyBhbiBvblNjcm9sbCBldmVudCB3aXRoIGFuIGludmFsaWQgdGFyZ2V0LnNjcm9sbExlZnQgLyB0YXJnZXQuc2Nyb2xsVG9wLlxuICAgICAgLy8gVGhpcyBpbnZhbGlkIGV2ZW50IGNhbiBiZSBkZXRlY3RlZCBieSBjb21wYXJpbmcgZXZlbnQudGFyZ2V0IHRvIHRoaXMgY29tcG9uZW50J3Mgc2Nyb2xsYWJsZSBET00gZWxlbWVudC5cbiAgICAgIC8vIFNlZSBpc3N1ZSAjNDA0IGZvciBtb3JlIGluZm9ybWF0aW9uLlxuICAgICAgaWYgKGV2ZW50LnRhcmdldCAhPT0gdGhpcy5fc2Nyb2xsaW5nQ29udGFpbmVyKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgLy8gUHJldmVudCBwb2ludGVyIGV2ZW50cyBmcm9tIGludGVycnVwdGluZyBhIHNtb290aCBzY3JvbGxcbiAgICAgIHRoaXMuX2VuYWJsZVBvaW50ZXJFdmVudHNBZnRlckRlbGF5KCk7XG5cbiAgICAgIC8vIFdoZW4gdGhpcyBjb21wb25lbnQgaXMgc2hydW5rIGRyYXN0aWNhbGx5LCBSZWFjdCBkaXNwYXRjaGVzIGEgc2VyaWVzIG9mIGJhY2stdG8tYmFjayBzY3JvbGwgZXZlbnRzLFxuICAgICAgLy8gR3JhZHVhbGx5IGNvbnZlcmdpbmcgb24gYSBzY3JvbGxUb3AgdGhhdCBpcyB3aXRoaW4gdGhlIGJvdW5kcyBvZiB0aGUgbmV3LCBzbWFsbGVyIGhlaWdodC5cbiAgICAgIC8vIFRoaXMgY2F1c2VzIGEgc2VyaWVzIG9mIHJhcGlkIHJlbmRlcnMgdGhhdCBpcyBzbG93IGZvciBsb25nIGxpc3RzLlxuICAgICAgLy8gV2UgY2FuIGF2b2lkIHRoYXQgYnkgZG9pbmcgc29tZSBzaW1wbGUgYm91bmRzIGNoZWNraW5nIHRvIGVuc3VyZSB0aGF0IHNjcm9sbFRvcCBuZXZlciBleGNlZWRzIHRoZSB0b3RhbCBoZWlnaHQuXG4gICAgICB2YXIgX3Byb3BzNyA9IHRoaXMucHJvcHM7XG4gICAgICB2YXIgY2VsbExheW91dE1hbmFnZXIgPSBfcHJvcHM3LmNlbGxMYXlvdXRNYW5hZ2VyO1xuICAgICAgdmFyIGhlaWdodCA9IF9wcm9wczcuaGVpZ2h0O1xuICAgICAgdmFyIGlzU2Nyb2xsaW5nQ2hhbmdlID0gX3Byb3BzNy5pc1Njcm9sbGluZ0NoYW5nZTtcbiAgICAgIHZhciB3aWR0aCA9IF9wcm9wczcud2lkdGg7XG5cbiAgICAgIHZhciBzY3JvbGxiYXJTaXplID0gdGhpcy5fc2Nyb2xsYmFyU2l6ZTtcblxuICAgICAgdmFyIF9jZWxsTGF5b3V0TWFuYWdlciRnZTMgPSBjZWxsTGF5b3V0TWFuYWdlci5nZXRUb3RhbFNpemUoKTtcblxuICAgICAgdmFyIHRvdGFsSGVpZ2h0ID0gX2NlbGxMYXlvdXRNYW5hZ2VyJGdlMy5oZWlnaHQ7XG4gICAgICB2YXIgdG90YWxXaWR0aCA9IF9jZWxsTGF5b3V0TWFuYWdlciRnZTMud2lkdGg7XG5cbiAgICAgIHZhciBzY3JvbGxMZWZ0ID0gTWF0aC5tYXgoMCwgTWF0aC5taW4odG90YWxXaWR0aCAtIHdpZHRoICsgc2Nyb2xsYmFyU2l6ZSwgZXZlbnQudGFyZ2V0LnNjcm9sbExlZnQpKTtcbiAgICAgIHZhciBzY3JvbGxUb3AgPSBNYXRoLm1heCgwLCBNYXRoLm1pbih0b3RhbEhlaWdodCAtIGhlaWdodCArIHNjcm9sbGJhclNpemUsIGV2ZW50LnRhcmdldC5zY3JvbGxUb3ApKTtcblxuICAgICAgLy8gQ2VydGFpbiBkZXZpY2VzIChsaWtlIEFwcGxlIHRvdWNocGFkKSByYXBpZC1maXJlIGR1cGxpY2F0ZSBldmVudHMuXG4gICAgICAvLyBEb24ndCBmb3JjZSBhIHJlLXJlbmRlciBpZiB0aGlzIGlzIHRoZSBjYXNlLlxuICAgICAgLy8gVGhlIG1vdXNlIG1heSBtb3ZlIGZhc3RlciB0aGVuIHRoZSBhbmltYXRpb24gZnJhbWUgZG9lcy5cbiAgICAgIC8vIFVzZSByZXF1ZXN0QW5pbWF0aW9uRnJhbWUgdG8gYXZvaWQgb3Zlci11cGRhdGluZy5cbiAgICAgIGlmICh0aGlzLnN0YXRlLnNjcm9sbExlZnQgIT09IHNjcm9sbExlZnQgfHwgdGhpcy5zdGF0ZS5zY3JvbGxUb3AgIT09IHNjcm9sbFRvcCkge1xuICAgICAgICAvLyBCcm93c2VycyB3aXRoIGNhbmNlbGFibGUgc2Nyb2xsIGV2ZW50cyAoZWcuIEZpcmVmb3gpIGludGVycnVwdCBzY3JvbGxpbmcgYW5pbWF0aW9ucyBpZiBzY3JvbGxUb3Avc2Nyb2xsTGVmdCBpcyBzZXQuXG4gICAgICAgIC8vIE90aGVyIGJyb3dzZXJzIChlZy4gU2FmYXJpKSBkb24ndCBzY3JvbGwgYXMgd2VsbCB3aXRob3V0IHRoZSBoZWxwIHVuZGVyIGNlcnRhaW4gY29uZGl0aW9ucyAoRE9NIG9yIHN0eWxlIGNoYW5nZXMgZHVyaW5nIHNjcm9sbGluZykuXG4gICAgICAgIC8vIEFsbCB0aGluZ3MgY29uc2lkZXJlZCwgdGhpcyBzZWVtcyB0byBiZSB0aGUgYmVzdCBjdXJyZW50IHdvcmsgYXJvdW5kIHRoYXQgSSdtIGF3YXJlIG9mLlxuICAgICAgICAvLyBGb3IgbW9yZSBpbmZvcm1hdGlvbiBzZWUgaHR0cHM6Ly9naXRodWIuY29tL2J2YXVnaG4vcmVhY3QtdmlydHVhbGl6ZWQvcHVsbC8xMjRcbiAgICAgICAgdmFyIHNjcm9sbFBvc2l0aW9uQ2hhbmdlUmVhc29uID0gZXZlbnQuY2FuY2VsYWJsZSA/IFNDUk9MTF9QT1NJVElPTl9DSEFOR0VfUkVBU09OUy5PQlNFUlZFRCA6IFNDUk9MTF9QT1NJVElPTl9DSEFOR0VfUkVBU09OUy5SRVFVRVNURUQ7XG5cbiAgICAgICAgLy8gU3luY2hyb25vdXNseSBzZXQgOmlzU2Nyb2xsaW5nIHRoZSBmaXJzdCB0aW1lIChzaW5jZSBfc2V0TmV4dFN0YXRlIHdpbGwgcmVzY2hlZHVsZSBpdHMgYW5pbWF0aW9uIGZyYW1lIGVhY2ggdGltZSBpdCdzIGNhbGxlZClcbiAgICAgICAgaWYgKCF0aGlzLnN0YXRlLmlzU2Nyb2xsaW5nKSB7XG4gICAgICAgICAgaXNTY3JvbGxpbmdDaGFuZ2UodHJ1ZSk7XG5cbiAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgIGlzU2Nyb2xsaW5nOiB0cnVlXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9zZXROZXh0U3RhdGUoe1xuICAgICAgICAgIGlzU2Nyb2xsaW5nOiB0cnVlLFxuICAgICAgICAgIHNjcm9sbExlZnQ6IHNjcm9sbExlZnQsXG4gICAgICAgICAgc2Nyb2xsUG9zaXRpb25DaGFuZ2VSZWFzb246IHNjcm9sbFBvc2l0aW9uQ2hhbmdlUmVhc29uLFxuICAgICAgICAgIHNjcm9sbFRvcDogc2Nyb2xsVG9wXG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9pbnZva2VPblNjcm9sbE1lbW9pemVyKHtcbiAgICAgICAgc2Nyb2xsTGVmdDogc2Nyb2xsTGVmdCxcbiAgICAgICAgc2Nyb2xsVG9wOiBzY3JvbGxUb3AsXG4gICAgICAgIHRvdGFsV2lkdGg6IHRvdGFsV2lkdGgsXG4gICAgICAgIHRvdGFsSGVpZ2h0OiB0b3RhbEhlaWdodFxuICAgICAgfSk7XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIENvbGxlY3Rpb25WaWV3O1xufShfcmVhY3QuQ29tcG9uZW50KTtcblxuQ29sbGVjdGlvblZpZXcucHJvcFR5cGVzID0ge1xuICAnYXJpYS1sYWJlbCc6IF9yZWFjdC5Qcm9wVHlwZXMuc3RyaW5nLFxuXG4gIC8qKlxuICAgKiBSZW1vdmVzIGZpeGVkIGhlaWdodCBmcm9tIHRoZSBzY3JvbGxpbmdDb250YWluZXIgc28gdGhhdCB0aGUgdG90YWwgaGVpZ2h0XG4gICAqIG9mIHJvd3MgY2FuIHN0cmV0Y2ggdGhlIHdpbmRvdy4gSW50ZW5kZWQgZm9yIHVzZSB3aXRoIFdpbmRvd1Njcm9sbGVyXG4gICAqL1xuICBhdXRvSGVpZ2h0OiBfcmVhY3QuUHJvcFR5cGVzLmJvb2wsXG5cbiAgLyoqXG4gICAqIE51bWJlciBvZiBjZWxscyBpbiBjb2xsZWN0aW9uLlxuICAgKi9cbiAgY2VsbENvdW50OiBfcmVhY3QuUHJvcFR5cGVzLm51bWJlci5pc1JlcXVpcmVkLFxuXG4gIC8qKlxuICAgKiBDYWxjdWxhdGVzIGNlbGwgc2l6ZXMgYW5kIHBvc2l0aW9ucyBhbmQgbWFuYWdlcyByZW5kZXJpbmcgdGhlIGFwcHJvcHJpYXRlIGNlbGxzIGdpdmVuIGEgc3BlY2lmaWVkIHdpbmRvdy5cbiAgICovXG4gIGNlbGxMYXlvdXRNYW5hZ2VyOiBfcmVhY3QuUHJvcFR5cGVzLm9iamVjdC5pc1JlcXVpcmVkLFxuXG4gIC8qKlxuICAgKiBPcHRpb25hbCBjdXN0b20gQ1NTIGNsYXNzIG5hbWUgdG8gYXR0YWNoIHRvIHJvb3QgQ29sbGVjdGlvbiBlbGVtZW50LlxuICAgKi9cbiAgY2xhc3NOYW1lOiBfcmVhY3QuUHJvcFR5cGVzLnN0cmluZyxcblxuICAvKipcbiAgICogSGVpZ2h0IG9mIENvbGxlY3Rpb247IHRoaXMgcHJvcGVydHkgZGV0ZXJtaW5lcyB0aGUgbnVtYmVyIG9mIHZpc2libGUgKHZzIHZpcnR1YWxpemVkKSByb3dzLlxuICAgKi9cbiAgaGVpZ2h0OiBfcmVhY3QuUHJvcFR5cGVzLm51bWJlci5pc1JlcXVpcmVkLFxuXG4gIC8qKlxuICAgKiBFbmFibGVzIHRoZSBgQ29sbGVjdGlvbmAgdG8gaG9yaW9udGFsbHkgXCJvdmVyc2NhblwiIGl0cyBjb250ZW50IHNpbWlsYXIgdG8gaG93IGBHcmlkYCBkb2VzLlxuICAgKiBUaGlzIGNhbiByZWR1Y2UgZmxpY2tlciBhcm91bmQgdGhlIGVkZ2VzIHdoZW4gYSB1c2VyIHNjcm9sbHMgcXVpY2tseS5cbiAgICovXG4gIGhvcml6b250YWxPdmVyc2NhblNpemU6IF9yZWFjdC5Qcm9wVHlwZXMubnVtYmVyLmlzUmVxdWlyZWQsXG5cbiAgaXNTY3JvbGxpbmdDaGFuZ2U6IF9yZWFjdC5Qcm9wVHlwZXMuZnVuYyxcblxuICAvKipcbiAgICogT3B0aW9uYWwgcmVuZGVyZXIgdG8gYmUgdXNlZCBpbiBwbGFjZSBvZiByb3dzIHdoZW4gZWl0aGVyIDpyb3dDb3VudCBvciA6Y2VsbENvdW50IGlzIDAuXG4gICAqL1xuICBub0NvbnRlbnRSZW5kZXJlcjogX3JlYWN0LlByb3BUeXBlcy5mdW5jLmlzUmVxdWlyZWQsXG5cbiAgLyoqXG4gICAqIENhbGxiYWNrIGludm9rZWQgd2hlbmV2ZXIgdGhlIHNjcm9sbCBvZmZzZXQgY2hhbmdlcyB3aXRoaW4gdGhlIGlubmVyIHNjcm9sbGFibGUgcmVnaW9uLlxuICAgKiBUaGlzIGNhbGxiYWNrIGNhbiBiZSB1c2VkIHRvIHN5bmMgc2Nyb2xsaW5nIGJldHdlZW4gbGlzdHMsIHRhYmxlcywgb3IgZ3JpZHMuXG4gICAqICh7IGNsaWVudEhlaWdodCwgY2xpZW50V2lkdGgsIHNjcm9sbEhlaWdodCwgc2Nyb2xsTGVmdCwgc2Nyb2xsVG9wLCBzY3JvbGxXaWR0aCB9KTogdm9pZFxuICAgKi9cbiAgb25TY3JvbGw6IF9yZWFjdC5Qcm9wVHlwZXMuZnVuYy5pc1JlcXVpcmVkLFxuXG4gIC8qKlxuICAgKiBDYWxsYmFjayBpbnZva2VkIHdpdGggaW5mb3JtYXRpb24gYWJvdXQgdGhlIHNlY3Rpb24gb2YgdGhlIENvbGxlY3Rpb24gdGhhdCB3YXMganVzdCByZW5kZXJlZC5cbiAgICogVGhpcyBjYWxsYmFjayBpcyBwYXNzZWQgYSBuYW1lZCA6aW5kaWNlcyBwYXJhbWV0ZXIgd2hpY2ggaXMgYW4gQXJyYXkgb2YgdGhlIG1vc3QgcmVjZW50bHkgcmVuZGVyZWQgc2VjdGlvbiBpbmRpY2VzLlxuICAgKi9cbiAgb25TZWN0aW9uUmVuZGVyZWQ6IF9yZWFjdC5Qcm9wVHlwZXMuZnVuYy5pc1JlcXVpcmVkLFxuXG4gIC8qKlxuICAgKiBIb3Jpem9udGFsIG9mZnNldC5cbiAgICovXG4gIHNjcm9sbExlZnQ6IF9yZWFjdC5Qcm9wVHlwZXMubnVtYmVyLFxuXG4gIC8qKlxuICAgKiBDb250cm9scyBzY3JvbGwtdG8tY2VsbCBiZWhhdmlvciBvZiB0aGUgR3JpZC5cbiAgICogVGhlIGRlZmF1bHQgKFwiYXV0b1wiKSBzY3JvbGxzIHRoZSBsZWFzdCBhbW91bnQgcG9zc2libGUgdG8gZW5zdXJlIHRoYXQgdGhlIHNwZWNpZmllZCBjZWxsIGlzIGZ1bGx5IHZpc2libGUuXG4gICAqIFVzZSBcInN0YXJ0XCIgdG8gYWxpZ24gY2VsbHMgdG8gdGhlIHRvcC9sZWZ0IG9mIHRoZSBHcmlkIGFuZCBcImVuZFwiIHRvIGFsaWduIGJvdHRvbS9yaWdodC5cbiAgICovXG4gIHNjcm9sbFRvQWxpZ25tZW50OiBfcmVhY3QuUHJvcFR5cGVzLm9uZU9mKFsnYXV0bycsICdlbmQnLCAnc3RhcnQnLCAnY2VudGVyJ10pLmlzUmVxdWlyZWQsXG5cbiAgLyoqXG4gICAqIENlbGwgaW5kZXggdG8gZW5zdXJlIHZpc2libGUgKGJ5IGZvcmNlZnVsbHkgc2Nyb2xsaW5nIGlmIG5lY2Vzc2FyeSkuXG4gICAqL1xuICBzY3JvbGxUb0NlbGw6IF9yZWFjdC5Qcm9wVHlwZXMubnVtYmVyLFxuXG4gIC8qKlxuICAgKiBWZXJ0aWNhbCBvZmZzZXQuXG4gICAqL1xuICBzY3JvbGxUb3A6IF9yZWFjdC5Qcm9wVHlwZXMubnVtYmVyLFxuXG4gIC8qKlxuICAgKiBPcHRpb25hbCBjdXN0b20gaW5saW5lIHN0eWxlIHRvIGF0dGFjaCB0byByb290IENvbGxlY3Rpb24gZWxlbWVudC5cbiAgICovXG4gIHN0eWxlOiBfcmVhY3QuUHJvcFR5cGVzLm9iamVjdCxcblxuICAvKipcbiAgICogRW5hYmxlcyB0aGUgYENvbGxlY3Rpb25gIHRvIHZlcnRpY2FsbHkgXCJvdmVyc2NhblwiIGl0cyBjb250ZW50IHNpbWlsYXIgdG8gaG93IGBHcmlkYCBkb2VzLlxuICAgKiBUaGlzIGNhbiByZWR1Y2UgZmxpY2tlciBhcm91bmQgdGhlIGVkZ2VzIHdoZW4gYSB1c2VyIHNjcm9sbHMgcXVpY2tseS5cbiAgICovXG4gIHZlcnRpY2FsT3ZlcnNjYW5TaXplOiBfcmVhY3QuUHJvcFR5cGVzLm51bWJlci5pc1JlcXVpcmVkLFxuXG4gIC8qKlxuICAgKiBXaWR0aCBvZiBDb2xsZWN0aW9uOyB0aGlzIHByb3BlcnR5IGRldGVybWluZXMgdGhlIG51bWJlciBvZiB2aXNpYmxlICh2cyB2aXJ0dWFsaXplZCkgY29sdW1ucy5cbiAgICovXG4gIHdpZHRoOiBfcmVhY3QuUHJvcFR5cGVzLm51bWJlci5pc1JlcXVpcmVkXG59O1xuQ29sbGVjdGlvblZpZXcuZGVmYXVsdFByb3BzID0ge1xuICAnYXJpYS1sYWJlbCc6ICdncmlkJyxcbiAgaG9yaXpvbnRhbE92ZXJzY2FuU2l6ZTogMCxcbiAgbm9Db250ZW50UmVuZGVyZXI6IGZ1bmN0aW9uIG5vQ29udGVudFJlbmRlcmVyKCkge1xuICAgIHJldHVybiBudWxsO1xuICB9LFxuICBvblNjcm9sbDogZnVuY3Rpb24gb25TY3JvbGwoKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH0sXG4gIG9uU2VjdGlvblJlbmRlcmVkOiBmdW5jdGlvbiBvblNlY3Rpb25SZW5kZXJlZCgpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfSxcbiAgc2Nyb2xsVG9BbGlnbm1lbnQ6ICdhdXRvJyxcbiAgc3R5bGU6IHt9LFxuICB2ZXJ0aWNhbE92ZXJzY2FuU2l6ZTogMFxufTtcbmV4cG9ydHMuZGVmYXVsdCA9IENvbGxlY3Rpb25WaWV3OyIsIid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9jcmVhdGVDbGFzcyA9IGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmIChcInZhbHVlXCIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0oKTtcblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uXCIpOyB9IH1cblxuLyoqXG4gKiBBIHNlY3Rpb24gb2YgdGhlIFdpbmRvdy5cbiAqIFdpbmRvdyBTZWN0aW9ucyBhcmUgdXNlZCB0byBncm91cCBuZWFyYnkgY2VsbHMuXG4gKiBUaGlzIGVuYWJsZXMgdXMgdG8gbW9yZSBxdWlja2x5IGRldGVybWluZSB3aGljaCBjZWxscyB0byBkaXNwbGF5IGluIGEgZ2l2ZW4gcmVnaW9uIG9mIHRoZSBXaW5kb3cuXG4gKiBTZWN0aW9ucyBoYXZlIGEgZml4ZWQgc2l6ZSBhbmQgY29udGFpbiAwIHRvIG1hbnkgY2VsbHMgKHRyYWNrZWQgYnkgdGhlaXIgaW5kaWNlcykuXG4gKi9cbnZhciBTZWN0aW9uID0gZnVuY3Rpb24gKCkge1xuICBmdW5jdGlvbiBTZWN0aW9uKF9yZWYpIHtcbiAgICB2YXIgaGVpZ2h0ID0gX3JlZi5oZWlnaHQ7XG4gICAgdmFyIHdpZHRoID0gX3JlZi53aWR0aDtcbiAgICB2YXIgeCA9IF9yZWYueDtcbiAgICB2YXIgeSA9IF9yZWYueTtcblxuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBTZWN0aW9uKTtcblxuICAgIHRoaXMuaGVpZ2h0ID0gaGVpZ2h0O1xuICAgIHRoaXMud2lkdGggPSB3aWR0aDtcbiAgICB0aGlzLnggPSB4O1xuICAgIHRoaXMueSA9IHk7XG5cbiAgICB0aGlzLl9pbmRleE1hcCA9IHt9O1xuICAgIHRoaXMuX2luZGljZXMgPSBbXTtcbiAgfVxuXG4gIC8qKiBBZGQgYSBjZWxsIHRvIHRoaXMgc2VjdGlvbi4gKi9cblxuXG4gIF9jcmVhdGVDbGFzcyhTZWN0aW9uLCBbe1xuICAgIGtleTogJ2FkZENlbGxJbmRleCcsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGFkZENlbGxJbmRleChfcmVmMikge1xuICAgICAgdmFyIGluZGV4ID0gX3JlZjIuaW5kZXg7XG5cbiAgICAgIGlmICghdGhpcy5faW5kZXhNYXBbaW5kZXhdKSB7XG4gICAgICAgIHRoaXMuX2luZGV4TWFwW2luZGV4XSA9IHRydWU7XG4gICAgICAgIHRoaXMuX2luZGljZXMucHVzaChpbmRleCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLyoqIEdldCBhbGwgY2VsbCBpbmRpY2VzIHRoYXQgaGF2ZSBiZWVuIGFkZGVkIHRvIHRoaXMgc2VjdGlvbi4gKi9cblxuICB9LCB7XG4gICAga2V5OiAnZ2V0Q2VsbEluZGljZXMnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBnZXRDZWxsSW5kaWNlcygpIHtcbiAgICAgIHJldHVybiB0aGlzLl9pbmRpY2VzO1xuICAgIH1cblxuICAgIC8qKiBJbnRlbmRlZCBmb3IgZGVidWdnZXIvdGVzdCBwdXJwb3NlcyBvbmx5ICovXG5cbiAgfSwge1xuICAgIGtleTogJ3RvU3RyaW5nJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gdG9TdHJpbmcoKSB7XG4gICAgICByZXR1cm4gdGhpcy54ICsgJywnICsgdGhpcy55ICsgJyAnICsgdGhpcy53aWR0aCArICd4JyArIHRoaXMuaGVpZ2h0O1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBTZWN0aW9uO1xufSgpOyAvKiogQHJsb3cgKi9cblxuXG5leHBvcnRzLmRlZmF1bHQgPSBTZWN0aW9uOyIsIid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9jcmVhdGVDbGFzcyA9IGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmIChcInZhbHVlXCIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0oKTsgLyoqXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICogV2luZG93IFNlY3Rpb25zIGFyZSB1c2VkIHRvIGdyb3VwIG5lYXJieSBjZWxscy5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKiBUaGlzIGVuYWJsZXMgdXMgdG8gbW9yZSBxdWlja2x5IGRldGVybWluZSB3aGljaCBjZWxscyB0byBkaXNwbGF5IGluIGEgZ2l2ZW4gcmVnaW9uIG9mIHRoZSBXaW5kb3cuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICogXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICovXG5cblxudmFyIF9TZWN0aW9uID0gcmVxdWlyZSgnLi9TZWN0aW9uJyk7XG5cbnZhciBfU2VjdGlvbjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9TZWN0aW9uKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgZGVmYXVsdDogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uXCIpOyB9IH1cblxudmFyIFNFQ1RJT05fU0laRSA9IDEwMDtcblxuLyoqXG4gKiBDb250YWlucyAwIHRvIG1hbnkgU2VjdGlvbnMuXG4gKiBHcm93cyAoYW5kIGFkZHMgU2VjdGlvbnMpIGR5bmFtaWNhbGx5IGFzIGNlbGxzIGFyZSByZWdpc3RlcmVkLlxuICogQXV0b21hdGljYWxseSBhZGRzIGNlbGxzIHRvIHRoZSBhcHByb3ByaWF0ZSBTZWN0aW9uKHMpLlxuICovXG52YXIgU2VjdGlvbk1hbmFnZXIgPSBmdW5jdGlvbiAoKSB7XG4gIGZ1bmN0aW9uIFNlY3Rpb25NYW5hZ2VyKCkge1xuICAgIHZhciBzZWN0aW9uU2l6ZSA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMCB8fCBhcmd1bWVudHNbMF0gPT09IHVuZGVmaW5lZCA/IFNFQ1RJT05fU0laRSA6IGFyZ3VtZW50c1swXTtcblxuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBTZWN0aW9uTWFuYWdlcik7XG5cbiAgICB0aGlzLl9zZWN0aW9uU2l6ZSA9IHNlY3Rpb25TaXplO1xuXG4gICAgdGhpcy5fY2VsbE1ldGFkYXRhID0gW107XG4gICAgdGhpcy5fc2VjdGlvbnMgPSB7fTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIGFsbCBjZWxsIGluZGljZXMgY29udGFpbmVkIGluIHRoZSBzcGVjaWZpZWQgcmVnaW9uLlxuICAgKiBBIHJlZ2lvbiBtYXkgZW5jb21wYXNzIDEgb3IgbW9yZSBTZWN0aW9ucy5cbiAgICovXG5cblxuICBfY3JlYXRlQ2xhc3MoU2VjdGlvbk1hbmFnZXIsIFt7XG4gICAga2V5OiAnZ2V0Q2VsbEluZGljZXMnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBnZXRDZWxsSW5kaWNlcyhfcmVmKSB7XG4gICAgICB2YXIgaGVpZ2h0ID0gX3JlZi5oZWlnaHQ7XG4gICAgICB2YXIgd2lkdGggPSBfcmVmLndpZHRoO1xuICAgICAgdmFyIHggPSBfcmVmLng7XG4gICAgICB2YXIgeSA9IF9yZWYueTtcblxuICAgICAgdmFyIGluZGljZXMgPSB7fTtcblxuICAgICAgdGhpcy5nZXRTZWN0aW9ucyh7IGhlaWdodDogaGVpZ2h0LCB3aWR0aDogd2lkdGgsIHg6IHgsIHk6IHkgfSkuZm9yRWFjaChmdW5jdGlvbiAoc2VjdGlvbikge1xuICAgICAgICByZXR1cm4gc2VjdGlvbi5nZXRDZWxsSW5kaWNlcygpLmZvckVhY2goZnVuY3Rpb24gKGluZGV4KSB7XG4gICAgICAgICAgaW5kaWNlc1tpbmRleF0gPSBpbmRleDtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgLy8gT2JqZWN0IGtleXMgYXJlIHN0cmluZ3M7IHRoaXMgZnVuY3Rpb24gcmV0dXJucyBudW1iZXJzXG4gICAgICByZXR1cm4gT2JqZWN0LmtleXMoaW5kaWNlcykubWFwKGZ1bmN0aW9uIChpbmRleCkge1xuICAgICAgICByZXR1cm4gaW5kaWNlc1tpbmRleF07XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKiogR2V0IHNpemUgYW5kIHBvc2l0aW9uIGluZm9ybWF0aW9uIGZvciB0aGUgY2VsbCBzcGVjaWZpZWQuICovXG5cbiAgfSwge1xuICAgIGtleTogJ2dldENlbGxNZXRhZGF0YScsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGdldENlbGxNZXRhZGF0YShfcmVmMikge1xuICAgICAgdmFyIGluZGV4ID0gX3JlZjIuaW5kZXg7XG5cbiAgICAgIHJldHVybiB0aGlzLl9jZWxsTWV0YWRhdGFbaW5kZXhdO1xuICAgIH1cblxuICAgIC8qKiBHZXQgYWxsIFNlY3Rpb25zIG92ZXJsYXBwaW5nIHRoZSBzcGVjaWZpZWQgcmVnaW9uLiAqL1xuXG4gIH0sIHtcbiAgICBrZXk6ICdnZXRTZWN0aW9ucycsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGdldFNlY3Rpb25zKF9yZWYzKSB7XG4gICAgICB2YXIgaGVpZ2h0ID0gX3JlZjMuaGVpZ2h0O1xuICAgICAgdmFyIHdpZHRoID0gX3JlZjMud2lkdGg7XG4gICAgICB2YXIgeCA9IF9yZWYzLng7XG4gICAgICB2YXIgeSA9IF9yZWYzLnk7XG5cbiAgICAgIHZhciBzZWN0aW9uWFN0YXJ0ID0gTWF0aC5mbG9vcih4IC8gdGhpcy5fc2VjdGlvblNpemUpO1xuICAgICAgdmFyIHNlY3Rpb25YU3RvcCA9IE1hdGguZmxvb3IoKHggKyB3aWR0aCAtIDEpIC8gdGhpcy5fc2VjdGlvblNpemUpO1xuICAgICAgdmFyIHNlY3Rpb25ZU3RhcnQgPSBNYXRoLmZsb29yKHkgLyB0aGlzLl9zZWN0aW9uU2l6ZSk7XG4gICAgICB2YXIgc2VjdGlvbllTdG9wID0gTWF0aC5mbG9vcigoeSArIGhlaWdodCAtIDEpIC8gdGhpcy5fc2VjdGlvblNpemUpO1xuXG4gICAgICB2YXIgc2VjdGlvbnMgPSBbXTtcblxuICAgICAgZm9yICh2YXIgc2VjdGlvblggPSBzZWN0aW9uWFN0YXJ0OyBzZWN0aW9uWCA8PSBzZWN0aW9uWFN0b3A7IHNlY3Rpb25YKyspIHtcbiAgICAgICAgZm9yICh2YXIgc2VjdGlvblkgPSBzZWN0aW9uWVN0YXJ0OyBzZWN0aW9uWSA8PSBzZWN0aW9uWVN0b3A7IHNlY3Rpb25ZKyspIHtcbiAgICAgICAgICB2YXIga2V5ID0gc2VjdGlvblggKyAnLicgKyBzZWN0aW9uWTtcblxuICAgICAgICAgIGlmICghdGhpcy5fc2VjdGlvbnNba2V5XSkge1xuICAgICAgICAgICAgdGhpcy5fc2VjdGlvbnNba2V5XSA9IG5ldyBfU2VjdGlvbjIuZGVmYXVsdCh7XG4gICAgICAgICAgICAgIGhlaWdodDogdGhpcy5fc2VjdGlvblNpemUsXG4gICAgICAgICAgICAgIHdpZHRoOiB0aGlzLl9zZWN0aW9uU2l6ZSxcbiAgICAgICAgICAgICAgeDogc2VjdGlvblggKiB0aGlzLl9zZWN0aW9uU2l6ZSxcbiAgICAgICAgICAgICAgeTogc2VjdGlvblkgKiB0aGlzLl9zZWN0aW9uU2l6ZVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgc2VjdGlvbnMucHVzaCh0aGlzLl9zZWN0aW9uc1trZXldKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gc2VjdGlvbnM7XG4gICAgfVxuXG4gICAgLyoqIFRvdGFsIG51bWJlciBvZiBTZWN0aW9ucyBiYXNlZCBvbiB0aGUgY3VycmVudGx5IHJlZ2lzdGVyZWQgY2VsbHMuICovXG5cbiAgfSwge1xuICAgIGtleTogJ2dldFRvdGFsU2VjdGlvbkNvdW50JyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gZ2V0VG90YWxTZWN0aW9uQ291bnQoKSB7XG4gICAgICByZXR1cm4gT2JqZWN0LmtleXModGhpcy5fc2VjdGlvbnMpLmxlbmd0aDtcbiAgICB9XG5cbiAgICAvKiogSW50ZW5kZWQgZm9yIGRlYnVnZ2VyL3Rlc3QgcHVycG9zZXMgb25seSAqL1xuXG4gIH0sIHtcbiAgICBrZXk6ICd0b1N0cmluZycsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHRvU3RyaW5nKCkge1xuICAgICAgdmFyIF90aGlzID0gdGhpcztcblxuICAgICAgcmV0dXJuIE9iamVjdC5rZXlzKHRoaXMuX3NlY3Rpb25zKS5tYXAoZnVuY3Rpb24gKGluZGV4KSB7XG4gICAgICAgIHJldHVybiBfdGhpcy5fc2VjdGlvbnNbaW5kZXhdLnRvU3RyaW5nKCk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKiogQWRkcyBhIGNlbGwgdG8gdGhlIGFwcHJvcHJpYXRlIFNlY3Rpb25zIGFuZCByZWdpc3RlcnMgaXQgbWV0YWRhdGEgZm9yIGxhdGVyIHJldHJpZXZhYmxlLiAqL1xuXG4gIH0sIHtcbiAgICBrZXk6ICdyZWdpc3RlckNlbGwnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiByZWdpc3RlckNlbGwoX3JlZjQpIHtcbiAgICAgIHZhciBjZWxsTWV0YWRhdHVtID0gX3JlZjQuY2VsbE1ldGFkYXR1bTtcbiAgICAgIHZhciBpbmRleCA9IF9yZWY0LmluZGV4O1xuXG4gICAgICB0aGlzLl9jZWxsTWV0YWRhdGFbaW5kZXhdID0gY2VsbE1ldGFkYXR1bTtcblxuICAgICAgdGhpcy5nZXRTZWN0aW9ucyhjZWxsTWV0YWRhdHVtKS5mb3JFYWNoKGZ1bmN0aW9uIChzZWN0aW9uKSB7XG4gICAgICAgIHJldHVybiBzZWN0aW9uLmFkZENlbGxJbmRleCh7IGluZGV4OiBpbmRleCB9KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBTZWN0aW9uTWFuYWdlcjtcbn0oKTtcblxuZXhwb3J0cy5kZWZhdWx0ID0gU2VjdGlvbk1hbmFnZXI7IiwiJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0cy5Db2xsZWN0aW9uID0gZXhwb3J0cy5kZWZhdWx0ID0gdW5kZWZpbmVkO1xuXG52YXIgX0NvbGxlY3Rpb24yID0gcmVxdWlyZSgnLi9Db2xsZWN0aW9uJyk7XG5cbnZhciBfQ29sbGVjdGlvbjMgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9Db2xsZWN0aW9uMik7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7IGRlZmF1bHQ6IG9iaiB9OyB9XG5cbmV4cG9ydHMuZGVmYXVsdCA9IF9Db2xsZWN0aW9uMy5kZWZhdWx0O1xuZXhwb3J0cy5Db2xsZWN0aW9uID0gX0NvbGxlY3Rpb24zLmRlZmF1bHQ7IiwiJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0cy5kZWZhdWx0ID0gY2FsY3VsYXRlU2l6ZUFuZFBvc2l0aW9uRGF0YTtcblxudmFyIF9TZWN0aW9uTWFuYWdlciA9IHJlcXVpcmUoJy4uL1NlY3Rpb25NYW5hZ2VyJyk7XG5cbnZhciBfU2VjdGlvbk1hbmFnZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfU2VjdGlvbk1hbmFnZXIpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyBkZWZhdWx0OiBvYmogfTsgfVxuXG5mdW5jdGlvbiBjYWxjdWxhdGVTaXplQW5kUG9zaXRpb25EYXRhKF9yZWYpIHtcbiAgdmFyIGNlbGxDb3VudCA9IF9yZWYuY2VsbENvdW50O1xuICB2YXIgY2VsbFNpemVBbmRQb3NpdGlvbkdldHRlciA9IF9yZWYuY2VsbFNpemVBbmRQb3NpdGlvbkdldHRlcjtcbiAgdmFyIHNlY3Rpb25TaXplID0gX3JlZi5zZWN0aW9uU2l6ZTtcblxuICB2YXIgY2VsbE1ldGFkYXRhID0gW107XG4gIHZhciBzZWN0aW9uTWFuYWdlciA9IG5ldyBfU2VjdGlvbk1hbmFnZXIyLmRlZmF1bHQoc2VjdGlvblNpemUpO1xuICB2YXIgaGVpZ2h0ID0gMDtcbiAgdmFyIHdpZHRoID0gMDtcblxuICBmb3IgKHZhciBpbmRleCA9IDA7IGluZGV4IDwgY2VsbENvdW50OyBpbmRleCsrKSB7XG4gICAgdmFyIGNlbGxNZXRhZGF0dW0gPSBjZWxsU2l6ZUFuZFBvc2l0aW9uR2V0dGVyKHsgaW5kZXg6IGluZGV4IH0pO1xuXG4gICAgaWYgKGNlbGxNZXRhZGF0dW0uaGVpZ2h0ID09IG51bGwgfHwgaXNOYU4oY2VsbE1ldGFkYXR1bS5oZWlnaHQpIHx8IGNlbGxNZXRhZGF0dW0ud2lkdGggPT0gbnVsbCB8fCBpc05hTihjZWxsTWV0YWRhdHVtLndpZHRoKSB8fCBjZWxsTWV0YWRhdHVtLnggPT0gbnVsbCB8fCBpc05hTihjZWxsTWV0YWRhdHVtLngpIHx8IGNlbGxNZXRhZGF0dW0ueSA9PSBudWxsIHx8IGlzTmFOKGNlbGxNZXRhZGF0dW0ueSkpIHtcbiAgICAgIHRocm93IEVycm9yKCdJbnZhbGlkIG1ldGFkYXRhIHJldHVybmVkIGZvciBjZWxsICcgKyBpbmRleCArICc6XFxuICAgICAgICB4OicgKyBjZWxsTWV0YWRhdHVtLnggKyAnLCB5OicgKyBjZWxsTWV0YWRhdHVtLnkgKyAnLCB3aWR0aDonICsgY2VsbE1ldGFkYXR1bS53aWR0aCArICcsIGhlaWdodDonICsgY2VsbE1ldGFkYXR1bS5oZWlnaHQpO1xuICAgIH1cblxuICAgIGhlaWdodCA9IE1hdGgubWF4KGhlaWdodCwgY2VsbE1ldGFkYXR1bS55ICsgY2VsbE1ldGFkYXR1bS5oZWlnaHQpO1xuICAgIHdpZHRoID0gTWF0aC5tYXgod2lkdGgsIGNlbGxNZXRhZGF0dW0ueCArIGNlbGxNZXRhZGF0dW0ud2lkdGgpO1xuXG4gICAgY2VsbE1ldGFkYXRhW2luZGV4XSA9IGNlbGxNZXRhZGF0dW07XG4gICAgc2VjdGlvbk1hbmFnZXIucmVnaXN0ZXJDZWxsKHtcbiAgICAgIGNlbGxNZXRhZGF0dW06IGNlbGxNZXRhZGF0dW0sXG4gICAgICBpbmRleDogaW5kZXhcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgY2VsbE1ldGFkYXRhOiBjZWxsTWV0YWRhdGEsXG4gICAgaGVpZ2h0OiBoZWlnaHQsXG4gICAgc2VjdGlvbk1hbmFnZXI6IHNlY3Rpb25NYW5hZ2VyLFxuICAgIHdpZHRoOiB3aWR0aFxuICB9O1xufSIsIid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9jcmVhdGVDbGFzcyA9IGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmIChcInZhbHVlXCIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0oKTtcblxudmFyIF9yZWFjdCA9IHJlcXVpcmUoJ3JlYWN0Jyk7XG5cbnZhciBfcmVhY3RBZGRvbnNTaGFsbG93Q29tcGFyZSA9IHJlcXVpcmUoJ3JlYWN0LWFkZG9ucy1zaGFsbG93LWNvbXBhcmUnKTtcblxudmFyIF9yZWFjdEFkZG9uc1NoYWxsb3dDb21wYXJlMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3JlYWN0QWRkb25zU2hhbGxvd0NvbXBhcmUpO1xuXG52YXIgX0dyaWQgPSByZXF1aXJlKCcuLi9HcmlkJyk7XG5cbnZhciBfR3JpZDIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9HcmlkKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgZGVmYXVsdDogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uXCIpOyB9IH1cblxuZnVuY3Rpb24gX3Bvc3NpYmxlQ29uc3RydWN0b3JSZXR1cm4oc2VsZiwgY2FsbCkgeyBpZiAoIXNlbGYpIHsgdGhyb3cgbmV3IFJlZmVyZW5jZUVycm9yKFwidGhpcyBoYXNuJ3QgYmVlbiBpbml0aWFsaXNlZCAtIHN1cGVyKCkgaGFzbid0IGJlZW4gY2FsbGVkXCIpOyB9IHJldHVybiBjYWxsICYmICh0eXBlb2YgY2FsbCA9PT0gXCJvYmplY3RcIiB8fCB0eXBlb2YgY2FsbCA9PT0gXCJmdW5jdGlvblwiKSA/IGNhbGwgOiBzZWxmOyB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09IFwiZnVuY3Rpb25cIiAmJiBzdXBlckNsYXNzICE9PSBudWxsKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoXCJTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90IFwiICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBPYmplY3Quc2V0UHJvdG90eXBlT2YgPyBPYmplY3Quc2V0UHJvdG90eXBlT2Yoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIDogc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG4vKipcbiAqIEhpZ2gtb3JkZXIgY29tcG9uZW50IHRoYXQgYXV0by1jYWxjdWxhdGVzIGNvbHVtbi13aWR0aHMgZm9yIGBHcmlkYCBjZWxscy5cbiAqL1xudmFyIENvbHVtblNpemVyID0gZnVuY3Rpb24gKF9Db21wb25lbnQpIHtcbiAgX2luaGVyaXRzKENvbHVtblNpemVyLCBfQ29tcG9uZW50KTtcblxuICBmdW5jdGlvbiBDb2x1bW5TaXplcihwcm9wcywgY29udGV4dCkge1xuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBDb2x1bW5TaXplcik7XG5cbiAgICB2YXIgX3RoaXMgPSBfcG9zc2libGVDb25zdHJ1Y3RvclJldHVybih0aGlzLCAoQ29sdW1uU2l6ZXIuX19wcm90b19fIHx8IE9iamVjdC5nZXRQcm90b3R5cGVPZihDb2x1bW5TaXplcikpLmNhbGwodGhpcywgcHJvcHMsIGNvbnRleHQpKTtcblxuICAgIF90aGlzLl9yZWdpc3RlckNoaWxkID0gX3RoaXMuX3JlZ2lzdGVyQ2hpbGQuYmluZChfdGhpcyk7XG4gICAgcmV0dXJuIF90aGlzO1xuICB9XG5cbiAgX2NyZWF0ZUNsYXNzKENvbHVtblNpemVyLCBbe1xuICAgIGtleTogJ2NvbXBvbmVudERpZFVwZGF0ZScsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGNvbXBvbmVudERpZFVwZGF0ZShwcmV2UHJvcHMsIHByZXZTdGF0ZSkge1xuICAgICAgdmFyIF9wcm9wcyA9IHRoaXMucHJvcHM7XG4gICAgICB2YXIgY29sdW1uTWF4V2lkdGggPSBfcHJvcHMuY29sdW1uTWF4V2lkdGg7XG4gICAgICB2YXIgY29sdW1uTWluV2lkdGggPSBfcHJvcHMuY29sdW1uTWluV2lkdGg7XG4gICAgICB2YXIgY29sdW1uQ291bnQgPSBfcHJvcHMuY29sdW1uQ291bnQ7XG4gICAgICB2YXIgd2lkdGggPSBfcHJvcHMud2lkdGg7XG5cblxuICAgICAgaWYgKGNvbHVtbk1heFdpZHRoICE9PSBwcmV2UHJvcHMuY29sdW1uTWF4V2lkdGggfHwgY29sdW1uTWluV2lkdGggIT09IHByZXZQcm9wcy5jb2x1bW5NaW5XaWR0aCB8fCBjb2x1bW5Db3VudCAhPT0gcHJldlByb3BzLmNvbHVtbkNvdW50IHx8IHdpZHRoICE9PSBwcmV2UHJvcHMud2lkdGgpIHtcbiAgICAgICAgaWYgKHRoaXMuX3JlZ2lzdGVyZWRDaGlsZCkge1xuICAgICAgICAgIHRoaXMuX3JlZ2lzdGVyZWRDaGlsZC5yZWNvbXB1dGVHcmlkU2l6ZSgpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAncmVuZGVyJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVuZGVyKCkge1xuICAgICAgdmFyIF9wcm9wczIgPSB0aGlzLnByb3BzO1xuICAgICAgdmFyIGNoaWxkcmVuID0gX3Byb3BzMi5jaGlsZHJlbjtcbiAgICAgIHZhciBjb2x1bW5NYXhXaWR0aCA9IF9wcm9wczIuY29sdW1uTWF4V2lkdGg7XG4gICAgICB2YXIgY29sdW1uTWluV2lkdGggPSBfcHJvcHMyLmNvbHVtbk1pbldpZHRoO1xuICAgICAgdmFyIGNvbHVtbkNvdW50ID0gX3Byb3BzMi5jb2x1bW5Db3VudDtcbiAgICAgIHZhciB3aWR0aCA9IF9wcm9wczIud2lkdGg7XG5cblxuICAgICAgdmFyIHNhZmVDb2x1bW5NaW5XaWR0aCA9IGNvbHVtbk1pbldpZHRoIHx8IDE7XG5cbiAgICAgIHZhciBzYWZlQ29sdW1uTWF4V2lkdGggPSBjb2x1bW5NYXhXaWR0aCA/IE1hdGgubWluKGNvbHVtbk1heFdpZHRoLCB3aWR0aCkgOiB3aWR0aDtcblxuICAgICAgdmFyIGNvbHVtbldpZHRoID0gd2lkdGggLyBjb2x1bW5Db3VudDtcbiAgICAgIGNvbHVtbldpZHRoID0gTWF0aC5tYXgoc2FmZUNvbHVtbk1pbldpZHRoLCBjb2x1bW5XaWR0aCk7XG4gICAgICBjb2x1bW5XaWR0aCA9IE1hdGgubWluKHNhZmVDb2x1bW5NYXhXaWR0aCwgY29sdW1uV2lkdGgpO1xuICAgICAgY29sdW1uV2lkdGggPSBNYXRoLmZsb29yKGNvbHVtbldpZHRoKTtcblxuICAgICAgdmFyIGFkanVzdGVkV2lkdGggPSBNYXRoLm1pbih3aWR0aCwgY29sdW1uV2lkdGggKiBjb2x1bW5Db3VudCk7XG5cbiAgICAgIHJldHVybiBjaGlsZHJlbih7XG4gICAgICAgIGFkanVzdGVkV2lkdGg6IGFkanVzdGVkV2lkdGgsXG4gICAgICAgIGdldENvbHVtbldpZHRoOiBmdW5jdGlvbiBnZXRDb2x1bW5XaWR0aCgpIHtcbiAgICAgICAgICByZXR1cm4gY29sdW1uV2lkdGg7XG4gICAgICAgIH0sXG4gICAgICAgIHJlZ2lzdGVyQ2hpbGQ6IHRoaXMuX3JlZ2lzdGVyQ2hpbGRcbiAgICAgIH0pO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ3Nob3VsZENvbXBvbmVudFVwZGF0ZScsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHNob3VsZENvbXBvbmVudFVwZGF0ZShuZXh0UHJvcHMsIG5leHRTdGF0ZSkge1xuICAgICAgcmV0dXJuICgwLCBfcmVhY3RBZGRvbnNTaGFsbG93Q29tcGFyZTIuZGVmYXVsdCkodGhpcywgbmV4dFByb3BzLCBuZXh0U3RhdGUpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19yZWdpc3RlckNoaWxkJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gX3JlZ2lzdGVyQ2hpbGQoY2hpbGQpIHtcbiAgICAgIGlmIChjaGlsZCAhPT0gbnVsbCAmJiAhKGNoaWxkIGluc3RhbmNlb2YgX0dyaWQyLmRlZmF1bHQpKSB7XG4gICAgICAgIHRocm93IEVycm9yKCdVbmV4cGVjdGVkIGNoaWxkIHR5cGUgcmVnaXN0ZXJlZDsgb25seSBHcmlkIGNoaWxkcmVuIGFyZSBzdXBwb3J0ZWQuJyk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX3JlZ2lzdGVyZWRDaGlsZCA9IGNoaWxkO1xuXG4gICAgICBpZiAodGhpcy5fcmVnaXN0ZXJlZENoaWxkKSB7XG4gICAgICAgIHRoaXMuX3JlZ2lzdGVyZWRDaGlsZC5yZWNvbXB1dGVHcmlkU2l6ZSgpO1xuICAgICAgfVxuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBDb2x1bW5TaXplcjtcbn0oX3JlYWN0LkNvbXBvbmVudCk7XG5cbkNvbHVtblNpemVyLnByb3BUeXBlcyA9IHtcbiAgLyoqXG4gICAqIEZ1bmN0aW9uIHJlc3BvbmRpYmxlIGZvciByZW5kZXJpbmcgYSB2aXJ0dWFsaXplZCBHcmlkLlxuICAgKiBUaGlzIGZ1bmN0aW9uIHNob3VsZCBpbXBsZW1lbnQgdGhlIGZvbGxvd2luZyBzaWduYXR1cmU6XG4gICAqICh7IGFkanVzdGVkV2lkdGgsIGdldENvbHVtbldpZHRoLCByZWdpc3RlckNoaWxkIH0pID0+IFByb3BUeXBlcy5lbGVtZW50XG4gICAqXG4gICAqIFRoZSBzcGVjaWZpZWQgOmdldENvbHVtbldpZHRoIGZ1bmN0aW9uIHNob3VsZCBiZSBwYXNzZWQgdG8gdGhlIEdyaWQncyA6Y29sdW1uV2lkdGggcHJvcGVydHkuXG4gICAqIFRoZSA6cmVnaXN0ZXJDaGlsZCBzaG91bGQgYmUgcGFzc2VkIHRvIHRoZSBHcmlkJ3MgOnJlZiBwcm9wZXJ0eS5cbiAgICogVGhlIDphZGp1c3RlZFdpZHRoIHByb3BlcnR5IGlzIG9wdGlvbmFsOyBpdCByZWZsZWN0cyB0aGUgbGVzc2VyIG9mIHRoZSBvdmVyYWxsIHdpZHRoIG9yIHRoZSB3aWR0aCBvZiBhbGwgY29sdW1ucy5cbiAgICovXG4gIGNoaWxkcmVuOiBfcmVhY3QuUHJvcFR5cGVzLmZ1bmMuaXNSZXF1aXJlZCxcblxuICAvKiogT3B0aW9uYWwgbWF4aW11bSBhbGxvd2VkIGNvbHVtbiB3aWR0aCAqL1xuICBjb2x1bW5NYXhXaWR0aDogX3JlYWN0LlByb3BUeXBlcy5udW1iZXIsXG5cbiAgLyoqIE9wdGlvbmFsIG1pbmltdW0gYWxsb3dlZCBjb2x1bW4gd2lkdGggKi9cbiAgY29sdW1uTWluV2lkdGg6IF9yZWFjdC5Qcm9wVHlwZXMubnVtYmVyLFxuXG4gIC8qKiBOdW1iZXIgb2YgY29sdW1ucyBpbiBHcmlkIG9yIEZsZXhUYWJsZSBjaGlsZCAqL1xuICBjb2x1bW5Db3VudDogX3JlYWN0LlByb3BUeXBlcy5udW1iZXIuaXNSZXF1aXJlZCxcblxuICAvKiogV2lkdGggb2YgR3JpZCBvciBGbGV4VGFibGUgY2hpbGQgKi9cbiAgd2lkdGg6IF9yZWFjdC5Qcm9wVHlwZXMubnVtYmVyLmlzUmVxdWlyZWRcbn07XG5leHBvcnRzLmRlZmF1bHQgPSBDb2x1bW5TaXplcjsiLCIndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5leHBvcnRzLkNvbHVtblNpemVyID0gZXhwb3J0cy5kZWZhdWx0ID0gdW5kZWZpbmVkO1xuXG52YXIgX0NvbHVtblNpemVyMiA9IHJlcXVpcmUoJy4vQ29sdW1uU2l6ZXInKTtcblxudmFyIF9Db2x1bW5TaXplcjMgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9Db2x1bW5TaXplcjIpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyBkZWZhdWx0OiBvYmogfTsgfVxuXG5leHBvcnRzLmRlZmF1bHQgPSBfQ29sdW1uU2l6ZXIzLmRlZmF1bHQ7XG5leHBvcnRzLkNvbHVtblNpemVyID0gX0NvbHVtblNpemVyMy5kZWZhdWx0OyIsIid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9yZWFjdCA9IHJlcXVpcmUoJ3JlYWN0Jyk7XG5cbnZhciBfZGVmYXVsdEhlYWRlclJlbmRlcmVyID0gcmVxdWlyZSgnLi9kZWZhdWx0SGVhZGVyUmVuZGVyZXInKTtcblxudmFyIF9kZWZhdWx0SGVhZGVyUmVuZGVyZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfZGVmYXVsdEhlYWRlclJlbmRlcmVyKTtcblxudmFyIF9kZWZhdWx0Q2VsbFJlbmRlcmVyID0gcmVxdWlyZSgnLi9kZWZhdWx0Q2VsbFJlbmRlcmVyJyk7XG5cbnZhciBfZGVmYXVsdENlbGxSZW5kZXJlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9kZWZhdWx0Q2VsbFJlbmRlcmVyKTtcblxudmFyIF9kZWZhdWx0Q2VsbERhdGFHZXR0ZXIgPSByZXF1aXJlKCcuL2RlZmF1bHRDZWxsRGF0YUdldHRlcicpO1xuXG52YXIgX2RlZmF1bHRDZWxsRGF0YUdldHRlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9kZWZhdWx0Q2VsbERhdGFHZXR0ZXIpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyBkZWZhdWx0OiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb25cIik7IH0gfVxuXG5mdW5jdGlvbiBfcG9zc2libGVDb25zdHJ1Y3RvclJldHVybihzZWxmLCBjYWxsKSB7IGlmICghc2VsZikgeyB0aHJvdyBuZXcgUmVmZXJlbmNlRXJyb3IoXCJ0aGlzIGhhc24ndCBiZWVuIGluaXRpYWxpc2VkIC0gc3VwZXIoKSBoYXNuJ3QgYmVlbiBjYWxsZWRcIik7IH0gcmV0dXJuIGNhbGwgJiYgKHR5cGVvZiBjYWxsID09PSBcIm9iamVjdFwiIHx8IHR5cGVvZiBjYWxsID09PSBcImZ1bmN0aW9uXCIpID8gY2FsbCA6IHNlbGY7IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gXCJmdW5jdGlvblwiICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgXCIgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIE9iamVjdC5zZXRQcm90b3R5cGVPZiA/IE9iamVjdC5zZXRQcm90b3R5cGVPZihzdWJDbGFzcywgc3VwZXJDbGFzcykgOiBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbi8qKlxuICogRGVzY3JpYmVzIHRoZSBoZWFkZXIgYW5kIGNlbGwgY29udGVudHMgb2YgYSB0YWJsZSBjb2x1bW4uXG4gKi9cbnZhciBDb2x1bW4gPSBmdW5jdGlvbiAoX0NvbXBvbmVudCkge1xuICBfaW5oZXJpdHMoQ29sdW1uLCBfQ29tcG9uZW50KTtcblxuICBmdW5jdGlvbiBDb2x1bW4oKSB7XG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIENvbHVtbik7XG5cbiAgICByZXR1cm4gX3Bvc3NpYmxlQ29uc3RydWN0b3JSZXR1cm4odGhpcywgKENvbHVtbi5fX3Byb3RvX18gfHwgT2JqZWN0LmdldFByb3RvdHlwZU9mKENvbHVtbikpLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykpO1xuICB9XG5cbiAgcmV0dXJuIENvbHVtbjtcbn0oX3JlYWN0LkNvbXBvbmVudCk7XG5cbkNvbHVtbi5kZWZhdWx0UHJvcHMgPSB7XG4gIGNlbGxEYXRhR2V0dGVyOiBfZGVmYXVsdENlbGxEYXRhR2V0dGVyMi5kZWZhdWx0LFxuICBjZWxsUmVuZGVyZXI6IF9kZWZhdWx0Q2VsbFJlbmRlcmVyMi5kZWZhdWx0LFxuICBmbGV4R3JvdzogMCxcbiAgZmxleFNocmluazogMSxcbiAgaGVhZGVyUmVuZGVyZXI6IF9kZWZhdWx0SGVhZGVyUmVuZGVyZXIyLmRlZmF1bHQsXG4gIHN0eWxlOiB7fVxufTtcbkNvbHVtbi5wcm9wVHlwZXMgPSB7XG4gIC8qKiBPcHRpb25hbCBhcmlhLWxhYmVsIHZhbHVlIHRvIHNldCBvbiB0aGUgY29sdW1uIGhlYWRlciAqL1xuICAnYXJpYS1sYWJlbCc6IF9yZWFjdC5Qcm9wVHlwZXMuc3RyaW5nLFxuXG4gIC8qKlxuICAgKiBDYWxsYmFjayByZXNwb25zaWJsZSBmb3IgcmV0dXJuaW5nIGEgY2VsbCdzIGRhdGEsIGdpdmVuIGl0cyA6ZGF0YUtleVxuICAgKiAoeyBjb2x1bW5EYXRhOiBhbnksIGRhdGFLZXk6IHN0cmluZywgcm93RGF0YTogYW55IH0pOiBhbnlcbiAgICovXG4gIGNlbGxEYXRhR2V0dGVyOiBfcmVhY3QuUHJvcFR5cGVzLmZ1bmMsXG5cbiAgLyoqXG4gICAqIENhbGxiYWNrIHJlc3BvbnNpYmxlIGZvciByZW5kZXJpbmcgYSBjZWxsJ3MgY29udGVudHMuXG4gICAqICh7IGNlbGxEYXRhOiBhbnksIGNvbHVtbkRhdGE6IGFueSwgZGF0YUtleTogc3RyaW5nLCByb3dEYXRhOiBhbnksIHJvd0luZGV4OiBudW1iZXIgfSk6IG5vZGVcbiAgICovXG4gIGNlbGxSZW5kZXJlcjogX3JlYWN0LlByb3BUeXBlcy5mdW5jLFxuXG4gIC8qKiBPcHRpb25hbCBDU1MgY2xhc3MgdG8gYXBwbHkgdG8gY2VsbCAqL1xuICBjbGFzc05hbWU6IF9yZWFjdC5Qcm9wVHlwZXMuc3RyaW5nLFxuXG4gIC8qKiBPcHRpb25hbCBhZGRpdGlvbmFsIGRhdGEgcGFzc2VkIHRvIHRoaXMgY29sdW1uJ3MgOmNlbGxEYXRhR2V0dGVyICovXG4gIGNvbHVtbkRhdGE6IF9yZWFjdC5Qcm9wVHlwZXMub2JqZWN0LFxuXG4gIC8qKiBVbmlxdWVseSBpZGVudGlmaWVzIHRoZSByb3ctZGF0YSBhdHRyaWJ1dGUgY29ycmVzcG5kaW5nIHRvIHRoaXMgY2VsbCAqL1xuICBkYXRhS2V5OiBfcmVhY3QuUHJvcFR5cGVzLmFueS5pc1JlcXVpcmVkLFxuXG4gIC8qKiBJZiBzb3J0IGlzIGVuYWJsZWQgZm9yIHRoZSB0YWJsZSBhdCBsYXJnZSwgZGlzYWJsZSBpdCBmb3IgdGhpcyBjb2x1bW4gKi9cbiAgZGlzYWJsZVNvcnQ6IF9yZWFjdC5Qcm9wVHlwZXMuYm9vbCxcblxuICAvKiogRmxleCBncm93IHN0eWxlOyBkZWZhdWx0cyB0byAwICovXG4gIGZsZXhHcm93OiBfcmVhY3QuUHJvcFR5cGVzLm51bWJlcixcblxuICAvKiogRmxleCBzaHJpbmsgc3R5bGU7IGRlZmF1bHRzIHRvIDEgKi9cbiAgZmxleFNocmluazogX3JlYWN0LlByb3BUeXBlcy5udW1iZXIsXG5cbiAgLyoqIE9wdGlvbmFsIENTUyBjbGFzcyB0byBhcHBseSB0byB0aGlzIGNvbHVtbidzIGhlYWRlciAqL1xuICBoZWFkZXJDbGFzc05hbWU6IF9yZWFjdC5Qcm9wVHlwZXMuc3RyaW5nLFxuXG4gIC8qKlxuICAgKiBPcHRpb25hbCBjYWxsYmFjayByZXNwb25zaWJsZSBmb3IgcmVuZGVyaW5nIGEgY29sdW1uIGhlYWRlciBjb250ZW50cy5cbiAgICogKHsgY29sdW1uRGF0YTogb2JqZWN0LCBkYXRhS2V5OiBzdHJpbmcsIGRpc2FibGVTb3J0OiBib29sZWFuLCBsYWJlbDogc3RyaW5nLCBzb3J0Qnk6IHN0cmluZywgc29ydERpcmVjdGlvbjogc3RyaW5nIH0pOiBQcm9wVHlwZXMubm9kZVxuICAgKi9cbiAgaGVhZGVyUmVuZGVyZXI6IF9yZWFjdC5Qcm9wVHlwZXMuZnVuYy5pc1JlcXVpcmVkLFxuXG4gIC8qKiBIZWFkZXIgbGFiZWwgZm9yIHRoaXMgY29sdW1uICovXG4gIGxhYmVsOiBfcmVhY3QuUHJvcFR5cGVzLnN0cmluZyxcblxuICAvKiogTWF4aW11bSB3aWR0aCBvZiBjb2x1bW47IHRoaXMgcHJvcGVydHkgd2lsbCBvbmx5IGJlIHVzZWQgaWYgOmZsZXhHcm93IGlzID4gMC4gKi9cbiAgbWF4V2lkdGg6IF9yZWFjdC5Qcm9wVHlwZXMubnVtYmVyLFxuXG4gIC8qKiBNaW5pbXVtIHdpZHRoIG9mIGNvbHVtbi4gKi9cbiAgbWluV2lkdGg6IF9yZWFjdC5Qcm9wVHlwZXMubnVtYmVyLFxuXG4gIC8qKiBPcHRpb25hbCBpbmxpbmUgc3R5bGUgdG8gYXBwbHkgdG8gY2VsbCAqL1xuICBzdHlsZTogX3JlYWN0LlByb3BUeXBlcy5vYmplY3QsXG5cbiAgLyoqIEZsZXggYmFzaXMgKHdpZHRoKSBmb3IgdGhpcyBjb2x1bW47IFRoaXMgdmFsdWUgY2FuIGdyb3cgb3Igc2hyaW5rIGJhc2VkIG9uIDpmbGV4R3JvdyBhbmQgOmZsZXhTaHJpbmsgcHJvcGVydGllcy4gKi9cbiAgd2lkdGg6IF9yZWFjdC5Qcm9wVHlwZXMubnVtYmVyLmlzUmVxdWlyZWRcbn07XG5leHBvcnRzLmRlZmF1bHQgPSBDb2x1bW47IiwiJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2V4dGVuZHMgPSBPYmplY3QuYXNzaWduIHx8IGZ1bmN0aW9uICh0YXJnZXQpIHsgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHsgdmFyIHNvdXJjZSA9IGFyZ3VtZW50c1tpXTsgZm9yICh2YXIga2V5IGluIHNvdXJjZSkgeyBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHNvdXJjZSwga2V5KSkgeyB0YXJnZXRba2V5XSA9IHNvdXJjZVtrZXldOyB9IH0gfSByZXR1cm4gdGFyZ2V0OyB9O1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKFwidmFsdWVcIiBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSgpO1xuXG52YXIgX2NsYXNzbmFtZXMgPSByZXF1aXJlKCdjbGFzc25hbWVzJyk7XG5cbnZhciBfY2xhc3NuYW1lczIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9jbGFzc25hbWVzKTtcblxudmFyIF9GbGV4Q29sdW1uID0gcmVxdWlyZSgnLi9GbGV4Q29sdW1uJyk7XG5cbnZhciBfRmxleENvbHVtbjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9GbGV4Q29sdW1uKTtcblxudmFyIF9yZWFjdCA9IHJlcXVpcmUoJ3JlYWN0Jyk7XG5cbnZhciBfcmVhY3QyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfcmVhY3QpO1xuXG52YXIgX3JlYWN0RG9tID0gcmVxdWlyZSgncmVhY3QtZG9tJyk7XG5cbnZhciBfcmVhY3RBZGRvbnNTaGFsbG93Q29tcGFyZSA9IHJlcXVpcmUoJ3JlYWN0LWFkZG9ucy1zaGFsbG93LWNvbXBhcmUnKTtcblxudmFyIF9yZWFjdEFkZG9uc1NoYWxsb3dDb21wYXJlMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3JlYWN0QWRkb25zU2hhbGxvd0NvbXBhcmUpO1xuXG52YXIgX0dyaWQgPSByZXF1aXJlKCcuLi9HcmlkJyk7XG5cbnZhciBfR3JpZDIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9HcmlkKTtcblxudmFyIF9kZWZhdWx0Um93UmVuZGVyZXIgPSByZXF1aXJlKCcuL2RlZmF1bHRSb3dSZW5kZXJlcicpO1xuXG52YXIgX2RlZmF1bHRSb3dSZW5kZXJlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9kZWZhdWx0Um93UmVuZGVyZXIpO1xuXG52YXIgX1NvcnREaXJlY3Rpb24gPSByZXF1aXJlKCcuL1NvcnREaXJlY3Rpb24nKTtcblxudmFyIF9Tb3J0RGlyZWN0aW9uMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX1NvcnREaXJlY3Rpb24pO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyBkZWZhdWx0OiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb25cIik7IH0gfVxuXG5mdW5jdGlvbiBfcG9zc2libGVDb25zdHJ1Y3RvclJldHVybihzZWxmLCBjYWxsKSB7IGlmICghc2VsZikgeyB0aHJvdyBuZXcgUmVmZXJlbmNlRXJyb3IoXCJ0aGlzIGhhc24ndCBiZWVuIGluaXRpYWxpc2VkIC0gc3VwZXIoKSBoYXNuJ3QgYmVlbiBjYWxsZWRcIik7IH0gcmV0dXJuIGNhbGwgJiYgKHR5cGVvZiBjYWxsID09PSBcIm9iamVjdFwiIHx8IHR5cGVvZiBjYWxsID09PSBcImZ1bmN0aW9uXCIpID8gY2FsbCA6IHNlbGY7IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gXCJmdW5jdGlvblwiICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgXCIgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIE9iamVjdC5zZXRQcm90b3R5cGVPZiA/IE9iamVjdC5zZXRQcm90b3R5cGVPZihzdWJDbGFzcywgc3VwZXJDbGFzcykgOiBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbi8qKlxuICogVGFibGUgY29tcG9uZW50IHdpdGggZml4ZWQgaGVhZGVycyBhbmQgdmlydHVhbGl6ZWQgcm93cyBmb3IgaW1wcm92ZWQgcGVyZm9ybWFuY2Ugd2l0aCBsYXJnZSBkYXRhIHNldHMuXG4gKiBUaGlzIGNvbXBvbmVudCBleHBlY3RzIGV4cGxpY2l0IHdpZHRoLCBoZWlnaHQsIGFuZCBwYWRkaW5nIHBhcmFtZXRlcnMuXG4gKi9cbnZhciBGbGV4VGFibGUgPSBmdW5jdGlvbiAoX0NvbXBvbmVudCkge1xuICBfaW5oZXJpdHMoRmxleFRhYmxlLCBfQ29tcG9uZW50KTtcblxuICBmdW5jdGlvbiBGbGV4VGFibGUocHJvcHMpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgRmxleFRhYmxlKTtcblxuICAgIHZhciBfdGhpcyA9IF9wb3NzaWJsZUNvbnN0cnVjdG9yUmV0dXJuKHRoaXMsIChGbGV4VGFibGUuX19wcm90b19fIHx8IE9iamVjdC5nZXRQcm90b3R5cGVPZihGbGV4VGFibGUpKS5jYWxsKHRoaXMsIHByb3BzKSk7XG5cbiAgICBfdGhpcy5zdGF0ZSA9IHtcbiAgICAgIHNjcm9sbGJhcldpZHRoOiAwXG4gICAgfTtcblxuICAgIF90aGlzLl9jZWxsQ2xhc3NOYW1lID0gX3RoaXMuX2NlbGxDbGFzc05hbWUuYmluZChfdGhpcyk7XG4gICAgX3RoaXMuX2NlbGxTdHlsZSA9IF90aGlzLl9jZWxsU3R5bGUuYmluZChfdGhpcyk7XG4gICAgX3RoaXMuX2NyZWF0ZUNvbHVtbiA9IF90aGlzLl9jcmVhdGVDb2x1bW4uYmluZChfdGhpcyk7XG4gICAgX3RoaXMuX2NyZWF0ZVJvdyA9IF90aGlzLl9jcmVhdGVSb3cuYmluZChfdGhpcyk7XG4gICAgX3RoaXMuX29uU2Nyb2xsID0gX3RoaXMuX29uU2Nyb2xsLmJpbmQoX3RoaXMpO1xuICAgIF90aGlzLl9vblNlY3Rpb25SZW5kZXJlZCA9IF90aGlzLl9vblNlY3Rpb25SZW5kZXJlZC5iaW5kKF90aGlzKTtcbiAgICByZXR1cm4gX3RoaXM7XG4gIH1cblxuICBfY3JlYXRlQ2xhc3MoRmxleFRhYmxlLCBbe1xuICAgIGtleTogJ2ZvcmNlVXBkYXRlR3JpZCcsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGZvcmNlVXBkYXRlR3JpZCgpIHtcbiAgICAgIHRoaXMuR3JpZC5mb3JjZVVwZGF0ZSgpO1xuICAgIH1cblxuICAgIC8qKiBTZWUgR3JpZCNtZWFzdXJlQWxsQ2VsbHMgKi9cblxuICB9LCB7XG4gICAga2V5OiAnbWVhc3VyZUFsbFJvd3MnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBtZWFzdXJlQWxsUm93cygpIHtcbiAgICAgIHRoaXMuR3JpZC5tZWFzdXJlQWxsQ2VsbHMoKTtcbiAgICB9XG5cbiAgICAvKiogU2VlIEdyaWQjcmVjb21wdXRlR3JpZFNpemUgKi9cblxuICB9LCB7XG4gICAga2V5OiAncmVjb21wdXRlUm93SGVpZ2h0cycsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJlY29tcHV0ZVJvd0hlaWdodHMoKSB7XG4gICAgICB2YXIgaW5kZXggPSBhcmd1bWVudHMubGVuZ3RoIDw9IDAgfHwgYXJndW1lbnRzWzBdID09PSB1bmRlZmluZWQgPyAwIDogYXJndW1lbnRzWzBdO1xuXG4gICAgICB0aGlzLkdyaWQucmVjb21wdXRlR3JpZFNpemUoe1xuICAgICAgICByb3dJbmRleDogaW5kZXhcbiAgICAgIH0pO1xuICAgICAgdGhpcy5mb3JjZVVwZGF0ZUdyaWQoKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdjb21wb25lbnREaWRNb3VudCcsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGNvbXBvbmVudERpZE1vdW50KCkge1xuICAgICAgdGhpcy5fc2V0U2Nyb2xsYmFyV2lkdGgoKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdjb21wb25lbnREaWRVcGRhdGUnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBjb21wb25lbnREaWRVcGRhdGUoKSB7XG4gICAgICB0aGlzLl9zZXRTY3JvbGxiYXJXaWR0aCgpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ3JlbmRlcicsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJlbmRlcigpIHtcbiAgICAgIHZhciBfdGhpczIgPSB0aGlzO1xuXG4gICAgICB2YXIgX3Byb3BzID0gdGhpcy5wcm9wcztcbiAgICAgIHZhciBjaGlsZHJlbiA9IF9wcm9wcy5jaGlsZHJlbjtcbiAgICAgIHZhciBjbGFzc05hbWUgPSBfcHJvcHMuY2xhc3NOYW1lO1xuICAgICAgdmFyIGRpc2FibGVIZWFkZXIgPSBfcHJvcHMuZGlzYWJsZUhlYWRlcjtcbiAgICAgIHZhciBncmlkQ2xhc3NOYW1lID0gX3Byb3BzLmdyaWRDbGFzc05hbWU7XG4gICAgICB2YXIgZ3JpZFN0eWxlID0gX3Byb3BzLmdyaWRTdHlsZTtcbiAgICAgIHZhciBoZWFkZXJIZWlnaHQgPSBfcHJvcHMuaGVhZGVySGVpZ2h0O1xuICAgICAgdmFyIGhlaWdodCA9IF9wcm9wcy5oZWlnaHQ7XG4gICAgICB2YXIgbm9Sb3dzUmVuZGVyZXIgPSBfcHJvcHMubm9Sb3dzUmVuZGVyZXI7XG4gICAgICB2YXIgcm93Q2xhc3NOYW1lID0gX3Byb3BzLnJvd0NsYXNzTmFtZTtcbiAgICAgIHZhciByb3dTdHlsZSA9IF9wcm9wcy5yb3dTdHlsZTtcbiAgICAgIHZhciBzY3JvbGxUb0luZGV4ID0gX3Byb3BzLnNjcm9sbFRvSW5kZXg7XG4gICAgICB2YXIgc3R5bGUgPSBfcHJvcHMuc3R5bGU7XG4gICAgICB2YXIgd2lkdGggPSBfcHJvcHMud2lkdGg7XG4gICAgICB2YXIgc2Nyb2xsYmFyV2lkdGggPSB0aGlzLnN0YXRlLnNjcm9sbGJhcldpZHRoO1xuXG5cbiAgICAgIHZhciBhdmFpbGFibGVSb3dzSGVpZ2h0ID0gaGVpZ2h0IC0gaGVhZGVySGVpZ2h0O1xuXG4gICAgICB2YXIgcm93Q2xhc3MgPSByb3dDbGFzc05hbWUgaW5zdGFuY2VvZiBGdW5jdGlvbiA/IHJvd0NsYXNzTmFtZSh7IGluZGV4OiAtMSB9KSA6IHJvd0NsYXNzTmFtZTtcbiAgICAgIHZhciByb3dTdHlsZU9iamVjdCA9IHJvd1N0eWxlIGluc3RhbmNlb2YgRnVuY3Rpb24gPyByb3dTdHlsZSh7IGluZGV4OiAtMSB9KSA6IHJvd1N0eWxlO1xuXG4gICAgICAvLyBQcmVjb21wdXRlIGFuZCBjYWNoZSBjb2x1bW4gc3R5bGVzIGJlZm9yZSByZW5kZXJpbmcgcm93cyBhbmQgY29sdW1ucyB0byBzcGVlZCB0aGluZ3MgdXBcbiAgICAgIHRoaXMuX2NhY2hlZENvbHVtblN0eWxlcyA9IFtdO1xuICAgICAgX3JlYWN0Mi5kZWZhdWx0LkNoaWxkcmVuLnRvQXJyYXkoY2hpbGRyZW4pLmZvckVhY2goZnVuY3Rpb24gKGNvbHVtbiwgaW5kZXgpIHtcbiAgICAgICAgX3RoaXMyLl9jYWNoZWRDb2x1bW5TdHlsZXNbaW5kZXhdID0gX3RoaXMyLl9nZXRGbGV4U3R5bGVGb3JDb2x1bW4oY29sdW1uLCBjb2x1bW4ucHJvcHMuc3R5bGUpO1xuICAgICAgfSk7XG5cbiAgICAgIC8vIE5vdGUgdGhhdCB3ZSBzcGVjaWZ5IDpudW1DaGlsZHJlbiwgOnNjcm9sbGJhcldpZHRoLCA6c29ydEJ5LCBhbmQgOnNvcnREaXJlY3Rpb24gYXMgcHJvcGVydGllcyBvbiBHcmlkIGV2ZW4gdGhvdWdoIHRoZXNlIGhhdmUgbm90aGluZyB0byBkbyB3aXRoIEdyaWQuXG4gICAgICAvLyBUaGlzIGlzIGRvbmUgYmVjYXVzZSBHcmlkIGlzIGEgcHVyZSBjb21wb25lbnQgYW5kIHdvbid0IHVwZGF0ZSB1bmxlc3MgaXRzIHByb3BlcnRpZXMgb3Igc3RhdGUgaGFzIGNoYW5nZWQuXG4gICAgICAvLyBBbnkgcHJvcGVydHkgdGhhdCBzaG91bGQgdHJpZ2dlciBhIHJlLXJlbmRlciBvZiBHcmlkIHRoZW4gaXMgc3BlY2lmaWVkIGhlcmUgdG8gYXZvaWQgYSBzdGFsZSBkaXNwbGF5LlxuICAgICAgcmV0dXJuIF9yZWFjdDIuZGVmYXVsdC5jcmVhdGVFbGVtZW50KFxuICAgICAgICAnZGl2JyxcbiAgICAgICAge1xuICAgICAgICAgIGNsYXNzTmFtZTogKDAsIF9jbGFzc25hbWVzMi5kZWZhdWx0KSgnRmxleFRhYmxlJywgY2xhc3NOYW1lKSxcbiAgICAgICAgICBzdHlsZTogc3R5bGVcbiAgICAgICAgfSxcbiAgICAgICAgIWRpc2FibGVIZWFkZXIgJiYgX3JlYWN0Mi5kZWZhdWx0LmNyZWF0ZUVsZW1lbnQoXG4gICAgICAgICAgJ2RpdicsXG4gICAgICAgICAge1xuICAgICAgICAgICAgY2xhc3NOYW1lOiAoMCwgX2NsYXNzbmFtZXMyLmRlZmF1bHQpKCdGbGV4VGFibGVfX2hlYWRlclJvdycsIHJvd0NsYXNzKSxcbiAgICAgICAgICAgIHN0eWxlOiBfZXh0ZW5kcyh7fSwgcm93U3R5bGVPYmplY3QsIHtcbiAgICAgICAgICAgICAgaGVpZ2h0OiBoZWFkZXJIZWlnaHQsXG4gICAgICAgICAgICAgIHBhZGRpbmdSaWdodDogc2Nyb2xsYmFyV2lkdGgsXG4gICAgICAgICAgICAgIHdpZHRoOiB3aWR0aFxuICAgICAgICAgICAgfSlcbiAgICAgICAgICB9LFxuICAgICAgICAgIHRoaXMuX2dldFJlbmRlcmVkSGVhZGVyUm93KClcbiAgICAgICAgKSxcbiAgICAgICAgX3JlYWN0Mi5kZWZhdWx0LmNyZWF0ZUVsZW1lbnQoX0dyaWQyLmRlZmF1bHQsIF9leHRlbmRzKHt9LCB0aGlzLnByb3BzLCB7XG4gICAgICAgICAgYXV0b0NvbnRhaW5lcldpZHRoOiB0cnVlLFxuICAgICAgICAgIGNsYXNzTmFtZTogKDAsIF9jbGFzc25hbWVzMi5kZWZhdWx0KSgnRmxleFRhYmxlX19HcmlkJywgZ3JpZENsYXNzTmFtZSksXG4gICAgICAgICAgY2VsbENsYXNzTmFtZTogdGhpcy5fY2VsbENsYXNzTmFtZSxcbiAgICAgICAgICBjZWxsUmVuZGVyZXI6IHRoaXMuX2NyZWF0ZVJvdyxcbiAgICAgICAgICBjZWxsU3R5bGU6IHRoaXMuX2NlbGxTdHlsZSxcbiAgICAgICAgICBjb2x1bW5XaWR0aDogd2lkdGgsXG4gICAgICAgICAgY29sdW1uQ291bnQ6IDEsXG4gICAgICAgICAgaGVpZ2h0OiBhdmFpbGFibGVSb3dzSGVpZ2h0LFxuICAgICAgICAgIG5vQ29udGVudFJlbmRlcmVyOiBub1Jvd3NSZW5kZXJlcixcbiAgICAgICAgICBvblNjcm9sbDogdGhpcy5fb25TY3JvbGwsXG4gICAgICAgICAgb25TZWN0aW9uUmVuZGVyZWQ6IHRoaXMuX29uU2VjdGlvblJlbmRlcmVkLFxuICAgICAgICAgIHJlZjogZnVuY3Rpb24gcmVmKF9yZWYpIHtcbiAgICAgICAgICAgIF90aGlzMi5HcmlkID0gX3JlZjtcbiAgICAgICAgICB9LFxuICAgICAgICAgIHNjcm9sbGJhcldpZHRoOiBzY3JvbGxiYXJXaWR0aCxcbiAgICAgICAgICBzY3JvbGxUb1Jvdzogc2Nyb2xsVG9JbmRleCxcbiAgICAgICAgICBzdHlsZTogZ3JpZFN0eWxlXG4gICAgICAgIH0pKVxuICAgICAgKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdzaG91bGRDb21wb25lbnRVcGRhdGUnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBzaG91bGRDb21wb25lbnRVcGRhdGUobmV4dFByb3BzLCBuZXh0U3RhdGUpIHtcbiAgICAgIHJldHVybiAoMCwgX3JlYWN0QWRkb25zU2hhbGxvd0NvbXBhcmUyLmRlZmF1bHQpKHRoaXMsIG5leHRQcm9wcywgbmV4dFN0YXRlKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfY2VsbENsYXNzTmFtZScsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9jZWxsQ2xhc3NOYW1lKF9yZWYyKSB7XG4gICAgICB2YXIgcm93SW5kZXggPSBfcmVmMi5yb3dJbmRleDtcbiAgICAgIHZhciByb3dXcmFwcGVyQ2xhc3NOYW1lID0gdGhpcy5wcm9wcy5yb3dXcmFwcGVyQ2xhc3NOYW1lO1xuXG5cbiAgICAgIHJldHVybiByb3dXcmFwcGVyQ2xhc3NOYW1lIGluc3RhbmNlb2YgRnVuY3Rpb24gPyByb3dXcmFwcGVyQ2xhc3NOYW1lKHsgaW5kZXg6IHJvd0luZGV4IC0gMSB9KSA6IHJvd1dyYXBwZXJDbGFzc05hbWU7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX2NlbGxTdHlsZScsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9jZWxsU3R5bGUoX3JlZjMpIHtcbiAgICAgIHZhciByb3dJbmRleCA9IF9yZWYzLnJvd0luZGV4O1xuICAgICAgdmFyIHJvd1dyYXBwZXJTdHlsZSA9IHRoaXMucHJvcHMucm93V3JhcHBlclN0eWxlO1xuXG5cbiAgICAgIHJldHVybiByb3dXcmFwcGVyU3R5bGUgaW5zdGFuY2VvZiBGdW5jdGlvbiA/IHJvd1dyYXBwZXJTdHlsZSh7IGluZGV4OiByb3dJbmRleCAtIDEgfSkgOiByb3dXcmFwcGVyU3R5bGU7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX2NyZWF0ZUNvbHVtbicsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9jcmVhdGVDb2x1bW4oX3JlZjQpIHtcbiAgICAgIHZhciBjb2x1bW4gPSBfcmVmNC5jb2x1bW47XG4gICAgICB2YXIgY29sdW1uSW5kZXggPSBfcmVmNC5jb2x1bW5JbmRleDtcbiAgICAgIHZhciBpc1Njcm9sbGluZyA9IF9yZWY0LmlzU2Nyb2xsaW5nO1xuICAgICAgdmFyIHJvd0RhdGEgPSBfcmVmNC5yb3dEYXRhO1xuICAgICAgdmFyIHJvd0luZGV4ID0gX3JlZjQucm93SW5kZXg7XG4gICAgICB2YXIgX2NvbHVtbiRwcm9wcyA9IGNvbHVtbi5wcm9wcztcbiAgICAgIHZhciBjZWxsRGF0YUdldHRlciA9IF9jb2x1bW4kcHJvcHMuY2VsbERhdGFHZXR0ZXI7XG4gICAgICB2YXIgY2VsbFJlbmRlcmVyID0gX2NvbHVtbiRwcm9wcy5jZWxsUmVuZGVyZXI7XG4gICAgICB2YXIgY2xhc3NOYW1lID0gX2NvbHVtbiRwcm9wcy5jbGFzc05hbWU7XG4gICAgICB2YXIgY29sdW1uRGF0YSA9IF9jb2x1bW4kcHJvcHMuY29sdW1uRGF0YTtcbiAgICAgIHZhciBkYXRhS2V5ID0gX2NvbHVtbiRwcm9wcy5kYXRhS2V5O1xuXG5cbiAgICAgIHZhciBjZWxsRGF0YSA9IGNlbGxEYXRhR2V0dGVyKHsgY29sdW1uRGF0YTogY29sdW1uRGF0YSwgZGF0YUtleTogZGF0YUtleSwgcm93RGF0YTogcm93RGF0YSB9KTtcbiAgICAgIHZhciByZW5kZXJlZENlbGwgPSBjZWxsUmVuZGVyZXIoeyBjZWxsRGF0YTogY2VsbERhdGEsIGNvbHVtbkRhdGE6IGNvbHVtbkRhdGEsIGRhdGFLZXk6IGRhdGFLZXksIGlzU2Nyb2xsaW5nOiBpc1Njcm9sbGluZywgcm93RGF0YTogcm93RGF0YSwgcm93SW5kZXg6IHJvd0luZGV4IH0pO1xuXG4gICAgICB2YXIgc3R5bGUgPSB0aGlzLl9jYWNoZWRDb2x1bW5TdHlsZXNbY29sdW1uSW5kZXhdO1xuXG4gICAgICB2YXIgdGl0bGUgPSB0eXBlb2YgcmVuZGVyZWRDZWxsID09PSAnc3RyaW5nJyA/IHJlbmRlcmVkQ2VsbCA6IG51bGw7XG5cbiAgICAgIHJldHVybiBfcmVhY3QyLmRlZmF1bHQuY3JlYXRlRWxlbWVudChcbiAgICAgICAgJ2RpdicsXG4gICAgICAgIHtcbiAgICAgICAgICBrZXk6ICdSb3cnICsgcm93SW5kZXggKyAnLUNvbCcgKyBjb2x1bW5JbmRleCxcbiAgICAgICAgICBjbGFzc05hbWU6ICgwLCBfY2xhc3NuYW1lczIuZGVmYXVsdCkoJ0ZsZXhUYWJsZV9fcm93Q29sdW1uJywgY2xhc3NOYW1lKSxcbiAgICAgICAgICBzdHlsZTogc3R5bGUsXG4gICAgICAgICAgdGl0bGU6IHRpdGxlXG4gICAgICAgIH0sXG4gICAgICAgIHJlbmRlcmVkQ2VsbFxuICAgICAgKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfY3JlYXRlSGVhZGVyJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gX2NyZWF0ZUhlYWRlcihfcmVmNSkge1xuICAgICAgdmFyIGNvbHVtbiA9IF9yZWY1LmNvbHVtbjtcbiAgICAgIHZhciBpbmRleCA9IF9yZWY1LmluZGV4O1xuICAgICAgdmFyIF9wcm9wczIgPSB0aGlzLnByb3BzO1xuICAgICAgdmFyIGhlYWRlckNsYXNzTmFtZSA9IF9wcm9wczIuaGVhZGVyQ2xhc3NOYW1lO1xuICAgICAgdmFyIGhlYWRlclN0eWxlID0gX3Byb3BzMi5oZWFkZXJTdHlsZTtcbiAgICAgIHZhciBvbkhlYWRlckNsaWNrID0gX3Byb3BzMi5vbkhlYWRlckNsaWNrO1xuICAgICAgdmFyIHNvcnQgPSBfcHJvcHMyLnNvcnQ7XG4gICAgICB2YXIgc29ydEJ5ID0gX3Byb3BzMi5zb3J0Qnk7XG4gICAgICB2YXIgc29ydERpcmVjdGlvbiA9IF9wcm9wczIuc29ydERpcmVjdGlvbjtcbiAgICAgIHZhciBfY29sdW1uJHByb3BzMiA9IGNvbHVtbi5wcm9wcztcbiAgICAgIHZhciBkYXRhS2V5ID0gX2NvbHVtbiRwcm9wczIuZGF0YUtleTtcbiAgICAgIHZhciBkaXNhYmxlU29ydCA9IF9jb2x1bW4kcHJvcHMyLmRpc2FibGVTb3J0O1xuICAgICAgdmFyIGhlYWRlclJlbmRlcmVyID0gX2NvbHVtbiRwcm9wczIuaGVhZGVyUmVuZGVyZXI7XG4gICAgICB2YXIgbGFiZWwgPSBfY29sdW1uJHByb3BzMi5sYWJlbDtcbiAgICAgIHZhciBjb2x1bW5EYXRhID0gX2NvbHVtbiRwcm9wczIuY29sdW1uRGF0YTtcblxuICAgICAgdmFyIHNvcnRFbmFibGVkID0gIWRpc2FibGVTb3J0ICYmIHNvcnQ7XG5cbiAgICAgIHZhciBjbGFzc05hbWVzID0gKDAsIF9jbGFzc25hbWVzMi5kZWZhdWx0KSgnRmxleFRhYmxlX19oZWFkZXJDb2x1bW4nLCBoZWFkZXJDbGFzc05hbWUsIGNvbHVtbi5wcm9wcy5oZWFkZXJDbGFzc05hbWUsIHtcbiAgICAgICAgJ0ZsZXhUYWJsZV9fc29ydGFibGVIZWFkZXJDb2x1bW4nOiBzb3J0RW5hYmxlZFxuICAgICAgfSk7XG4gICAgICB2YXIgc3R5bGUgPSB0aGlzLl9nZXRGbGV4U3R5bGVGb3JDb2x1bW4oY29sdW1uLCBoZWFkZXJTdHlsZSk7XG5cbiAgICAgIHZhciByZW5kZXJlZEhlYWRlciA9IGhlYWRlclJlbmRlcmVyKHtcbiAgICAgICAgY29sdW1uRGF0YTogY29sdW1uRGF0YSxcbiAgICAgICAgZGF0YUtleTogZGF0YUtleSxcbiAgICAgICAgZGlzYWJsZVNvcnQ6IGRpc2FibGVTb3J0LFxuICAgICAgICBsYWJlbDogbGFiZWwsXG4gICAgICAgIHNvcnRCeTogc29ydEJ5LFxuICAgICAgICBzb3J0RGlyZWN0aW9uOiBzb3J0RGlyZWN0aW9uXG4gICAgICB9KTtcblxuICAgICAgdmFyIGExMXlQcm9wcyA9IHt9O1xuXG4gICAgICBpZiAoc29ydEVuYWJsZWQgfHwgb25IZWFkZXJDbGljaykge1xuICAgICAgICAoZnVuY3Rpb24gKCkge1xuICAgICAgICAgIC8vIElmIHRoaXMgaXMgYSBzb3J0YWJsZSBoZWFkZXIsIGNsaWNraW5nIGl0IHNob3VsZCB1cGRhdGUgdGhlIHRhYmxlIGRhdGEncyBzb3J0aW5nLlxuICAgICAgICAgIHZhciBuZXdTb3J0RGlyZWN0aW9uID0gc29ydEJ5ICE9PSBkYXRhS2V5IHx8IHNvcnREaXJlY3Rpb24gPT09IF9Tb3J0RGlyZWN0aW9uMi5kZWZhdWx0LkRFU0MgPyBfU29ydERpcmVjdGlvbjIuZGVmYXVsdC5BU0MgOiBfU29ydERpcmVjdGlvbjIuZGVmYXVsdC5ERVNDO1xuXG4gICAgICAgICAgdmFyIG9uQ2xpY2sgPSBmdW5jdGlvbiBvbkNsaWNrKCkge1xuICAgICAgICAgICAgc29ydEVuYWJsZWQgJiYgc29ydCh7XG4gICAgICAgICAgICAgIHNvcnRCeTogZGF0YUtleSxcbiAgICAgICAgICAgICAgc29ydERpcmVjdGlvbjogbmV3U29ydERpcmVjdGlvblxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBvbkhlYWRlckNsaWNrICYmIG9uSGVhZGVyQ2xpY2soeyBjb2x1bW5EYXRhOiBjb2x1bW5EYXRhLCBkYXRhS2V5OiBkYXRhS2V5IH0pO1xuICAgICAgICAgIH07XG5cbiAgICAgICAgICB2YXIgb25LZXlEb3duID0gZnVuY3Rpb24gb25LZXlEb3duKGV2ZW50KSB7XG4gICAgICAgICAgICBpZiAoZXZlbnQua2V5ID09PSAnRW50ZXInIHx8IGV2ZW50LmtleSA9PT0gJyAnKSB7XG4gICAgICAgICAgICAgIG9uQ2xpY2soKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9O1xuXG4gICAgICAgICAgYTExeVByb3BzWydhcmlhLWxhYmVsJ10gPSBjb2x1bW4ucHJvcHNbJ2FyaWEtbGFiZWwnXSB8fCBsYWJlbCB8fCBkYXRhS2V5O1xuICAgICAgICAgIGExMXlQcm9wcy5yb2xlID0gJ3Jvd2hlYWRlcic7XG4gICAgICAgICAgYTExeVByb3BzLnRhYkluZGV4ID0gMDtcbiAgICAgICAgICBhMTF5UHJvcHMub25DbGljayA9IG9uQ2xpY2s7XG4gICAgICAgICAgYTExeVByb3BzLm9uS2V5RG93biA9IG9uS2V5RG93bjtcbiAgICAgICAgfSkoKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIF9yZWFjdDIuZGVmYXVsdC5jcmVhdGVFbGVtZW50KFxuICAgICAgICAnZGl2JyxcbiAgICAgICAgX2V4dGVuZHMoe30sIGExMXlQcm9wcywge1xuICAgICAgICAgIGtleTogJ0hlYWRlci1Db2wnICsgaW5kZXgsXG4gICAgICAgICAgY2xhc3NOYW1lOiBjbGFzc05hbWVzLFxuICAgICAgICAgIHN0eWxlOiBzdHlsZVxuICAgICAgICB9KSxcbiAgICAgICAgcmVuZGVyZWRIZWFkZXJcbiAgICAgICk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX2NyZWF0ZVJvdycsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9jcmVhdGVSb3coX3JlZjYpIHtcbiAgICAgIHZhciBfdGhpczMgPSB0aGlzO1xuXG4gICAgICB2YXIgaW5kZXggPSBfcmVmNi5yb3dJbmRleDtcbiAgICAgIHZhciBpc1Njcm9sbGluZyA9IF9yZWY2LmlzU2Nyb2xsaW5nO1xuICAgICAgdmFyIF9wcm9wczMgPSB0aGlzLnByb3BzO1xuICAgICAgdmFyIGNoaWxkcmVuID0gX3Byb3BzMy5jaGlsZHJlbjtcbiAgICAgIHZhciBvblJvd0NsaWNrID0gX3Byb3BzMy5vblJvd0NsaWNrO1xuICAgICAgdmFyIG9uUm93RG91YmxlQ2xpY2sgPSBfcHJvcHMzLm9uUm93RG91YmxlQ2xpY2s7XG4gICAgICB2YXIgb25Sb3dNb3VzZU92ZXIgPSBfcHJvcHMzLm9uUm93TW91c2VPdmVyO1xuICAgICAgdmFyIG9uUm93TW91c2VPdXQgPSBfcHJvcHMzLm9uUm93TW91c2VPdXQ7XG4gICAgICB2YXIgcm93Q2xhc3NOYW1lID0gX3Byb3BzMy5yb3dDbGFzc05hbWU7XG4gICAgICB2YXIgcm93R2V0dGVyID0gX3Byb3BzMy5yb3dHZXR0ZXI7XG4gICAgICB2YXIgcm93UmVuZGVyZXIgPSBfcHJvcHMzLnJvd1JlbmRlcmVyO1xuICAgICAgdmFyIHJvd1N0eWxlID0gX3Byb3BzMy5yb3dTdHlsZTtcbiAgICAgIHZhciBzY3JvbGxiYXJXaWR0aCA9IHRoaXMuc3RhdGUuc2Nyb2xsYmFyV2lkdGg7XG5cblxuICAgICAgdmFyIHJvd0NsYXNzID0gcm93Q2xhc3NOYW1lIGluc3RhbmNlb2YgRnVuY3Rpb24gPyByb3dDbGFzc05hbWUoeyBpbmRleDogaW5kZXggfSkgOiByb3dDbGFzc05hbWU7XG4gICAgICB2YXIgcm93U3R5bGVPYmplY3QgPSByb3dTdHlsZSBpbnN0YW5jZW9mIEZ1bmN0aW9uID8gcm93U3R5bGUoeyBpbmRleDogaW5kZXggfSkgOiByb3dTdHlsZTtcbiAgICAgIHZhciByb3dEYXRhID0gcm93R2V0dGVyKHsgaW5kZXg6IGluZGV4IH0pO1xuXG4gICAgICB2YXIgY29sdW1ucyA9IF9yZWFjdDIuZGVmYXVsdC5DaGlsZHJlbi50b0FycmF5KGNoaWxkcmVuKS5tYXAoZnVuY3Rpb24gKGNvbHVtbiwgY29sdW1uSW5kZXgpIHtcbiAgICAgICAgcmV0dXJuIF90aGlzMy5fY3JlYXRlQ29sdW1uKHtcbiAgICAgICAgICBjb2x1bW46IGNvbHVtbixcbiAgICAgICAgICBjb2x1bW5JbmRleDogY29sdW1uSW5kZXgsXG4gICAgICAgICAgaXNTY3JvbGxpbmc6IGlzU2Nyb2xsaW5nLFxuICAgICAgICAgIHJvd0RhdGE6IHJvd0RhdGEsXG4gICAgICAgICAgcm93SW5kZXg6IGluZGV4LFxuICAgICAgICAgIHNjcm9sbGJhcldpZHRoOiBzY3JvbGxiYXJXaWR0aFxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICB2YXIgY2xhc3NOYW1lID0gKDAsIF9jbGFzc25hbWVzMi5kZWZhdWx0KSgnRmxleFRhYmxlX19yb3cnLCByb3dDbGFzcyk7XG4gICAgICB2YXIgc3R5bGUgPSBfZXh0ZW5kcyh7fSwgcm93U3R5bGVPYmplY3QsIHtcbiAgICAgICAgaGVpZ2h0OiB0aGlzLl9nZXRSb3dIZWlnaHQoaW5kZXgpLFxuICAgICAgICBwYWRkaW5nUmlnaHQ6IHNjcm9sbGJhcldpZHRoXG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIHJvd1JlbmRlcmVyKHtcbiAgICAgICAgY2xhc3NOYW1lOiBjbGFzc05hbWUsXG4gICAgICAgIGNvbHVtbnM6IGNvbHVtbnMsXG4gICAgICAgIGluZGV4OiBpbmRleCxcbiAgICAgICAgaXNTY3JvbGxpbmc6IGlzU2Nyb2xsaW5nLFxuICAgICAgICBvblJvd0NsaWNrOiBvblJvd0NsaWNrLFxuICAgICAgICBvblJvd0RvdWJsZUNsaWNrOiBvblJvd0RvdWJsZUNsaWNrLFxuICAgICAgICBvblJvd01vdXNlT3Zlcjogb25Sb3dNb3VzZU92ZXIsXG4gICAgICAgIG9uUm93TW91c2VPdXQ6IG9uUm93TW91c2VPdXQsXG4gICAgICAgIHJvd0RhdGE6IHJvd0RhdGEsXG4gICAgICAgIHN0eWxlOiBzdHlsZVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGV0ZXJtaW5lcyB0aGUgZmxleC1zaHJpbmssIGZsZXgtZ3JvdywgYW5kIHdpZHRoIHZhbHVlcyBmb3IgYSBjZWxsIChoZWFkZXIgb3IgY29sdW1uKS5cbiAgICAgKi9cblxuICB9LCB7XG4gICAga2V5OiAnX2dldEZsZXhTdHlsZUZvckNvbHVtbicsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9nZXRGbGV4U3R5bGVGb3JDb2x1bW4oY29sdW1uKSB7XG4gICAgICB2YXIgY3VzdG9tU3R5bGUgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDEgfHwgYXJndW1lbnRzWzFdID09PSB1bmRlZmluZWQgPyB7fSA6IGFyZ3VtZW50c1sxXTtcblxuICAgICAgdmFyIGZsZXhWYWx1ZSA9IGNvbHVtbi5wcm9wcy5mbGV4R3JvdyArICcgJyArIGNvbHVtbi5wcm9wcy5mbGV4U2hyaW5rICsgJyAnICsgY29sdW1uLnByb3BzLndpZHRoICsgJ3B4JztcblxuICAgICAgdmFyIHN0eWxlID0gX2V4dGVuZHMoe30sIGN1c3RvbVN0eWxlLCB7XG4gICAgICAgIGZsZXg6IGZsZXhWYWx1ZSxcbiAgICAgICAgbXNGbGV4OiBmbGV4VmFsdWUsXG4gICAgICAgIFdlYmtpdEZsZXg6IGZsZXhWYWx1ZVxuICAgICAgfSk7XG5cbiAgICAgIGlmIChjb2x1bW4ucHJvcHMubWF4V2lkdGgpIHtcbiAgICAgICAgc3R5bGUubWF4V2lkdGggPSBjb2x1bW4ucHJvcHMubWF4V2lkdGg7XG4gICAgICB9XG5cbiAgICAgIGlmIChjb2x1bW4ucHJvcHMubWluV2lkdGgpIHtcbiAgICAgICAgc3R5bGUubWluV2lkdGggPSBjb2x1bW4ucHJvcHMubWluV2lkdGg7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBzdHlsZTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfZ2V0UmVuZGVyZWRIZWFkZXJSb3cnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBfZ2V0UmVuZGVyZWRIZWFkZXJSb3coKSB7XG4gICAgICB2YXIgX3RoaXM0ID0gdGhpcztcblxuICAgICAgdmFyIF9wcm9wczQgPSB0aGlzLnByb3BzO1xuICAgICAgdmFyIGNoaWxkcmVuID0gX3Byb3BzNC5jaGlsZHJlbjtcbiAgICAgIHZhciBkaXNhYmxlSGVhZGVyID0gX3Byb3BzNC5kaXNhYmxlSGVhZGVyO1xuXG4gICAgICB2YXIgaXRlbXMgPSBkaXNhYmxlSGVhZGVyID8gW10gOiBfcmVhY3QyLmRlZmF1bHQuQ2hpbGRyZW4udG9BcnJheShjaGlsZHJlbik7XG5cbiAgICAgIHJldHVybiBpdGVtcy5tYXAoZnVuY3Rpb24gKGNvbHVtbiwgaW5kZXgpIHtcbiAgICAgICAgcmV0dXJuIF90aGlzNC5fY3JlYXRlSGVhZGVyKHsgY29sdW1uOiBjb2x1bW4sIGluZGV4OiBpbmRleCB9KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19nZXRSb3dIZWlnaHQnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBfZ2V0Um93SGVpZ2h0KHJvd0luZGV4KSB7XG4gICAgICB2YXIgcm93SGVpZ2h0ID0gdGhpcy5wcm9wcy5yb3dIZWlnaHQ7XG5cblxuICAgICAgcmV0dXJuIHJvd0hlaWdodCBpbnN0YW5jZW9mIEZ1bmN0aW9uID8gcm93SGVpZ2h0KHsgaW5kZXg6IHJvd0luZGV4IH0pIDogcm93SGVpZ2h0O1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vblNjcm9sbCcsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vblNjcm9sbChfcmVmNykge1xuICAgICAgdmFyIGNsaWVudEhlaWdodCA9IF9yZWY3LmNsaWVudEhlaWdodDtcbiAgICAgIHZhciBzY3JvbGxIZWlnaHQgPSBfcmVmNy5zY3JvbGxIZWlnaHQ7XG4gICAgICB2YXIgc2Nyb2xsVG9wID0gX3JlZjcuc2Nyb2xsVG9wO1xuICAgICAgdmFyIG9uU2Nyb2xsID0gdGhpcy5wcm9wcy5vblNjcm9sbDtcblxuXG4gICAgICBvblNjcm9sbCh7IGNsaWVudEhlaWdodDogY2xpZW50SGVpZ2h0LCBzY3JvbGxIZWlnaHQ6IHNjcm9sbEhlaWdodCwgc2Nyb2xsVG9wOiBzY3JvbGxUb3AgfSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uU2VjdGlvblJlbmRlcmVkJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uU2VjdGlvblJlbmRlcmVkKF9yZWY4KSB7XG4gICAgICB2YXIgcm93T3ZlcnNjYW5TdGFydEluZGV4ID0gX3JlZjgucm93T3ZlcnNjYW5TdGFydEluZGV4O1xuICAgICAgdmFyIHJvd092ZXJzY2FuU3RvcEluZGV4ID0gX3JlZjgucm93T3ZlcnNjYW5TdG9wSW5kZXg7XG4gICAgICB2YXIgcm93U3RhcnRJbmRleCA9IF9yZWY4LnJvd1N0YXJ0SW5kZXg7XG4gICAgICB2YXIgcm93U3RvcEluZGV4ID0gX3JlZjgucm93U3RvcEluZGV4O1xuICAgICAgdmFyIG9uUm93c1JlbmRlcmVkID0gdGhpcy5wcm9wcy5vblJvd3NSZW5kZXJlZDtcblxuXG4gICAgICBvblJvd3NSZW5kZXJlZCh7XG4gICAgICAgIG92ZXJzY2FuU3RhcnRJbmRleDogcm93T3ZlcnNjYW5TdGFydEluZGV4LFxuICAgICAgICBvdmVyc2NhblN0b3BJbmRleDogcm93T3ZlcnNjYW5TdG9wSW5kZXgsXG4gICAgICAgIHN0YXJ0SW5kZXg6IHJvd1N0YXJ0SW5kZXgsXG4gICAgICAgIHN0b3BJbmRleDogcm93U3RvcEluZGV4XG4gICAgICB9KTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfc2V0U2Nyb2xsYmFyV2lkdGgnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBfc2V0U2Nyb2xsYmFyV2lkdGgoKSB7XG4gICAgICB2YXIgR3JpZCA9ICgwLCBfcmVhY3REb20uZmluZERPTU5vZGUpKHRoaXMuR3JpZCk7XG4gICAgICB2YXIgY2xpZW50V2lkdGggPSBHcmlkLmNsaWVudFdpZHRoIHx8IDA7XG4gICAgICB2YXIgb2Zmc2V0V2lkdGggPSBHcmlkLm9mZnNldFdpZHRoIHx8IDA7XG4gICAgICB2YXIgc2Nyb2xsYmFyV2lkdGggPSBvZmZzZXRXaWR0aCAtIGNsaWVudFdpZHRoO1xuXG4gICAgICB0aGlzLnNldFN0YXRlKHsgc2Nyb2xsYmFyV2lkdGg6IHNjcm9sbGJhcldpZHRoIH0pO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBGbGV4VGFibGU7XG59KF9yZWFjdC5Db21wb25lbnQpO1xuXG5GbGV4VGFibGUucHJvcFR5cGVzID0ge1xuICAnYXJpYS1sYWJlbCc6IF9yZWFjdC5Qcm9wVHlwZXMuc3RyaW5nLFxuXG4gIC8qKlxuICAgKiBSZW1vdmVzIGZpeGVkIGhlaWdodCBmcm9tIHRoZSBzY3JvbGxpbmdDb250YWluZXIgc28gdGhhdCB0aGUgdG90YWwgaGVpZ2h0XG4gICAqIG9mIHJvd3MgY2FuIHN0cmV0Y2ggdGhlIHdpbmRvdy4gSW50ZW5kZWQgZm9yIHVzZSB3aXRoIFdpbmRvd1Njcm9sbGVyXG4gICAqL1xuICBhdXRvSGVpZ2h0OiBfcmVhY3QuUHJvcFR5cGVzLmJvb2wsXG5cbiAgLyoqIE9uZSBvciBtb3JlIEZsZXhDb2x1bW5zIGRlc2NyaWJpbmcgdGhlIGRhdGEgZGlzcGxheWVkIGluIHRoaXMgcm93ICovXG4gIGNoaWxkcmVuOiBmdW5jdGlvbiBjaGlsZHJlbihwcm9wcywgcHJvcE5hbWUsIGNvbXBvbmVudE5hbWUpIHtcbiAgICB2YXIgY2hpbGRyZW4gPSBfcmVhY3QyLmRlZmF1bHQuQ2hpbGRyZW4udG9BcnJheShwcm9wcy5jaGlsZHJlbik7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKGNoaWxkcmVuW2ldLnR5cGUgIT09IF9GbGV4Q29sdW1uMi5kZWZhdWx0KSB7XG4gICAgICAgIHJldHVybiBuZXcgRXJyb3IoJ0ZsZXhUYWJsZSBvbmx5IGFjY2VwdHMgY2hpbGRyZW4gb2YgdHlwZSBGbGV4Q29sdW1uJyk7XG4gICAgICB9XG4gICAgfVxuICB9LFxuXG4gIC8qKiBPcHRpb25hbCBDU1MgY2xhc3MgbmFtZSAqL1xuICBjbGFzc05hbWU6IF9yZWFjdC5Qcm9wVHlwZXMuc3RyaW5nLFxuXG4gIC8qKiBEaXNhYmxlIHJlbmRlcmluZyB0aGUgaGVhZGVyIGF0IGFsbCAqL1xuICBkaXNhYmxlSGVhZGVyOiBfcmVhY3QuUHJvcFR5cGVzLmJvb2wsXG5cbiAgLyoqXG4gICAqIFVzZWQgdG8gZXN0aW1hdGUgdGhlIHRvdGFsIGhlaWdodCBvZiBhIEZsZXhUYWJsZSBiZWZvcmUgYWxsIG9mIGl0cyByb3dzIGhhdmUgYWN0dWFsbHkgYmVlbiBtZWFzdXJlZC5cbiAgICogVGhlIGVzdGltYXRlZCB0b3RhbCBoZWlnaHQgaXMgYWRqdXN0ZWQgYXMgcm93cyBhcmUgcmVuZGVyZWQuXG4gICAqL1xuICBlc3RpbWF0ZWRSb3dTaXplOiBfcmVhY3QuUHJvcFR5cGVzLm51bWJlci5pc1JlcXVpcmVkLFxuXG4gIC8qKiBPcHRpb25hbCBjdXN0b20gQ1NTIGNsYXNzIG5hbWUgdG8gYXR0YWNoIHRvIGlubmVyIEdyaWQgZWxlbWVudC4gKi9cbiAgZ3JpZENsYXNzTmFtZTogX3JlYWN0LlByb3BUeXBlcy5zdHJpbmcsXG5cbiAgLyoqIE9wdGlvbmFsIGlubGluZSBzdHlsZSB0byBhdHRhY2ggdG8gaW5uZXIgR3JpZCBlbGVtZW50LiAqL1xuICBncmlkU3R5bGU6IF9yZWFjdC5Qcm9wVHlwZXMub2JqZWN0LFxuXG4gIC8qKiBPcHRpb25hbCBDU1MgY2xhc3MgdG8gYXBwbHkgdG8gYWxsIGNvbHVtbiBoZWFkZXJzICovXG4gIGhlYWRlckNsYXNzTmFtZTogX3JlYWN0LlByb3BUeXBlcy5zdHJpbmcsXG5cbiAgLyoqIEZpeGVkIGhlaWdodCBvZiBoZWFkZXIgcm93ICovXG4gIGhlYWRlckhlaWdodDogX3JlYWN0LlByb3BUeXBlcy5udW1iZXIuaXNSZXF1aXJlZCxcblxuICAvKiogRml4ZWQvYXZhaWxhYmxlIGhlaWdodCBmb3Igb3V0IERPTSBlbGVtZW50ICovXG4gIGhlaWdodDogX3JlYWN0LlByb3BUeXBlcy5udW1iZXIuaXNSZXF1aXJlZCxcblxuICAvKiogT3B0aW9uYWwgcmVuZGVyZXIgdG8gYmUgdXNlZCBpbiBwbGFjZSBvZiB0YWJsZSBib2R5IHJvd3Mgd2hlbiByb3dDb3VudCBpcyAwICovXG4gIG5vUm93c1JlbmRlcmVyOiBfcmVhY3QuUHJvcFR5cGVzLmZ1bmMsXG5cbiAgLyoqXG4gICogT3B0aW9uYWwgY2FsbGJhY2sgd2hlbiBhIGNvbHVtbidzIGhlYWRlciBpcyBjbGlja2VkLlxuICAqICh7IGNvbHVtbkRhdGE6IGFueSwgZGF0YUtleTogc3RyaW5nIH0pOiB2b2lkXG4gICovXG4gIG9uSGVhZGVyQ2xpY2s6IF9yZWFjdC5Qcm9wVHlwZXMuZnVuYyxcblxuICAvKiogT3B0aW9uYWwgY3VzdG9tIGlubGluZSBzdHlsZSB0byBhdHRhY2ggdG8gdGFibGUgaGVhZGVyIGNvbHVtbnMuICovXG4gIGhlYWRlclN0eWxlOiBfcmVhY3QuUHJvcFR5cGVzLm9iamVjdCxcblxuICAvKipcbiAgICogQ2FsbGJhY2sgaW52b2tlZCB3aGVuIGEgdXNlciBjbGlja3Mgb24gYSB0YWJsZSByb3cuXG4gICAqICh7IGluZGV4OiBudW1iZXIgfSk6IHZvaWRcbiAgICovXG4gIG9uUm93Q2xpY2s6IF9yZWFjdC5Qcm9wVHlwZXMuZnVuYyxcblxuICAvKipcbiAgICogQ2FsbGJhY2sgaW52b2tlZCB3aGVuIGEgdXNlciBkb3VibGUtY2xpY2tzIG9uIGEgdGFibGUgcm93LlxuICAgKiAoeyBpbmRleDogbnVtYmVyIH0pOiB2b2lkXG4gICAqL1xuICBvblJvd0RvdWJsZUNsaWNrOiBfcmVhY3QuUHJvcFR5cGVzLmZ1bmMsXG5cbiAgLyoqXG4gICAqIENhbGxiYWNrIGludm9rZWQgd2hlbiB0aGUgbW91c2UgbGVhdmVzIGEgdGFibGUgcm93LlxuICAgKiAoeyBpbmRleDogbnVtYmVyIH0pOiB2b2lkXG4gICAqL1xuICBvblJvd01vdXNlT3V0OiBfcmVhY3QuUHJvcFR5cGVzLmZ1bmMsXG5cbiAgLyoqXG4gICAqIENhbGxiYWNrIGludm9rZWQgd2hlbiBhIHVzZXIgbW92ZXMgdGhlIG1vdXNlIG92ZXIgYSB0YWJsZSByb3cuXG4gICAqICh7IGluZGV4OiBudW1iZXIgfSk6IHZvaWRcbiAgICovXG4gIG9uUm93TW91c2VPdmVyOiBfcmVhY3QuUHJvcFR5cGVzLmZ1bmMsXG5cbiAgLyoqXG4gICAqIENhbGxiYWNrIGludm9rZWQgd2l0aCBpbmZvcm1hdGlvbiBhYm91dCB0aGUgc2xpY2Ugb2Ygcm93cyB0aGF0IHdlcmUganVzdCByZW5kZXJlZC5cbiAgICogKHsgc3RhcnRJbmRleCwgc3RvcEluZGV4IH0pOiB2b2lkXG4gICAqL1xuICBvblJvd3NSZW5kZXJlZDogX3JlYWN0LlByb3BUeXBlcy5mdW5jLFxuXG4gIC8qKlxuICAgKiBDYWxsYmFjayBpbnZva2VkIHdoZW5ldmVyIHRoZSBzY3JvbGwgb2Zmc2V0IGNoYW5nZXMgd2l0aGluIHRoZSBpbm5lciBzY3JvbGxhYmxlIHJlZ2lvbi5cbiAgICogVGhpcyBjYWxsYmFjayBjYW4gYmUgdXNlZCB0byBzeW5jIHNjcm9sbGluZyBiZXR3ZWVuIGxpc3RzLCB0YWJsZXMsIG9yIGdyaWRzLlxuICAgKiAoeyBjbGllbnRIZWlnaHQsIHNjcm9sbEhlaWdodCwgc2Nyb2xsVG9wIH0pOiB2b2lkXG4gICAqL1xuICBvblNjcm9sbDogX3JlYWN0LlByb3BUeXBlcy5mdW5jLmlzUmVxdWlyZWQsXG5cbiAgLyoqXG4gICAqIE51bWJlciBvZiByb3dzIHRvIHJlbmRlciBhYm92ZS9iZWxvdyB0aGUgdmlzaWJsZSBib3VuZHMgb2YgdGhlIGxpc3QuXG4gICAqIFRoZXNlIHJvd3MgY2FuIGhlbHAgZm9yIHNtb290aGVyIHNjcm9sbGluZyBvbiB0b3VjaCBkZXZpY2VzLlxuICAgKi9cbiAgb3ZlcnNjYW5Sb3dDb3VudDogX3JlYWN0LlByb3BUeXBlcy5udW1iZXIuaXNSZXF1aXJlZCxcblxuICAvKipcbiAgICogT3B0aW9uYWwgQ1NTIGNsYXNzIHRvIGFwcGx5IHRvIGFsbCB0YWJsZSByb3dzIChpbmNsdWRpbmcgdGhlIGhlYWRlciByb3cpLlxuICAgKiBUaGlzIHByb3BlcnR5IGNhbiBiZSBhIENTUyBjbGFzcyBuYW1lIChzdHJpbmcpIG9yIGEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIGEgY2xhc3MgbmFtZS5cbiAgICogSWYgYSBmdW5jdGlvbiBpcyBwcm92aWRlZCBpdHMgc2lnbmF0dXJlIHNob3VsZCBiZTogKHsgaW5kZXg6IG51bWJlciB9KTogc3RyaW5nXG4gICAqL1xuICByb3dDbGFzc05hbWU6IF9yZWFjdC5Qcm9wVHlwZXMub25lT2ZUeXBlKFtfcmVhY3QuUHJvcFR5cGVzLnN0cmluZywgX3JlYWN0LlByb3BUeXBlcy5mdW5jXSksXG5cbiAgLyoqXG4gICAqIENhbGxiYWNrIHJlc3BvbnNpYmxlIGZvciByZXR1cm5pbmcgYSBkYXRhIHJvdyBnaXZlbiBhbiBpbmRleC5cbiAgICogKHsgaW5kZXg6IG51bWJlciB9KTogYW55XG4gICAqL1xuICByb3dHZXR0ZXI6IF9yZWFjdC5Qcm9wVHlwZXMuZnVuYy5pc1JlcXVpcmVkLFxuXG4gIC8qKlxuICAgKiBFaXRoZXIgYSBmaXhlZCByb3cgaGVpZ2h0IChudW1iZXIpIG9yIGEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIHRoZSBoZWlnaHQgb2YgYSByb3cgZ2l2ZW4gaXRzIGluZGV4LlxuICAgKiAoeyBpbmRleDogbnVtYmVyIH0pOiBudW1iZXJcbiAgICovXG4gIHJvd0hlaWdodDogX3JlYWN0LlByb3BUeXBlcy5vbmVPZlR5cGUoW19yZWFjdC5Qcm9wVHlwZXMubnVtYmVyLCBfcmVhY3QuUHJvcFR5cGVzLmZ1bmNdKS5pc1JlcXVpcmVkLFxuXG4gIC8qKiBOdW1iZXIgb2Ygcm93cyBpbiB0YWJsZS4gKi9cbiAgcm93Q291bnQ6IF9yZWFjdC5Qcm9wVHlwZXMubnVtYmVyLmlzUmVxdWlyZWQsXG5cbiAgLyoqXG4gICAqIFJlc3BvbnNpYmxlIGZvciByZW5kZXJpbmcgYSB0YWJsZSByb3cgZ2l2ZW4gYW4gYXJyYXkgb2YgY29sdW1uczpcbiAgICogU2hvdWxkIGltcGxlbWVudCB0aGUgZm9sbG93aW5nIGludGVyZmFjZTogKHtcbiAgICogICBjbGFzc05hbWU6IHN0cmluZyxcbiAgICogICBjb2x1bW5zOiBBcnJheSxcbiAgICogICBpbmRleDogbnVtYmVyLFxuICAgKiAgIGlzU2Nyb2xsaW5nOiBib29sZWFuLFxuICAgKiAgIG9uUm93Q2xpY2s6ID9GdW5jdGlvbixcbiAgICogICBvblJvd0RvdWJsZUNsaWNrOiA/RnVuY3Rpb24sXG4gICAqICAgb25Sb3dNb3VzZU92ZXI6ID9GdW5jdGlvbixcbiAgICogICBvblJvd01vdXNlT3V0OiA/RnVuY3Rpb24sXG4gICAqICAgcm93RGF0YTogYW55LFxuICAgKiAgIHN0eWxlOiBhbnlcbiAgICogfSk6IFByb3BUeXBlcy5ub2RlXG4gICAqL1xuICByb3dSZW5kZXJlcjogX3JlYWN0LlByb3BUeXBlcy5mdW5jLFxuXG4gIC8qKiBPcHRpb25hbCBjdXN0b20gaW5saW5lIHN0eWxlIHRvIGF0dGFjaCB0byB0YWJsZSByb3dzLiAqL1xuICByb3dTdHlsZTogX3JlYWN0LlByb3BUeXBlcy5vbmVPZlR5cGUoW19yZWFjdC5Qcm9wVHlwZXMub2JqZWN0LCBfcmVhY3QuUHJvcFR5cGVzLmZ1bmNdKS5pc1JlcXVpcmVkLFxuXG4gIC8qKiBPcHRpb25hbCBjdXN0b20gQ1NTIGNsYXNzIGZvciBpbmRpdmlkdWFsIHJvd3MgKi9cbiAgcm93V3JhcHBlckNsYXNzTmFtZTogX3JlYWN0LlByb3BUeXBlcy5vbmVPZlR5cGUoW19yZWFjdC5Qcm9wVHlwZXMuc3RyaW5nLCBfcmVhY3QuUHJvcFR5cGVzLmZ1bmNdKSxcblxuICAvKiogT3B0aW9uYWwgY3VzdG9tIENTUyBjbGFzcyBmb3IgaW5kaXZpZHVhbCByb3dzICovXG4gIHJvd1dyYXBwZXJTdHlsZTogX3JlYWN0LlByb3BUeXBlcy5vbmVPZlR5cGUoW19yZWFjdC5Qcm9wVHlwZXMub2JqZWN0LCBfcmVhY3QuUHJvcFR5cGVzLmZ1bmNdKSxcblxuICAvKiogU2VlIEdyaWQjc2Nyb2xsVG9BbGlnbm1lbnQgKi9cbiAgc2Nyb2xsVG9BbGlnbm1lbnQ6IF9yZWFjdC5Qcm9wVHlwZXMub25lT2YoWydhdXRvJywgJ2VuZCcsICdzdGFydCcsICdjZW50ZXInXSkuaXNSZXF1aXJlZCxcblxuICAvKiogUm93IGluZGV4IHRvIGVuc3VyZSB2aXNpYmxlIChieSBmb3JjZWZ1bGx5IHNjcm9sbGluZyBpZiBuZWNlc3NhcnkpICovXG4gIHNjcm9sbFRvSW5kZXg6IF9yZWFjdC5Qcm9wVHlwZXMubnVtYmVyLFxuXG4gIC8qKiBWZXJ0aWNhbCBvZmZzZXQuICovXG4gIHNjcm9sbFRvcDogX3JlYWN0LlByb3BUeXBlcy5udW1iZXIsXG5cbiAgLyoqXG4gICAqIFNvcnQgZnVuY3Rpb24gdG8gYmUgY2FsbGVkIGlmIGEgc29ydGFibGUgaGVhZGVyIGlzIGNsaWNrZWQuXG4gICAqICh7IHNvcnRCeTogc3RyaW5nLCBzb3J0RGlyZWN0aW9uOiBTb3J0RGlyZWN0aW9uIH0pOiB2b2lkXG4gICAqL1xuICBzb3J0OiBfcmVhY3QuUHJvcFR5cGVzLmZ1bmMsXG5cbiAgLyoqIEZsZXhUYWJsZSBkYXRhIGlzIGN1cnJlbnRseSBzb3J0ZWQgYnkgdGhpcyA6ZGF0YUtleSAoaWYgaXQgaXMgc29ydGVkIGF0IGFsbCkgKi9cbiAgc29ydEJ5OiBfcmVhY3QuUHJvcFR5cGVzLnN0cmluZyxcblxuICAvKiogRmxleFRhYmxlIGRhdGEgaXMgY3VycmVudGx5IHNvcnRlZCBpbiB0aGlzIGRpcmVjdGlvbiAoaWYgaXQgaXMgc29ydGVkIGF0IGFsbCkgKi9cbiAgc29ydERpcmVjdGlvbjogX3JlYWN0LlByb3BUeXBlcy5vbmVPZihbX1NvcnREaXJlY3Rpb24yLmRlZmF1bHQuQVNDLCBfU29ydERpcmVjdGlvbjIuZGVmYXVsdC5ERVNDXSksXG5cbiAgLyoqIE9wdGlvbmFsIGlubGluZSBzdHlsZSAqL1xuICBzdHlsZTogX3JlYWN0LlByb3BUeXBlcy5vYmplY3QsXG5cbiAgLyoqIFRhYiBpbmRleCBmb3IgZm9jdXMgKi9cbiAgdGFiSW5kZXg6IF9yZWFjdC5Qcm9wVHlwZXMubnVtYmVyLFxuXG4gIC8qKiBXaWR0aCBvZiBsaXN0ICovXG4gIHdpZHRoOiBfcmVhY3QuUHJvcFR5cGVzLm51bWJlci5pc1JlcXVpcmVkXG59O1xuRmxleFRhYmxlLmRlZmF1bHRQcm9wcyA9IHtcbiAgZGlzYWJsZUhlYWRlcjogZmFsc2UsXG4gIGVzdGltYXRlZFJvd1NpemU6IDMwLFxuICBoZWFkZXJIZWlnaHQ6IDAsXG4gIGhlYWRlclN0eWxlOiB7fSxcbiAgbm9Sb3dzUmVuZGVyZXI6IGZ1bmN0aW9uIG5vUm93c1JlbmRlcmVyKCkge1xuICAgIHJldHVybiBudWxsO1xuICB9LFxuICBvblJvd3NSZW5kZXJlZDogZnVuY3Rpb24gb25Sb3dzUmVuZGVyZWQoKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH0sXG4gIG9uU2Nyb2xsOiBmdW5jdGlvbiBvblNjcm9sbCgpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfSxcbiAgb3ZlcnNjYW5Sb3dDb3VudDogMTAsXG4gIHJvd1JlbmRlcmVyOiBfZGVmYXVsdFJvd1JlbmRlcmVyMi5kZWZhdWx0LFxuICByb3dTdHlsZToge30sXG4gIHNjcm9sbFRvQWxpZ25tZW50OiAnYXV0bycsXG4gIHN0eWxlOiB7fVxufTtcbmV4cG9ydHMuZGVmYXVsdCA9IEZsZXhUYWJsZTsiLCIndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG52YXIgU29ydERpcmVjdGlvbiA9IHtcbiAgLyoqXG4gICAqIFNvcnQgaXRlbXMgaW4gYXNjZW5kaW5nIG9yZGVyLlxuICAgKiBUaGlzIG1lYW5zIGFycmFuZ2luZyBmcm9tIHRoZSBsb3dlc3QgdmFsdWUgdG8gdGhlIGhpZ2hlc3QgKGUuZy4gYS16LCAwLTkpLlxuICAgKi9cbiAgQVNDOiAnQVNDJyxcblxuICAvKipcbiAgICogU29ydCBpdGVtcyBpbiBkZXNjZW5kaW5nIG9yZGVyLlxuICAgKiBUaGlzIG1lYW5zIGFycmFuZ2luZyBmcm9tIHRoZSBoaWdoZXN0IHZhbHVlIHRvIHRoZSBsb3dlc3QgKGUuZy4gei1hLCA5LTApLlxuICAgKi9cbiAgREVTQzogJ0RFU0MnXG59O1xuXG5leHBvcnRzLmRlZmF1bHQgPSBTb3J0RGlyZWN0aW9uOyIsIid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcbmV4cG9ydHMuZGVmYXVsdCA9IFNvcnRJbmRpY2F0b3I7XG5cbnZhciBfcmVhY3QgPSByZXF1aXJlKCdyZWFjdCcpO1xuXG52YXIgX3JlYWN0MiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3JlYWN0KTtcblxudmFyIF9jbGFzc25hbWVzID0gcmVxdWlyZSgnY2xhc3NuYW1lcycpO1xuXG52YXIgX2NsYXNzbmFtZXMyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfY2xhc3NuYW1lcyk7XG5cbnZhciBfU29ydERpcmVjdGlvbiA9IHJlcXVpcmUoJy4vU29ydERpcmVjdGlvbicpO1xuXG52YXIgX1NvcnREaXJlY3Rpb24yID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfU29ydERpcmVjdGlvbik7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7IGRlZmF1bHQ6IG9iaiB9OyB9XG5cbi8qKlxuICogRGlzcGxheWVkIGJlc2lkZSBhIGhlYWRlciB0byBpbmRpY2F0ZSB0aGF0IGEgRmxleFRhYmxlIGlzIGN1cnJlbnRseSBzb3J0ZWQgYnkgdGhpcyBjb2x1bW4uXG4gKi9cbmZ1bmN0aW9uIFNvcnRJbmRpY2F0b3IoX3JlZikge1xuICB2YXIgc29ydERpcmVjdGlvbiA9IF9yZWYuc29ydERpcmVjdGlvbjtcblxuICB2YXIgY2xhc3NOYW1lcyA9ICgwLCBfY2xhc3NuYW1lczIuZGVmYXVsdCkoJ0ZsZXhUYWJsZV9fc29ydGFibGVIZWFkZXJJY29uJywge1xuICAgICdGbGV4VGFibGVfX3NvcnRhYmxlSGVhZGVySWNvbi0tQVNDJzogc29ydERpcmVjdGlvbiA9PT0gX1NvcnREaXJlY3Rpb24yLmRlZmF1bHQuQVNDLFxuICAgICdGbGV4VGFibGVfX3NvcnRhYmxlSGVhZGVySWNvbi0tREVTQyc6IHNvcnREaXJlY3Rpb24gPT09IF9Tb3J0RGlyZWN0aW9uMi5kZWZhdWx0LkRFU0NcbiAgfSk7XG5cbiAgcmV0dXJuIF9yZWFjdDIuZGVmYXVsdC5jcmVhdGVFbGVtZW50KFxuICAgICdzdmcnLFxuICAgIHtcbiAgICAgIGNsYXNzTmFtZTogY2xhc3NOYW1lcyxcbiAgICAgIHdpZHRoOiAxOCxcbiAgICAgIGhlaWdodDogMTgsXG4gICAgICB2aWV3Qm94OiAnMCAwIDI0IDI0J1xuICAgIH0sXG4gICAgc29ydERpcmVjdGlvbiA9PT0gX1NvcnREaXJlY3Rpb24yLmRlZmF1bHQuQVNDID8gX3JlYWN0Mi5kZWZhdWx0LmNyZWF0ZUVsZW1lbnQoJ3BhdGgnLCB7IGQ6ICdNNyAxNGw1LTUgNSA1eicgfSkgOiBfcmVhY3QyLmRlZmF1bHQuY3JlYXRlRWxlbWVudCgncGF0aCcsIHsgZDogJ003IDEwbDUgNSA1LTV6JyB9KSxcbiAgICBfcmVhY3QyLmRlZmF1bHQuY3JlYXRlRWxlbWVudCgncGF0aCcsIHsgZDogJ00wIDBoMjR2MjRIMHonLCBmaWxsOiAnbm9uZScgfSlcbiAgKTtcbn1cblNvcnRJbmRpY2F0b3IucHJvcFR5cGVzID0ge1xuICBzb3J0RGlyZWN0aW9uOiBfcmVhY3QuUHJvcFR5cGVzLm9uZU9mKFtfU29ydERpcmVjdGlvbjIuZGVmYXVsdC5BU0MsIF9Tb3J0RGlyZWN0aW9uMi5kZWZhdWx0LkRFU0NdKVxufTsiLCIndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5leHBvcnRzLmRlZmF1bHQgPSBkZWZhdWx0Q2VsbERhdGFHZXR0ZXI7XG5cblxuLyoqXG4gKiBEZWZhdWx0IGFjY2Vzc29yIGZvciByZXR1cm5pbmcgYSBjZWxsIHZhbHVlIGZvciBhIGdpdmVuIGF0dHJpYnV0ZS5cbiAqIFRoaXMgZnVuY3Rpb24gZXhwZWN0cyB0byBvcGVyYXRlIG9uIGVpdGhlciBhIHZhbmlsbGEgT2JqZWN0IG9yIGFuIEltbXV0YWJsZSBNYXAuXG4gKiBZb3Ugc2hvdWxkIG92ZXJyaWRlIHRoZSBjb2x1bW4ncyBjZWxsRGF0YUdldHRlciBpZiB5b3VyIGRhdGEgaXMgc29tZSBvdGhlciB0eXBlIG9mIG9iamVjdC5cbiAqL1xuZnVuY3Rpb24gZGVmYXVsdENlbGxEYXRhR2V0dGVyKF9yZWYpIHtcbiAgdmFyIGNvbHVtbkRhdGEgPSBfcmVmLmNvbHVtbkRhdGE7XG4gIHZhciBkYXRhS2V5ID0gX3JlZi5kYXRhS2V5O1xuICB2YXIgcm93RGF0YSA9IF9yZWYucm93RGF0YTtcblxuICBpZiAocm93RGF0YS5nZXQgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgIHJldHVybiByb3dEYXRhLmdldChkYXRhS2V5KTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gcm93RGF0YVtkYXRhS2V5XTtcbiAgfVxufSIsIid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcbmV4cG9ydHMuZGVmYXVsdCA9IGRlZmF1bHRDZWxsUmVuZGVyZXI7XG5cblxuLyoqXG4gKiBEZWZhdWx0IGNlbGwgcmVuZGVyZXIgdGhhdCBkaXNwbGF5cyBhbiBhdHRyaWJ1dGUgYXMgYSBzaW1wbGUgc3RyaW5nXG4gKiBZb3Ugc2hvdWxkIG92ZXJyaWRlIHRoZSBjb2x1bW4ncyBjZWxsUmVuZGVyZXIgaWYgeW91ciBkYXRhIGlzIHNvbWUgb3RoZXIgdHlwZSBvZiBvYmplY3QuXG4gKi9cbmZ1bmN0aW9uIGRlZmF1bHRDZWxsUmVuZGVyZXIoX3JlZikge1xuICB2YXIgY2VsbERhdGEgPSBfcmVmLmNlbGxEYXRhO1xuICB2YXIgY2VsbERhdGFLZXkgPSBfcmVmLmNlbGxEYXRhS2V5O1xuICB2YXIgY29sdW1uRGF0YSA9IF9yZWYuY29sdW1uRGF0YTtcbiAgdmFyIHJvd0RhdGEgPSBfcmVmLnJvd0RhdGE7XG4gIHZhciByb3dJbmRleCA9IF9yZWYucm93SW5kZXg7XG5cbiAgaWYgKGNlbGxEYXRhID09IG51bGwpIHtcbiAgICByZXR1cm4gJyc7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIFN0cmluZyhjZWxsRGF0YSk7XG4gIH1cbn0iLCIndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5leHBvcnRzLmRlZmF1bHQgPSBkZWZhdWx0SGVhZGVyUmVuZGVyZXI7XG5cbnZhciBfcmVhY3QgPSByZXF1aXJlKCdyZWFjdCcpO1xuXG52YXIgX3JlYWN0MiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3JlYWN0KTtcblxudmFyIF9Tb3J0SW5kaWNhdG9yID0gcmVxdWlyZSgnLi9Tb3J0SW5kaWNhdG9yJyk7XG5cbnZhciBfU29ydEluZGljYXRvcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9Tb3J0SW5kaWNhdG9yKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgZGVmYXVsdDogb2JqIH07IH1cblxuLyoqXG4gKiBEZWZhdWx0IHRhYmxlIGhlYWRlciByZW5kZXJlci5cbiAqL1xuZnVuY3Rpb24gZGVmYXVsdEhlYWRlclJlbmRlcmVyKF9yZWYpIHtcbiAgdmFyIGNvbHVtbkRhdGEgPSBfcmVmLmNvbHVtbkRhdGE7XG4gIHZhciBkYXRhS2V5ID0gX3JlZi5kYXRhS2V5O1xuICB2YXIgZGlzYWJsZVNvcnQgPSBfcmVmLmRpc2FibGVTb3J0O1xuICB2YXIgbGFiZWwgPSBfcmVmLmxhYmVsO1xuICB2YXIgc29ydEJ5ID0gX3JlZi5zb3J0Qnk7XG4gIHZhciBzb3J0RGlyZWN0aW9uID0gX3JlZi5zb3J0RGlyZWN0aW9uO1xuXG4gIHZhciBzaG93U29ydEluZGljYXRvciA9IHNvcnRCeSA9PT0gZGF0YUtleTtcbiAgdmFyIGNoaWxkcmVuID0gW19yZWFjdDIuZGVmYXVsdC5jcmVhdGVFbGVtZW50KFxuICAgICdzcGFuJyxcbiAgICB7XG4gICAgICBjbGFzc05hbWU6ICdGbGV4VGFibGVfX2hlYWRlclRydW5jYXRlZFRleHQnLFxuICAgICAga2V5OiAnbGFiZWwnLFxuICAgICAgdGl0bGU6IGxhYmVsXG4gICAgfSxcbiAgICBsYWJlbFxuICApXTtcblxuICBpZiAoc2hvd1NvcnRJbmRpY2F0b3IpIHtcbiAgICBjaGlsZHJlbi5wdXNoKF9yZWFjdDIuZGVmYXVsdC5jcmVhdGVFbGVtZW50KF9Tb3J0SW5kaWNhdG9yMi5kZWZhdWx0LCB7XG4gICAgICBrZXk6ICdTb3J0SW5kaWNhdG9yJyxcbiAgICAgIHNvcnREaXJlY3Rpb246IHNvcnREaXJlY3Rpb25cbiAgICB9KSk7XG4gIH1cblxuICByZXR1cm4gY2hpbGRyZW47XG59IiwiJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2V4dGVuZHMgPSBPYmplY3QuYXNzaWduIHx8IGZ1bmN0aW9uICh0YXJnZXQpIHsgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHsgdmFyIHNvdXJjZSA9IGFyZ3VtZW50c1tpXTsgZm9yICh2YXIga2V5IGluIHNvdXJjZSkgeyBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHNvdXJjZSwga2V5KSkgeyB0YXJnZXRba2V5XSA9IHNvdXJjZVtrZXldOyB9IH0gfSByZXR1cm4gdGFyZ2V0OyB9O1xuXG5leHBvcnRzLmRlZmF1bHQgPSBkZWZhdWx0Um93UmVuZGVyZXI7XG5cbnZhciBfcmVhY3QgPSByZXF1aXJlKCdyZWFjdCcpO1xuXG52YXIgX3JlYWN0MiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3JlYWN0KTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgZGVmYXVsdDogb2JqIH07IH1cblxuLyoqXG4gKiBEZWZhdWx0IHJvdyByZW5kZXJlciBmb3IgRmxleFRhYmxlLlxuICovXG5mdW5jdGlvbiBkZWZhdWx0Um93UmVuZGVyZXIoX3JlZikge1xuICB2YXIgY2xhc3NOYW1lID0gX3JlZi5jbGFzc05hbWU7XG4gIHZhciBjb2x1bW5zID0gX3JlZi5jb2x1bW5zO1xuICB2YXIgaW5kZXggPSBfcmVmLmluZGV4O1xuICB2YXIgaXNTY3JvbGxpbmcgPSBfcmVmLmlzU2Nyb2xsaW5nO1xuICB2YXIgb25Sb3dDbGljayA9IF9yZWYub25Sb3dDbGljaztcbiAgdmFyIG9uUm93RG91YmxlQ2xpY2sgPSBfcmVmLm9uUm93RG91YmxlQ2xpY2s7XG4gIHZhciBvblJvd01vdXNlT3ZlciA9IF9yZWYub25Sb3dNb3VzZU92ZXI7XG4gIHZhciBvblJvd01vdXNlT3V0ID0gX3JlZi5vblJvd01vdXNlT3V0O1xuICB2YXIgcm93RGF0YSA9IF9yZWYucm93RGF0YTtcbiAgdmFyIHN0eWxlID0gX3JlZi5zdHlsZTtcblxuICB2YXIgYTExeVByb3BzID0ge307XG5cbiAgaWYgKG9uUm93Q2xpY2sgfHwgb25Sb3dEb3VibGVDbGljayB8fCBvblJvd01vdXNlT3ZlciB8fCBvblJvd01vdXNlT3V0KSB7XG4gICAgYTExeVByb3BzWydhcmlhLWxhYmVsJ10gPSAncm93JztcbiAgICBhMTF5UHJvcHMucm9sZSA9ICdyb3cnO1xuICAgIGExMXlQcm9wcy50YWJJbmRleCA9IDA7XG5cbiAgICBpZiAob25Sb3dDbGljaykge1xuICAgICAgYTExeVByb3BzLm9uQ2xpY2sgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBvblJvd0NsaWNrKHsgaW5kZXg6IGluZGV4IH0pO1xuICAgICAgfTtcbiAgICB9XG4gICAgaWYgKG9uUm93RG91YmxlQ2xpY2spIHtcbiAgICAgIGExMXlQcm9wcy5vbkRvdWJsZUNsaWNrID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gb25Sb3dEb3VibGVDbGljayh7IGluZGV4OiBpbmRleCB9KTtcbiAgICAgIH07XG4gICAgfVxuICAgIGlmIChvblJvd01vdXNlT3V0KSB7XG4gICAgICBhMTF5UHJvcHMub25Nb3VzZU91dCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIG9uUm93TW91c2VPdXQoeyBpbmRleDogaW5kZXggfSk7XG4gICAgICB9O1xuICAgIH1cbiAgICBpZiAob25Sb3dNb3VzZU92ZXIpIHtcbiAgICAgIGExMXlQcm9wcy5vbk1vdXNlT3ZlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIG9uUm93TW91c2VPdmVyKHsgaW5kZXg6IGluZGV4IH0pO1xuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gX3JlYWN0Mi5kZWZhdWx0LmNyZWF0ZUVsZW1lbnQoXG4gICAgJ2RpdicsXG4gICAgX2V4dGVuZHMoe30sIGExMXlQcm9wcywge1xuICAgICAgY2xhc3NOYW1lOiBjbGFzc05hbWUsXG4gICAgICBzdHlsZTogc3R5bGVcbiAgICB9KSxcbiAgICBjb2x1bW5zXG4gICk7XG59IiwiJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0cy5Tb3J0SW5kaWNhdG9yID0gZXhwb3J0cy5Tb3J0RGlyZWN0aW9uID0gZXhwb3J0cy5GbGV4Q29sdW1uID0gZXhwb3J0cy5GbGV4VGFibGUgPSBleHBvcnRzLmRlZmF1bHRSb3dSZW5kZXJlciA9IGV4cG9ydHMuZGVmYXVsdEhlYWRlclJlbmRlcmVyID0gZXhwb3J0cy5kZWZhdWx0Q2VsbFJlbmRlcmVyID0gZXhwb3J0cy5kZWZhdWx0Q2VsbERhdGFHZXR0ZXIgPSBleHBvcnRzLmRlZmF1bHQgPSB1bmRlZmluZWQ7XG5cbnZhciBfRmxleFRhYmxlMiA9IHJlcXVpcmUoJy4vRmxleFRhYmxlJyk7XG5cbnZhciBfRmxleFRhYmxlMyA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX0ZsZXhUYWJsZTIpO1xuXG52YXIgX2RlZmF1bHRDZWxsRGF0YUdldHRlcjIgPSByZXF1aXJlKCcuL2RlZmF1bHRDZWxsRGF0YUdldHRlcicpO1xuXG52YXIgX2RlZmF1bHRDZWxsRGF0YUdldHRlcjMgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9kZWZhdWx0Q2VsbERhdGFHZXR0ZXIyKTtcblxudmFyIF9kZWZhdWx0Q2VsbFJlbmRlcmVyMiA9IHJlcXVpcmUoJy4vZGVmYXVsdENlbGxSZW5kZXJlcicpO1xuXG52YXIgX2RlZmF1bHRDZWxsUmVuZGVyZXIzID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfZGVmYXVsdENlbGxSZW5kZXJlcjIpO1xuXG52YXIgX2RlZmF1bHRIZWFkZXJSZW5kZXJlcjIgPSByZXF1aXJlKCcuL2RlZmF1bHRIZWFkZXJSZW5kZXJlcicpO1xuXG52YXIgX2RlZmF1bHRIZWFkZXJSZW5kZXJlcjMgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9kZWZhdWx0SGVhZGVyUmVuZGVyZXIyKTtcblxudmFyIF9kZWZhdWx0Um93UmVuZGVyZXIyID0gcmVxdWlyZSgnLi9kZWZhdWx0Um93UmVuZGVyZXInKTtcblxudmFyIF9kZWZhdWx0Um93UmVuZGVyZXIzID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfZGVmYXVsdFJvd1JlbmRlcmVyMik7XG5cbnZhciBfRmxleENvbHVtbjIgPSByZXF1aXJlKCcuL0ZsZXhDb2x1bW4nKTtcblxudmFyIF9GbGV4Q29sdW1uMyA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX0ZsZXhDb2x1bW4yKTtcblxudmFyIF9Tb3J0RGlyZWN0aW9uMiA9IHJlcXVpcmUoJy4vU29ydERpcmVjdGlvbicpO1xuXG52YXIgX1NvcnREaXJlY3Rpb24zID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfU29ydERpcmVjdGlvbjIpO1xuXG52YXIgX1NvcnRJbmRpY2F0b3IyID0gcmVxdWlyZSgnLi9Tb3J0SW5kaWNhdG9yJyk7XG5cbnZhciBfU29ydEluZGljYXRvcjMgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9Tb3J0SW5kaWNhdG9yMik7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7IGRlZmF1bHQ6IG9iaiB9OyB9XG5cbmV4cG9ydHMuZGVmYXVsdCA9IF9GbGV4VGFibGUzLmRlZmF1bHQ7XG5leHBvcnRzLmRlZmF1bHRDZWxsRGF0YUdldHRlciA9IF9kZWZhdWx0Q2VsbERhdGFHZXR0ZXIzLmRlZmF1bHQ7XG5leHBvcnRzLmRlZmF1bHRDZWxsUmVuZGVyZXIgPSBfZGVmYXVsdENlbGxSZW5kZXJlcjMuZGVmYXVsdDtcbmV4cG9ydHMuZGVmYXVsdEhlYWRlclJlbmRlcmVyID0gX2RlZmF1bHRIZWFkZXJSZW5kZXJlcjMuZGVmYXVsdDtcbmV4cG9ydHMuZGVmYXVsdFJvd1JlbmRlcmVyID0gX2RlZmF1bHRSb3dSZW5kZXJlcjMuZGVmYXVsdDtcbmV4cG9ydHMuRmxleFRhYmxlID0gX0ZsZXhUYWJsZTMuZGVmYXVsdDtcbmV4cG9ydHMuRmxleENvbHVtbiA9IF9GbGV4Q29sdW1uMy5kZWZhdWx0O1xuZXhwb3J0cy5Tb3J0RGlyZWN0aW9uID0gX1NvcnREaXJlY3Rpb24zLmRlZmF1bHQ7XG5leHBvcnRzLlNvcnRJbmRpY2F0b3IgPSBfU29ydEluZGljYXRvcjMuZGVmYXVsdDsiLCIndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5leHBvcnRzLkRFRkFVTFRfU0NST0xMSU5HX1JFU0VUX1RJTUVfSU5URVJWQUwgPSB1bmRlZmluZWQ7XG5cbnZhciBfZXh0ZW5kcyA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24gKHRhcmdldCkgeyBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykgeyB2YXIgc291cmNlID0gYXJndW1lbnRzW2ldOyBmb3IgKHZhciBrZXkgaW4gc291cmNlKSB7IGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoc291cmNlLCBrZXkpKSB7IHRhcmdldFtrZXldID0gc291cmNlW2tleV07IH0gfSB9IHJldHVybiB0YXJnZXQ7IH07XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSBmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoXCJ2YWx1ZVwiIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KCk7XG5cbnZhciBfcmVhY3QgPSByZXF1aXJlKCdyZWFjdCcpO1xuXG52YXIgX3JlYWN0MiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3JlYWN0KTtcblxudmFyIF9jbGFzc25hbWVzID0gcmVxdWlyZSgnY2xhc3NuYW1lcycpO1xuXG52YXIgX2NsYXNzbmFtZXMyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfY2xhc3NuYW1lcyk7XG5cbnZhciBfY2FsY3VsYXRlU2l6ZUFuZFBvc2l0aW9uRGF0YUFuZFVwZGF0ZVNjcm9sbE9mZnNldCA9IHJlcXVpcmUoJy4vdXRpbHMvY2FsY3VsYXRlU2l6ZUFuZFBvc2l0aW9uRGF0YUFuZFVwZGF0ZVNjcm9sbE9mZnNldCcpO1xuXG52YXIgX2NhbGN1bGF0ZVNpemVBbmRQb3NpdGlvbkRhdGFBbmRVcGRhdGVTY3JvbGxPZmZzZXQyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfY2FsY3VsYXRlU2l6ZUFuZFBvc2l0aW9uRGF0YUFuZFVwZGF0ZVNjcm9sbE9mZnNldCk7XG5cbnZhciBfU2NhbGluZ0NlbGxTaXplQW5kUG9zaXRpb25NYW5hZ2VyID0gcmVxdWlyZSgnLi91dGlscy9TY2FsaW5nQ2VsbFNpemVBbmRQb3NpdGlvbk1hbmFnZXInKTtcblxudmFyIF9TY2FsaW5nQ2VsbFNpemVBbmRQb3NpdGlvbk1hbmFnZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfU2NhbGluZ0NlbGxTaXplQW5kUG9zaXRpb25NYW5hZ2VyKTtcblxudmFyIF9jcmVhdGVDYWxsYmFja01lbW9pemVyID0gcmVxdWlyZSgnLi4vdXRpbHMvY3JlYXRlQ2FsbGJhY2tNZW1vaXplcicpO1xuXG52YXIgX2NyZWF0ZUNhbGxiYWNrTWVtb2l6ZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfY3JlYXRlQ2FsbGJhY2tNZW1vaXplcik7XG5cbnZhciBfZ2V0T3ZlcnNjYW5JbmRpY2VzID0gcmVxdWlyZSgnLi91dGlscy9nZXRPdmVyc2NhbkluZGljZXMnKTtcblxudmFyIF9nZXRPdmVyc2NhbkluZGljZXMyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfZ2V0T3ZlcnNjYW5JbmRpY2VzKTtcblxudmFyIF9zY3JvbGxiYXJTaXplID0gcmVxdWlyZSgnZG9tLWhlbHBlcnMvdXRpbC9zY3JvbGxiYXJTaXplJyk7XG5cbnZhciBfc2Nyb2xsYmFyU2l6ZTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9zY3JvbGxiYXJTaXplKTtcblxudmFyIF9yYWYgPSByZXF1aXJlKCdyYWYnKTtcblxudmFyIF9yYWYyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfcmFmKTtcblxudmFyIF9yZWFjdEFkZG9uc1NoYWxsb3dDb21wYXJlID0gcmVxdWlyZSgncmVhY3QtYWRkb25zLXNoYWxsb3ctY29tcGFyZScpO1xuXG52YXIgX3JlYWN0QWRkb25zU2hhbGxvd0NvbXBhcmUyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfcmVhY3RBZGRvbnNTaGFsbG93Q29tcGFyZSk7XG5cbnZhciBfdXBkYXRlU2Nyb2xsSW5kZXhIZWxwZXIgPSByZXF1aXJlKCcuL3V0aWxzL3VwZGF0ZVNjcm9sbEluZGV4SGVscGVyJyk7XG5cbnZhciBfdXBkYXRlU2Nyb2xsSW5kZXhIZWxwZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfdXBkYXRlU2Nyb2xsSW5kZXhIZWxwZXIpO1xuXG52YXIgX2RlZmF1bHRDZWxsUmFuZ2VSZW5kZXJlciA9IHJlcXVpcmUoJy4vZGVmYXVsdENlbGxSYW5nZVJlbmRlcmVyJyk7XG5cbnZhciBfZGVmYXVsdENlbGxSYW5nZVJlbmRlcmVyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2RlZmF1bHRDZWxsUmFuZ2VSZW5kZXJlcik7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7IGRlZmF1bHQ6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvblwiKTsgfSB9XG5cbmZ1bmN0aW9uIF9wb3NzaWJsZUNvbnN0cnVjdG9yUmV0dXJuKHNlbGYsIGNhbGwpIHsgaWYgKCFzZWxmKSB7IHRocm93IG5ldyBSZWZlcmVuY2VFcnJvcihcInRoaXMgaGFzbid0IGJlZW4gaW5pdGlhbGlzZWQgLSBzdXBlcigpIGhhc24ndCBiZWVuIGNhbGxlZFwiKTsgfSByZXR1cm4gY2FsbCAmJiAodHlwZW9mIGNhbGwgPT09IFwib2JqZWN0XCIgfHwgdHlwZW9mIGNhbGwgPT09IFwiZnVuY3Rpb25cIikgPyBjYWxsIDogc2VsZjsgfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSBcImZ1bmN0aW9uXCIgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCBcIiArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgT2JqZWN0LnNldFByb3RvdHlwZU9mID8gT2JqZWN0LnNldFByb3RvdHlwZU9mKHN1YkNsYXNzLCBzdXBlckNsYXNzKSA6IHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxuLyoqXG4gKiBTcGVjaWZpZXMgdGhlIG51bWJlciBvZiBtaWxpc2Vjb25kcyBkdXJpbmcgd2hpY2ggdG8gZGlzYWJsZSBwb2ludGVyIGV2ZW50cyB3aGlsZSBhIHNjcm9sbCBpcyBpbiBwcm9ncmVzcy5cbiAqIFRoaXMgaW1wcm92ZXMgcGVyZm9ybWFuY2UgYW5kIG1ha2VzIHNjcm9sbGluZyBzbW9vdGhlci5cbiAqL1xudmFyIERFRkFVTFRfU0NST0xMSU5HX1JFU0VUX1RJTUVfSU5URVJWQUwgPSBleHBvcnRzLkRFRkFVTFRfU0NST0xMSU5HX1JFU0VUX1RJTUVfSU5URVJWQUwgPSAxNTA7XG5cbi8qKlxuICogQ29udHJvbHMgd2hldGhlciB0aGUgR3JpZCB1cGRhdGVzIHRoZSBET00gZWxlbWVudCdzIHNjcm9sbExlZnQvc2Nyb2xsVG9wIGJhc2VkIG9uIHRoZSBjdXJyZW50IHN0YXRlIG9yIGp1c3Qgb2JzZXJ2ZXMgaXQuXG4gKiBUaGlzIHByZXZlbnRzIEdyaWQgZnJvbSBpbnRlcnJ1cHRpbmcgbW91c2Utd2hlZWwgYW5pbWF0aW9ucyAoc2VlIGlzc3VlICMyKS5cbiAqL1xudmFyIFNDUk9MTF9QT1NJVElPTl9DSEFOR0VfUkVBU09OUyA9IHtcbiAgT0JTRVJWRUQ6ICdvYnNlcnZlZCcsXG4gIFJFUVVFU1RFRDogJ3JlcXVlc3RlZCdcbn07XG5cbi8qKlxuICogUmVuZGVycyB0YWJ1bGFyIGRhdGEgd2l0aCB2aXJ0dWFsaXphdGlvbiBhbG9uZyB0aGUgdmVydGljYWwgYW5kIGhvcml6b250YWwgYXhlcy5cbiAqIFJvdyBoZWlnaHRzIGFuZCBjb2x1bW4gd2lkdGhzIG11c3QgYmUga25vd24gYWhlYWQgb2YgdGltZSBhbmQgc3BlY2lmaWVkIGFzIHByb3BlcnRpZXMuXG4gKi9cblxudmFyIEdyaWQgPSBmdW5jdGlvbiAoX0NvbXBvbmVudCkge1xuICBfaW5oZXJpdHMoR3JpZCwgX0NvbXBvbmVudCk7XG5cbiAgZnVuY3Rpb24gR3JpZChwcm9wcywgY29udGV4dCkge1xuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBHcmlkKTtcblxuICAgIHZhciBfdGhpcyA9IF9wb3NzaWJsZUNvbnN0cnVjdG9yUmV0dXJuKHRoaXMsIChHcmlkLl9fcHJvdG9fXyB8fCBPYmplY3QuZ2V0UHJvdG90eXBlT2YoR3JpZCkpLmNhbGwodGhpcywgcHJvcHMsIGNvbnRleHQpKTtcblxuICAgIF90aGlzLnN0YXRlID0ge1xuICAgICAgaXNTY3JvbGxpbmc6IGZhbHNlLFxuICAgICAgc2Nyb2xsRGlyZWN0aW9uSG9yaXpvbnRhbDogX2dldE92ZXJzY2FuSW5kaWNlcy5TQ1JPTExfRElSRUNUSU9OX0ZJWEVELFxuICAgICAgc2Nyb2xsRGlyZWN0aW9uVmVydGljYWw6IF9nZXRPdmVyc2NhbkluZGljZXMuU0NST0xMX0RJUkVDVElPTl9GSVhFRCxcbiAgICAgIHNjcm9sbExlZnQ6IDAsXG4gICAgICBzY3JvbGxUb3A6IDBcbiAgICB9O1xuXG4gICAgLy8gSW52b2tlcyBvblNlY3Rpb25SZW5kZXJlZCBjYWxsYmFjayBvbmx5IHdoZW4gc3RhcnQvc3RvcCByb3cgb3IgY29sdW1uIGluZGljZXMgY2hhbmdlXG4gICAgX3RoaXMuX29uR3JpZFJlbmRlcmVkTWVtb2l6ZXIgPSAoMCwgX2NyZWF0ZUNhbGxiYWNrTWVtb2l6ZXIyLmRlZmF1bHQpKCk7XG4gICAgX3RoaXMuX29uU2Nyb2xsTWVtb2l6ZXIgPSAoMCwgX2NyZWF0ZUNhbGxiYWNrTWVtb2l6ZXIyLmRlZmF1bHQpKGZhbHNlKTtcblxuICAgIC8vIEJpbmQgZnVuY3Rpb25zIHRvIGluc3RhbmNlIHNvIHRoZXkgZG9uJ3QgbG9zZSBjb250ZXh0IHdoZW4gcGFzc2VkIGFyb3VuZFxuICAgIF90aGlzLl9lbmFibGVQb2ludGVyRXZlbnRzQWZ0ZXJEZWxheUNhbGxiYWNrID0gX3RoaXMuX2VuYWJsZVBvaW50ZXJFdmVudHNBZnRlckRlbGF5Q2FsbGJhY2suYmluZChfdGhpcyk7XG4gICAgX3RoaXMuX2ludm9rZU9uR3JpZFJlbmRlcmVkSGVscGVyID0gX3RoaXMuX2ludm9rZU9uR3JpZFJlbmRlcmVkSGVscGVyLmJpbmQoX3RoaXMpO1xuICAgIF90aGlzLl9vblNjcm9sbCA9IF90aGlzLl9vblNjcm9sbC5iaW5kKF90aGlzKTtcbiAgICBfdGhpcy5fc2V0TmV4dFN0YXRlQ2FsbGJhY2sgPSBfdGhpcy5fc2V0TmV4dFN0YXRlQ2FsbGJhY2suYmluZChfdGhpcyk7XG4gICAgX3RoaXMuX3VwZGF0ZVNjcm9sbExlZnRGb3JTY3JvbGxUb0NvbHVtbiA9IF90aGlzLl91cGRhdGVTY3JvbGxMZWZ0Rm9yU2Nyb2xsVG9Db2x1bW4uYmluZChfdGhpcyk7XG4gICAgX3RoaXMuX3VwZGF0ZVNjcm9sbFRvcEZvclNjcm9sbFRvUm93ID0gX3RoaXMuX3VwZGF0ZVNjcm9sbFRvcEZvclNjcm9sbFRvUm93LmJpbmQoX3RoaXMpO1xuXG4gICAgX3RoaXMuX2NvbHVtbldpZHRoR2V0dGVyID0gX3RoaXMuX3dyYXBTaXplR2V0dGVyKHByb3BzLmNvbHVtbldpZHRoKTtcbiAgICBfdGhpcy5fcm93SGVpZ2h0R2V0dGVyID0gX3RoaXMuX3dyYXBTaXplR2V0dGVyKHByb3BzLnJvd0hlaWdodCk7XG5cbiAgICBfdGhpcy5fY29sdW1uU2l6ZUFuZFBvc2l0aW9uTWFuYWdlciA9IG5ldyBfU2NhbGluZ0NlbGxTaXplQW5kUG9zaXRpb25NYW5hZ2VyMi5kZWZhdWx0KHtcbiAgICAgIGNlbGxDb3VudDogcHJvcHMuY29sdW1uQ291bnQsXG4gICAgICBjZWxsU2l6ZUdldHRlcjogZnVuY3Rpb24gY2VsbFNpemVHZXR0ZXIoaW5kZXgpIHtcbiAgICAgICAgcmV0dXJuIF90aGlzLl9jb2x1bW5XaWR0aEdldHRlcihpbmRleCk7XG4gICAgICB9LFxuICAgICAgZXN0aW1hdGVkQ2VsbFNpemU6IF90aGlzLl9nZXRFc3RpbWF0ZWRDb2x1bW5TaXplKHByb3BzKVxuICAgIH0pO1xuICAgIF90aGlzLl9yb3dTaXplQW5kUG9zaXRpb25NYW5hZ2VyID0gbmV3IF9TY2FsaW5nQ2VsbFNpemVBbmRQb3NpdGlvbk1hbmFnZXIyLmRlZmF1bHQoe1xuICAgICAgY2VsbENvdW50OiBwcm9wcy5yb3dDb3VudCxcbiAgICAgIGNlbGxTaXplR2V0dGVyOiBmdW5jdGlvbiBjZWxsU2l6ZUdldHRlcihpbmRleCkge1xuICAgICAgICByZXR1cm4gX3RoaXMuX3Jvd0hlaWdodEdldHRlcihpbmRleCk7XG4gICAgICB9LFxuICAgICAgZXN0aW1hdGVkQ2VsbFNpemU6IF90aGlzLl9nZXRFc3RpbWF0ZWRSb3dTaXplKHByb3BzKVxuICAgIH0pO1xuXG4gICAgLy8gU2VlIGRlZmF1bHRDZWxsUmFuZ2VSZW5kZXJlcigpIGZvciBtb3JlIGluZm9ybWF0aW9uIG9uIHRoZSB1c2FnZSBvZiB0aGlzIGNhY2hlXG4gICAgX3RoaXMuX2NlbGxDYWNoZSA9IHt9O1xuICAgIHJldHVybiBfdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBQcmUtbWVhc3VyZSBhbGwgY29sdW1ucyBhbmQgcm93cyBpbiBhIEdyaWQuXG4gICAqIFR5cGljYWxseSBjZWxscyBhcmUgb25seSBtZWFzdXJlZCBhcyBuZWVkZWQgYW5kIGVzdGltYXRlZCBzaXplcyBhcmUgdXNlZCBmb3IgY2VsbHMgdGhhdCBoYXZlIG5vdCB5ZXQgYmVlbiBtZWFzdXJlZC5cbiAgICogVGhpcyBtZXRob2QgZW5zdXJlcyB0aGF0IHRoZSBuZXh0IGNhbGwgdG8gZ2V0VG90YWxTaXplKCkgcmV0dXJucyBhbiBleGFjdCBzaXplIChhcyBvcHBvc2VkIHRvIGp1c3QgYW4gZXN0aW1hdGVkIG9uZSkuXG4gICAqL1xuXG5cbiAgX2NyZWF0ZUNsYXNzKEdyaWQsIFt7XG4gICAga2V5OiAnbWVhc3VyZUFsbENlbGxzJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gbWVhc3VyZUFsbENlbGxzKCkge1xuICAgICAgdmFyIF9wcm9wcyA9IHRoaXMucHJvcHM7XG4gICAgICB2YXIgY29sdW1uQ291bnQgPSBfcHJvcHMuY29sdW1uQ291bnQ7XG4gICAgICB2YXIgcm93Q291bnQgPSBfcHJvcHMucm93Q291bnQ7XG5cblxuICAgICAgdGhpcy5fY29sdW1uU2l6ZUFuZFBvc2l0aW9uTWFuYWdlci5nZXRTaXplQW5kUG9zaXRpb25PZkNlbGwoY29sdW1uQ291bnQgLSAxKTtcbiAgICAgIHRoaXMuX3Jvd1NpemVBbmRQb3NpdGlvbk1hbmFnZXIuZ2V0U2l6ZUFuZFBvc2l0aW9uT2ZDZWxsKHJvd0NvdW50IC0gMSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRm9yY2VkIHJlY29tcHV0ZSBvZiByb3cgaGVpZ2h0cyBhbmQgY29sdW1uIHdpZHRocy5cbiAgICAgKiBUaGlzIGZ1bmN0aW9uIHNob3VsZCBiZSBjYWxsZWQgaWYgZHluYW1pYyBjb2x1bW4gb3Igcm93IHNpemVzIGhhdmUgY2hhbmdlZCBidXQgbm90aGluZyBlbHNlIGhhcy5cbiAgICAgKiBTaW5jZSBHcmlkIG9ubHkgcmVjZWl2ZXMgOmNvbHVtbkNvdW50IGFuZCA6cm93Q291bnQgaXQgaGFzIG5vIHdheSBvZiBkZXRlY3Rpbmcgd2hlbiB0aGUgdW5kZXJseWluZyBkYXRhIGNoYW5nZXMuXG4gICAgICovXG5cbiAgfSwge1xuICAgIGtleTogJ3JlY29tcHV0ZUdyaWRTaXplJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVjb21wdXRlR3JpZFNpemUoKSB7XG4gICAgICB2YXIgX3JlZiA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMCB8fCBhcmd1bWVudHNbMF0gPT09IHVuZGVmaW5lZCA/IHt9IDogYXJndW1lbnRzWzBdO1xuXG4gICAgICB2YXIgX3JlZiRjb2x1bW5JbmRleCA9IF9yZWYuY29sdW1uSW5kZXg7XG4gICAgICB2YXIgY29sdW1uSW5kZXggPSBfcmVmJGNvbHVtbkluZGV4ID09PSB1bmRlZmluZWQgPyAwIDogX3JlZiRjb2x1bW5JbmRleDtcbiAgICAgIHZhciBfcmVmJHJvd0luZGV4ID0gX3JlZi5yb3dJbmRleDtcbiAgICAgIHZhciByb3dJbmRleCA9IF9yZWYkcm93SW5kZXggPT09IHVuZGVmaW5lZCA/IDAgOiBfcmVmJHJvd0luZGV4O1xuXG4gICAgICB0aGlzLl9jb2x1bW5TaXplQW5kUG9zaXRpb25NYW5hZ2VyLnJlc2V0Q2VsbChjb2x1bW5JbmRleCk7XG4gICAgICB0aGlzLl9yb3dTaXplQW5kUG9zaXRpb25NYW5hZ2VyLnJlc2V0Q2VsbChyb3dJbmRleCk7XG5cbiAgICAgIC8vIENsZWFyIGNlbGwgY2FjaGUgaW4gY2FzZSB3ZSBhcmUgc2Nyb2xsaW5nO1xuICAgICAgLy8gSW52YWxpZCByb3cgaGVpZ2h0cyBsaWtlbHkgbWVhbiBpbnZhbGlkIGNhY2hlZCBjb250ZW50IGFzIHdlbGwuXG4gICAgICB0aGlzLl9jZWxsQ2FjaGUgPSB7fTtcblxuICAgICAgdGhpcy5mb3JjZVVwZGF0ZSgpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ2NvbXBvbmVudERpZE1vdW50JyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gY29tcG9uZW50RGlkTW91bnQoKSB7XG4gICAgICB2YXIgX3Byb3BzMiA9IHRoaXMucHJvcHM7XG4gICAgICB2YXIgc2Nyb2xsTGVmdCA9IF9wcm9wczIuc2Nyb2xsTGVmdDtcbiAgICAgIHZhciBzY3JvbGxUb0NvbHVtbiA9IF9wcm9wczIuc2Nyb2xsVG9Db2x1bW47XG4gICAgICB2YXIgc2Nyb2xsVG9wID0gX3Byb3BzMi5zY3JvbGxUb3A7XG4gICAgICB2YXIgc2Nyb2xsVG9Sb3cgPSBfcHJvcHMyLnNjcm9sbFRvUm93O1xuXG4gICAgICAvLyBJZiB0aGlzIGNvbXBvbmVudCB3YXMgZmlyc3QgcmVuZGVyZWQgc2VydmVyLXNpZGUsIHNjcm9sbGJhciBzaXplIHdpbGwgYmUgdW5kZWZpbmVkLlxuICAgICAgLy8gSW4gdGhhdCBldmVudCB3ZSBuZWVkIHRvIHJlbWVhc3VyZS5cblxuICAgICAgaWYgKCF0aGlzLl9zY3JvbGxiYXJTaXplTWVhc3VyZWQpIHtcbiAgICAgICAgdGhpcy5fc2Nyb2xsYmFyU2l6ZSA9ICgwLCBfc2Nyb2xsYmFyU2l6ZTIuZGVmYXVsdCkoKTtcbiAgICAgICAgdGhpcy5fc2Nyb2xsYmFyU2l6ZU1lYXN1cmVkID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7fSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChzY3JvbGxMZWZ0ID49IDAgfHwgc2Nyb2xsVG9wID49IDApIHtcbiAgICAgICAgdGhpcy5fc2V0U2Nyb2xsUG9zaXRpb24oeyBzY3JvbGxMZWZ0OiBzY3JvbGxMZWZ0LCBzY3JvbGxUb3A6IHNjcm9sbFRvcCB9KTtcbiAgICAgIH1cblxuICAgICAgaWYgKHNjcm9sbFRvQ29sdW1uID49IDAgfHwgc2Nyb2xsVG9Sb3cgPj0gMCkge1xuICAgICAgICB0aGlzLl91cGRhdGVTY3JvbGxMZWZ0Rm9yU2Nyb2xsVG9Db2x1bW4oKTtcbiAgICAgICAgdGhpcy5fdXBkYXRlU2Nyb2xsVG9wRm9yU2Nyb2xsVG9Sb3coKTtcbiAgICAgIH1cblxuICAgICAgLy8gVXBkYXRlIG9uUm93c1JlbmRlcmVkIGNhbGxiYWNrXG4gICAgICB0aGlzLl9pbnZva2VPbkdyaWRSZW5kZXJlZEhlbHBlcigpO1xuXG4gICAgICAvLyBJbml0aWFsaXplIG9uU2Nyb2xsIGNhbGxiYWNrXG4gICAgICB0aGlzLl9pbnZva2VPblNjcm9sbE1lbW9pemVyKHtcbiAgICAgICAgc2Nyb2xsTGVmdDogc2Nyb2xsTGVmdCB8fCAwLFxuICAgICAgICBzY3JvbGxUb3A6IHNjcm9sbFRvcCB8fCAwLFxuICAgICAgICB0b3RhbENvbHVtbnNXaWR0aDogdGhpcy5fY29sdW1uU2l6ZUFuZFBvc2l0aW9uTWFuYWdlci5nZXRUb3RhbFNpemUoKSxcbiAgICAgICAgdG90YWxSb3dzSGVpZ2h0OiB0aGlzLl9yb3dTaXplQW5kUG9zaXRpb25NYW5hZ2VyLmdldFRvdGFsU2l6ZSgpXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIFRoaXMgbWV0aG9kIHVwZGF0ZXMgc2Nyb2xsTGVmdC9zY3JvbGxUb3AgaW4gc3RhdGUgZm9yIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcbiAgICAgKiAxKSBOZXcgc2Nyb2xsLXRvLWNlbGwgcHJvcHMgaGF2ZSBiZWVuIHNldFxuICAgICAqL1xuXG4gIH0sIHtcbiAgICBrZXk6ICdjb21wb25lbnREaWRVcGRhdGUnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBjb21wb25lbnREaWRVcGRhdGUocHJldlByb3BzLCBwcmV2U3RhdGUpIHtcbiAgICAgIHZhciBfdGhpczIgPSB0aGlzO1xuXG4gICAgICB2YXIgX3Byb3BzMyA9IHRoaXMucHJvcHM7XG4gICAgICB2YXIgYXV0b0hlaWdodCA9IF9wcm9wczMuYXV0b0hlaWdodDtcbiAgICAgIHZhciBjb2x1bW5Db3VudCA9IF9wcm9wczMuY29sdW1uQ291bnQ7XG4gICAgICB2YXIgaGVpZ2h0ID0gX3Byb3BzMy5oZWlnaHQ7XG4gICAgICB2YXIgcm93Q291bnQgPSBfcHJvcHMzLnJvd0NvdW50O1xuICAgICAgdmFyIHNjcm9sbFRvQWxpZ25tZW50ID0gX3Byb3BzMy5zY3JvbGxUb0FsaWdubWVudDtcbiAgICAgIHZhciBzY3JvbGxUb0NvbHVtbiA9IF9wcm9wczMuc2Nyb2xsVG9Db2x1bW47XG4gICAgICB2YXIgc2Nyb2xsVG9Sb3cgPSBfcHJvcHMzLnNjcm9sbFRvUm93O1xuICAgICAgdmFyIHdpZHRoID0gX3Byb3BzMy53aWR0aDtcbiAgICAgIHZhciBfc3RhdGUgPSB0aGlzLnN0YXRlO1xuICAgICAgdmFyIHNjcm9sbExlZnQgPSBfc3RhdGUuc2Nyb2xsTGVmdDtcbiAgICAgIHZhciBzY3JvbGxQb3NpdGlvbkNoYW5nZVJlYXNvbiA9IF9zdGF0ZS5zY3JvbGxQb3NpdGlvbkNoYW5nZVJlYXNvbjtcbiAgICAgIHZhciBzY3JvbGxUb3AgPSBfc3RhdGUuc2Nyb2xsVG9wO1xuXG4gICAgICAvLyBIYW5kbGUgZWRnZSBjYXNlIHdoZXJlIGNvbHVtbiBvciByb3cgY291bnQgaGFzIG9ubHkganVzdCBpbmNyZWFzZWQgb3ZlciAwLlxuICAgICAgLy8gSW4gdGhpcyBjYXNlIHdlIG1heSBoYXZlIHRvIHJlc3RvcmUgYSBwcmV2aW91c2x5LXNwZWNpZmllZCBzY3JvbGwgb2Zmc2V0LlxuICAgICAgLy8gRm9yIG1vcmUgaW5mbyBzZWUgYnZhdWdobi9yZWFjdC12aXJ0dWFsaXplZC9pc3N1ZXMvMjE4XG5cbiAgICAgIHZhciBjb2x1bW5PclJvd0NvdW50SnVzdEluY3JlYXNlZEZyb21aZXJvID0gY29sdW1uQ291bnQgPiAwICYmIHByZXZQcm9wcy5jb2x1bW5Db3VudCA9PT0gMCB8fCByb3dDb3VudCA+IDAgJiYgcHJldlByb3BzLnJvd0NvdW50ID09PSAwO1xuXG4gICAgICAvLyBNYWtlIHN1cmUgcmVxdWVzdGVkIGNoYW5nZXMgdG8gOnNjcm9sbExlZnQgb3IgOnNjcm9sbFRvcCBnZXQgYXBwbGllZC5cbiAgICAgIC8vIEFzc2lnbmluZyB0byBzY3JvbGxMZWZ0L3Njcm9sbFRvcCB0ZWxscyB0aGUgYnJvd3NlciB0byBpbnRlcnJ1cHQgYW55IHJ1bm5pbmcgc2Nyb2xsIGFuaW1hdGlvbnMsXG4gICAgICAvLyBBbmQgdG8gZGlzY2FyZCBhbnkgcGVuZGluZyBhc3luYyBjaGFuZ2VzIHRvIHRoZSBzY3JvbGwgcG9zaXRpb24gdGhhdCBtYXkgaGF2ZSBoYXBwZW5lZCBpbiB0aGUgbWVhbnRpbWUgKGUuZy4gb24gYSBzZXBhcmF0ZSBzY3JvbGxpbmcgdGhyZWFkKS5cbiAgICAgIC8vIFNvIHdlIG9ubHkgc2V0IHRoZXNlIHdoZW4gd2UgcmVxdWlyZSBhbiBhZGp1c3RtZW50IG9mIHRoZSBzY3JvbGwgcG9zaXRpb24uXG4gICAgICAvLyBTZWUgaXNzdWUgIzIgZm9yIG1vcmUgaW5mb3JtYXRpb24uXG4gICAgICBpZiAoc2Nyb2xsUG9zaXRpb25DaGFuZ2VSZWFzb24gPT09IFNDUk9MTF9QT1NJVElPTl9DSEFOR0VfUkVBU09OUy5SRVFVRVNURUQpIHtcbiAgICAgICAgaWYgKHNjcm9sbExlZnQgPj0gMCAmJiAoc2Nyb2xsTGVmdCAhPT0gcHJldlN0YXRlLnNjcm9sbExlZnQgJiYgc2Nyb2xsTGVmdCAhPT0gdGhpcy5fc2Nyb2xsaW5nQ29udGFpbmVyLnNjcm9sbExlZnQgfHwgY29sdW1uT3JSb3dDb3VudEp1c3RJbmNyZWFzZWRGcm9tWmVybykpIHtcbiAgICAgICAgICB0aGlzLl9zY3JvbGxpbmdDb250YWluZXIuc2Nyb2xsTGVmdCA9IHNjcm9sbExlZnQ7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBAVFJJQ0tZIDphdXRvSGVpZ2h0IHByb3BlcnR5IGluc3RydWN0cyBHcmlkIHRvIGxlYXZlIDpzY3JvbGxUb3AgbWFuYWdlbWVudCB0byBhbiBleHRlcm5hbCBIT0MgKGVnIFdpbmRvd1Njcm9sbGVyKS5cbiAgICAgICAgLy8gSW4gdGhpcyBjYXNlIHdlIHNob3VsZCBhdm9pZCBjaGVja2luZyBzY3JvbGxpbmdDb250YWluZXIuc2Nyb2xsVG9wIHNpbmNlIGl0IGZvcmNlcyBsYXlvdXQvZmxvdy5cbiAgICAgICAgaWYgKCFhdXRvSGVpZ2h0ICYmIHNjcm9sbFRvcCA+PSAwICYmIChzY3JvbGxUb3AgIT09IHByZXZTdGF0ZS5zY3JvbGxUb3AgJiYgc2Nyb2xsVG9wICE9PSB0aGlzLl9zY3JvbGxpbmdDb250YWluZXIuc2Nyb2xsVG9wIHx8IGNvbHVtbk9yUm93Q291bnRKdXN0SW5jcmVhc2VkRnJvbVplcm8pKSB7XG4gICAgICAgICAgdGhpcy5fc2Nyb2xsaW5nQ29udGFpbmVyLnNjcm9sbFRvcCA9IHNjcm9sbFRvcDtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBVcGRhdGUgc2Nyb2xsIG9mZnNldHMgaWYgdGhlIGN1cnJlbnQgOnNjcm9sbFRvQ29sdW1uIG9yIDpzY3JvbGxUb1JvdyB2YWx1ZXMgcmVxdWlyZXMgaXRcbiAgICAgIC8vIEBUT0RPIERvIHdlIGFsc28gbmVlZCB0aGlzIGNoZWNrIG9yIGNhbiB0aGUgb25lIGluIGNvbXBvbmVudFdpbGxVcGRhdGUoKSBzdWZmaWNlP1xuICAgICAgKDAsIF91cGRhdGVTY3JvbGxJbmRleEhlbHBlcjIuZGVmYXVsdCkoe1xuICAgICAgICBjZWxsU2l6ZUFuZFBvc2l0aW9uTWFuYWdlcjogdGhpcy5fY29sdW1uU2l6ZUFuZFBvc2l0aW9uTWFuYWdlcixcbiAgICAgICAgcHJldmlvdXNDZWxsc0NvdW50OiBwcmV2UHJvcHMuY29sdW1uQ291bnQsXG4gICAgICAgIHByZXZpb3VzQ2VsbFNpemU6IHByZXZQcm9wcy5jb2x1bW5XaWR0aCxcbiAgICAgICAgcHJldmlvdXNTY3JvbGxUb0FsaWdubWVudDogcHJldlByb3BzLnNjcm9sbFRvQWxpZ25tZW50LFxuICAgICAgICBwcmV2aW91c1Njcm9sbFRvSW5kZXg6IHByZXZQcm9wcy5zY3JvbGxUb0NvbHVtbixcbiAgICAgICAgcHJldmlvdXNTaXplOiBwcmV2UHJvcHMud2lkdGgsXG4gICAgICAgIHNjcm9sbE9mZnNldDogc2Nyb2xsTGVmdCxcbiAgICAgICAgc2Nyb2xsVG9BbGlnbm1lbnQ6IHNjcm9sbFRvQWxpZ25tZW50LFxuICAgICAgICBzY3JvbGxUb0luZGV4OiBzY3JvbGxUb0NvbHVtbixcbiAgICAgICAgc2l6ZTogd2lkdGgsXG4gICAgICAgIHVwZGF0ZVNjcm9sbEluZGV4Q2FsbGJhY2s6IGZ1bmN0aW9uIHVwZGF0ZVNjcm9sbEluZGV4Q2FsbGJhY2soc2Nyb2xsVG9Db2x1bW4pIHtcbiAgICAgICAgICByZXR1cm4gX3RoaXMyLl91cGRhdGVTY3JvbGxMZWZ0Rm9yU2Nyb2xsVG9Db2x1bW4oX2V4dGVuZHMoe30sIF90aGlzMi5wcm9wcywgeyBzY3JvbGxUb0NvbHVtbjogc2Nyb2xsVG9Db2x1bW4gfSkpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgICgwLCBfdXBkYXRlU2Nyb2xsSW5kZXhIZWxwZXIyLmRlZmF1bHQpKHtcbiAgICAgICAgY2VsbFNpemVBbmRQb3NpdGlvbk1hbmFnZXI6IHRoaXMuX3Jvd1NpemVBbmRQb3NpdGlvbk1hbmFnZXIsXG4gICAgICAgIHByZXZpb3VzQ2VsbHNDb3VudDogcHJldlByb3BzLnJvd0NvdW50LFxuICAgICAgICBwcmV2aW91c0NlbGxTaXplOiBwcmV2UHJvcHMucm93SGVpZ2h0LFxuICAgICAgICBwcmV2aW91c1Njcm9sbFRvQWxpZ25tZW50OiBwcmV2UHJvcHMuc2Nyb2xsVG9BbGlnbm1lbnQsXG4gICAgICAgIHByZXZpb3VzU2Nyb2xsVG9JbmRleDogcHJldlByb3BzLnNjcm9sbFRvUm93LFxuICAgICAgICBwcmV2aW91c1NpemU6IHByZXZQcm9wcy5oZWlnaHQsXG4gICAgICAgIHNjcm9sbE9mZnNldDogc2Nyb2xsVG9wLFxuICAgICAgICBzY3JvbGxUb0FsaWdubWVudDogc2Nyb2xsVG9BbGlnbm1lbnQsXG4gICAgICAgIHNjcm9sbFRvSW5kZXg6IHNjcm9sbFRvUm93LFxuICAgICAgICBzaXplOiBoZWlnaHQsXG4gICAgICAgIHVwZGF0ZVNjcm9sbEluZGV4Q2FsbGJhY2s6IGZ1bmN0aW9uIHVwZGF0ZVNjcm9sbEluZGV4Q2FsbGJhY2soc2Nyb2xsVG9Sb3cpIHtcbiAgICAgICAgICByZXR1cm4gX3RoaXMyLl91cGRhdGVTY3JvbGxUb3BGb3JTY3JvbGxUb1JvdyhfZXh0ZW5kcyh7fSwgX3RoaXMyLnByb3BzLCB7IHNjcm9sbFRvUm93OiBzY3JvbGxUb1JvdyB9KSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICAvLyBVcGRhdGUgb25Sb3dzUmVuZGVyZWQgY2FsbGJhY2sgaWYgc3RhcnQvc3RvcCBpbmRpY2VzIGhhdmUgY2hhbmdlZFxuICAgICAgdGhpcy5faW52b2tlT25HcmlkUmVuZGVyZWRIZWxwZXIoKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdjb21wb25lbnRXaWxsTW91bnQnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBjb21wb25lbnRXaWxsTW91bnQoKSB7XG4gICAgICAvLyBJZiB0aGlzIGNvbXBvbmVudCBpcyBiZWluZyByZW5kZXJlZCBzZXJ2ZXItc2lkZSwgZ2V0U2Nyb2xsYmFyU2l6ZSgpIHdpbGwgcmV0dXJuIHVuZGVmaW5lZC5cbiAgICAgIC8vIFdlIGhhbmRsZSB0aGlzIGNhc2UgaW4gY29tcG9uZW50RGlkTW91bnQoKVxuICAgICAgdGhpcy5fc2Nyb2xsYmFyU2l6ZSA9ICgwLCBfc2Nyb2xsYmFyU2l6ZTIuZGVmYXVsdCkoKTtcbiAgICAgIGlmICh0aGlzLl9zY3JvbGxiYXJTaXplID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhpcy5fc2Nyb2xsYmFyU2l6ZU1lYXN1cmVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuX3Njcm9sbGJhclNpemUgPSAwO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5fc2Nyb2xsYmFyU2l6ZU1lYXN1cmVkID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fY2FsY3VsYXRlQ2hpbGRyZW5Ub1JlbmRlcigpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ2NvbXBvbmVudFdpbGxVbm1vdW50JyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gY29tcG9uZW50V2lsbFVubW91bnQoKSB7XG4gICAgICBpZiAodGhpcy5fZGlzYWJsZVBvaW50ZXJFdmVudHNUaW1lb3V0SWQpIHtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMuX2Rpc2FibGVQb2ludGVyRXZlbnRzVGltZW91dElkKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuX3NldE5leHRTdGF0ZUFuaW1hdGlvbkZyYW1lSWQpIHtcbiAgICAgICAgX3JhZjIuZGVmYXVsdC5jYW5jZWwodGhpcy5fc2V0TmV4dFN0YXRlQW5pbWF0aW9uRnJhbWVJZCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBUaGlzIG1ldGhvZCB1cGRhdGVzIHNjcm9sbExlZnQvc2Nyb2xsVG9wIGluIHN0YXRlIGZvciB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4gICAgICogMSkgRW1wdHkgY29udGVudCAoMCByb3dzIG9yIGNvbHVtbnMpXG4gICAgICogMikgTmV3IHNjcm9sbCBwcm9wcyBvdmVycmlkaW5nIHRoZSBjdXJyZW50IHN0YXRlXG4gICAgICogMykgQ2VsbHMtY291bnQgb3IgY2VsbHMtc2l6ZSBoYXMgY2hhbmdlZCwgbWFraW5nIHByZXZpb3VzIHNjcm9sbCBvZmZzZXRzIGludmFsaWRcbiAgICAgKi9cblxuICB9LCB7XG4gICAga2V5OiAnY29tcG9uZW50V2lsbFVwZGF0ZScsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGNvbXBvbmVudFdpbGxVcGRhdGUobmV4dFByb3BzLCBuZXh0U3RhdGUpIHtcbiAgICAgIHZhciBfdGhpczMgPSB0aGlzO1xuXG4gICAgICBpZiAobmV4dFByb3BzLmNvbHVtbkNvdW50ID09PSAwICYmIG5leHRTdGF0ZS5zY3JvbGxMZWZ0ICE9PSAwIHx8IG5leHRQcm9wcy5yb3dDb3VudCA9PT0gMCAmJiBuZXh0U3RhdGUuc2Nyb2xsVG9wICE9PSAwKSB7XG4gICAgICAgIHRoaXMuX3NldFNjcm9sbFBvc2l0aW9uKHtcbiAgICAgICAgICBzY3JvbGxMZWZ0OiAwLFxuICAgICAgICAgIHNjcm9sbFRvcDogMFxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSBpZiAobmV4dFByb3BzLnNjcm9sbExlZnQgIT09IHRoaXMucHJvcHMuc2Nyb2xsTGVmdCB8fCBuZXh0UHJvcHMuc2Nyb2xsVG9wICE9PSB0aGlzLnByb3BzLnNjcm9sbFRvcCkge1xuICAgICAgICB0aGlzLl9zZXRTY3JvbGxQb3NpdGlvbih7XG4gICAgICAgICAgc2Nyb2xsTGVmdDogbmV4dFByb3BzLnNjcm9sbExlZnQsXG4gICAgICAgICAgc2Nyb2xsVG9wOiBuZXh0UHJvcHMuc2Nyb2xsVG9wXG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9jb2x1bW5XaWR0aEdldHRlciA9IHRoaXMuX3dyYXBTaXplR2V0dGVyKG5leHRQcm9wcy5jb2x1bW5XaWR0aCk7XG4gICAgICB0aGlzLl9yb3dIZWlnaHRHZXR0ZXIgPSB0aGlzLl93cmFwU2l6ZUdldHRlcihuZXh0UHJvcHMucm93SGVpZ2h0KTtcblxuICAgICAgdGhpcy5fY29sdW1uU2l6ZUFuZFBvc2l0aW9uTWFuYWdlci5jb25maWd1cmUoe1xuICAgICAgICBjZWxsQ291bnQ6IG5leHRQcm9wcy5jb2x1bW5Db3VudCxcbiAgICAgICAgZXN0aW1hdGVkQ2VsbFNpemU6IHRoaXMuX2dldEVzdGltYXRlZENvbHVtblNpemUobmV4dFByb3BzKVxuICAgICAgfSk7XG4gICAgICB0aGlzLl9yb3dTaXplQW5kUG9zaXRpb25NYW5hZ2VyLmNvbmZpZ3VyZSh7XG4gICAgICAgIGNlbGxDb3VudDogbmV4dFByb3BzLnJvd0NvdW50LFxuICAgICAgICBlc3RpbWF0ZWRDZWxsU2l6ZTogdGhpcy5fZ2V0RXN0aW1hdGVkUm93U2l6ZShuZXh0UHJvcHMpXG4gICAgICB9KTtcblxuICAgICAgLy8gVXBkYXRlIHNjcm9sbCBvZmZzZXRzIGlmIHRoZSBzaXplIG9yIG51bWJlciBvZiBjZWxscyBoYXZlIGNoYW5nZWQsIGludmFsaWRhdGluZyB0aGUgcHJldmlvdXMgdmFsdWVcbiAgICAgICgwLCBfY2FsY3VsYXRlU2l6ZUFuZFBvc2l0aW9uRGF0YUFuZFVwZGF0ZVNjcm9sbE9mZnNldDIuZGVmYXVsdCkoe1xuICAgICAgICBjZWxsQ291bnQ6IHRoaXMucHJvcHMuY29sdW1uQ291bnQsXG4gICAgICAgIGNlbGxTaXplOiB0aGlzLnByb3BzLmNvbHVtbldpZHRoLFxuICAgICAgICBjb21wdXRlTWV0YWRhdGFDYWxsYmFjazogZnVuY3Rpb24gY29tcHV0ZU1ldGFkYXRhQ2FsbGJhY2soKSB7XG4gICAgICAgICAgcmV0dXJuIF90aGlzMy5fY29sdW1uU2l6ZUFuZFBvc2l0aW9uTWFuYWdlci5yZXNldENlbGwoMCk7XG4gICAgICAgIH0sXG4gICAgICAgIGNvbXB1dGVNZXRhZGF0YUNhbGxiYWNrUHJvcHM6IG5leHRQcm9wcyxcbiAgICAgICAgbmV4dENlbGxzQ291bnQ6IG5leHRQcm9wcy5jb2x1bW5Db3VudCxcbiAgICAgICAgbmV4dENlbGxTaXplOiBuZXh0UHJvcHMuY29sdW1uV2lkdGgsXG4gICAgICAgIG5leHRTY3JvbGxUb0luZGV4OiBuZXh0UHJvcHMuc2Nyb2xsVG9Db2x1bW4sXG4gICAgICAgIHNjcm9sbFRvSW5kZXg6IHRoaXMucHJvcHMuc2Nyb2xsVG9Db2x1bW4sXG4gICAgICAgIHVwZGF0ZVNjcm9sbE9mZnNldEZvclNjcm9sbFRvSW5kZXg6IGZ1bmN0aW9uIHVwZGF0ZVNjcm9sbE9mZnNldEZvclNjcm9sbFRvSW5kZXgoKSB7XG4gICAgICAgICAgcmV0dXJuIF90aGlzMy5fdXBkYXRlU2Nyb2xsTGVmdEZvclNjcm9sbFRvQ29sdW1uKG5leHRQcm9wcywgbmV4dFN0YXRlKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICAoMCwgX2NhbGN1bGF0ZVNpemVBbmRQb3NpdGlvbkRhdGFBbmRVcGRhdGVTY3JvbGxPZmZzZXQyLmRlZmF1bHQpKHtcbiAgICAgICAgY2VsbENvdW50OiB0aGlzLnByb3BzLnJvd0NvdW50LFxuICAgICAgICBjZWxsU2l6ZTogdGhpcy5wcm9wcy5yb3dIZWlnaHQsXG4gICAgICAgIGNvbXB1dGVNZXRhZGF0YUNhbGxiYWNrOiBmdW5jdGlvbiBjb21wdXRlTWV0YWRhdGFDYWxsYmFjaygpIHtcbiAgICAgICAgICByZXR1cm4gX3RoaXMzLl9yb3dTaXplQW5kUG9zaXRpb25NYW5hZ2VyLnJlc2V0Q2VsbCgwKTtcbiAgICAgICAgfSxcbiAgICAgICAgY29tcHV0ZU1ldGFkYXRhQ2FsbGJhY2tQcm9wczogbmV4dFByb3BzLFxuICAgICAgICBuZXh0Q2VsbHNDb3VudDogbmV4dFByb3BzLnJvd0NvdW50LFxuICAgICAgICBuZXh0Q2VsbFNpemU6IG5leHRQcm9wcy5yb3dIZWlnaHQsXG4gICAgICAgIG5leHRTY3JvbGxUb0luZGV4OiBuZXh0UHJvcHMuc2Nyb2xsVG9Sb3csXG4gICAgICAgIHNjcm9sbFRvSW5kZXg6IHRoaXMucHJvcHMuc2Nyb2xsVG9Sb3csXG4gICAgICAgIHVwZGF0ZVNjcm9sbE9mZnNldEZvclNjcm9sbFRvSW5kZXg6IGZ1bmN0aW9uIHVwZGF0ZVNjcm9sbE9mZnNldEZvclNjcm9sbFRvSW5kZXgoKSB7XG4gICAgICAgICAgcmV0dXJuIF90aGlzMy5fdXBkYXRlU2Nyb2xsVG9wRm9yU2Nyb2xsVG9Sb3cobmV4dFByb3BzLCBuZXh0U3RhdGUpO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgdGhpcy5fY2FsY3VsYXRlQ2hpbGRyZW5Ub1JlbmRlcihuZXh0UHJvcHMsIG5leHRTdGF0ZSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAncmVuZGVyJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVuZGVyKCkge1xuICAgICAgdmFyIF90aGlzNCA9IHRoaXM7XG5cbiAgICAgIHZhciBfcHJvcHM0ID0gdGhpcy5wcm9wcztcbiAgICAgIHZhciBhdXRvQ29udGFpbmVyV2lkdGggPSBfcHJvcHM0LmF1dG9Db250YWluZXJXaWR0aDtcbiAgICAgIHZhciBhdXRvSGVpZ2h0ID0gX3Byb3BzNC5hdXRvSGVpZ2h0O1xuICAgICAgdmFyIGNsYXNzTmFtZSA9IF9wcm9wczQuY2xhc3NOYW1lO1xuICAgICAgdmFyIGhlaWdodCA9IF9wcm9wczQuaGVpZ2h0O1xuICAgICAgdmFyIG5vQ29udGVudFJlbmRlcmVyID0gX3Byb3BzNC5ub0NvbnRlbnRSZW5kZXJlcjtcbiAgICAgIHZhciBzdHlsZSA9IF9wcm9wczQuc3R5bGU7XG4gICAgICB2YXIgdGFiSW5kZXggPSBfcHJvcHM0LnRhYkluZGV4O1xuICAgICAgdmFyIHdpZHRoID0gX3Byb3BzNC53aWR0aDtcbiAgICAgIHZhciBpc1Njcm9sbGluZyA9IHRoaXMuc3RhdGUuaXNTY3JvbGxpbmc7XG5cblxuICAgICAgdmFyIGdyaWRTdHlsZSA9IHtcbiAgICAgICAgaGVpZ2h0OiBhdXRvSGVpZ2h0ID8gJ2F1dG8nIDogaGVpZ2h0LFxuICAgICAgICB3aWR0aDogd2lkdGhcbiAgICAgIH07XG5cbiAgICAgIHZhciB0b3RhbENvbHVtbnNXaWR0aCA9IHRoaXMuX2NvbHVtblNpemVBbmRQb3NpdGlvbk1hbmFnZXIuZ2V0VG90YWxTaXplKCk7XG4gICAgICB2YXIgdG90YWxSb3dzSGVpZ2h0ID0gdGhpcy5fcm93U2l6ZUFuZFBvc2l0aW9uTWFuYWdlci5nZXRUb3RhbFNpemUoKTtcblxuICAgICAgLy8gRm9yY2UgYnJvd3NlciB0byBoaWRlIHNjcm9sbGJhcnMgd2hlbiB3ZSBrbm93IHRoZXkgYXJlbid0IG5lY2Vzc2FyeS5cbiAgICAgIC8vIE90aGVyd2lzZSBvbmNlIHNjcm9sbGJhcnMgYXBwZWFyIHRoZXkgbWF5IG5vdCBkaXNhcHBlYXIgYWdhaW4uXG4gICAgICAvLyBGb3IgbW9yZSBpbmZvIHNlZSBpc3N1ZSAjMTE2XG4gICAgICB2YXIgdmVydGljYWxTY3JvbGxCYXJTaXplID0gdG90YWxSb3dzSGVpZ2h0ID4gaGVpZ2h0ID8gdGhpcy5fc2Nyb2xsYmFyU2l6ZSA6IDA7XG4gICAgICB2YXIgaG9yaXpvbnRhbFNjcm9sbEJhclNpemUgPSB0b3RhbENvbHVtbnNXaWR0aCA+IHdpZHRoID8gdGhpcy5fc2Nyb2xsYmFyU2l6ZSA6IDA7XG5cbiAgICAgIC8vIEFsc28gZXhwbGljaXRseSBpbml0IHN0eWxlcyB0byAnYXV0bycgaWYgc2Nyb2xsYmFycyBhcmUgcmVxdWlyZWQuXG4gICAgICAvLyBUaGlzIHdvcmtzIGFyb3VuZCBhbiBvYnNjdXJlIGVkZ2UgY2FzZSB3aGVyZSBleHRlcm5hbCBDU1Mgc3R5bGVzIGhhdmUgbm90IHlldCBiZWVuIGxvYWRlZCxcbiAgICAgIC8vIEJ1dCBhbiBpbml0aWFsIHNjcm9sbCBpbmRleCBvZiBvZmZzZXQgaXMgc2V0IGFzIGFuIGV4dGVybmFsIHByb3AuXG4gICAgICAvLyBXaXRob3V0IHRoaXMgc3R5bGUsIEdyaWQgd291bGQgcmVuZGVyIHRoZSBjb3JyZWN0IHJhbmdlIG9mIGNlbGxzIGJ1dCB3b3VsZCBOT1QgdXBkYXRlIGl0cyBpbnRlcm5hbCBvZmZzZXQuXG4gICAgICAvLyBUaGlzIHdhcyBvcmlnaW5hbGx5IHJlcG9ydGVkIHZpYSBjbGF1ZGVyaWMvcmVhY3QtaW5maW5pdGUtY2FsZW5kYXIvaXNzdWVzLzIzXG4gICAgICBncmlkU3R5bGUub3ZlcmZsb3dYID0gdG90YWxDb2x1bW5zV2lkdGggKyB2ZXJ0aWNhbFNjcm9sbEJhclNpemUgPD0gd2lkdGggPyAnaGlkZGVuJyA6ICdhdXRvJztcbiAgICAgIGdyaWRTdHlsZS5vdmVyZmxvd1kgPSB0b3RhbFJvd3NIZWlnaHQgKyBob3Jpem9udGFsU2Nyb2xsQmFyU2l6ZSA8PSBoZWlnaHQgPyAnaGlkZGVuJyA6ICdhdXRvJztcblxuICAgICAgdmFyIGNoaWxkcmVuVG9EaXNwbGF5ID0gdGhpcy5fY2hpbGRyZW5Ub0Rpc3BsYXk7XG5cbiAgICAgIHZhciBzaG93Tm9Db250ZW50UmVuZGVyZXIgPSBjaGlsZHJlblRvRGlzcGxheS5sZW5ndGggPT09IDAgJiYgaGVpZ2h0ID4gMCAmJiB3aWR0aCA+IDA7XG5cbiAgICAgIHJldHVybiBfcmVhY3QyLmRlZmF1bHQuY3JlYXRlRWxlbWVudChcbiAgICAgICAgJ2RpdicsXG4gICAgICAgIHtcbiAgICAgICAgICByZWY6IGZ1bmN0aW9uIHJlZihfcmVmMikge1xuICAgICAgICAgICAgX3RoaXM0Ll9zY3JvbGxpbmdDb250YWluZXIgPSBfcmVmMjtcbiAgICAgICAgICB9LFxuICAgICAgICAgICdhcmlhLWxhYmVsJzogdGhpcy5wcm9wc1snYXJpYS1sYWJlbCddLFxuICAgICAgICAgIGNsYXNzTmFtZTogKDAsIF9jbGFzc25hbWVzMi5kZWZhdWx0KSgnR3JpZCcsIGNsYXNzTmFtZSksXG4gICAgICAgICAgb25TY3JvbGw6IHRoaXMuX29uU2Nyb2xsLFxuICAgICAgICAgIHJvbGU6ICdncmlkJyxcbiAgICAgICAgICBzdHlsZTogX2V4dGVuZHMoe30sIGdyaWRTdHlsZSwgc3R5bGUpLFxuICAgICAgICAgIHRhYkluZGV4OiB0YWJJbmRleFxuICAgICAgICB9LFxuICAgICAgICBjaGlsZHJlblRvRGlzcGxheS5sZW5ndGggPiAwICYmIF9yZWFjdDIuZGVmYXVsdC5jcmVhdGVFbGVtZW50KFxuICAgICAgICAgICdkaXYnLFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGNsYXNzTmFtZTogJ0dyaWRfX2lubmVyU2Nyb2xsQ29udGFpbmVyJyxcbiAgICAgICAgICAgIHN0eWxlOiB7XG4gICAgICAgICAgICAgIHdpZHRoOiBhdXRvQ29udGFpbmVyV2lkdGggPyAnYXV0bycgOiB0b3RhbENvbHVtbnNXaWR0aCxcbiAgICAgICAgICAgICAgaGVpZ2h0OiB0b3RhbFJvd3NIZWlnaHQsXG4gICAgICAgICAgICAgIG1heFdpZHRoOiB0b3RhbENvbHVtbnNXaWR0aCxcbiAgICAgICAgICAgICAgbWF4SGVpZ2h0OiB0b3RhbFJvd3NIZWlnaHQsXG4gICAgICAgICAgICAgIHBvaW50ZXJFdmVudHM6IGlzU2Nyb2xsaW5nID8gJ25vbmUnIDogJydcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIGNoaWxkcmVuVG9EaXNwbGF5XG4gICAgICAgICksXG4gICAgICAgIHNob3dOb0NvbnRlbnRSZW5kZXJlciAmJiBub0NvbnRlbnRSZW5kZXJlcigpXG4gICAgICApO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ3Nob3VsZENvbXBvbmVudFVwZGF0ZScsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHNob3VsZENvbXBvbmVudFVwZGF0ZShuZXh0UHJvcHMsIG5leHRTdGF0ZSkge1xuICAgICAgcmV0dXJuICgwLCBfcmVhY3RBZGRvbnNTaGFsbG93Q29tcGFyZTIuZGVmYXVsdCkodGhpcywgbmV4dFByb3BzLCBuZXh0U3RhdGUpO1xuICAgIH1cblxuICAgIC8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gSGVscGVyIG1ldGhvZHMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuXG4gIH0sIHtcbiAgICBrZXk6ICdfY2FsY3VsYXRlQ2hpbGRyZW5Ub1JlbmRlcicsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9jYWxjdWxhdGVDaGlsZHJlblRvUmVuZGVyKCkge1xuICAgICAgdmFyIHByb3BzID0gYXJndW1lbnRzLmxlbmd0aCA8PSAwIHx8IGFyZ3VtZW50c1swXSA9PT0gdW5kZWZpbmVkID8gdGhpcy5wcm9wcyA6IGFyZ3VtZW50c1swXTtcbiAgICAgIHZhciBzdGF0ZSA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMSB8fCBhcmd1bWVudHNbMV0gPT09IHVuZGVmaW5lZCA/IHRoaXMuc3RhdGUgOiBhcmd1bWVudHNbMV07XG4gICAgICB2YXIgY2VsbENsYXNzTmFtZSA9IHByb3BzLmNlbGxDbGFzc05hbWU7XG4gICAgICB2YXIgY2VsbFJlbmRlcmVyID0gcHJvcHMuY2VsbFJlbmRlcmVyO1xuICAgICAgdmFyIGNlbGxSYW5nZVJlbmRlcmVyID0gcHJvcHMuY2VsbFJhbmdlUmVuZGVyZXI7XG4gICAgICB2YXIgY2VsbFN0eWxlID0gcHJvcHMuY2VsbFN0eWxlO1xuICAgICAgdmFyIGNvbHVtbkNvdW50ID0gcHJvcHMuY29sdW1uQ291bnQ7XG4gICAgICB2YXIgaGVpZ2h0ID0gcHJvcHMuaGVpZ2h0O1xuICAgICAgdmFyIG92ZXJzY2FuQ29sdW1uQ291bnQgPSBwcm9wcy5vdmVyc2NhbkNvbHVtbkNvdW50O1xuICAgICAgdmFyIG92ZXJzY2FuUm93Q291bnQgPSBwcm9wcy5vdmVyc2NhblJvd0NvdW50O1xuICAgICAgdmFyIHJvd0NvdW50ID0gcHJvcHMucm93Q291bnQ7XG4gICAgICB2YXIgd2lkdGggPSBwcm9wcy53aWR0aDtcbiAgICAgIHZhciBpc1Njcm9sbGluZyA9IHN0YXRlLmlzU2Nyb2xsaW5nO1xuICAgICAgdmFyIHNjcm9sbERpcmVjdGlvbkhvcml6b250YWwgPSBzdGF0ZS5zY3JvbGxEaXJlY3Rpb25Ib3Jpem9udGFsO1xuICAgICAgdmFyIHNjcm9sbERpcmVjdGlvblZlcnRpY2FsID0gc3RhdGUuc2Nyb2xsRGlyZWN0aW9uVmVydGljYWw7XG4gICAgICB2YXIgc2Nyb2xsTGVmdCA9IHN0YXRlLnNjcm9sbExlZnQ7XG4gICAgICB2YXIgc2Nyb2xsVG9wID0gc3RhdGUuc2Nyb2xsVG9wO1xuXG5cbiAgICAgIHRoaXMuX2NoaWxkcmVuVG9EaXNwbGF5ID0gW107XG5cbiAgICAgIC8vIFJlbmRlciBvbmx5IGVub3VnaCBjb2x1bW5zIGFuZCByb3dzIHRvIGNvdmVyIHRoZSB2aXNpYmxlIGFyZWEgb2YgdGhlIGdyaWQuXG4gICAgICBpZiAoaGVpZ2h0ID4gMCAmJiB3aWR0aCA+IDApIHtcbiAgICAgICAgdmFyIHZpc2libGVDb2x1bW5JbmRpY2VzID0gdGhpcy5fY29sdW1uU2l6ZUFuZFBvc2l0aW9uTWFuYWdlci5nZXRWaXNpYmxlQ2VsbFJhbmdlKHtcbiAgICAgICAgICBjb250YWluZXJTaXplOiB3aWR0aCxcbiAgICAgICAgICBvZmZzZXQ6IHNjcm9sbExlZnRcbiAgICAgICAgfSk7XG4gICAgICAgIHZhciB2aXNpYmxlUm93SW5kaWNlcyA9IHRoaXMuX3Jvd1NpemVBbmRQb3NpdGlvbk1hbmFnZXIuZ2V0VmlzaWJsZUNlbGxSYW5nZSh7XG4gICAgICAgICAgY29udGFpbmVyU2l6ZTogaGVpZ2h0LFxuICAgICAgICAgIG9mZnNldDogc2Nyb2xsVG9wXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHZhciBob3Jpem9udGFsT2Zmc2V0QWRqdXN0bWVudCA9IHRoaXMuX2NvbHVtblNpemVBbmRQb3NpdGlvbk1hbmFnZXIuZ2V0T2Zmc2V0QWRqdXN0bWVudCh7XG4gICAgICAgICAgY29udGFpbmVyU2l6ZTogd2lkdGgsXG4gICAgICAgICAgb2Zmc2V0OiBzY3JvbGxMZWZ0XG4gICAgICAgIH0pO1xuICAgICAgICB2YXIgdmVydGljYWxPZmZzZXRBZGp1c3RtZW50ID0gdGhpcy5fcm93U2l6ZUFuZFBvc2l0aW9uTWFuYWdlci5nZXRPZmZzZXRBZGp1c3RtZW50KHtcbiAgICAgICAgICBjb250YWluZXJTaXplOiBoZWlnaHQsXG4gICAgICAgICAgb2Zmc2V0OiBzY3JvbGxUb3BcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gU3RvcmUgZm9yIF9pbnZva2VPbkdyaWRSZW5kZXJlZEhlbHBlcigpXG4gICAgICAgIHRoaXMuX3JlbmRlcmVkQ29sdW1uU3RhcnRJbmRleCA9IHZpc2libGVDb2x1bW5JbmRpY2VzLnN0YXJ0O1xuICAgICAgICB0aGlzLl9yZW5kZXJlZENvbHVtblN0b3BJbmRleCA9IHZpc2libGVDb2x1bW5JbmRpY2VzLnN0b3A7XG4gICAgICAgIHRoaXMuX3JlbmRlcmVkUm93U3RhcnRJbmRleCA9IHZpc2libGVSb3dJbmRpY2VzLnN0YXJ0O1xuICAgICAgICB0aGlzLl9yZW5kZXJlZFJvd1N0b3BJbmRleCA9IHZpc2libGVSb3dJbmRpY2VzLnN0b3A7XG5cbiAgICAgICAgdmFyIG92ZXJzY2FuQ29sdW1uSW5kaWNlcyA9ICgwLCBfZ2V0T3ZlcnNjYW5JbmRpY2VzMi5kZWZhdWx0KSh7XG4gICAgICAgICAgY2VsbENvdW50OiBjb2x1bW5Db3VudCxcbiAgICAgICAgICBvdmVyc2NhbkNlbGxzQ291bnQ6IG92ZXJzY2FuQ29sdW1uQ291bnQsXG4gICAgICAgICAgc2Nyb2xsRGlyZWN0aW9uOiBzY3JvbGxEaXJlY3Rpb25Ib3Jpem9udGFsLFxuICAgICAgICAgIHN0YXJ0SW5kZXg6IHRoaXMuX3JlbmRlcmVkQ29sdW1uU3RhcnRJbmRleCxcbiAgICAgICAgICBzdG9wSW5kZXg6IHRoaXMuX3JlbmRlcmVkQ29sdW1uU3RvcEluZGV4XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHZhciBvdmVyc2NhblJvd0luZGljZXMgPSAoMCwgX2dldE92ZXJzY2FuSW5kaWNlczIuZGVmYXVsdCkoe1xuICAgICAgICAgIGNlbGxDb3VudDogcm93Q291bnQsXG4gICAgICAgICAgb3ZlcnNjYW5DZWxsc0NvdW50OiBvdmVyc2NhblJvd0NvdW50LFxuICAgICAgICAgIHNjcm9sbERpcmVjdGlvbjogc2Nyb2xsRGlyZWN0aW9uVmVydGljYWwsXG4gICAgICAgICAgc3RhcnRJbmRleDogdGhpcy5fcmVuZGVyZWRSb3dTdGFydEluZGV4LFxuICAgICAgICAgIHN0b3BJbmRleDogdGhpcy5fcmVuZGVyZWRSb3dTdG9wSW5kZXhcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gU3RvcmUgZm9yIF9pbnZva2VPbkdyaWRSZW5kZXJlZEhlbHBlcigpXG4gICAgICAgIHRoaXMuX2NvbHVtblN0YXJ0SW5kZXggPSBvdmVyc2NhbkNvbHVtbkluZGljZXMub3ZlcnNjYW5TdGFydEluZGV4O1xuICAgICAgICB0aGlzLl9jb2x1bW5TdG9wSW5kZXggPSBvdmVyc2NhbkNvbHVtbkluZGljZXMub3ZlcnNjYW5TdG9wSW5kZXg7XG4gICAgICAgIHRoaXMuX3Jvd1N0YXJ0SW5kZXggPSBvdmVyc2NhblJvd0luZGljZXMub3ZlcnNjYW5TdGFydEluZGV4O1xuICAgICAgICB0aGlzLl9yb3dTdG9wSW5kZXggPSBvdmVyc2NhblJvd0luZGljZXMub3ZlcnNjYW5TdG9wSW5kZXg7XG5cbiAgICAgICAgdGhpcy5fY2hpbGRyZW5Ub0Rpc3BsYXkgPSBjZWxsUmFuZ2VSZW5kZXJlcih7XG4gICAgICAgICAgY2VsbENhY2hlOiB0aGlzLl9jZWxsQ2FjaGUsXG4gICAgICAgICAgY2VsbENsYXNzTmFtZTogdGhpcy5fd3JhcENlbGxDbGFzc05hbWVHZXR0ZXIoY2VsbENsYXNzTmFtZSksXG4gICAgICAgICAgY2VsbFJlbmRlcmVyOiBjZWxsUmVuZGVyZXIsXG4gICAgICAgICAgY2VsbFN0eWxlOiB0aGlzLl93cmFwQ2VsbFN0eWxlR2V0dGVyKGNlbGxTdHlsZSksXG4gICAgICAgICAgY29sdW1uU2l6ZUFuZFBvc2l0aW9uTWFuYWdlcjogdGhpcy5fY29sdW1uU2l6ZUFuZFBvc2l0aW9uTWFuYWdlcixcbiAgICAgICAgICBjb2x1bW5TdGFydEluZGV4OiB0aGlzLl9jb2x1bW5TdGFydEluZGV4LFxuICAgICAgICAgIGNvbHVtblN0b3BJbmRleDogdGhpcy5fY29sdW1uU3RvcEluZGV4LFxuICAgICAgICAgIGhvcml6b250YWxPZmZzZXRBZGp1c3RtZW50OiBob3Jpem9udGFsT2Zmc2V0QWRqdXN0bWVudCxcbiAgICAgICAgICBpc1Njcm9sbGluZzogaXNTY3JvbGxpbmcsXG4gICAgICAgICAgcm93U2l6ZUFuZFBvc2l0aW9uTWFuYWdlcjogdGhpcy5fcm93U2l6ZUFuZFBvc2l0aW9uTWFuYWdlcixcbiAgICAgICAgICByb3dTdGFydEluZGV4OiB0aGlzLl9yb3dTdGFydEluZGV4LFxuICAgICAgICAgIHJvd1N0b3BJbmRleDogdGhpcy5fcm93U3RvcEluZGV4LFxuICAgICAgICAgIHNjcm9sbExlZnQ6IHNjcm9sbExlZnQsXG4gICAgICAgICAgc2Nyb2xsVG9wOiBzY3JvbGxUb3AsXG4gICAgICAgICAgdmVydGljYWxPZmZzZXRBZGp1c3RtZW50OiB2ZXJ0aWNhbE9mZnNldEFkanVzdG1lbnRcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyBhbiA6aXNTY3JvbGxpbmcgZmxhZyBmb3IgYSBzbWFsbCB3aW5kb3cgb2YgdGltZS5cbiAgICAgKiBUaGlzIGZsYWcgaXMgdXNlZCB0byBkaXNhYmxlIHBvaW50ZXIgZXZlbnRzIG9uIHRoZSBzY3JvbGxhYmxlIHBvcnRpb24gb2YgdGhlIEdyaWQuXG4gICAgICogVGhpcyBwcmV2ZW50cyBqZXJreS9zdHV0dGVyeSBtb3VzZS13aGVlbCBzY3JvbGxpbmcuXG4gICAgICovXG5cbiAgfSwge1xuICAgIGtleTogJ19lbmFibGVQb2ludGVyRXZlbnRzQWZ0ZXJEZWxheScsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9lbmFibGVQb2ludGVyRXZlbnRzQWZ0ZXJEZWxheSgpIHtcbiAgICAgIHZhciBzY3JvbGxpbmdSZXNldFRpbWVJbnRlcnZhbCA9IHRoaXMucHJvcHMuc2Nyb2xsaW5nUmVzZXRUaW1lSW50ZXJ2YWw7XG5cblxuICAgICAgaWYgKHRoaXMuX2Rpc2FibGVQb2ludGVyRXZlbnRzVGltZW91dElkKSB7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aGlzLl9kaXNhYmxlUG9pbnRlckV2ZW50c1RpbWVvdXRJZCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX2Rpc2FibGVQb2ludGVyRXZlbnRzVGltZW91dElkID0gc2V0VGltZW91dCh0aGlzLl9lbmFibGVQb2ludGVyRXZlbnRzQWZ0ZXJEZWxheUNhbGxiYWNrLCBzY3JvbGxpbmdSZXNldFRpbWVJbnRlcnZhbCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX2VuYWJsZVBvaW50ZXJFdmVudHNBZnRlckRlbGF5Q2FsbGJhY2snLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBfZW5hYmxlUG9pbnRlckV2ZW50c0FmdGVyRGVsYXlDYWxsYmFjaygpIHtcbiAgICAgIHRoaXMuX2Rpc2FibGVQb2ludGVyRXZlbnRzVGltZW91dElkID0gbnVsbDtcblxuICAgICAgLy8gVGhyb3cgYXdheSBjZWxsIGNhY2hlIG9uY2Ugc2Nyb2xsaW5nIGlzIGNvbXBsZXRlXG4gICAgICB0aGlzLl9jZWxsQ2FjaGUgPSB7fTtcblxuICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgIGlzU2Nyb2xsaW5nOiBmYWxzZSxcbiAgICAgICAgc2Nyb2xsRGlyZWN0aW9uSG9yaXpvbnRhbDogX2dldE92ZXJzY2FuSW5kaWNlcy5TQ1JPTExfRElSRUNUSU9OX0ZJWEVELFxuICAgICAgICBzY3JvbGxEaXJlY3Rpb25WZXJ0aWNhbDogX2dldE92ZXJzY2FuSW5kaWNlcy5TQ1JPTExfRElSRUNUSU9OX0ZJWEVEXG4gICAgICB9KTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfZ2V0RXN0aW1hdGVkQ29sdW1uU2l6ZScsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9nZXRFc3RpbWF0ZWRDb2x1bW5TaXplKHByb3BzKSB7XG4gICAgICByZXR1cm4gdHlwZW9mIHByb3BzLmNvbHVtbldpZHRoID09PSAnbnVtYmVyJyA/IHByb3BzLmNvbHVtbldpZHRoIDogcHJvcHMuZXN0aW1hdGVkQ29sdW1uU2l6ZTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfZ2V0RXN0aW1hdGVkUm93U2l6ZScsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9nZXRFc3RpbWF0ZWRSb3dTaXplKHByb3BzKSB7XG4gICAgICByZXR1cm4gdHlwZW9mIHByb3BzLnJvd0hlaWdodCA9PT0gJ251bWJlcicgPyBwcm9wcy5yb3dIZWlnaHQgOiBwcm9wcy5lc3RpbWF0ZWRSb3dTaXplO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19pbnZva2VPbkdyaWRSZW5kZXJlZEhlbHBlcicsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9pbnZva2VPbkdyaWRSZW5kZXJlZEhlbHBlcigpIHtcbiAgICAgIHZhciBvblNlY3Rpb25SZW5kZXJlZCA9IHRoaXMucHJvcHMub25TZWN0aW9uUmVuZGVyZWQ7XG5cblxuICAgICAgdGhpcy5fb25HcmlkUmVuZGVyZWRNZW1vaXplcih7XG4gICAgICAgIGNhbGxiYWNrOiBvblNlY3Rpb25SZW5kZXJlZCxcbiAgICAgICAgaW5kaWNlczoge1xuICAgICAgICAgIGNvbHVtbk92ZXJzY2FuU3RhcnRJbmRleDogdGhpcy5fY29sdW1uU3RhcnRJbmRleCxcbiAgICAgICAgICBjb2x1bW5PdmVyc2NhblN0b3BJbmRleDogdGhpcy5fY29sdW1uU3RvcEluZGV4LFxuICAgICAgICAgIGNvbHVtblN0YXJ0SW5kZXg6IHRoaXMuX3JlbmRlcmVkQ29sdW1uU3RhcnRJbmRleCxcbiAgICAgICAgICBjb2x1bW5TdG9wSW5kZXg6IHRoaXMuX3JlbmRlcmVkQ29sdW1uU3RvcEluZGV4LFxuICAgICAgICAgIHJvd092ZXJzY2FuU3RhcnRJbmRleDogdGhpcy5fcm93U3RhcnRJbmRleCxcbiAgICAgICAgICByb3dPdmVyc2NhblN0b3BJbmRleDogdGhpcy5fcm93U3RvcEluZGV4LFxuICAgICAgICAgIHJvd1N0YXJ0SW5kZXg6IHRoaXMuX3JlbmRlcmVkUm93U3RhcnRJbmRleCxcbiAgICAgICAgICByb3dTdG9wSW5kZXg6IHRoaXMuX3JlbmRlcmVkUm93U3RvcEluZGV4XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19pbnZva2VPblNjcm9sbE1lbW9pemVyJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gX2ludm9rZU9uU2Nyb2xsTWVtb2l6ZXIoX3JlZjMpIHtcbiAgICAgIHZhciBfdGhpczUgPSB0aGlzO1xuXG4gICAgICB2YXIgc2Nyb2xsTGVmdCA9IF9yZWYzLnNjcm9sbExlZnQ7XG4gICAgICB2YXIgc2Nyb2xsVG9wID0gX3JlZjMuc2Nyb2xsVG9wO1xuICAgICAgdmFyIHRvdGFsQ29sdW1uc1dpZHRoID0gX3JlZjMudG90YWxDb2x1bW5zV2lkdGg7XG4gICAgICB2YXIgdG90YWxSb3dzSGVpZ2h0ID0gX3JlZjMudG90YWxSb3dzSGVpZ2h0O1xuXG4gICAgICB0aGlzLl9vblNjcm9sbE1lbW9pemVyKHtcbiAgICAgICAgY2FsbGJhY2s6IGZ1bmN0aW9uIGNhbGxiYWNrKF9yZWY0KSB7XG4gICAgICAgICAgdmFyIHNjcm9sbExlZnQgPSBfcmVmNC5zY3JvbGxMZWZ0O1xuICAgICAgICAgIHZhciBzY3JvbGxUb3AgPSBfcmVmNC5zY3JvbGxUb3A7XG4gICAgICAgICAgdmFyIF9wcm9wczUgPSBfdGhpczUucHJvcHM7XG4gICAgICAgICAgdmFyIGhlaWdodCA9IF9wcm9wczUuaGVpZ2h0O1xuICAgICAgICAgIHZhciBvblNjcm9sbCA9IF9wcm9wczUub25TY3JvbGw7XG4gICAgICAgICAgdmFyIHdpZHRoID0gX3Byb3BzNS53aWR0aDtcblxuXG4gICAgICAgICAgb25TY3JvbGwoe1xuICAgICAgICAgICAgY2xpZW50SGVpZ2h0OiBoZWlnaHQsXG4gICAgICAgICAgICBjbGllbnRXaWR0aDogd2lkdGgsXG4gICAgICAgICAgICBzY3JvbGxIZWlnaHQ6IHRvdGFsUm93c0hlaWdodCxcbiAgICAgICAgICAgIHNjcm9sbExlZnQ6IHNjcm9sbExlZnQsXG4gICAgICAgICAgICBzY3JvbGxUb3A6IHNjcm9sbFRvcCxcbiAgICAgICAgICAgIHNjcm9sbFdpZHRoOiB0b3RhbENvbHVtbnNXaWR0aFxuICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBpbmRpY2VzOiB7XG4gICAgICAgICAgc2Nyb2xsTGVmdDogc2Nyb2xsTGVmdCxcbiAgICAgICAgICBzY3JvbGxUb3A6IHNjcm9sbFRvcFxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGVzIHRoZSBzdGF0ZSBkdXJpbmcgdGhlIG5leHQgYW5pbWF0aW9uIGZyYW1lLlxuICAgICAqIFVzZSB0aGlzIG1ldGhvZCB0byBhdm9pZCBtdWx0aXBsZSByZW5kZXJzIGluIGEgc21hbGwgc3BhbiBvZiB0aW1lLlxuICAgICAqIFRoaXMgaGVscHMgcGVyZm9ybWFuY2UgZm9yIGJ1cnN0eSBldmVudHMgKGxpa2Ugb25TY3JvbGwpLlxuICAgICAqL1xuXG4gIH0sIHtcbiAgICBrZXk6ICdfc2V0TmV4dFN0YXRlJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gX3NldE5leHRTdGF0ZShzdGF0ZSkge1xuICAgICAgdGhpcy5fbmV4dFN0YXRlID0gc3RhdGU7XG5cbiAgICAgIGlmICghdGhpcy5fc2V0TmV4dFN0YXRlQW5pbWF0aW9uRnJhbWVJZCkge1xuICAgICAgICB0aGlzLl9zZXROZXh0U3RhdGVBbmltYXRpb25GcmFtZUlkID0gKDAsIF9yYWYyLmRlZmF1bHQpKHRoaXMuX3NldE5leHRTdGF0ZUNhbGxiYWNrKTtcbiAgICAgIH1cbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfc2V0TmV4dFN0YXRlQ2FsbGJhY2snLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBfc2V0TmV4dFN0YXRlQ2FsbGJhY2soKSB7XG4gICAgICB2YXIgc3RhdGUgPSB0aGlzLl9uZXh0U3RhdGU7XG5cbiAgICAgIHRoaXMuX3NldE5leHRTdGF0ZUFuaW1hdGlvbkZyYW1lSWQgPSBudWxsO1xuICAgICAgdGhpcy5fbmV4dFN0YXRlID0gbnVsbDtcblxuICAgICAgdGhpcy5zZXRTdGF0ZShzdGF0ZSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX3NldFNjcm9sbFBvc2l0aW9uJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gX3NldFNjcm9sbFBvc2l0aW9uKF9yZWY1KSB7XG4gICAgICB2YXIgc2Nyb2xsTGVmdCA9IF9yZWY1LnNjcm9sbExlZnQ7XG4gICAgICB2YXIgc2Nyb2xsVG9wID0gX3JlZjUuc2Nyb2xsVG9wO1xuXG4gICAgICB2YXIgbmV3U3RhdGUgPSB7XG4gICAgICAgIHNjcm9sbFBvc2l0aW9uQ2hhbmdlUmVhc29uOiBTQ1JPTExfUE9TSVRJT05fQ0hBTkdFX1JFQVNPTlMuUkVRVUVTVEVEXG4gICAgICB9O1xuXG4gICAgICBpZiAoc2Nyb2xsTGVmdCA+PSAwKSB7XG4gICAgICAgIG5ld1N0YXRlLnNjcm9sbExlZnQgPSBzY3JvbGxMZWZ0O1xuICAgICAgfVxuXG4gICAgICBpZiAoc2Nyb2xsVG9wID49IDApIHtcbiAgICAgICAgbmV3U3RhdGUuc2Nyb2xsVG9wID0gc2Nyb2xsVG9wO1xuICAgICAgfVxuXG4gICAgICBpZiAoc2Nyb2xsTGVmdCA+PSAwICYmIHNjcm9sbExlZnQgIT09IHRoaXMuc3RhdGUuc2Nyb2xsTGVmdCB8fCBzY3JvbGxUb3AgPj0gMCAmJiBzY3JvbGxUb3AgIT09IHRoaXMuc3RhdGUuc2Nyb2xsVG9wKSB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUobmV3U3RhdGUpO1xuICAgICAgfVxuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ193cmFwQ2VsbENsYXNzTmFtZUdldHRlcicsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF93cmFwQ2VsbENsYXNzTmFtZUdldHRlcihjbGFzc05hbWUpIHtcbiAgICAgIHJldHVybiB0aGlzLl93cmFwUHJvcGVydHlHZXR0ZXIoY2xhc3NOYW1lKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfd3JhcENlbGxTdHlsZUdldHRlcicsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF93cmFwQ2VsbFN0eWxlR2V0dGVyKHN0eWxlKSB7XG4gICAgICByZXR1cm4gdGhpcy5fd3JhcFByb3BlcnR5R2V0dGVyKHN0eWxlKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfd3JhcFByb3BlcnR5R2V0dGVyJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gX3dyYXBQcm9wZXJ0eUdldHRlcih2YWx1ZSkge1xuICAgICAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgRnVuY3Rpb24gPyB2YWx1ZSA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgfTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfd3JhcFNpemVHZXR0ZXInLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBfd3JhcFNpemVHZXR0ZXIoc2l6ZSkge1xuICAgICAgcmV0dXJuIHRoaXMuX3dyYXBQcm9wZXJ0eUdldHRlcihzaXplKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfdXBkYXRlU2Nyb2xsTGVmdEZvclNjcm9sbFRvQ29sdW1uJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gX3VwZGF0ZVNjcm9sbExlZnRGb3JTY3JvbGxUb0NvbHVtbigpIHtcbiAgICAgIHZhciBwcm9wcyA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMCB8fCBhcmd1bWVudHNbMF0gPT09IHVuZGVmaW5lZCA/IHRoaXMucHJvcHMgOiBhcmd1bWVudHNbMF07XG4gICAgICB2YXIgc3RhdGUgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDEgfHwgYXJndW1lbnRzWzFdID09PSB1bmRlZmluZWQgPyB0aGlzLnN0YXRlIDogYXJndW1lbnRzWzFdO1xuICAgICAgdmFyIGNvbHVtbkNvdW50ID0gcHJvcHMuY29sdW1uQ291bnQ7XG4gICAgICB2YXIgc2Nyb2xsVG9BbGlnbm1lbnQgPSBwcm9wcy5zY3JvbGxUb0FsaWdubWVudDtcbiAgICAgIHZhciBzY3JvbGxUb0NvbHVtbiA9IHByb3BzLnNjcm9sbFRvQ29sdW1uO1xuICAgICAgdmFyIHdpZHRoID0gcHJvcHMud2lkdGg7XG4gICAgICB2YXIgc2Nyb2xsTGVmdCA9IHN0YXRlLnNjcm9sbExlZnQ7XG5cblxuICAgICAgaWYgKHNjcm9sbFRvQ29sdW1uID49IDAgJiYgY29sdW1uQ291bnQgPiAwKSB7XG4gICAgICAgIHZhciB0YXJnZXRJbmRleCA9IE1hdGgubWF4KDAsIE1hdGgubWluKGNvbHVtbkNvdW50IC0gMSwgc2Nyb2xsVG9Db2x1bW4pKTtcblxuICAgICAgICB2YXIgY2FsY3VsYXRlZFNjcm9sbExlZnQgPSB0aGlzLl9jb2x1bW5TaXplQW5kUG9zaXRpb25NYW5hZ2VyLmdldFVwZGF0ZWRPZmZzZXRGb3JJbmRleCh7XG4gICAgICAgICAgYWxpZ246IHNjcm9sbFRvQWxpZ25tZW50LFxuICAgICAgICAgIGNvbnRhaW5lclNpemU6IHdpZHRoLFxuICAgICAgICAgIGN1cnJlbnRPZmZzZXQ6IHNjcm9sbExlZnQsXG4gICAgICAgICAgdGFyZ2V0SW5kZXg6IHRhcmdldEluZGV4XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChzY3JvbGxMZWZ0ICE9PSBjYWxjdWxhdGVkU2Nyb2xsTGVmdCkge1xuICAgICAgICAgIHRoaXMuX3NldFNjcm9sbFBvc2l0aW9uKHtcbiAgICAgICAgICAgIHNjcm9sbExlZnQ6IGNhbGN1bGF0ZWRTY3JvbGxMZWZ0XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfdXBkYXRlU2Nyb2xsVG9wRm9yU2Nyb2xsVG9Sb3cnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBfdXBkYXRlU2Nyb2xsVG9wRm9yU2Nyb2xsVG9Sb3coKSB7XG4gICAgICB2YXIgcHJvcHMgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDAgfHwgYXJndW1lbnRzWzBdID09PSB1bmRlZmluZWQgPyB0aGlzLnByb3BzIDogYXJndW1lbnRzWzBdO1xuICAgICAgdmFyIHN0YXRlID0gYXJndW1lbnRzLmxlbmd0aCA8PSAxIHx8IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gdGhpcy5zdGF0ZSA6IGFyZ3VtZW50c1sxXTtcbiAgICAgIHZhciBoZWlnaHQgPSBwcm9wcy5oZWlnaHQ7XG4gICAgICB2YXIgcm93Q291bnQgPSBwcm9wcy5yb3dDb3VudDtcbiAgICAgIHZhciBzY3JvbGxUb0FsaWdubWVudCA9IHByb3BzLnNjcm9sbFRvQWxpZ25tZW50O1xuICAgICAgdmFyIHNjcm9sbFRvUm93ID0gcHJvcHMuc2Nyb2xsVG9Sb3c7XG4gICAgICB2YXIgc2Nyb2xsVG9wID0gc3RhdGUuc2Nyb2xsVG9wO1xuXG5cbiAgICAgIGlmIChzY3JvbGxUb1JvdyA+PSAwICYmIHJvd0NvdW50ID4gMCkge1xuICAgICAgICB2YXIgdGFyZ2V0SW5kZXggPSBNYXRoLm1heCgwLCBNYXRoLm1pbihyb3dDb3VudCAtIDEsIHNjcm9sbFRvUm93KSk7XG5cbiAgICAgICAgdmFyIGNhbGN1bGF0ZWRTY3JvbGxUb3AgPSB0aGlzLl9yb3dTaXplQW5kUG9zaXRpb25NYW5hZ2VyLmdldFVwZGF0ZWRPZmZzZXRGb3JJbmRleCh7XG4gICAgICAgICAgYWxpZ246IHNjcm9sbFRvQWxpZ25tZW50LFxuICAgICAgICAgIGNvbnRhaW5lclNpemU6IGhlaWdodCxcbiAgICAgICAgICBjdXJyZW50T2Zmc2V0OiBzY3JvbGxUb3AsXG4gICAgICAgICAgdGFyZ2V0SW5kZXg6IHRhcmdldEluZGV4XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChzY3JvbGxUb3AgIT09IGNhbGN1bGF0ZWRTY3JvbGxUb3ApIHtcbiAgICAgICAgICB0aGlzLl9zZXRTY3JvbGxQb3NpdGlvbih7XG4gICAgICAgICAgICBzY3JvbGxUb3A6IGNhbGN1bGF0ZWRTY3JvbGxUb3BcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vblNjcm9sbCcsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vblNjcm9sbChldmVudCkge1xuICAgICAgLy8gSW4gY2VydGFpbiBlZGdlLWNhc2VzIFJlYWN0IGRpc3BhdGNoZXMgYW4gb25TY3JvbGwgZXZlbnQgd2l0aCBhbiBpbnZhbGlkIHRhcmdldC5zY3JvbGxMZWZ0IC8gdGFyZ2V0LnNjcm9sbFRvcC5cbiAgICAgIC8vIFRoaXMgaW52YWxpZCBldmVudCBjYW4gYmUgZGV0ZWN0ZWQgYnkgY29tcGFyaW5nIGV2ZW50LnRhcmdldCB0byB0aGlzIGNvbXBvbmVudCdzIHNjcm9sbGFibGUgRE9NIGVsZW1lbnQuXG4gICAgICAvLyBTZWUgaXNzdWUgIzQwNCBmb3IgbW9yZSBpbmZvcm1hdGlvbi5cbiAgICAgIGlmIChldmVudC50YXJnZXQgIT09IHRoaXMuX3Njcm9sbGluZ0NvbnRhaW5lcikge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIC8vIFByZXZlbnQgcG9pbnRlciBldmVudHMgZnJvbSBpbnRlcnJ1cHRpbmcgYSBzbW9vdGggc2Nyb2xsXG4gICAgICB0aGlzLl9lbmFibGVQb2ludGVyRXZlbnRzQWZ0ZXJEZWxheSgpO1xuXG4gICAgICAvLyBXaGVuIHRoaXMgY29tcG9uZW50IGlzIHNocnVuayBkcmFzdGljYWxseSwgUmVhY3QgZGlzcGF0Y2hlcyBhIHNlcmllcyBvZiBiYWNrLXRvLWJhY2sgc2Nyb2xsIGV2ZW50cyxcbiAgICAgIC8vIEdyYWR1YWxseSBjb252ZXJnaW5nIG9uIGEgc2Nyb2xsVG9wIHRoYXQgaXMgd2l0aGluIHRoZSBib3VuZHMgb2YgdGhlIG5ldywgc21hbGxlciBoZWlnaHQuXG4gICAgICAvLyBUaGlzIGNhdXNlcyBhIHNlcmllcyBvZiByYXBpZCByZW5kZXJzIHRoYXQgaXMgc2xvdyBmb3IgbG9uZyBsaXN0cy5cbiAgICAgIC8vIFdlIGNhbiBhdm9pZCB0aGF0IGJ5IGRvaW5nIHNvbWUgc2ltcGxlIGJvdW5kcyBjaGVja2luZyB0byBlbnN1cmUgdGhhdCBzY3JvbGxUb3AgbmV2ZXIgZXhjZWVkcyB0aGUgdG90YWwgaGVpZ2h0LlxuICAgICAgdmFyIF9wcm9wczYgPSB0aGlzLnByb3BzO1xuICAgICAgdmFyIGhlaWdodCA9IF9wcm9wczYuaGVpZ2h0O1xuICAgICAgdmFyIHdpZHRoID0gX3Byb3BzNi53aWR0aDtcblxuICAgICAgdmFyIHNjcm9sbGJhclNpemUgPSB0aGlzLl9zY3JvbGxiYXJTaXplO1xuICAgICAgdmFyIHRvdGFsUm93c0hlaWdodCA9IHRoaXMuX3Jvd1NpemVBbmRQb3NpdGlvbk1hbmFnZXIuZ2V0VG90YWxTaXplKCk7XG4gICAgICB2YXIgdG90YWxDb2x1bW5zV2lkdGggPSB0aGlzLl9jb2x1bW5TaXplQW5kUG9zaXRpb25NYW5hZ2VyLmdldFRvdGFsU2l6ZSgpO1xuICAgICAgdmFyIHNjcm9sbExlZnQgPSBNYXRoLm1pbihNYXRoLm1heCgwLCB0b3RhbENvbHVtbnNXaWR0aCAtIHdpZHRoICsgc2Nyb2xsYmFyU2l6ZSksIGV2ZW50LnRhcmdldC5zY3JvbGxMZWZ0KTtcbiAgICAgIHZhciBzY3JvbGxUb3AgPSBNYXRoLm1pbihNYXRoLm1heCgwLCB0b3RhbFJvd3NIZWlnaHQgLSBoZWlnaHQgKyBzY3JvbGxiYXJTaXplKSwgZXZlbnQudGFyZ2V0LnNjcm9sbFRvcCk7XG5cbiAgICAgIC8vIENlcnRhaW4gZGV2aWNlcyAobGlrZSBBcHBsZSB0b3VjaHBhZCkgcmFwaWQtZmlyZSBkdXBsaWNhdGUgZXZlbnRzLlxuICAgICAgLy8gRG9uJ3QgZm9yY2UgYSByZS1yZW5kZXIgaWYgdGhpcyBpcyB0aGUgY2FzZS5cbiAgICAgIC8vIFRoZSBtb3VzZSBtYXkgbW92ZSBmYXN0ZXIgdGhlbiB0aGUgYW5pbWF0aW9uIGZyYW1lIGRvZXMuXG4gICAgICAvLyBVc2UgcmVxdWVzdEFuaW1hdGlvbkZyYW1lIHRvIGF2b2lkIG92ZXItdXBkYXRpbmcuXG4gICAgICBpZiAodGhpcy5zdGF0ZS5zY3JvbGxMZWZ0ICE9PSBzY3JvbGxMZWZ0IHx8IHRoaXMuc3RhdGUuc2Nyb2xsVG9wICE9PSBzY3JvbGxUb3ApIHtcbiAgICAgICAgLy8gQnJvd3NlcnMgd2l0aCBjYW5jZWxhYmxlIHNjcm9sbCBldmVudHMgKGVnLiBGaXJlZm94KSBpbnRlcnJ1cHQgc2Nyb2xsaW5nIGFuaW1hdGlvbnMgaWYgc2Nyb2xsVG9wL3Njcm9sbExlZnQgaXMgc2V0LlxuICAgICAgICAvLyBPdGhlciBicm93c2VycyAoZWcuIFNhZmFyaSkgZG9uJ3Qgc2Nyb2xsIGFzIHdlbGwgd2l0aG91dCB0aGUgaGVscCB1bmRlciBjZXJ0YWluIGNvbmRpdGlvbnMgKERPTSBvciBzdHlsZSBjaGFuZ2VzIGR1cmluZyBzY3JvbGxpbmcpLlxuICAgICAgICAvLyBBbGwgdGhpbmdzIGNvbnNpZGVyZWQsIHRoaXMgc2VlbXMgdG8gYmUgdGhlIGJlc3QgY3VycmVudCB3b3JrIGFyb3VuZCB0aGF0IEknbSBhd2FyZSBvZi5cbiAgICAgICAgLy8gRm9yIG1vcmUgaW5mb3JtYXRpb24gc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9idmF1Z2huL3JlYWN0LXZpcnR1YWxpemVkL3B1bGwvMTI0XG4gICAgICAgIHZhciBzY3JvbGxQb3NpdGlvbkNoYW5nZVJlYXNvbiA9IGV2ZW50LmNhbmNlbGFibGUgPyBTQ1JPTExfUE9TSVRJT05fQ0hBTkdFX1JFQVNPTlMuT0JTRVJWRUQgOiBTQ1JPTExfUE9TSVRJT05fQ0hBTkdFX1JFQVNPTlMuUkVRVUVTVEVEO1xuXG4gICAgICAgIC8vIFRyYWNrIHNjcm9sbGluZyBkaXJlY3Rpb24gc28gd2UgY2FuIG1vcmUgZWZmaWNpZW50bHkgb3ZlcnNjYW4gcm93cyB0byByZWR1Y2UgZW1wdHkgc3BhY2UgYXJvdW5kIHRoZSBlZGdlcyB3aGlsZSBzY3JvbGxpbmcuXG4gICAgICAgIHZhciBzY3JvbGxEaXJlY3Rpb25WZXJ0aWNhbCA9IHNjcm9sbFRvcCA+IHRoaXMuc3RhdGUuc2Nyb2xsVG9wID8gX2dldE92ZXJzY2FuSW5kaWNlcy5TQ1JPTExfRElSRUNUSU9OX0ZPUldBUkQgOiBfZ2V0T3ZlcnNjYW5JbmRpY2VzLlNDUk9MTF9ESVJFQ1RJT05fQkFDS1dBUkQ7XG4gICAgICAgIHZhciBzY3JvbGxEaXJlY3Rpb25Ib3Jpem9udGFsID0gc2Nyb2xsTGVmdCA+IHRoaXMuc3RhdGUuc2Nyb2xsTGVmdCA/IF9nZXRPdmVyc2NhbkluZGljZXMuU0NST0xMX0RJUkVDVElPTl9GT1JXQVJEIDogX2dldE92ZXJzY2FuSW5kaWNlcy5TQ1JPTExfRElSRUNUSU9OX0JBQ0tXQVJEO1xuXG4gICAgICAgIGlmICghdGhpcy5zdGF0ZS5pc1Njcm9sbGluZykge1xuICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgaXNTY3JvbGxpbmc6IHRydWVcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX3NldE5leHRTdGF0ZSh7XG4gICAgICAgICAgaXNTY3JvbGxpbmc6IHRydWUsXG4gICAgICAgICAgc2Nyb2xsRGlyZWN0aW9uSG9yaXpvbnRhbDogc2Nyb2xsRGlyZWN0aW9uSG9yaXpvbnRhbCxcbiAgICAgICAgICBzY3JvbGxEaXJlY3Rpb25WZXJ0aWNhbDogc2Nyb2xsRGlyZWN0aW9uVmVydGljYWwsXG4gICAgICAgICAgc2Nyb2xsTGVmdDogc2Nyb2xsTGVmdCxcbiAgICAgICAgICBzY3JvbGxQb3NpdGlvbkNoYW5nZVJlYXNvbjogc2Nyb2xsUG9zaXRpb25DaGFuZ2VSZWFzb24sXG4gICAgICAgICAgc2Nyb2xsVG9wOiBzY3JvbGxUb3BcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX2ludm9rZU9uU2Nyb2xsTWVtb2l6ZXIoeyBzY3JvbGxMZWZ0OiBzY3JvbGxMZWZ0LCBzY3JvbGxUb3A6IHNjcm9sbFRvcCwgdG90YWxDb2x1bW5zV2lkdGg6IHRvdGFsQ29sdW1uc1dpZHRoLCB0b3RhbFJvd3NIZWlnaHQ6IHRvdGFsUm93c0hlaWdodCB9KTtcbiAgICB9XG4gIH1dKTtcblxuICByZXR1cm4gR3JpZDtcbn0oX3JlYWN0LkNvbXBvbmVudCk7XG5cbkdyaWQucHJvcFR5cGVzID0ge1xuICAnYXJpYS1sYWJlbCc6IF9yZWFjdC5Qcm9wVHlwZXMuc3RyaW5nLFxuXG4gIC8qKlxuICAgKiBTZXQgdGhlIHdpZHRoIG9mIHRoZSBpbm5lciBzY3JvbGxhYmxlIGNvbnRhaW5lciB0byAnYXV0bycuXG4gICAqIFRoaXMgaXMgdXNlZnVsIGZvciBzaW5nbGUtY29sdW1uIEdyaWRzIHRvIGVuc3VyZSB0aGF0IHRoZSBjb2x1bW4gZG9lc24ndCBleHRlbmQgYmVsb3cgYSB2ZXJ0aWNhbCBzY3JvbGxiYXIuXG4gICAqL1xuICBhdXRvQ29udGFpbmVyV2lkdGg6IF9yZWFjdC5Qcm9wVHlwZXMuYm9vbCxcblxuICAvKipcbiAgICogUmVtb3ZlcyBmaXhlZCBoZWlnaHQgZnJvbSB0aGUgc2Nyb2xsaW5nQ29udGFpbmVyIHNvIHRoYXQgdGhlIHRvdGFsIGhlaWdodFxuICAgKiBvZiByb3dzIGNhbiBzdHJldGNoIHRoZSB3aW5kb3cuIEludGVuZGVkIGZvciB1c2Ugd2l0aCBXaW5kb3dTY3JvbGxlclxuICAgKi9cbiAgYXV0b0hlaWdodDogX3JlYWN0LlByb3BUeXBlcy5ib29sLFxuXG4gIC8qKiBPcHRpb25hbCBjdXN0b20gQ1NTIGNsYXNzIGZvciBpbmRpdmlkdWFsIGNlbGxzICovXG4gIGNlbGxDbGFzc05hbWU6IF9yZWFjdC5Qcm9wVHlwZXMub25lT2ZUeXBlKFtfcmVhY3QuUHJvcFR5cGVzLnN0cmluZywgX3JlYWN0LlByb3BUeXBlcy5mdW5jXSksXG5cbiAgLyoqIE9wdGlvbmFsIGN1c3RvbSBzdHlsZXMgZm9yIGluZGl2aWR1YWwgY2VsbHMgKi9cbiAgY2VsbFN0eWxlOiBfcmVhY3QuUHJvcFR5cGVzLm9uZU9mVHlwZShbX3JlYWN0LlByb3BUeXBlcy5vYmplY3QsIF9yZWFjdC5Qcm9wVHlwZXMuZnVuY10pLFxuXG4gIC8qKlxuICAgKiBSZXNwb25zaWJsZSBmb3IgcmVuZGVyaW5nIGEgY2VsbCBnaXZlbiBhbiByb3cgYW5kIGNvbHVtbiBpbmRleC5cbiAgICogU2hvdWxkIGltcGxlbWVudCB0aGUgZm9sbG93aW5nIGludGVyZmFjZTogKHsgY29sdW1uSW5kZXg6IG51bWJlciwgcm93SW5kZXg6IG51bWJlciB9KTogUHJvcFR5cGVzLm5vZGVcbiAgICovXG4gIGNlbGxSZW5kZXJlcjogX3JlYWN0LlByb3BUeXBlcy5mdW5jLmlzUmVxdWlyZWQsXG5cbiAgLyoqXG4gICAqIFJlc3BvbnNpYmxlIGZvciByZW5kZXJpbmcgYSBncm91cCBvZiBjZWxscyBnaXZlbiB0aGVpciBpbmRleCByYW5nZXMuXG4gICAqIFNob3VsZCBpbXBsZW1lbnQgdGhlIGZvbGxvd2luZyBpbnRlcmZhY2U6ICh7XG4gICAqICAgY2VsbENhY2hlOiBNYXAsXG4gICAqICAgY2VsbFJlbmRlcmVyOiBGdW5jdGlvbixcbiAgICogICBjb2x1bW5TaXplQW5kUG9zaXRpb25NYW5hZ2VyOiBDZWxsU2l6ZUFuZFBvc2l0aW9uTWFuYWdlcixcbiAgICogICBjb2x1bW5TdGFydEluZGV4OiBudW1iZXIsXG4gICAqICAgY29sdW1uU3RvcEluZGV4OiBudW1iZXIsXG4gICAqICAgaXNTY3JvbGxpbmc6IGJvb2xlYW4sXG4gICAqICAgcm93U2l6ZUFuZFBvc2l0aW9uTWFuYWdlcjogQ2VsbFNpemVBbmRQb3NpdGlvbk1hbmFnZXIsXG4gICAqICAgcm93U3RhcnRJbmRleDogbnVtYmVyLFxuICAgKiAgIHJvd1N0b3BJbmRleDogbnVtYmVyLFxuICAgKiAgIHNjcm9sbExlZnQ6IG51bWJlcixcbiAgICogICBzY3JvbGxUb3A6IG51bWJlclxuICAgKiB9KTogQXJyYXk8UHJvcFR5cGVzLm5vZGU+XG4gICAqL1xuICBjZWxsUmFuZ2VSZW5kZXJlcjogX3JlYWN0LlByb3BUeXBlcy5mdW5jLmlzUmVxdWlyZWQsXG5cbiAgLyoqXG4gICAqIE9wdGlvbmFsIGN1c3RvbSBDU1MgY2xhc3MgbmFtZSB0byBhdHRhY2ggdG8gcm9vdCBHcmlkIGVsZW1lbnQuXG4gICAqL1xuICBjbGFzc05hbWU6IF9yZWFjdC5Qcm9wVHlwZXMuc3RyaW5nLFxuXG4gIC8qKlxuICAgKiBOdW1iZXIgb2YgY29sdW1ucyBpbiBncmlkLlxuICAgKi9cbiAgY29sdW1uQ291bnQ6IF9yZWFjdC5Qcm9wVHlwZXMubnVtYmVyLmlzUmVxdWlyZWQsXG5cbiAgLyoqXG4gICAqIEVpdGhlciBhIGZpeGVkIGNvbHVtbiB3aWR0aCAobnVtYmVyKSBvciBhIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyB0aGUgd2lkdGggb2YgYSBjb2x1bW4gZ2l2ZW4gaXRzIGluZGV4LlxuICAgKiBTaG91bGQgaW1wbGVtZW50IHRoZSBmb2xsb3dpbmcgaW50ZXJmYWNlOiAoaW5kZXg6IG51bWJlcik6IG51bWJlclxuICAgKi9cbiAgY29sdW1uV2lkdGg6IF9yZWFjdC5Qcm9wVHlwZXMub25lT2ZUeXBlKFtfcmVhY3QuUHJvcFR5cGVzLm51bWJlciwgX3JlYWN0LlByb3BUeXBlcy5mdW5jXSkuaXNSZXF1aXJlZCxcblxuICAvKipcbiAgICogVXNlZCB0byBlc3RpbWF0ZSB0aGUgdG90YWwgd2lkdGggb2YgYSBHcmlkIGJlZm9yZSBhbGwgb2YgaXRzIGNvbHVtbnMgaGF2ZSBhY3R1YWxseSBiZWVuIG1lYXN1cmVkLlxuICAgKiBUaGUgZXN0aW1hdGVkIHRvdGFsIHdpZHRoIGlzIGFkanVzdGVkIGFzIGNvbHVtbnMgYXJlIHJlbmRlcmVkLlxuICAgKi9cbiAgZXN0aW1hdGVkQ29sdW1uU2l6ZTogX3JlYWN0LlByb3BUeXBlcy5udW1iZXIuaXNSZXF1aXJlZCxcblxuICAvKipcbiAgICogVXNlZCB0byBlc3RpbWF0ZSB0aGUgdG90YWwgaGVpZ2h0IG9mIGEgR3JpZCBiZWZvcmUgYWxsIG9mIGl0cyByb3dzIGhhdmUgYWN0dWFsbHkgYmVlbiBtZWFzdXJlZC5cbiAgICogVGhlIGVzdGltYXRlZCB0b3RhbCBoZWlnaHQgaXMgYWRqdXN0ZWQgYXMgcm93cyBhcmUgcmVuZGVyZWQuXG4gICAqL1xuICBlc3RpbWF0ZWRSb3dTaXplOiBfcmVhY3QuUHJvcFR5cGVzLm51bWJlci5pc1JlcXVpcmVkLFxuXG4gIC8qKlxuICAgKiBIZWlnaHQgb2YgR3JpZDsgdGhpcyBwcm9wZXJ0eSBkZXRlcm1pbmVzIHRoZSBudW1iZXIgb2YgdmlzaWJsZSAodnMgdmlydHVhbGl6ZWQpIHJvd3MuXG4gICAqL1xuICBoZWlnaHQ6IF9yZWFjdC5Qcm9wVHlwZXMubnVtYmVyLmlzUmVxdWlyZWQsXG5cbiAgLyoqXG4gICAqIE9wdGlvbmFsIHJlbmRlcmVyIHRvIGJlIHVzZWQgaW4gcGxhY2Ugb2Ygcm93cyB3aGVuIGVpdGhlciA6cm93Q291bnQgb3IgOmNvbHVtbkNvdW50IGlzIDAuXG4gICAqL1xuICBub0NvbnRlbnRSZW5kZXJlcjogX3JlYWN0LlByb3BUeXBlcy5mdW5jLmlzUmVxdWlyZWQsXG5cbiAgLyoqXG4gICAqIENhbGxiYWNrIGludm9rZWQgd2hlbmV2ZXIgdGhlIHNjcm9sbCBvZmZzZXQgY2hhbmdlcyB3aXRoaW4gdGhlIGlubmVyIHNjcm9sbGFibGUgcmVnaW9uLlxuICAgKiBUaGlzIGNhbGxiYWNrIGNhbiBiZSB1c2VkIHRvIHN5bmMgc2Nyb2xsaW5nIGJldHdlZW4gbGlzdHMsIHRhYmxlcywgb3IgZ3JpZHMuXG4gICAqICh7IGNsaWVudEhlaWdodCwgY2xpZW50V2lkdGgsIHNjcm9sbEhlaWdodCwgc2Nyb2xsTGVmdCwgc2Nyb2xsVG9wLCBzY3JvbGxXaWR0aCB9KTogdm9pZFxuICAgKi9cbiAgb25TY3JvbGw6IF9yZWFjdC5Qcm9wVHlwZXMuZnVuYy5pc1JlcXVpcmVkLFxuXG4gIC8qKlxuICAgKiBDYWxsYmFjayBpbnZva2VkIHdpdGggaW5mb3JtYXRpb24gYWJvdXQgdGhlIHNlY3Rpb24gb2YgdGhlIEdyaWQgdGhhdCB3YXMganVzdCByZW5kZXJlZC5cbiAgICogKHsgY29sdW1uU3RhcnRJbmRleCwgY29sdW1uU3RvcEluZGV4LCByb3dTdGFydEluZGV4LCByb3dTdG9wSW5kZXggfSk6IHZvaWRcbiAgICovXG4gIG9uU2VjdGlvblJlbmRlcmVkOiBfcmVhY3QuUHJvcFR5cGVzLmZ1bmMuaXNSZXF1aXJlZCxcblxuICAvKipcbiAgICogTnVtYmVyIG9mIGNvbHVtbnMgdG8gcmVuZGVyIGJlZm9yZS9hZnRlciB0aGUgdmlzaWJsZSBzZWN0aW9uIG9mIHRoZSBncmlkLlxuICAgKiBUaGVzZSBjb2x1bW5zIGNhbiBoZWxwIGZvciBzbW9vdGhlciBzY3JvbGxpbmcgb24gdG91Y2ggZGV2aWNlcyBvciBicm93c2VycyB0aGF0IHNlbmQgc2Nyb2xsIGV2ZW50cyBpbmZyZXF1ZW50bHkuXG4gICAqL1xuICBvdmVyc2NhbkNvbHVtbkNvdW50OiBfcmVhY3QuUHJvcFR5cGVzLm51bWJlci5pc1JlcXVpcmVkLFxuXG4gIC8qKlxuICAgKiBOdW1iZXIgb2Ygcm93cyB0byByZW5kZXIgYWJvdmUvYmVsb3cgdGhlIHZpc2libGUgc2VjdGlvbiBvZiB0aGUgZ3JpZC5cbiAgICogVGhlc2Ugcm93cyBjYW4gaGVscCBmb3Igc21vb3RoZXIgc2Nyb2xsaW5nIG9uIHRvdWNoIGRldmljZXMgb3IgYnJvd3NlcnMgdGhhdCBzZW5kIHNjcm9sbCBldmVudHMgaW5mcmVxdWVudGx5LlxuICAgKi9cbiAgb3ZlcnNjYW5Sb3dDb3VudDogX3JlYWN0LlByb3BUeXBlcy5udW1iZXIuaXNSZXF1aXJlZCxcblxuICAvKipcbiAgICogRWl0aGVyIGEgZml4ZWQgcm93IGhlaWdodCAobnVtYmVyKSBvciBhIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyB0aGUgaGVpZ2h0IG9mIGEgcm93IGdpdmVuIGl0cyBpbmRleC5cbiAgICogU2hvdWxkIGltcGxlbWVudCB0aGUgZm9sbG93aW5nIGludGVyZmFjZTogKHsgaW5kZXg6IG51bWJlciB9KTogbnVtYmVyXG4gICAqL1xuICByb3dIZWlnaHQ6IF9yZWFjdC5Qcm9wVHlwZXMub25lT2ZUeXBlKFtfcmVhY3QuUHJvcFR5cGVzLm51bWJlciwgX3JlYWN0LlByb3BUeXBlcy5mdW5jXSkuaXNSZXF1aXJlZCxcblxuICAvKipcbiAgICogTnVtYmVyIG9mIHJvd3MgaW4gZ3JpZC5cbiAgICovXG4gIHJvd0NvdW50OiBfcmVhY3QuUHJvcFR5cGVzLm51bWJlci5pc1JlcXVpcmVkLFxuXG4gIC8qKiBXYWl0IHRoaXMgYW1vdW50IG9mIHRpbWUgYWZ0ZXIgdGhlIGxhc3Qgc2Nyb2xsIGV2ZW50IGJlZm9yZSByZXNldHRpbmcgR3JpZCBgcG9pbnRlci1ldmVudHNgLiAqL1xuICBzY3JvbGxpbmdSZXNldFRpbWVJbnRlcnZhbDogX3JlYWN0LlByb3BUeXBlcy5udW1iZXIsXG5cbiAgLyoqIEhvcml6b250YWwgb2Zmc2V0LiAqL1xuICBzY3JvbGxMZWZ0OiBfcmVhY3QuUHJvcFR5cGVzLm51bWJlcixcblxuICAvKipcbiAgICogQ29udHJvbHMgc2Nyb2xsLXRvLWNlbGwgYmVoYXZpb3Igb2YgdGhlIEdyaWQuXG4gICAqIFRoZSBkZWZhdWx0IChcImF1dG9cIikgc2Nyb2xscyB0aGUgbGVhc3QgYW1vdW50IHBvc3NpYmxlIHRvIGVuc3VyZSB0aGF0IHRoZSBzcGVjaWZpZWQgY2VsbCBpcyBmdWxseSB2aXNpYmxlLlxuICAgKiBVc2UgXCJzdGFydFwiIHRvIGFsaWduIGNlbGxzIHRvIHRoZSB0b3AvbGVmdCBvZiB0aGUgR3JpZCBhbmQgXCJlbmRcIiB0byBhbGlnbiBib3R0b20vcmlnaHQuXG4gICAqL1xuICBzY3JvbGxUb0FsaWdubWVudDogX3JlYWN0LlByb3BUeXBlcy5vbmVPZihbJ2F1dG8nLCAnZW5kJywgJ3N0YXJ0JywgJ2NlbnRlciddKS5pc1JlcXVpcmVkLFxuXG4gIC8qKlxuICAgKiBDb2x1bW4gaW5kZXggdG8gZW5zdXJlIHZpc2libGUgKGJ5IGZvcmNlZnVsbHkgc2Nyb2xsaW5nIGlmIG5lY2Vzc2FyeSlcbiAgICovXG4gIHNjcm9sbFRvQ29sdW1uOiBfcmVhY3QuUHJvcFR5cGVzLm51bWJlcixcblxuICAvKiogVmVydGljYWwgb2Zmc2V0LiAqL1xuICBzY3JvbGxUb3A6IF9yZWFjdC5Qcm9wVHlwZXMubnVtYmVyLFxuXG4gIC8qKlxuICAgKiBSb3cgaW5kZXggdG8gZW5zdXJlIHZpc2libGUgKGJ5IGZvcmNlZnVsbHkgc2Nyb2xsaW5nIGlmIG5lY2Vzc2FyeSlcbiAgICovXG4gIHNjcm9sbFRvUm93OiBfcmVhY3QuUHJvcFR5cGVzLm51bWJlcixcblxuICAvKiogT3B0aW9uYWwgaW5saW5lIHN0eWxlICovXG4gIHN0eWxlOiBfcmVhY3QuUHJvcFR5cGVzLm9iamVjdCxcblxuICAvKiogVGFiIGluZGV4IGZvciBmb2N1cyAqL1xuICB0YWJJbmRleDogX3JlYWN0LlByb3BUeXBlcy5udW1iZXIsXG5cbiAgLyoqXG4gICAqIFdpZHRoIG9mIEdyaWQ7IHRoaXMgcHJvcGVydHkgZGV0ZXJtaW5lcyB0aGUgbnVtYmVyIG9mIHZpc2libGUgKHZzIHZpcnR1YWxpemVkKSBjb2x1bW5zLlxuICAgKi9cbiAgd2lkdGg6IF9yZWFjdC5Qcm9wVHlwZXMubnVtYmVyLmlzUmVxdWlyZWRcbn07XG5HcmlkLmRlZmF1bHRQcm9wcyA9IHtcbiAgJ2FyaWEtbGFiZWwnOiAnZ3JpZCcsXG4gIGNlbGxTdHlsZToge30sXG4gIGNlbGxSYW5nZVJlbmRlcmVyOiBfZGVmYXVsdENlbGxSYW5nZVJlbmRlcmVyMi5kZWZhdWx0LFxuICBlc3RpbWF0ZWRDb2x1bW5TaXplOiAxMDAsXG4gIGVzdGltYXRlZFJvd1NpemU6IDMwLFxuICBub0NvbnRlbnRSZW5kZXJlcjogZnVuY3Rpb24gbm9Db250ZW50UmVuZGVyZXIoKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH0sXG4gIG9uU2Nyb2xsOiBmdW5jdGlvbiBvblNjcm9sbCgpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfSxcbiAgb25TZWN0aW9uUmVuZGVyZWQ6IGZ1bmN0aW9uIG9uU2VjdGlvblJlbmRlcmVkKCkge1xuICAgIHJldHVybiBudWxsO1xuICB9LFxuICBvdmVyc2NhbkNvbHVtbkNvdW50OiAwLFxuICBvdmVyc2NhblJvd0NvdW50OiAxMCxcbiAgc2Nyb2xsaW5nUmVzZXRUaW1lSW50ZXJ2YWw6IERFRkFVTFRfU0NST0xMSU5HX1JFU0VUX1RJTUVfSU5URVJWQUwsXG4gIHNjcm9sbFRvQWxpZ25tZW50OiAnYXV0bycsXG4gIHN0eWxlOiB7fSxcbiAgdGFiSW5kZXg6IDBcbn07XG5leHBvcnRzLmRlZmF1bHQgPSBHcmlkOyIsIid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9leHRlbmRzID0gT2JqZWN0LmFzc2lnbiB8fCBmdW5jdGlvbiAodGFyZ2V0KSB7IGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7IHZhciBzb3VyY2UgPSBhcmd1bWVudHNbaV07IGZvciAodmFyIGtleSBpbiBzb3VyY2UpIHsgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzb3VyY2UsIGtleSkpIHsgdGFyZ2V0W2tleV0gPSBzb3VyY2Vba2V5XTsgfSB9IH0gcmV0dXJuIHRhcmdldDsgfTtcblxuZXhwb3J0cy5kZWZhdWx0ID0gZGVmYXVsdENlbGxSYW5nZVJlbmRlcmVyO1xuXG52YXIgX3JlYWN0ID0gcmVxdWlyZSgncmVhY3QnKTtcblxudmFyIF9yZWFjdDIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9yZWFjdCk7XG5cbnZhciBfY2xhc3NuYW1lcyA9IHJlcXVpcmUoJ2NsYXNzbmFtZXMnKTtcblxudmFyIF9jbGFzc25hbWVzMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2NsYXNzbmFtZXMpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyBkZWZhdWx0OiBvYmogfTsgfVxuXG4vKipcbiAqIERlZmF1bHQgaW1wbGVtZW50YXRpb24gb2YgY2VsbFJhbmdlUmVuZGVyZXIgdXNlZCBieSBHcmlkLlxuICogVGhpcyByZW5kZXJlciBzdXBwb3J0cyBjZWxsLWNhY2hpbmcgd2hpbGUgdGhlIHVzZXIgaXMgc2Nyb2xsaW5nLlxuICovXG5mdW5jdGlvbiBkZWZhdWx0Q2VsbFJhbmdlUmVuZGVyZXIoX3JlZikge1xuICB2YXIgY2VsbENhY2hlID0gX3JlZi5jZWxsQ2FjaGU7XG4gIHZhciBjZWxsQ2xhc3NOYW1lID0gX3JlZi5jZWxsQ2xhc3NOYW1lO1xuICB2YXIgY2VsbFJlbmRlcmVyID0gX3JlZi5jZWxsUmVuZGVyZXI7XG4gIHZhciBjZWxsU3R5bGUgPSBfcmVmLmNlbGxTdHlsZTtcbiAgdmFyIGNvbHVtblNpemVBbmRQb3NpdGlvbk1hbmFnZXIgPSBfcmVmLmNvbHVtblNpemVBbmRQb3NpdGlvbk1hbmFnZXI7XG4gIHZhciBjb2x1bW5TdGFydEluZGV4ID0gX3JlZi5jb2x1bW5TdGFydEluZGV4O1xuICB2YXIgY29sdW1uU3RvcEluZGV4ID0gX3JlZi5jb2x1bW5TdG9wSW5kZXg7XG4gIHZhciBob3Jpem9udGFsT2Zmc2V0QWRqdXN0bWVudCA9IF9yZWYuaG9yaXpvbnRhbE9mZnNldEFkanVzdG1lbnQ7XG4gIHZhciBpc1Njcm9sbGluZyA9IF9yZWYuaXNTY3JvbGxpbmc7XG4gIHZhciByb3dTaXplQW5kUG9zaXRpb25NYW5hZ2VyID0gX3JlZi5yb3dTaXplQW5kUG9zaXRpb25NYW5hZ2VyO1xuICB2YXIgcm93U3RhcnRJbmRleCA9IF9yZWYucm93U3RhcnRJbmRleDtcbiAgdmFyIHJvd1N0b3BJbmRleCA9IF9yZWYucm93U3RvcEluZGV4O1xuICB2YXIgc2Nyb2xsTGVmdCA9IF9yZWYuc2Nyb2xsTGVmdDtcbiAgdmFyIHNjcm9sbFRvcCA9IF9yZWYuc2Nyb2xsVG9wO1xuICB2YXIgdmVydGljYWxPZmZzZXRBZGp1c3RtZW50ID0gX3JlZi52ZXJ0aWNhbE9mZnNldEFkanVzdG1lbnQ7XG5cbiAgdmFyIHJlbmRlcmVkQ2VsbHMgPSBbXTtcblxuICBmb3IgKHZhciByb3dJbmRleCA9IHJvd1N0YXJ0SW5kZXg7IHJvd0luZGV4IDw9IHJvd1N0b3BJbmRleDsgcm93SW5kZXgrKykge1xuICAgIHZhciByb3dEYXR1bSA9IHJvd1NpemVBbmRQb3NpdGlvbk1hbmFnZXIuZ2V0U2l6ZUFuZFBvc2l0aW9uT2ZDZWxsKHJvd0luZGV4KTtcblxuICAgIGZvciAodmFyIGNvbHVtbkluZGV4ID0gY29sdW1uU3RhcnRJbmRleDsgY29sdW1uSW5kZXggPD0gY29sdW1uU3RvcEluZGV4OyBjb2x1bW5JbmRleCsrKSB7XG4gICAgICB2YXIgY29sdW1uRGF0dW0gPSBjb2x1bW5TaXplQW5kUG9zaXRpb25NYW5hZ2VyLmdldFNpemVBbmRQb3NpdGlvbk9mQ2VsbChjb2x1bW5JbmRleCk7XG4gICAgICB2YXIga2V5ID0gcm93SW5kZXggKyAnLScgKyBjb2x1bW5JbmRleDtcbiAgICAgIHZhciBjZWxsU3R5bGVPYmplY3QgPSBjZWxsU3R5bGUoeyByb3dJbmRleDogcm93SW5kZXgsIGNvbHVtbkluZGV4OiBjb2x1bW5JbmRleCB9KTtcbiAgICAgIHZhciByZW5kZXJlZENlbGwgPSB2b2lkIDA7XG5cbiAgICAgIC8vIEF2b2lkIHJlLWNyZWF0aW5nIGNlbGxzIHdoaWxlIHNjcm9sbGluZy5cbiAgICAgIC8vIFRoaXMgY2FuIGxlYWQgdG8gdGhlIHNhbWUgY2VsbCBiZWluZyBjcmVhdGVkIG1hbnkgdGltZXMgYW5kIGNhbiBjYXVzZSBwZXJmb3JtYW5jZSBpc3N1ZXMgZm9yIFwiaGVhdnlcIiBjZWxscy5cbiAgICAgIC8vIElmIGEgc2Nyb2xsIGlzIGluIHByb2dyZXNzLSBjYWNoZSBhbmQgcmV1c2UgY2VsbHMuXG4gICAgICAvLyBUaGlzIGNhY2hlIHdpbGwgYmUgdGhyb3duIGF3YXkgb25jZSBzY3JvbGxpbmcgY29tcGxldHMuXG4gICAgICBpZiAoaXNTY3JvbGxpbmcpIHtcbiAgICAgICAgaWYgKCFjZWxsQ2FjaGVba2V5XSkge1xuICAgICAgICAgIGNlbGxDYWNoZVtrZXldID0gY2VsbFJlbmRlcmVyKHtcbiAgICAgICAgICAgIGNvbHVtbkluZGV4OiBjb2x1bW5JbmRleCxcbiAgICAgICAgICAgIGlzU2Nyb2xsaW5nOiBpc1Njcm9sbGluZyxcbiAgICAgICAgICAgIHJvd0luZGV4OiByb3dJbmRleFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJlbmRlcmVkQ2VsbCA9IGNlbGxDYWNoZVtrZXldO1xuICAgICAgICAvLyBJZiB0aGUgdXNlciBpcyBubyBsb25nZXIgc2Nyb2xsaW5nLCBkb24ndCBjYWNoZSBjZWxscy5cbiAgICAgICAgLy8gVGhpcyBtYWtlcyBkeW5hbWljIGNlbGwgY29udGVudCBkaWZmaWN1bHQgZm9yIHVzZXJzIGFuZCB3b3VsZCBhbHNvIGxlYWQgdG8gYSBoZWF2aWVyIG1lbW9yeSBmb290cHJpbnQuXG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZW5kZXJlZENlbGwgPSBjZWxsUmVuZGVyZXIoe1xuICAgICAgICAgIGNvbHVtbkluZGV4OiBjb2x1bW5JbmRleCxcbiAgICAgICAgICBpc1Njcm9sbGluZzogaXNTY3JvbGxpbmcsXG4gICAgICAgICAgcm93SW5kZXg6IHJvd0luZGV4XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBpZiAocmVuZGVyZWRDZWxsID09IG51bGwgfHwgcmVuZGVyZWRDZWxsID09PSBmYWxzZSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgdmFyIGNsYXNzTmFtZSA9IGNlbGxDbGFzc05hbWUoeyBjb2x1bW5JbmRleDogY29sdW1uSW5kZXgsIHJvd0luZGV4OiByb3dJbmRleCB9KTtcblxuICAgICAgdmFyIGNoaWxkID0gX3JlYWN0Mi5kZWZhdWx0LmNyZWF0ZUVsZW1lbnQoXG4gICAgICAgICdkaXYnLFxuICAgICAgICB7XG4gICAgICAgICAga2V5OiBrZXksXG4gICAgICAgICAgY2xhc3NOYW1lOiAoMCwgX2NsYXNzbmFtZXMyLmRlZmF1bHQpKCdHcmlkX19jZWxsJywgY2xhc3NOYW1lKSxcbiAgICAgICAgICBzdHlsZTogX2V4dGVuZHMoe1xuICAgICAgICAgICAgaGVpZ2h0OiByb3dEYXR1bS5zaXplLFxuICAgICAgICAgICAgbGVmdDogY29sdW1uRGF0dW0ub2Zmc2V0ICsgaG9yaXpvbnRhbE9mZnNldEFkanVzdG1lbnQsXG4gICAgICAgICAgICB0b3A6IHJvd0RhdHVtLm9mZnNldCArIHZlcnRpY2FsT2Zmc2V0QWRqdXN0bWVudCxcbiAgICAgICAgICAgIHdpZHRoOiBjb2x1bW5EYXR1bS5zaXplXG4gICAgICAgICAgfSwgY2VsbFN0eWxlT2JqZWN0KVxuICAgICAgICB9LFxuICAgICAgICByZW5kZXJlZENlbGxcbiAgICAgICk7XG5cbiAgICAgIHJlbmRlcmVkQ2VsbHMucHVzaChjaGlsZCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJlbmRlcmVkQ2VsbHM7XG59IiwiJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0cy5kZWZhdWx0Q2VsbFJhbmdlUmVuZGVyZXIgPSBleHBvcnRzLkdyaWQgPSBleHBvcnRzLmRlZmF1bHQgPSB1bmRlZmluZWQ7XG5cbnZhciBfR3JpZDIgPSByZXF1aXJlKCcuL0dyaWQnKTtcblxudmFyIF9HcmlkMyA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX0dyaWQyKTtcblxudmFyIF9kZWZhdWx0Q2VsbFJhbmdlUmVuZGVyZXIyID0gcmVxdWlyZSgnLi9kZWZhdWx0Q2VsbFJhbmdlUmVuZGVyZXInKTtcblxudmFyIF9kZWZhdWx0Q2VsbFJhbmdlUmVuZGVyZXIzID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfZGVmYXVsdENlbGxSYW5nZVJlbmRlcmVyMik7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7IGRlZmF1bHQ6IG9iaiB9OyB9XG5cbmV4cG9ydHMuZGVmYXVsdCA9IF9HcmlkMy5kZWZhdWx0O1xuZXhwb3J0cy5HcmlkID0gX0dyaWQzLmRlZmF1bHQ7XG5leHBvcnRzLmRlZmF1bHRDZWxsUmFuZ2VSZW5kZXJlciA9IF9kZWZhdWx0Q2VsbFJhbmdlUmVuZGVyZXIzLmRlZmF1bHQ7IiwiJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKFwidmFsdWVcIiBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSgpO1xuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb25cIik7IH0gfVxuXG4vKipcbiAqIEp1c3QtaW4tdGltZSBjYWxjdWxhdGVzIGFuZCBjYWNoZXMgc2l6ZSBhbmQgcG9zaXRpb24gaW5mb3JtYXRpb24gZm9yIGEgY29sbGVjdGlvbiBvZiBjZWxscy5cbiAqL1xudmFyIENlbGxTaXplQW5kUG9zaXRpb25NYW5hZ2VyID0gZnVuY3Rpb24gKCkge1xuICBmdW5jdGlvbiBDZWxsU2l6ZUFuZFBvc2l0aW9uTWFuYWdlcihfcmVmKSB7XG4gICAgdmFyIGNlbGxDb3VudCA9IF9yZWYuY2VsbENvdW50O1xuICAgIHZhciBjZWxsU2l6ZUdldHRlciA9IF9yZWYuY2VsbFNpemVHZXR0ZXI7XG4gICAgdmFyIGVzdGltYXRlZENlbGxTaXplID0gX3JlZi5lc3RpbWF0ZWRDZWxsU2l6ZTtcblxuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBDZWxsU2l6ZUFuZFBvc2l0aW9uTWFuYWdlcik7XG5cbiAgICB0aGlzLl9jZWxsU2l6ZUdldHRlciA9IGNlbGxTaXplR2V0dGVyO1xuICAgIHRoaXMuX2NlbGxDb3VudCA9IGNlbGxDb3VudDtcbiAgICB0aGlzLl9lc3RpbWF0ZWRDZWxsU2l6ZSA9IGVzdGltYXRlZENlbGxTaXplO1xuXG4gICAgLy8gQ2FjaGUgb2Ygc2l6ZSBhbmQgcG9zaXRpb24gZGF0YSBmb3IgY2VsbHMsIG1hcHBlZCBieSBjZWxsIGluZGV4LlxuICAgIC8vIE5vdGUgdGhhdCBpbnZhbGlkIHZhbHVlcyBtYXkgZXhpc3QgaW4gdGhpcyBtYXAgc28gb25seSByZWx5IG9uIGNlbGxzIHVwIHRvIHRoaXMuX2xhc3RNZWFzdXJlZEluZGV4XG4gICAgdGhpcy5fY2VsbFNpemVBbmRQb3NpdGlvbkRhdGEgPSB7fTtcblxuICAgIC8vIE1lYXN1cmVtZW50cyBmb3IgY2VsbHMgdXAgdG8gdGhpcyBpbmRleCBjYW4gYmUgdHJ1c3RlZDsgY2VsbHMgYWZ0ZXJ3YXJkIHNob3VsZCBiZSBlc3RpbWF0ZWQuXG4gICAgdGhpcy5fbGFzdE1lYXN1cmVkSW5kZXggPSAtMTtcbiAgfVxuXG4gIF9jcmVhdGVDbGFzcyhDZWxsU2l6ZUFuZFBvc2l0aW9uTWFuYWdlciwgW3tcbiAgICBrZXk6ICdjb25maWd1cmUnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBjb25maWd1cmUoX3JlZjIpIHtcbiAgICAgIHZhciBjZWxsQ291bnQgPSBfcmVmMi5jZWxsQ291bnQ7XG4gICAgICB2YXIgZXN0aW1hdGVkQ2VsbFNpemUgPSBfcmVmMi5lc3RpbWF0ZWRDZWxsU2l6ZTtcblxuICAgICAgdGhpcy5fY2VsbENvdW50ID0gY2VsbENvdW50O1xuICAgICAgdGhpcy5fZXN0aW1hdGVkQ2VsbFNpemUgPSBlc3RpbWF0ZWRDZWxsU2l6ZTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdnZXRDZWxsQ291bnQnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBnZXRDZWxsQ291bnQoKSB7XG4gICAgICByZXR1cm4gdGhpcy5fY2VsbENvdW50O1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ2dldEVzdGltYXRlZENlbGxTaXplJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gZ2V0RXN0aW1hdGVkQ2VsbFNpemUoKSB7XG4gICAgICByZXR1cm4gdGhpcy5fZXN0aW1hdGVkQ2VsbFNpemU7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnZ2V0TGFzdE1lYXN1cmVkSW5kZXgnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBnZXRMYXN0TWVhc3VyZWRJbmRleCgpIHtcbiAgICAgIHJldHVybiB0aGlzLl9sYXN0TWVhc3VyZWRJbmRleDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCByZXR1cm5zIHRoZSBzaXplIGFuZCBwb3NpdGlvbiBmb3IgdGhlIGNlbGwgYXQgdGhlIHNwZWNpZmllZCBpbmRleC5cbiAgICAgKiBJdCBqdXN0LWluLXRpbWUgY2FsY3VsYXRlcyAob3IgdXNlZCBjYWNoZWQgdmFsdWVzKSBmb3IgY2VsbHMgbGVhZGluZyB1cCB0byB0aGUgaW5kZXguXG4gICAgICovXG5cbiAgfSwge1xuICAgIGtleTogJ2dldFNpemVBbmRQb3NpdGlvbk9mQ2VsbCcsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGdldFNpemVBbmRQb3NpdGlvbk9mQ2VsbChpbmRleCkge1xuICAgICAgaWYgKGluZGV4IDwgMCB8fCBpbmRleCA+PSB0aGlzLl9jZWxsQ291bnQpIHtcbiAgICAgICAgdGhyb3cgRXJyb3IoJ1JlcXVlc3RlZCBpbmRleCAnICsgaW5kZXggKyAnIGlzIG91dHNpZGUgb2YgcmFuZ2UgMC4uJyArIHRoaXMuX2NlbGxDb3VudCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChpbmRleCA+IHRoaXMuX2xhc3RNZWFzdXJlZEluZGV4KSB7XG4gICAgICAgIHZhciBsYXN0TWVhc3VyZWRDZWxsU2l6ZUFuZFBvc2l0aW9uID0gdGhpcy5nZXRTaXplQW5kUG9zaXRpb25PZkxhc3RNZWFzdXJlZENlbGwoKTtcbiAgICAgICAgdmFyIF9vZmZzZXQgPSBsYXN0TWVhc3VyZWRDZWxsU2l6ZUFuZFBvc2l0aW9uLm9mZnNldCArIGxhc3RNZWFzdXJlZENlbGxTaXplQW5kUG9zaXRpb24uc2l6ZTtcblxuICAgICAgICBmb3IgKHZhciBpID0gdGhpcy5fbGFzdE1lYXN1cmVkSW5kZXggKyAxOyBpIDw9IGluZGV4OyBpKyspIHtcbiAgICAgICAgICB2YXIgX3NpemUgPSB0aGlzLl9jZWxsU2l6ZUdldHRlcih7IGluZGV4OiBpIH0pO1xuXG4gICAgICAgICAgaWYgKF9zaXplID09IG51bGwgfHwgaXNOYU4oX3NpemUpKSB7XG4gICAgICAgICAgICB0aHJvdyBFcnJvcignSW52YWxpZCBzaXplIHJldHVybmVkIGZvciBjZWxsICcgKyBpICsgJyBvZiB2YWx1ZSAnICsgX3NpemUpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHRoaXMuX2NlbGxTaXplQW5kUG9zaXRpb25EYXRhW2ldID0ge1xuICAgICAgICAgICAgb2Zmc2V0OiBfb2Zmc2V0LFxuICAgICAgICAgICAgc2l6ZTogX3NpemVcbiAgICAgICAgICB9O1xuXG4gICAgICAgICAgX29mZnNldCArPSBfc2l6ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX2xhc3RNZWFzdXJlZEluZGV4ID0gaW5kZXg7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzLl9jZWxsU2l6ZUFuZFBvc2l0aW9uRGF0YVtpbmRleF07XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnZ2V0U2l6ZUFuZFBvc2l0aW9uT2ZMYXN0TWVhc3VyZWRDZWxsJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gZ2V0U2l6ZUFuZFBvc2l0aW9uT2ZMYXN0TWVhc3VyZWRDZWxsKCkge1xuICAgICAgcmV0dXJuIHRoaXMuX2xhc3RNZWFzdXJlZEluZGV4ID49IDAgPyB0aGlzLl9jZWxsU2l6ZUFuZFBvc2l0aW9uRGF0YVt0aGlzLl9sYXN0TWVhc3VyZWRJbmRleF0gOiB7XG4gICAgICAgIG9mZnNldDogMCxcbiAgICAgICAgc2l6ZTogMFxuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUb3RhbCBzaXplIG9mIGFsbCBjZWxscyBiZWluZyBtZWFzdXJlZC5cbiAgICAgKiBUaGlzIHZhbHVlIHdpbGwgYmUgY29tcGxldGVkbHkgZXN0aW1hdGVkIGluaXRpYWxseS5cbiAgICAgKiBBcyBjZWxscyBhcyBtZWFzdXJlZCB0aGUgZXN0aW1hdGUgd2lsbCBiZSB1cGRhdGVkLlxuICAgICAqL1xuXG4gIH0sIHtcbiAgICBrZXk6ICdnZXRUb3RhbFNpemUnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBnZXRUb3RhbFNpemUoKSB7XG4gICAgICB2YXIgbGFzdE1lYXN1cmVkQ2VsbFNpemVBbmRQb3NpdGlvbiA9IHRoaXMuZ2V0U2l6ZUFuZFBvc2l0aW9uT2ZMYXN0TWVhc3VyZWRDZWxsKCk7XG5cbiAgICAgIHJldHVybiBsYXN0TWVhc3VyZWRDZWxsU2l6ZUFuZFBvc2l0aW9uLm9mZnNldCArIGxhc3RNZWFzdXJlZENlbGxTaXplQW5kUG9zaXRpb24uc2l6ZSArICh0aGlzLl9jZWxsQ291bnQgLSB0aGlzLl9sYXN0TWVhc3VyZWRJbmRleCAtIDEpICogdGhpcy5fZXN0aW1hdGVkQ2VsbFNpemU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGV0ZXJtaW5lcyBhIG5ldyBvZmZzZXQgdGhhdCBlbnN1cmVzIGEgY2VydGFpbiBjZWxsIGlzIHZpc2libGUsIGdpdmVuIHRoZSBjdXJyZW50IG9mZnNldC5cbiAgICAgKiBJZiB0aGUgY2VsbCBpcyBhbHJlYWR5IHZpc2libGUgdGhlbiB0aGUgY3VycmVudCBvZmZzZXQgd2lsbCBiZSByZXR1cm5lZC5cbiAgICAgKiBJZiB0aGUgY3VycmVudCBvZmZzZXQgaXMgdG9vIGdyZWF0IG9yIHNtYWxsLCBpdCB3aWxsIGJlIGFkanVzdGVkIGp1c3QgZW5vdWdoIHRvIGVuc3VyZSB0aGUgc3BlY2lmaWVkIGluZGV4IGlzIHZpc2libGUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gYWxpZ24gRGVzaXJlZCBhbGlnbm1lbnQgd2l0aGluIGNvbnRhaW5lcjsgb25lIG9mIFwiYXV0b1wiIChkZWZhdWx0KSwgXCJzdGFydFwiLCBvciBcImVuZFwiXG4gICAgICogQHBhcmFtIGNvbnRhaW5lclNpemUgU2l6ZSAod2lkdGggb3IgaGVpZ2h0KSBvZiB0aGUgY29udGFpbmVyIHZpZXdwb3J0XG4gICAgICogQHBhcmFtIGN1cnJlbnRPZmZzZXQgQ29udGFpbmVyJ3MgY3VycmVudCAoeCBvciB5KSBvZmZzZXRcbiAgICAgKiBAcGFyYW0gdG90YWxTaXplIFRvdGFsIHNpemUgKHdpZHRoIG9yIGhlaWdodCkgb2YgYWxsIGNlbGxzXG4gICAgICogQHJldHVybiBPZmZzZXQgdG8gdXNlIHRvIGVuc3VyZSB0aGUgc3BlY2lmaWVkIGNlbGwgaXMgdmlzaWJsZVxuICAgICAqL1xuXG4gIH0sIHtcbiAgICBrZXk6ICdnZXRVcGRhdGVkT2Zmc2V0Rm9ySW5kZXgnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBnZXRVcGRhdGVkT2Zmc2V0Rm9ySW5kZXgoX3JlZjMpIHtcbiAgICAgIHZhciBfcmVmMyRhbGlnbiA9IF9yZWYzLmFsaWduO1xuICAgICAgdmFyIGFsaWduID0gX3JlZjMkYWxpZ24gPT09IHVuZGVmaW5lZCA/ICdhdXRvJyA6IF9yZWYzJGFsaWduO1xuICAgICAgdmFyIGNvbnRhaW5lclNpemUgPSBfcmVmMy5jb250YWluZXJTaXplO1xuICAgICAgdmFyIGN1cnJlbnRPZmZzZXQgPSBfcmVmMy5jdXJyZW50T2Zmc2V0O1xuICAgICAgdmFyIHRhcmdldEluZGV4ID0gX3JlZjMudGFyZ2V0SW5kZXg7XG5cbiAgICAgIHZhciBkYXR1bSA9IHRoaXMuZ2V0U2l6ZUFuZFBvc2l0aW9uT2ZDZWxsKHRhcmdldEluZGV4KTtcbiAgICAgIHZhciBtYXhPZmZzZXQgPSBkYXR1bS5vZmZzZXQ7XG4gICAgICB2YXIgbWluT2Zmc2V0ID0gbWF4T2Zmc2V0IC0gY29udGFpbmVyU2l6ZSArIGRhdHVtLnNpemU7XG5cbiAgICAgIHZhciBpZGVhbE9mZnNldCA9IHZvaWQgMDtcblxuICAgICAgc3dpdGNoIChhbGlnbikge1xuICAgICAgICBjYXNlICdzdGFydCc6XG4gICAgICAgICAgaWRlYWxPZmZzZXQgPSBtYXhPZmZzZXQ7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ2VuZCc6XG4gICAgICAgICAgaWRlYWxPZmZzZXQgPSBtaW5PZmZzZXQ7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ2NlbnRlcic6XG4gICAgICAgICAgaWRlYWxPZmZzZXQgPSBtYXhPZmZzZXQgLSAoY29udGFpbmVyU2l6ZSAtIGRhdHVtLnNpemUpIC8gMjtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICBpZGVhbE9mZnNldCA9IE1hdGgubWF4KG1pbk9mZnNldCwgTWF0aC5taW4obWF4T2Zmc2V0LCBjdXJyZW50T2Zmc2V0KSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICB9XG5cbiAgICAgIHZhciB0b3RhbFNpemUgPSB0aGlzLmdldFRvdGFsU2l6ZSgpO1xuXG4gICAgICByZXR1cm4gTWF0aC5tYXgoMCwgTWF0aC5taW4odG90YWxTaXplIC0gY29udGFpbmVyU2l6ZSwgaWRlYWxPZmZzZXQpKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdnZXRWaXNpYmxlQ2VsbFJhbmdlJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gZ2V0VmlzaWJsZUNlbGxSYW5nZShfcmVmNCkge1xuICAgICAgdmFyIGNvbnRhaW5lclNpemUgPSBfcmVmNC5jb250YWluZXJTaXplO1xuICAgICAgdmFyIG9mZnNldCA9IF9yZWY0Lm9mZnNldDtcblxuICAgICAgdmFyIHRvdGFsU2l6ZSA9IHRoaXMuZ2V0VG90YWxTaXplKCk7XG5cbiAgICAgIGlmICh0b3RhbFNpemUgPT09IDApIHtcbiAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgfVxuXG4gICAgICB2YXIgbWF4T2Zmc2V0ID0gb2Zmc2V0ICsgY29udGFpbmVyU2l6ZTtcbiAgICAgIHZhciBzdGFydCA9IHRoaXMuX2ZpbmROZWFyZXN0Q2VsbChvZmZzZXQpO1xuXG4gICAgICB2YXIgZGF0dW0gPSB0aGlzLmdldFNpemVBbmRQb3NpdGlvbk9mQ2VsbChzdGFydCk7XG4gICAgICBvZmZzZXQgPSBkYXR1bS5vZmZzZXQgKyBkYXR1bS5zaXplO1xuXG4gICAgICB2YXIgc3RvcCA9IHN0YXJ0O1xuXG4gICAgICB3aGlsZSAob2Zmc2V0IDwgbWF4T2Zmc2V0ICYmIHN0b3AgPCB0aGlzLl9jZWxsQ291bnQgLSAxKSB7XG4gICAgICAgIHN0b3ArKztcblxuICAgICAgICBvZmZzZXQgKz0gdGhpcy5nZXRTaXplQW5kUG9zaXRpb25PZkNlbGwoc3RvcCkuc2l6ZTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgc3RhcnQ6IHN0YXJ0LFxuICAgICAgICBzdG9wOiBzdG9wXG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENsZWFyIGFsbCBjYWNoZWQgdmFsdWVzIGZvciBjZWxscyBhZnRlciB0aGUgc3BlY2lmaWVkIGluZGV4LlxuICAgICAqIFRoaXMgbWV0aG9kIHNob3VsZCBiZSBjYWxsZWQgZm9yIGFueSBjZWxsIHRoYXQgaGFzIGNoYW5nZWQgaXRzIHNpemUuXG4gICAgICogSXQgd2lsbCBub3QgaW1tZWRpYXRlbHkgcGVyZm9ybSBhbnkgY2FsY3VsYXRpb25zOyB0aGV5J2xsIGJlIHBlcmZvcm1lZCB0aGUgbmV4dCB0aW1lIGdldFNpemVBbmRQb3NpdGlvbk9mQ2VsbCgpIGlzIGNhbGxlZC5cbiAgICAgKi9cblxuICB9LCB7XG4gICAga2V5OiAncmVzZXRDZWxsJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVzZXRDZWxsKGluZGV4KSB7XG4gICAgICB0aGlzLl9sYXN0TWVhc3VyZWRJbmRleCA9IE1hdGgubWluKHRoaXMuX2xhc3RNZWFzdXJlZEluZGV4LCBpbmRleCAtIDEpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19iaW5hcnlTZWFyY2gnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBfYmluYXJ5U2VhcmNoKF9yZWY1KSB7XG4gICAgICB2YXIgaGlnaCA9IF9yZWY1LmhpZ2g7XG4gICAgICB2YXIgbG93ID0gX3JlZjUubG93O1xuICAgICAgdmFyIG9mZnNldCA9IF9yZWY1Lm9mZnNldDtcblxuICAgICAgdmFyIG1pZGRsZSA9IHZvaWQgMDtcbiAgICAgIHZhciBjdXJyZW50T2Zmc2V0ID0gdm9pZCAwO1xuXG4gICAgICB3aGlsZSAobG93IDw9IGhpZ2gpIHtcbiAgICAgICAgbWlkZGxlID0gbG93ICsgTWF0aC5mbG9vcigoaGlnaCAtIGxvdykgLyAyKTtcbiAgICAgICAgY3VycmVudE9mZnNldCA9IHRoaXMuZ2V0U2l6ZUFuZFBvc2l0aW9uT2ZDZWxsKG1pZGRsZSkub2Zmc2V0O1xuXG4gICAgICAgIGlmIChjdXJyZW50T2Zmc2V0ID09PSBvZmZzZXQpIHtcbiAgICAgICAgICByZXR1cm4gbWlkZGxlO1xuICAgICAgICB9IGVsc2UgaWYgKGN1cnJlbnRPZmZzZXQgPCBvZmZzZXQpIHtcbiAgICAgICAgICBsb3cgPSBtaWRkbGUgKyAxO1xuICAgICAgICB9IGVsc2UgaWYgKGN1cnJlbnRPZmZzZXQgPiBvZmZzZXQpIHtcbiAgICAgICAgICBoaWdoID0gbWlkZGxlIC0gMTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAobG93ID4gMCkge1xuICAgICAgICByZXR1cm4gbG93IC0gMTtcbiAgICAgIH1cbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfZXhwb25lbnRpYWxTZWFyY2gnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBfZXhwb25lbnRpYWxTZWFyY2goX3JlZjYpIHtcbiAgICAgIHZhciBpbmRleCA9IF9yZWY2LmluZGV4O1xuICAgICAgdmFyIG9mZnNldCA9IF9yZWY2Lm9mZnNldDtcblxuICAgICAgdmFyIGludGVydmFsID0gMTtcblxuICAgICAgd2hpbGUgKGluZGV4IDwgdGhpcy5fY2VsbENvdW50ICYmIHRoaXMuZ2V0U2l6ZUFuZFBvc2l0aW9uT2ZDZWxsKGluZGV4KS5vZmZzZXQgPCBvZmZzZXQpIHtcbiAgICAgICAgaW5kZXggKz0gaW50ZXJ2YWw7XG4gICAgICAgIGludGVydmFsICo9IDI7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzLl9iaW5hcnlTZWFyY2goe1xuICAgICAgICBoaWdoOiBNYXRoLm1pbihpbmRleCwgdGhpcy5fY2VsbENvdW50IC0gMSksXG4gICAgICAgIGxvdzogTWF0aC5mbG9vcihpbmRleCAvIDIpLFxuICAgICAgICBvZmZzZXQ6IG9mZnNldFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VhcmNoZXMgZm9yIHRoZSBjZWxsIChpbmRleCkgbmVhcmVzdCB0aGUgc3BlY2lmaWVkIG9mZnNldC5cbiAgICAgKlxuICAgICAqIElmIG5vIGV4YWN0IG1hdGNoIGlzIGZvdW5kIHRoZSBuZXh0IGxvd2VzdCBjZWxsIGluZGV4IHdpbGwgYmUgcmV0dXJuZWQuXG4gICAgICogVGhpcyBhbGxvd3MgcGFydGlhbGx5IHZpc2libGUgY2VsbHMgKHdpdGggb2Zmc2V0cyBqdXN0IGJlZm9yZS9hYm92ZSB0aGUgZm9sZCkgdG8gYmUgdmlzaWJsZS5cbiAgICAgKi9cblxuICB9LCB7XG4gICAga2V5OiAnX2ZpbmROZWFyZXN0Q2VsbCcsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9maW5kTmVhcmVzdENlbGwob2Zmc2V0KSB7XG4gICAgICBpZiAoaXNOYU4ob2Zmc2V0KSkge1xuICAgICAgICB0aHJvdyBFcnJvcignSW52YWxpZCBvZmZzZXQgJyArIG9mZnNldCArICcgc3BlY2lmaWVkJyk7XG4gICAgICB9XG5cbiAgICAgIC8vIE91ciBzZWFyY2ggYWxnb3JpdGhtcyBmaW5kIHRoZSBuZWFyZXN0IG1hdGNoIGF0IG9yIGJlbG93IHRoZSBzcGVjaWZpZWQgb2Zmc2V0LlxuICAgICAgLy8gU28gbWFrZSBzdXJlIHRoZSBvZmZzZXQgaXMgYXQgbGVhc3QgMCBvciBubyBtYXRjaCB3aWxsIGJlIGZvdW5kLlxuICAgICAgb2Zmc2V0ID0gTWF0aC5tYXgoMCwgb2Zmc2V0KTtcblxuICAgICAgdmFyIGxhc3RNZWFzdXJlZENlbGxTaXplQW5kUG9zaXRpb24gPSB0aGlzLmdldFNpemVBbmRQb3NpdGlvbk9mTGFzdE1lYXN1cmVkQ2VsbCgpO1xuICAgICAgdmFyIGxhc3RNZWFzdXJlZEluZGV4ID0gTWF0aC5tYXgoMCwgdGhpcy5fbGFzdE1lYXN1cmVkSW5kZXgpO1xuXG4gICAgICBpZiAobGFzdE1lYXN1cmVkQ2VsbFNpemVBbmRQb3NpdGlvbi5vZmZzZXQgPj0gb2Zmc2V0KSB7XG4gICAgICAgIC8vIElmIHdlJ3ZlIGFscmVhZHkgbWVhc3VyZWQgY2VsbHMgd2l0aGluIHRoaXMgcmFuZ2UganVzdCB1c2UgYSBiaW5hcnkgc2VhcmNoIGFzIGl0J3MgZmFzdGVyLlxuICAgICAgICByZXR1cm4gdGhpcy5fYmluYXJ5U2VhcmNoKHtcbiAgICAgICAgICBoaWdoOiBsYXN0TWVhc3VyZWRJbmRleCxcbiAgICAgICAgICBsb3c6IDAsXG4gICAgICAgICAgb2Zmc2V0OiBvZmZzZXRcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBJZiB3ZSBoYXZlbid0IHlldCBtZWFzdXJlZCB0aGlzIGhpZ2gsIGZhbGxiYWNrIHRvIGFuIGV4cG9uZW50aWFsIHNlYXJjaCB3aXRoIGFuIGlubmVyIGJpbmFyeSBzZWFyY2guXG4gICAgICAgIC8vIFRoZSBleHBvbmVudGlhbCBzZWFyY2ggYXZvaWRzIHByZS1jb21wdXRpbmcgc2l6ZXMgZm9yIHRoZSBmdWxsIHNldCBvZiBjZWxscyBhcyBhIGJpbmFyeSBzZWFyY2ggd291bGQuXG4gICAgICAgIC8vIFRoZSBvdmVyYWxsIGNvbXBsZXhpdHkgZm9yIHRoaXMgYXBwcm9hY2ggaXMgTyhsb2cgbikuXG4gICAgICAgIHJldHVybiB0aGlzLl9leHBvbmVudGlhbFNlYXJjaCh7XG4gICAgICAgICAgaW5kZXg6IGxhc3RNZWFzdXJlZEluZGV4LFxuICAgICAgICAgIG9mZnNldDogb2Zmc2V0XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBDZWxsU2l6ZUFuZFBvc2l0aW9uTWFuYWdlcjtcbn0oKTtcblxuZXhwb3J0cy5kZWZhdWx0ID0gQ2VsbFNpemVBbmRQb3NpdGlvbk1hbmFnZXI7IiwiJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0cy5ERUZBVUxUX01BWF9TQ1JPTExfU0laRSA9IHVuZGVmaW5lZDtcblxudmFyIF9jcmVhdGVDbGFzcyA9IGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmIChcInZhbHVlXCIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0oKTtcblxudmFyIF9DZWxsU2l6ZUFuZFBvc2l0aW9uTWFuYWdlciA9IHJlcXVpcmUoJy4vQ2VsbFNpemVBbmRQb3NpdGlvbk1hbmFnZXInKTtcblxudmFyIF9DZWxsU2l6ZUFuZFBvc2l0aW9uTWFuYWdlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9DZWxsU2l6ZUFuZFBvc2l0aW9uTWFuYWdlcik7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7IGRlZmF1bHQ6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9vYmplY3RXaXRob3V0UHJvcGVydGllcyhvYmosIGtleXMpIHsgdmFyIHRhcmdldCA9IHt9OyBmb3IgKHZhciBpIGluIG9iaikgeyBpZiAoa2V5cy5pbmRleE9mKGkpID49IDApIGNvbnRpbnVlOyBpZiAoIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmosIGkpKSBjb250aW51ZTsgdGFyZ2V0W2ldID0gb2JqW2ldOyB9IHJldHVybiB0YXJnZXQ7IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uXCIpOyB9IH1cblxuLyoqXG4gKiBCcm93c2VycyBoYXZlIHNjcm9sbCBvZmZzZXQgbGltaXRhdGlvbnMgKGVnIENocm9tZSBzdG9wcyBzY3JvbGxpbmcgYXQgfjMzLjVNIHBpeGVscyB3aGVyZSBhcyBFZGdlIHRvcHMgb3V0IGF0IH4xLjVNIHBpeGVscykuXG4gKiBBZnRlciBhIGNlcnRhaW4gcG9zaXRpb24sIHRoZSBicm93c2VyIHdvbid0IGFsbG93IHRoZSB1c2VyIHRvIHNjcm9sbCBmdXJ0aGVyIChldmVuIHZpYSBKYXZhU2NyaXB0IHNjcm9sbCBvZmZzZXQgYWRqdXN0bWVudHMpLlxuICogVGhpcyB1dGlsIHBpY2tzIGEgbG93ZXIgY2VpbGluZyBmb3IgbWF4IHNpemUgYW5kIGFydGlmaWNpYWxseSBhZGp1c3RzIHBvc2l0aW9ucyB3aXRoaW4gdG8gbWFrZSBpdCB0cmFuc3BhcmVudCBmb3IgdXNlcnMuXG4gKi9cbnZhciBERUZBVUxUX01BWF9TQ1JPTExfU0laRSA9IGV4cG9ydHMuREVGQVVMVF9NQVhfU0NST0xMX1NJWkUgPSAxNTAwMDAwO1xuXG4vKipcbiAqIEV4dGVuZHMgQ2VsbFNpemVBbmRQb3NpdGlvbk1hbmFnZXIgYW5kIGFkZHMgc2NhbGluZyBiZWhhdmlvciBmb3IgbGlzdHMgdGhhdCBhcmUgdG9vIGxhcmdlIHRvIGZpdCB3aXRoaW4gYSBicm93c2VyJ3MgbmF0aXZlIGxpbWl0cy5cbiAqL1xuXG52YXIgU2NhbGluZ0NlbGxTaXplQW5kUG9zaXRpb25NYW5hZ2VyID0gZnVuY3Rpb24gKCkge1xuICBmdW5jdGlvbiBTY2FsaW5nQ2VsbFNpemVBbmRQb3NpdGlvbk1hbmFnZXIoX3JlZikge1xuICAgIHZhciBfcmVmJG1heFNjcm9sbFNpemUgPSBfcmVmLm1heFNjcm9sbFNpemU7XG4gICAgdmFyIG1heFNjcm9sbFNpemUgPSBfcmVmJG1heFNjcm9sbFNpemUgPT09IHVuZGVmaW5lZCA/IERFRkFVTFRfTUFYX1NDUk9MTF9TSVpFIDogX3JlZiRtYXhTY3JvbGxTaXplO1xuXG4gICAgdmFyIHBhcmFtcyA9IF9vYmplY3RXaXRob3V0UHJvcGVydGllcyhfcmVmLCBbJ21heFNjcm9sbFNpemUnXSk7XG5cbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgU2NhbGluZ0NlbGxTaXplQW5kUG9zaXRpb25NYW5hZ2VyKTtcblxuICAgIC8vIEZhdm9yIGNvbXBvc2l0aW9uIG92ZXIgaW5oZXJpdGFuY2UgdG8gc2ltcGxpZnkgSUUxMCBzdXBwb3J0XG4gICAgdGhpcy5fY2VsbFNpemVBbmRQb3NpdGlvbk1hbmFnZXIgPSBuZXcgX0NlbGxTaXplQW5kUG9zaXRpb25NYW5hZ2VyMi5kZWZhdWx0KHBhcmFtcyk7XG4gICAgdGhpcy5fbWF4U2Nyb2xsU2l6ZSA9IG1heFNjcm9sbFNpemU7XG4gIH1cblxuICBfY3JlYXRlQ2xhc3MoU2NhbGluZ0NlbGxTaXplQW5kUG9zaXRpb25NYW5hZ2VyLCBbe1xuICAgIGtleTogJ2NvbmZpZ3VyZScsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGNvbmZpZ3VyZShwYXJhbXMpIHtcbiAgICAgIHRoaXMuX2NlbGxTaXplQW5kUG9zaXRpb25NYW5hZ2VyLmNvbmZpZ3VyZShwYXJhbXMpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ2dldENlbGxDb3VudCcsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGdldENlbGxDb3VudCgpIHtcbiAgICAgIHJldHVybiB0aGlzLl9jZWxsU2l6ZUFuZFBvc2l0aW9uTWFuYWdlci5nZXRDZWxsQ291bnQoKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdnZXRFc3RpbWF0ZWRDZWxsU2l6ZScsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGdldEVzdGltYXRlZENlbGxTaXplKCkge1xuICAgICAgcmV0dXJuIHRoaXMuX2NlbGxTaXplQW5kUG9zaXRpb25NYW5hZ2VyLmdldEVzdGltYXRlZENlbGxTaXplKCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnZ2V0TGFzdE1lYXN1cmVkSW5kZXgnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBnZXRMYXN0TWVhc3VyZWRJbmRleCgpIHtcbiAgICAgIHJldHVybiB0aGlzLl9jZWxsU2l6ZUFuZFBvc2l0aW9uTWFuYWdlci5nZXRMYXN0TWVhc3VyZWRJbmRleCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE51bWJlciBvZiBwaXhlbHMgYSBjZWxsIGF0IHRoZSBnaXZlbiBwb3NpdGlvbiAob2Zmc2V0KSBzaG91bGQgYmUgc2hpZnRlZCBpbiBvcmRlciB0byBmaXQgd2l0aGluIHRoZSBzY2FsZWQgY29udGFpbmVyLlxuICAgICAqIFRoZSBvZmZzZXQgcGFzc2VkIHRvIHRoaXMgZnVuY3Rpb24gaXMgc2NhbGxlZCAoc2FmZSkgYXMgd2VsbC5cbiAgICAgKi9cblxuICB9LCB7XG4gICAga2V5OiAnZ2V0T2Zmc2V0QWRqdXN0bWVudCcsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGdldE9mZnNldEFkanVzdG1lbnQoX3JlZjIpIHtcbiAgICAgIHZhciBjb250YWluZXJTaXplID0gX3JlZjIuY29udGFpbmVyU2l6ZTtcbiAgICAgIHZhciBvZmZzZXQgPSBfcmVmMi5vZmZzZXQ7XG5cbiAgICAgIHZhciB0b3RhbFNpemUgPSB0aGlzLl9jZWxsU2l6ZUFuZFBvc2l0aW9uTWFuYWdlci5nZXRUb3RhbFNpemUoKTtcbiAgICAgIHZhciBzYWZlVG90YWxTaXplID0gdGhpcy5nZXRUb3RhbFNpemUoKTtcbiAgICAgIHZhciBvZmZzZXRQZXJjZW50YWdlID0gdGhpcy5fZ2V0T2Zmc2V0UGVyY2VudGFnZSh7XG4gICAgICAgIGNvbnRhaW5lclNpemU6IGNvbnRhaW5lclNpemUsXG4gICAgICAgIG9mZnNldDogb2Zmc2V0LFxuICAgICAgICB0b3RhbFNpemU6IHNhZmVUb3RhbFNpemVcbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm4gTWF0aC5yb3VuZChvZmZzZXRQZXJjZW50YWdlICogKHNhZmVUb3RhbFNpemUgLSB0b3RhbFNpemUpKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdnZXRTaXplQW5kUG9zaXRpb25PZkNlbGwnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBnZXRTaXplQW5kUG9zaXRpb25PZkNlbGwoaW5kZXgpIHtcbiAgICAgIHJldHVybiB0aGlzLl9jZWxsU2l6ZUFuZFBvc2l0aW9uTWFuYWdlci5nZXRTaXplQW5kUG9zaXRpb25PZkNlbGwoaW5kZXgpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ2dldFNpemVBbmRQb3NpdGlvbk9mTGFzdE1lYXN1cmVkQ2VsbCcsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGdldFNpemVBbmRQb3NpdGlvbk9mTGFzdE1lYXN1cmVkQ2VsbCgpIHtcbiAgICAgIHJldHVybiB0aGlzLl9jZWxsU2l6ZUFuZFBvc2l0aW9uTWFuYWdlci5nZXRTaXplQW5kUG9zaXRpb25PZkxhc3RNZWFzdXJlZENlbGwoKTtcbiAgICB9XG5cbiAgICAvKiogU2VlIENlbGxTaXplQW5kUG9zaXRpb25NYW5hZ2VyI2dldFRvdGFsU2l6ZSAqL1xuXG4gIH0sIHtcbiAgICBrZXk6ICdnZXRUb3RhbFNpemUnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBnZXRUb3RhbFNpemUoKSB7XG4gICAgICByZXR1cm4gTWF0aC5taW4odGhpcy5fbWF4U2Nyb2xsU2l6ZSwgdGhpcy5fY2VsbFNpemVBbmRQb3NpdGlvbk1hbmFnZXIuZ2V0VG90YWxTaXplKCkpO1xuICAgIH1cblxuICAgIC8qKiBTZWUgQ2VsbFNpemVBbmRQb3NpdGlvbk1hbmFnZXIjZ2V0VXBkYXRlZE9mZnNldEZvckluZGV4ICovXG5cbiAgfSwge1xuICAgIGtleTogJ2dldFVwZGF0ZWRPZmZzZXRGb3JJbmRleCcsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGdldFVwZGF0ZWRPZmZzZXRGb3JJbmRleChfcmVmMykge1xuICAgICAgdmFyIF9yZWYzJGFsaWduID0gX3JlZjMuYWxpZ247XG4gICAgICB2YXIgYWxpZ24gPSBfcmVmMyRhbGlnbiA9PT0gdW5kZWZpbmVkID8gJ2F1dG8nIDogX3JlZjMkYWxpZ247XG4gICAgICB2YXIgY29udGFpbmVyU2l6ZSA9IF9yZWYzLmNvbnRhaW5lclNpemU7XG4gICAgICB2YXIgY3VycmVudE9mZnNldCA9IF9yZWYzLmN1cnJlbnRPZmZzZXQ7XG4gICAgICB2YXIgdGFyZ2V0SW5kZXggPSBfcmVmMy50YXJnZXRJbmRleDtcbiAgICAgIHZhciB0b3RhbFNpemUgPSBfcmVmMy50b3RhbFNpemU7XG5cbiAgICAgIGN1cnJlbnRPZmZzZXQgPSB0aGlzLl9zYWZlT2Zmc2V0VG9PZmZzZXQoe1xuICAgICAgICBjb250YWluZXJTaXplOiBjb250YWluZXJTaXplLFxuICAgICAgICBvZmZzZXQ6IGN1cnJlbnRPZmZzZXRcbiAgICAgIH0pO1xuXG4gICAgICB2YXIgb2Zmc2V0ID0gdGhpcy5fY2VsbFNpemVBbmRQb3NpdGlvbk1hbmFnZXIuZ2V0VXBkYXRlZE9mZnNldEZvckluZGV4KHtcbiAgICAgICAgYWxpZ246IGFsaWduLFxuICAgICAgICBjb250YWluZXJTaXplOiBjb250YWluZXJTaXplLFxuICAgICAgICBjdXJyZW50T2Zmc2V0OiBjdXJyZW50T2Zmc2V0LFxuICAgICAgICB0YXJnZXRJbmRleDogdGFyZ2V0SW5kZXgsXG4gICAgICAgIHRvdGFsU2l6ZTogdG90YWxTaXplXG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIHRoaXMuX29mZnNldFRvU2FmZU9mZnNldCh7XG4gICAgICAgIGNvbnRhaW5lclNpemU6IGNvbnRhaW5lclNpemUsXG4gICAgICAgIG9mZnNldDogb2Zmc2V0XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKiogU2VlIENlbGxTaXplQW5kUG9zaXRpb25NYW5hZ2VyI2dldFZpc2libGVDZWxsUmFuZ2UgKi9cblxuICB9LCB7XG4gICAga2V5OiAnZ2V0VmlzaWJsZUNlbGxSYW5nZScsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGdldFZpc2libGVDZWxsUmFuZ2UoX3JlZjQpIHtcbiAgICAgIHZhciBjb250YWluZXJTaXplID0gX3JlZjQuY29udGFpbmVyU2l6ZTtcbiAgICAgIHZhciBvZmZzZXQgPSBfcmVmNC5vZmZzZXQ7XG5cbiAgICAgIG9mZnNldCA9IHRoaXMuX3NhZmVPZmZzZXRUb09mZnNldCh7XG4gICAgICAgIGNvbnRhaW5lclNpemU6IGNvbnRhaW5lclNpemUsXG4gICAgICAgIG9mZnNldDogb2Zmc2V0XG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIHRoaXMuX2NlbGxTaXplQW5kUG9zaXRpb25NYW5hZ2VyLmdldFZpc2libGVDZWxsUmFuZ2Uoe1xuICAgICAgICBjb250YWluZXJTaXplOiBjb250YWluZXJTaXplLFxuICAgICAgICBvZmZzZXQ6IG9mZnNldFxuICAgICAgfSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAncmVzZXRDZWxsJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVzZXRDZWxsKGluZGV4KSB7XG4gICAgICB0aGlzLl9jZWxsU2l6ZUFuZFBvc2l0aW9uTWFuYWdlci5yZXNldENlbGwoaW5kZXgpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19nZXRPZmZzZXRQZXJjZW50YWdlJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gX2dldE9mZnNldFBlcmNlbnRhZ2UoX3JlZjUpIHtcbiAgICAgIHZhciBjb250YWluZXJTaXplID0gX3JlZjUuY29udGFpbmVyU2l6ZTtcbiAgICAgIHZhciBvZmZzZXQgPSBfcmVmNS5vZmZzZXQ7XG4gICAgICB2YXIgdG90YWxTaXplID0gX3JlZjUudG90YWxTaXplO1xuXG4gICAgICByZXR1cm4gdG90YWxTaXplIDw9IGNvbnRhaW5lclNpemUgPyAwIDogb2Zmc2V0IC8gKHRvdGFsU2l6ZSAtIGNvbnRhaW5lclNpemUpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vZmZzZXRUb1NhZmVPZmZzZXQnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBfb2Zmc2V0VG9TYWZlT2Zmc2V0KF9yZWY2KSB7XG4gICAgICB2YXIgY29udGFpbmVyU2l6ZSA9IF9yZWY2LmNvbnRhaW5lclNpemU7XG4gICAgICB2YXIgb2Zmc2V0ID0gX3JlZjYub2Zmc2V0O1xuXG4gICAgICB2YXIgdG90YWxTaXplID0gdGhpcy5fY2VsbFNpemVBbmRQb3NpdGlvbk1hbmFnZXIuZ2V0VG90YWxTaXplKCk7XG4gICAgICB2YXIgc2FmZVRvdGFsU2l6ZSA9IHRoaXMuZ2V0VG90YWxTaXplKCk7XG5cbiAgICAgIGlmICh0b3RhbFNpemUgPT09IHNhZmVUb3RhbFNpemUpIHtcbiAgICAgICAgcmV0dXJuIG9mZnNldDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBvZmZzZXRQZXJjZW50YWdlID0gdGhpcy5fZ2V0T2Zmc2V0UGVyY2VudGFnZSh7XG4gICAgICAgICAgY29udGFpbmVyU2l6ZTogY29udGFpbmVyU2l6ZSxcbiAgICAgICAgICBvZmZzZXQ6IG9mZnNldCxcbiAgICAgICAgICB0b3RhbFNpemU6IHRvdGFsU2l6ZVxuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gTWF0aC5yb3VuZChvZmZzZXRQZXJjZW50YWdlICogKHNhZmVUb3RhbFNpemUgLSBjb250YWluZXJTaXplKSk7XG4gICAgICB9XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX3NhZmVPZmZzZXRUb09mZnNldCcsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9zYWZlT2Zmc2V0VG9PZmZzZXQoX3JlZjcpIHtcbiAgICAgIHZhciBjb250YWluZXJTaXplID0gX3JlZjcuY29udGFpbmVyU2l6ZTtcbiAgICAgIHZhciBvZmZzZXQgPSBfcmVmNy5vZmZzZXQ7XG5cbiAgICAgIHZhciB0b3RhbFNpemUgPSB0aGlzLl9jZWxsU2l6ZUFuZFBvc2l0aW9uTWFuYWdlci5nZXRUb3RhbFNpemUoKTtcbiAgICAgIHZhciBzYWZlVG90YWxTaXplID0gdGhpcy5nZXRUb3RhbFNpemUoKTtcblxuICAgICAgaWYgKHRvdGFsU2l6ZSA9PT0gc2FmZVRvdGFsU2l6ZSkge1xuICAgICAgICByZXR1cm4gb2Zmc2V0O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIG9mZnNldFBlcmNlbnRhZ2UgPSB0aGlzLl9nZXRPZmZzZXRQZXJjZW50YWdlKHtcbiAgICAgICAgICBjb250YWluZXJTaXplOiBjb250YWluZXJTaXplLFxuICAgICAgICAgIG9mZnNldDogb2Zmc2V0LFxuICAgICAgICAgIHRvdGFsU2l6ZTogc2FmZVRvdGFsU2l6ZVxuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gTWF0aC5yb3VuZChvZmZzZXRQZXJjZW50YWdlICogKHRvdGFsU2l6ZSAtIGNvbnRhaW5lclNpemUpKTtcbiAgICAgIH1cbiAgICB9XG4gIH1dKTtcblxuICByZXR1cm4gU2NhbGluZ0NlbGxTaXplQW5kUG9zaXRpb25NYW5hZ2VyO1xufSgpO1xuXG5leHBvcnRzLmRlZmF1bHQgPSBTY2FsaW5nQ2VsbFNpemVBbmRQb3NpdGlvbk1hbmFnZXI7IiwiJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0cy5kZWZhdWx0ID0gY2FsY3VsYXRlU2l6ZUFuZFBvc2l0aW9uRGF0YUFuZFVwZGF0ZVNjcm9sbE9mZnNldDtcbi8qKlxuICogSGVscGVyIG1ldGhvZCB0aGF0IGRldGVybWluZXMgd2hlbiB0byByZWNhbGN1bGF0ZSByb3cgb3IgY29sdW1uIG1ldGFkYXRhLlxuICpcbiAqIEBwYXJhbSBjZWxsQ291bnQgTnVtYmVyIG9mIHJvd3Mgb3IgY29sdW1ucyBpbiB0aGUgY3VycmVudCBheGlzXG4gKiBAcGFyYW0gY2VsbHNTaXplIFdpZHRoIG9yIGhlaWdodCBvZiBjZWxscyBmb3IgdGhlIGN1cnJlbnQgYXhpc1xuICogQHBhcmFtIGNvbXB1dGVNZXRhZGF0YUNhbGxiYWNrIE1ldGhvZCB0byBpbnZva2UgaWYgY2VsbCBtZXRhZGF0YSBzaG91bGQgYmUgcmVjYWxjdWxhdGVkXG4gKiBAcGFyYW0gY29tcHV0ZU1ldGFkYXRhQ2FsbGJhY2tQcm9wcyBQYXJhbWV0ZXJzIHRvIHBhc3MgdG8gOmNvbXB1dGVNZXRhZGF0YUNhbGxiYWNrXG4gKiBAcGFyYW0gbmV4dENlbGxzQ291bnQgTmV3bHkgdXBkYXRlZCBudW1iZXIgb2Ygcm93cyBvciBjb2x1bW5zIGluIHRoZSBjdXJyZW50IGF4aXNcbiAqIEBwYXJhbSBuZXh0Q2VsbHNTaXplIE5ld2x5IHVwZGF0ZWQgd2lkdGggb3IgaGVpZ2h0IG9mIGNlbGxzIGZvciB0aGUgY3VycmVudCBheGlzXG4gKiBAcGFyYW0gbmV4dFNjcm9sbFRvSW5kZXggTmV3bHkgdXBkYXRlZCBzY3JvbGwtdG8taW5kZXhcbiAqIEBwYXJhbSBzY3JvbGxUb0luZGV4IFNjcm9sbC10by1pbmRleFxuICogQHBhcmFtIHVwZGF0ZVNjcm9sbE9mZnNldEZvclNjcm9sbFRvSW5kZXggQ2FsbGJhY2sgdG8gaW52b2tlIGlmIHRoZSBzY3JvbGwgcG9zaXRpb24gc2hvdWxkIGJlIHJlY2FsY3VsYXRlZFxuICovXG5mdW5jdGlvbiBjYWxjdWxhdGVTaXplQW5kUG9zaXRpb25EYXRhQW5kVXBkYXRlU2Nyb2xsT2Zmc2V0KF9yZWYpIHtcbiAgdmFyIGNlbGxDb3VudCA9IF9yZWYuY2VsbENvdW50O1xuICB2YXIgY2VsbFNpemUgPSBfcmVmLmNlbGxTaXplO1xuICB2YXIgY29tcHV0ZU1ldGFkYXRhQ2FsbGJhY2sgPSBfcmVmLmNvbXB1dGVNZXRhZGF0YUNhbGxiYWNrO1xuICB2YXIgY29tcHV0ZU1ldGFkYXRhQ2FsbGJhY2tQcm9wcyA9IF9yZWYuY29tcHV0ZU1ldGFkYXRhQ2FsbGJhY2tQcm9wcztcbiAgdmFyIG5leHRDZWxsc0NvdW50ID0gX3JlZi5uZXh0Q2VsbHNDb3VudDtcbiAgdmFyIG5leHRDZWxsU2l6ZSA9IF9yZWYubmV4dENlbGxTaXplO1xuICB2YXIgbmV4dFNjcm9sbFRvSW5kZXggPSBfcmVmLm5leHRTY3JvbGxUb0luZGV4O1xuICB2YXIgc2Nyb2xsVG9JbmRleCA9IF9yZWYuc2Nyb2xsVG9JbmRleDtcbiAgdmFyIHVwZGF0ZVNjcm9sbE9mZnNldEZvclNjcm9sbFRvSW5kZXggPSBfcmVmLnVwZGF0ZVNjcm9sbE9mZnNldEZvclNjcm9sbFRvSW5kZXg7XG5cbiAgLy8gRG9uJ3QgY29tcGFyZSBjZWxsIHNpemVzIGlmIHRoZXkgYXJlIGZ1bmN0aW9ucyBiZWNhdXNlIGlubGluZSBmdW5jdGlvbnMgd291bGQgY2F1c2UgaW5maW5pdGUgbG9vcHMuXG4gIC8vIEluIHRoYXQgZXZlbnQgdXNlcnMgc2hvdWxkIHVzZSB0aGUgbWFudWFsIHJlY29tcHV0ZSBtZXRob2RzIHRvIGluZm9ybSBvZiBjaGFuZ2VzLlxuICBpZiAoY2VsbENvdW50ICE9PSBuZXh0Q2VsbHNDb3VudCB8fCAodHlwZW9mIGNlbGxTaXplID09PSAnbnVtYmVyJyB8fCB0eXBlb2YgbmV4dENlbGxTaXplID09PSAnbnVtYmVyJykgJiYgY2VsbFNpemUgIT09IG5leHRDZWxsU2l6ZSkge1xuICAgIGNvbXB1dGVNZXRhZGF0YUNhbGxiYWNrKGNvbXB1dGVNZXRhZGF0YUNhbGxiYWNrUHJvcHMpO1xuXG4gICAgLy8gVXBkYXRlZCBjZWxsIG1ldGFkYXRhIG1heSBoYXZlIGhpZGRlbiB0aGUgcHJldmlvdXMgc2Nyb2xsZWQtdG8gaXRlbS5cbiAgICAvLyBJbiB0aGlzIGNhc2Ugd2Ugc2hvdWxkIGFsc28gdXBkYXRlIHRoZSBzY3JvbGxUb3AgdG8gZW5zdXJlIGl0IHN0YXlzIHZpc2libGUuXG4gICAgaWYgKHNjcm9sbFRvSW5kZXggPj0gMCAmJiBzY3JvbGxUb0luZGV4ID09PSBuZXh0U2Nyb2xsVG9JbmRleCkge1xuICAgICAgdXBkYXRlU2Nyb2xsT2Zmc2V0Rm9yU2Nyb2xsVG9JbmRleCgpO1xuICAgIH1cbiAgfVxufSIsIlwidXNlIHN0cmljdFwiO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0cy5kZWZhdWx0ID0gZ2V0T3ZlcnNjYW5JbmRpY2VzO1xudmFyIFNDUk9MTF9ESVJFQ1RJT05fQkFDS1dBUkQgPSBleHBvcnRzLlNDUk9MTF9ESVJFQ1RJT05fQkFDS1dBUkQgPSAtMTtcbnZhciBTQ1JPTExfRElSRUNUSU9OX0ZJWEVEID0gZXhwb3J0cy5TQ1JPTExfRElSRUNUSU9OX0ZJWEVEID0gMDtcbnZhciBTQ1JPTExfRElSRUNUSU9OX0ZPUldBUkQgPSBleHBvcnRzLlNDUk9MTF9ESVJFQ1RJT05fRk9SV0FSRCA9IDE7XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgbnVtYmVyIG9mIGNlbGxzIHRvIG92ZXJzY2FuIGJlZm9yZSBhbmQgYWZ0ZXIgYSBzcGVjaWZpZWQgcmFuZ2UuXG4gKiBUaGlzIGZ1bmN0aW9uIGVuc3VyZXMgdGhhdCBvdmVyc2Nhbm5pbmcgZG9lc24ndCBleGNlZWQgdGhlIGF2YWlsYWJsZSBjZWxscy5cbiAqXG4gKiBAcGFyYW0gY2VsbENvdW50IE51bWJlciBvZiByb3dzIG9yIGNvbHVtbnMgaW4gdGhlIGN1cnJlbnQgYXhpc1xuICogQHBhcmFtIHNjcm9sbERpcmVjdGlvbiBPbmUgb2YgU0NST0xMX0RJUkVDVElPTl9CQUNLV0FSRFxuICogQHBhcmFtIG92ZXJzY2FuQ2VsbHNDb3VudCBNYXhpbXVtIG51bWJlciBvZiBjZWxscyB0byBvdmVyLXJlbmRlciBpbiBlaXRoZXIgZGlyZWN0aW9uXG4gKiBAcGFyYW0gc3RhcnRJbmRleCBCZWdpbiBvZiByYW5nZSBvZiB2aXNpYmxlIGNlbGxzXG4gKiBAcGFyYW0gc3RvcEluZGV4IEVuZCBvZiByYW5nZSBvZiB2aXNpYmxlIGNlbGxzXG4gKi9cbmZ1bmN0aW9uIGdldE92ZXJzY2FuSW5kaWNlcyhfcmVmKSB7XG4gIHZhciBjZWxsQ291bnQgPSBfcmVmLmNlbGxDb3VudDtcbiAgdmFyIG92ZXJzY2FuQ2VsbHNDb3VudCA9IF9yZWYub3ZlcnNjYW5DZWxsc0NvdW50O1xuICB2YXIgc2Nyb2xsRGlyZWN0aW9uID0gX3JlZi5zY3JvbGxEaXJlY3Rpb247XG4gIHZhciBzdGFydEluZGV4ID0gX3JlZi5zdGFydEluZGV4O1xuICB2YXIgc3RvcEluZGV4ID0gX3JlZi5zdG9wSW5kZXg7XG5cbiAgdmFyIG92ZXJzY2FuU3RhcnRJbmRleCA9IHZvaWQgMDtcbiAgdmFyIG92ZXJzY2FuU3RvcEluZGV4ID0gdm9pZCAwO1xuXG4gIGlmIChzY3JvbGxEaXJlY3Rpb24gPT09IFNDUk9MTF9ESVJFQ1RJT05fRk9SV0FSRCkge1xuICAgIG92ZXJzY2FuU3RhcnRJbmRleCA9IHN0YXJ0SW5kZXg7XG4gICAgb3ZlcnNjYW5TdG9wSW5kZXggPSBzdG9wSW5kZXggKyBvdmVyc2NhbkNlbGxzQ291bnQgKiAyO1xuICB9IGVsc2UgaWYgKHNjcm9sbERpcmVjdGlvbiA9PT0gU0NST0xMX0RJUkVDVElPTl9CQUNLV0FSRCkge1xuICAgIG92ZXJzY2FuU3RhcnRJbmRleCA9IHN0YXJ0SW5kZXggLSBvdmVyc2NhbkNlbGxzQ291bnQgKiAyO1xuICAgIG92ZXJzY2FuU3RvcEluZGV4ID0gc3RvcEluZGV4O1xuICB9IGVsc2Uge1xuICAgIG92ZXJzY2FuU3RhcnRJbmRleCA9IHN0YXJ0SW5kZXggLSBvdmVyc2NhbkNlbGxzQ291bnQ7XG4gICAgb3ZlcnNjYW5TdG9wSW5kZXggPSBzdG9wSW5kZXggKyBvdmVyc2NhbkNlbGxzQ291bnQ7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIG92ZXJzY2FuU3RhcnRJbmRleDogTWF0aC5tYXgoMCwgb3ZlcnNjYW5TdGFydEluZGV4KSxcbiAgICBvdmVyc2NhblN0b3BJbmRleDogTWF0aC5taW4oY2VsbENvdW50IC0gMSwgb3ZlcnNjYW5TdG9wSW5kZXgpXG4gIH07XG59IiwiJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0cy5kZWZhdWx0ID0gdXBkYXRlU2Nyb2xsSW5kZXhIZWxwZXI7XG4vKipcbiAqIEhlbHBlciBmdW5jdGlvbiB0aGF0IGRldGVybWluZXMgd2hlbiB0byB1cGRhdGUgc2Nyb2xsIG9mZnNldHMgdG8gZW5zdXJlIHRoYXQgYSBzY3JvbGwtdG8taW5kZXggcmVtYWlucyB2aXNpYmxlLlxuICogVGhpcyBmdW5jdGlvbiBhbHNvIGVuc3VyZXMgdGhhdCB0aGUgc2Nyb2xsIG9mc2V0IGlzbid0IHBhc3QgdGhlIGxhc3QgY29sdW1uL3JvdyBvZiBjZWxscy5cbiAqXG4gKiBAcGFyYW0gY2VsbHNTaXplIFdpZHRoIG9yIGhlaWdodCBvZiBjZWxscyBmb3IgdGhlIGN1cnJlbnQgYXhpc1xuICogQHBhcmFtIGNlbGxTaXplQW5kUG9zaXRpb25NYW5hZ2VyIE1hbmFnZXMgc2l6ZSBhbmQgcG9zaXRpb24gbWV0YWRhdGEgb2YgY2VsbHNcbiAqIEBwYXJhbSBwcmV2aW91c0NlbGxzQ291bnQgUHJldmlvdXMgbnVtYmVyIG9mIHJvd3Mgb3IgY29sdW1uc1xuICogQHBhcmFtIHByZXZpb3VzQ2VsbHNTaXplIFByZXZpb3VzIHdpZHRoIG9yIGhlaWdodCBvZiBjZWxsc1xuICogQHBhcmFtIHByZXZpb3VzU2Nyb2xsVG9JbmRleCBQcmV2aW91cyBzY3JvbGwtdG8taW5kZXhcbiAqIEBwYXJhbSBwcmV2aW91c1NpemUgUHJldmlvdXMgd2lkdGggb3IgaGVpZ2h0IG9mIHRoZSB2aXJ0dWFsaXplZCBjb250YWluZXJcbiAqIEBwYXJhbSBzY3JvbGxPZmZzZXQgQ3VycmVudCBzY3JvbGxMZWZ0IG9yIHNjcm9sbFRvcFxuICogQHBhcmFtIHNjcm9sbFRvSW5kZXggU2Nyb2xsLXRvLWluZGV4XG4gKiBAcGFyYW0gc2l6ZSBXaWR0aCBvciBoZWlnaHQgb2YgdGhlIHZpcnR1YWxpemVkIGNvbnRhaW5lclxuICogQHBhcmFtIHVwZGF0ZVNjcm9sbEluZGV4Q2FsbGJhY2sgQ2FsbGJhY2sgdG8gaW52b2tlIHdpdGggYW4gc2Nyb2xsLXRvLWluZGV4IHZhbHVlXG4gKi9cbmZ1bmN0aW9uIHVwZGF0ZVNjcm9sbEluZGV4SGVscGVyKF9yZWYpIHtcbiAgdmFyIGNlbGxTaXplID0gX3JlZi5jZWxsU2l6ZTtcbiAgdmFyIGNlbGxTaXplQW5kUG9zaXRpb25NYW5hZ2VyID0gX3JlZi5jZWxsU2l6ZUFuZFBvc2l0aW9uTWFuYWdlcjtcbiAgdmFyIHByZXZpb3VzQ2VsbHNDb3VudCA9IF9yZWYucHJldmlvdXNDZWxsc0NvdW50O1xuICB2YXIgcHJldmlvdXNDZWxsU2l6ZSA9IF9yZWYucHJldmlvdXNDZWxsU2l6ZTtcbiAgdmFyIHByZXZpb3VzU2Nyb2xsVG9BbGlnbm1lbnQgPSBfcmVmLnByZXZpb3VzU2Nyb2xsVG9BbGlnbm1lbnQ7XG4gIHZhciBwcmV2aW91c1Njcm9sbFRvSW5kZXggPSBfcmVmLnByZXZpb3VzU2Nyb2xsVG9JbmRleDtcbiAgdmFyIHByZXZpb3VzU2l6ZSA9IF9yZWYucHJldmlvdXNTaXplO1xuICB2YXIgc2Nyb2xsT2Zmc2V0ID0gX3JlZi5zY3JvbGxPZmZzZXQ7XG4gIHZhciBzY3JvbGxUb0FsaWdubWVudCA9IF9yZWYuc2Nyb2xsVG9BbGlnbm1lbnQ7XG4gIHZhciBzY3JvbGxUb0luZGV4ID0gX3JlZi5zY3JvbGxUb0luZGV4O1xuICB2YXIgc2l6ZSA9IF9yZWYuc2l6ZTtcbiAgdmFyIHVwZGF0ZVNjcm9sbEluZGV4Q2FsbGJhY2sgPSBfcmVmLnVwZGF0ZVNjcm9sbEluZGV4Q2FsbGJhY2s7XG5cbiAgdmFyIGNlbGxDb3VudCA9IGNlbGxTaXplQW5kUG9zaXRpb25NYW5hZ2VyLmdldENlbGxDb3VudCgpO1xuICB2YXIgaGFzU2Nyb2xsVG9JbmRleCA9IHNjcm9sbFRvSW5kZXggPj0gMCAmJiBzY3JvbGxUb0luZGV4IDwgY2VsbENvdW50O1xuICB2YXIgc2l6ZUhhc0NoYW5nZWQgPSBzaXplICE9PSBwcmV2aW91c1NpemUgfHwgIXByZXZpb3VzQ2VsbFNpemUgfHwgdHlwZW9mIGNlbGxTaXplID09PSAnbnVtYmVyJyAmJiBjZWxsU2l6ZSAhPT0gcHJldmlvdXNDZWxsU2l6ZTtcblxuICAvLyBJZiB3ZSBoYXZlIGEgbmV3IHNjcm9sbCB0YXJnZXQgT1IgaWYgaGVpZ2h0L3Jvdy1oZWlnaHQgaGFzIGNoYW5nZWQsXG4gIC8vIFdlIHNob3VsZCBlbnN1cmUgdGhhdCB0aGUgc2Nyb2xsIHRhcmdldCBpcyB2aXNpYmxlLlxuICBpZiAoaGFzU2Nyb2xsVG9JbmRleCAmJiAoc2l6ZUhhc0NoYW5nZWQgfHwgc2Nyb2xsVG9BbGlnbm1lbnQgIT09IHByZXZpb3VzU2Nyb2xsVG9BbGlnbm1lbnQgfHwgc2Nyb2xsVG9JbmRleCAhPT0gcHJldmlvdXNTY3JvbGxUb0luZGV4KSkge1xuICAgIHVwZGF0ZVNjcm9sbEluZGV4Q2FsbGJhY2soc2Nyb2xsVG9JbmRleCk7XG5cbiAgICAvLyBJZiB3ZSBkb24ndCBoYXZlIGEgc2VsZWN0ZWQgaXRlbSBidXQgbGlzdCBzaXplIG9yIG51bWJlciBvZiBjaGlsZHJlbiBoYXZlIGRlY3JlYXNlZCxcbiAgICAvLyBNYWtlIHN1cmUgd2UgYXJlbid0IHNjcm9sbGVkIHRvbyBmYXIgcGFzdCB0aGUgY3VycmVudCBjb250ZW50LlxuICB9IGVsc2UgaWYgKCFoYXNTY3JvbGxUb0luZGV4ICYmIGNlbGxDb3VudCA+IDAgJiYgKHNpemUgPCBwcmV2aW91c1NpemUgfHwgY2VsbENvdW50IDwgcHJldmlvdXNDZWxsc0NvdW50KSkge1xuICAgIC8vIFdlIG5lZWQgdG8gZW5zdXJlIHRoYXQgdGhlIGN1cnJlbnQgc2Nyb2xsIG9mZnNldCBpcyBzdGlsbCB3aXRoaW4gdGhlIGNvbGxlY3Rpb24ncyByYW5nZS5cbiAgICAvLyBUbyBkbyB0aGlzLCB3ZSBkb24ndCBuZWVkIHRvIG1lYXN1cmUgZXZlcnl0aGluZzsgQ2VsbE1lYXN1cmVyIHdvdWxkIHBlcmZvcm0gcG9vcmx5LlxuICAgIC8vIEp1c3QgY2hlY2sgdG8gbWFrZSBzdXJlIHdlJ3JlIHN0aWxsIG9rYXkuXG4gICAgLy8gT25seSBhZGp1c3QgdGhlIHNjcm9sbCBwb3NpdGlvbiBpZiB3ZSd2ZSBzY3JvbGxlZCBiZWxvdyB0aGUgbGFzdCBzZXQgb2Ygcm93cy5cbiAgICBpZiAoc2Nyb2xsT2Zmc2V0ID4gY2VsbFNpemVBbmRQb3NpdGlvbk1hbmFnZXIuZ2V0VG90YWxTaXplKCkgLSBzaXplKSB7XG4gICAgICB1cGRhdGVTY3JvbGxJbmRleENhbGxiYWNrKGNlbGxDb3VudCAtIDEpO1xuICAgIH1cbiAgfVxufSIsIid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9jcmVhdGVDbGFzcyA9IGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmIChcInZhbHVlXCIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0oKTtcblxuZXhwb3J0cy5pc1JhbmdlVmlzaWJsZSA9IGlzUmFuZ2VWaXNpYmxlO1xuZXhwb3J0cy5zY2FuRm9yVW5sb2FkZWRSYW5nZXMgPSBzY2FuRm9yVW5sb2FkZWRSYW5nZXM7XG5leHBvcnRzLmZvcmNlVXBkYXRlUmVhY3RWaXJ0dWFsaXplZENvbXBvbmVudCA9IGZvcmNlVXBkYXRlUmVhY3RWaXJ0dWFsaXplZENvbXBvbmVudDtcblxudmFyIF9yZWFjdCA9IHJlcXVpcmUoJ3JlYWN0Jyk7XG5cbnZhciBfcmVhY3RBZGRvbnNTaGFsbG93Q29tcGFyZSA9IHJlcXVpcmUoJ3JlYWN0LWFkZG9ucy1zaGFsbG93LWNvbXBhcmUnKTtcblxudmFyIF9yZWFjdEFkZG9uc1NoYWxsb3dDb21wYXJlMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3JlYWN0QWRkb25zU2hhbGxvd0NvbXBhcmUpO1xuXG52YXIgX2NyZWF0ZUNhbGxiYWNrTWVtb2l6ZXIgPSByZXF1aXJlKCcuLi91dGlscy9jcmVhdGVDYWxsYmFja01lbW9pemVyJyk7XG5cbnZhciBfY3JlYXRlQ2FsbGJhY2tNZW1vaXplcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9jcmVhdGVDYWxsYmFja01lbW9pemVyKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgZGVmYXVsdDogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uXCIpOyB9IH1cblxuZnVuY3Rpb24gX3Bvc3NpYmxlQ29uc3RydWN0b3JSZXR1cm4oc2VsZiwgY2FsbCkgeyBpZiAoIXNlbGYpIHsgdGhyb3cgbmV3IFJlZmVyZW5jZUVycm9yKFwidGhpcyBoYXNuJ3QgYmVlbiBpbml0aWFsaXNlZCAtIHN1cGVyKCkgaGFzbid0IGJlZW4gY2FsbGVkXCIpOyB9IHJldHVybiBjYWxsICYmICh0eXBlb2YgY2FsbCA9PT0gXCJvYmplY3RcIiB8fCB0eXBlb2YgY2FsbCA9PT0gXCJmdW5jdGlvblwiKSA/IGNhbGwgOiBzZWxmOyB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09IFwiZnVuY3Rpb25cIiAmJiBzdXBlckNsYXNzICE9PSBudWxsKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoXCJTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90IFwiICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBPYmplY3Quc2V0UHJvdG90eXBlT2YgPyBPYmplY3Quc2V0UHJvdG90eXBlT2Yoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIDogc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG4vKipcbiAqIEhpZ2hlci1vcmRlciBjb21wb25lbnQgdGhhdCBtYW5hZ2VzIGxhenktbG9hZGluZyBmb3IgXCJpbmZpbml0ZVwiIGRhdGEuXG4gKiBUaGlzIGNvbXBvbmVudCBkZWNvcmF0ZXMgYSB2aXJ0dWFsIGNvbXBvbmVudCBhbmQganVzdC1pbi10aW1lIHByZWZldGNoZXMgcm93cyBhcyBhIHVzZXIgc2Nyb2xscy5cbiAqIEl0IGlzIGludGVuZGVkIGFzIGEgY29udmVuaWVuY2UgY29tcG9uZW50OyBmb3JrIGl0IGlmIHlvdSdkIGxpa2UgZmluZXItZ3JhaW5lZCBjb250cm9sIG92ZXIgZGF0YS1sb2FkaW5nLlxuICovXG52YXIgSW5maW5pdGVMb2FkZXIgPSBmdW5jdGlvbiAoX0NvbXBvbmVudCkge1xuICBfaW5oZXJpdHMoSW5maW5pdGVMb2FkZXIsIF9Db21wb25lbnQpO1xuXG4gIGZ1bmN0aW9uIEluZmluaXRlTG9hZGVyKHByb3BzLCBjb250ZXh0KSB7XG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIEluZmluaXRlTG9hZGVyKTtcblxuICAgIHZhciBfdGhpcyA9IF9wb3NzaWJsZUNvbnN0cnVjdG9yUmV0dXJuKHRoaXMsIChJbmZpbml0ZUxvYWRlci5fX3Byb3RvX18gfHwgT2JqZWN0LmdldFByb3RvdHlwZU9mKEluZmluaXRlTG9hZGVyKSkuY2FsbCh0aGlzLCBwcm9wcywgY29udGV4dCkpO1xuXG4gICAgX3RoaXMuX2xvYWRNb3JlUm93c01lbW9pemVyID0gKDAsIF9jcmVhdGVDYWxsYmFja01lbW9pemVyMi5kZWZhdWx0KSgpO1xuXG4gICAgX3RoaXMuX29uUm93c1JlbmRlcmVkID0gX3RoaXMuX29uUm93c1JlbmRlcmVkLmJpbmQoX3RoaXMpO1xuICAgIF90aGlzLl9yZWdpc3RlckNoaWxkID0gX3RoaXMuX3JlZ2lzdGVyQ2hpbGQuYmluZChfdGhpcyk7XG4gICAgcmV0dXJuIF90aGlzO1xuICB9XG5cbiAgX2NyZWF0ZUNsYXNzKEluZmluaXRlTG9hZGVyLCBbe1xuICAgIGtleTogJ3JlbmRlcicsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJlbmRlcigpIHtcbiAgICAgIHZhciBjaGlsZHJlbiA9IHRoaXMucHJvcHMuY2hpbGRyZW47XG5cblxuICAgICAgcmV0dXJuIGNoaWxkcmVuKHtcbiAgICAgICAgb25Sb3dzUmVuZGVyZWQ6IHRoaXMuX29uUm93c1JlbmRlcmVkLFxuICAgICAgICByZWdpc3RlckNoaWxkOiB0aGlzLl9yZWdpc3RlckNoaWxkXG4gICAgICB9KTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdzaG91bGRDb21wb25lbnRVcGRhdGUnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBzaG91bGRDb21wb25lbnRVcGRhdGUobmV4dFByb3BzLCBuZXh0U3RhdGUpIHtcbiAgICAgIHJldHVybiAoMCwgX3JlYWN0QWRkb25zU2hhbGxvd0NvbXBhcmUyLmRlZmF1bHQpKHRoaXMsIG5leHRQcm9wcywgbmV4dFN0YXRlKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfbG9hZFVubG9hZGVkUmFuZ2VzJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gX2xvYWRVbmxvYWRlZFJhbmdlcyh1bmxvYWRlZFJhbmdlcykge1xuICAgICAgdmFyIF90aGlzMiA9IHRoaXM7XG5cbiAgICAgIHZhciBsb2FkTW9yZVJvd3MgPSB0aGlzLnByb3BzLmxvYWRNb3JlUm93cztcblxuXG4gICAgICB1bmxvYWRlZFJhbmdlcy5mb3JFYWNoKGZ1bmN0aW9uICh1bmxvYWRlZFJhbmdlKSB7XG4gICAgICAgIHZhciBwcm9taXNlID0gbG9hZE1vcmVSb3dzKHVubG9hZGVkUmFuZ2UpO1xuICAgICAgICBpZiAocHJvbWlzZSkge1xuICAgICAgICAgIHByb21pc2UudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAvLyBSZWZyZXNoIHRoZSB2aXNpYmxlIHJvd3MgaWYgYW55IG9mIHRoZW0gaGF2ZSBqdXN0IGJlZW4gbG9hZGVkLlxuICAgICAgICAgICAgLy8gT3RoZXJ3aXNlIHRoZXkgd2lsbCByZW1haW4gaW4gdGhlaXIgdW5sb2FkZWQgdmlzdWFsIHN0YXRlLlxuICAgICAgICAgICAgaWYgKGlzUmFuZ2VWaXNpYmxlKHtcbiAgICAgICAgICAgICAgbGFzdFJlbmRlcmVkU3RhcnRJbmRleDogX3RoaXMyLl9sYXN0UmVuZGVyZWRTdGFydEluZGV4LFxuICAgICAgICAgICAgICBsYXN0UmVuZGVyZWRTdG9wSW5kZXg6IF90aGlzMi5fbGFzdFJlbmRlcmVkU3RvcEluZGV4LFxuICAgICAgICAgICAgICBzdGFydEluZGV4OiB1bmxvYWRlZFJhbmdlLnN0YXJ0SW5kZXgsXG4gICAgICAgICAgICAgIHN0b3BJbmRleDogdW5sb2FkZWRSYW5nZS5zdG9wSW5kZXhcbiAgICAgICAgICAgIH0pKSB7XG4gICAgICAgICAgICAgIGlmIChfdGhpczIuX3JlZ2lzdGVyZWRDaGlsZCkge1xuICAgICAgICAgICAgICAgIGZvcmNlVXBkYXRlUmVhY3RWaXJ0dWFsaXplZENvbXBvbmVudChfdGhpczIuX3JlZ2lzdGVyZWRDaGlsZCk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uUm93c1JlbmRlcmVkJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uUm93c1JlbmRlcmVkKF9yZWYpIHtcbiAgICAgIHZhciBfdGhpczMgPSB0aGlzO1xuXG4gICAgICB2YXIgc3RhcnRJbmRleCA9IF9yZWYuc3RhcnRJbmRleDtcbiAgICAgIHZhciBzdG9wSW5kZXggPSBfcmVmLnN0b3BJbmRleDtcbiAgICAgIHZhciBfcHJvcHMgPSB0aGlzLnByb3BzO1xuICAgICAgdmFyIGlzUm93TG9hZGVkID0gX3Byb3BzLmlzUm93TG9hZGVkO1xuICAgICAgdmFyIG1pbmltdW1CYXRjaFNpemUgPSBfcHJvcHMubWluaW11bUJhdGNoU2l6ZTtcbiAgICAgIHZhciByb3dDb3VudCA9IF9wcm9wcy5yb3dDb3VudDtcbiAgICAgIHZhciB0aHJlc2hvbGQgPSBfcHJvcHMudGhyZXNob2xkO1xuXG5cbiAgICAgIHRoaXMuX2xhc3RSZW5kZXJlZFN0YXJ0SW5kZXggPSBzdGFydEluZGV4O1xuICAgICAgdGhpcy5fbGFzdFJlbmRlcmVkU3RvcEluZGV4ID0gc3RvcEluZGV4O1xuXG4gICAgICB2YXIgdW5sb2FkZWRSYW5nZXMgPSBzY2FuRm9yVW5sb2FkZWRSYW5nZXMoe1xuICAgICAgICBpc1Jvd0xvYWRlZDogaXNSb3dMb2FkZWQsXG4gICAgICAgIG1pbmltdW1CYXRjaFNpemU6IG1pbmltdW1CYXRjaFNpemUsXG4gICAgICAgIHJvd0NvdW50OiByb3dDb3VudCxcbiAgICAgICAgc3RhcnRJbmRleDogTWF0aC5tYXgoMCwgc3RhcnRJbmRleCAtIHRocmVzaG9sZCksXG4gICAgICAgIHN0b3BJbmRleDogTWF0aC5taW4ocm93Q291bnQgLSAxLCBzdG9wSW5kZXggKyB0aHJlc2hvbGQpXG4gICAgICB9KTtcblxuICAgICAgLy8gRm9yIG1lbW9pemUgY29tcGFyaXNvblxuICAgICAgdmFyIHNxdWFzaGVkVW5sb2FkZWRSYW5nZXMgPSB1bmxvYWRlZFJhbmdlcy5yZWR1Y2UoZnVuY3Rpb24gKHJlZHVjZWQsIHVubG9hZGVkUmFuZ2UpIHtcbiAgICAgICAgcmV0dXJuIHJlZHVjZWQuY29uY2F0KFt1bmxvYWRlZFJhbmdlLnN0YXJ0SW5kZXgsIHVubG9hZGVkUmFuZ2Uuc3RvcEluZGV4XSk7XG4gICAgICB9LCBbXSk7XG5cbiAgICAgIHRoaXMuX2xvYWRNb3JlUm93c01lbW9pemVyKHtcbiAgICAgICAgY2FsbGJhY2s6IGZ1bmN0aW9uIGNhbGxiYWNrKCkge1xuICAgICAgICAgIF90aGlzMy5fbG9hZFVubG9hZGVkUmFuZ2VzKHVubG9hZGVkUmFuZ2VzKTtcbiAgICAgICAgfSxcbiAgICAgICAgaW5kaWNlczogeyBzcXVhc2hlZFVubG9hZGVkUmFuZ2VzOiBzcXVhc2hlZFVubG9hZGVkUmFuZ2VzIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19yZWdpc3RlckNoaWxkJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gX3JlZ2lzdGVyQ2hpbGQocmVnaXN0ZXJlZENoaWxkKSB7XG4gICAgICB0aGlzLl9yZWdpc3RlcmVkQ2hpbGQgPSByZWdpc3RlcmVkQ2hpbGQ7XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIEluZmluaXRlTG9hZGVyO1xufShfcmVhY3QuQ29tcG9uZW50KTtcblxuLyoqXG4gKiBEZXRlcm1pbmVzIGlmIHRoZSBzcGVjaWZpZWQgc3RhcnQvc3RvcCByYW5nZSBpcyB2aXNpYmxlIGJhc2VkIG9uIHRoZSBtb3N0IHJlY2VudGx5IHJlbmRlcmVkIHJhbmdlLlxuICovXG5cblxuSW5maW5pdGVMb2FkZXIucHJvcFR5cGVzID0ge1xuICAvKipcbiAgICogRnVuY3Rpb24gcmVzcG9uZGlibGUgZm9yIHJlbmRlcmluZyBhIHZpcnR1YWxpemVkIGNvbXBvbmVudC5cbiAgICogVGhpcyBmdW5jdGlvbiBzaG91bGQgaW1wbGVtZW50IHRoZSBmb2xsb3dpbmcgc2lnbmF0dXJlOlxuICAgKiAoeyBvblJvd3NSZW5kZXJlZCwgcmVnaXN0ZXJDaGlsZCB9KSA9PiBQcm9wVHlwZXMuZWxlbWVudFxuICAgKlxuICAgKiBUaGUgc3BlY2lmaWVkIDpvblJvd3NSZW5kZXJlZCBmdW5jdGlvbiBzaG91bGQgYmUgcGFzc2VkIHRocm91Z2ggdG8gdGhlIGNoaWxkJ3MgOm9uUm93c1JlbmRlcmVkIHByb3BlcnR5LlxuICAgKiBUaGUgOnJlZ2lzdGVyQ2hpbGQgY2FsbGJhY2sgc2hvdWxkIGJlIHNldCBhcyB0aGUgdmlydHVhbGl6ZWQgY29tcG9uZW50J3MgOnJlZi5cbiAgICovXG4gIGNoaWxkcmVuOiBfcmVhY3QuUHJvcFR5cGVzLmZ1bmMuaXNSZXF1aXJlZCxcblxuICAvKipcbiAgICogRnVuY3Rpb24gcmVzcG9uc2libGUgZm9yIHRyYWNraW5nIHRoZSBsb2FkZWQgc3RhdGUgb2YgZWFjaCByb3cuXG4gICAqIEl0IHNob3VsZCBpbXBsZW1lbnQgdGhlIGZvbGxvd2luZyBzaWduYXR1cmU6ICh7IGluZGV4OiBudW1iZXIgfSk6IGJvb2xlYW5cbiAgICovXG4gIGlzUm93TG9hZGVkOiBfcmVhY3QuUHJvcFR5cGVzLmZ1bmMuaXNSZXF1aXJlZCxcblxuICAvKipcbiAgICogQ2FsbGJhY2sgdG8gYmUgaW52b2tlZCB3aGVuIG1vcmUgcm93cyBtdXN0IGJlIGxvYWRlZC5cbiAgICogSXQgc2hvdWxkIGltcGxlbWVudCB0aGUgZm9sbG93aW5nIHNpZ25hdHVyZTogKHsgc3RhcnRJbmRleCwgc3RvcEluZGV4IH0pOiBQcm9taXNlXG4gICAqIFRoZSByZXR1cm5lZCBQcm9taXNlIHNob3VsZCBiZSByZXNvbHZlZCBvbmNlIHJvdyBkYXRhIGhhcyBmaW5pc2hlZCBsb2FkaW5nLlxuICAgKiBJdCB3aWxsIGJlIHVzZWQgdG8gZGV0ZXJtaW5lIHdoZW4gdG8gcmVmcmVzaCB0aGUgbGlzdCB3aXRoIHRoZSBuZXdseS1sb2FkZWQgZGF0YS5cbiAgICogVGhpcyBjYWxsYmFjayBtYXkgYmUgY2FsbGVkIG11bHRpcGxlIHRpbWVzIGluIHJlYWN0aW9uIHRvIGEgc2luZ2xlIHNjcm9sbCBldmVudC5cbiAgICovXG4gIGxvYWRNb3JlUm93czogX3JlYWN0LlByb3BUeXBlcy5mdW5jLmlzUmVxdWlyZWQsXG5cbiAgLyoqXG4gICAqIE1pbmltdW0gbnVtYmVyIG9mIHJvd3MgdG8gYmUgbG9hZGVkIGF0IGEgdGltZS5cbiAgICogVGhpcyBwcm9wZXJ0eSBjYW4gYmUgdXNlZCB0byBiYXRjaCByZXF1ZXN0cyB0byByZWR1Y2UgSFRUUCByZXF1ZXN0cy5cbiAgICovXG4gIG1pbmltdW1CYXRjaFNpemU6IF9yZWFjdC5Qcm9wVHlwZXMubnVtYmVyLmlzUmVxdWlyZWQsXG5cbiAgLyoqXG4gICAqIE51bWJlciBvZiByb3dzIGluIGxpc3Q7IGNhbiBiZSBhcmJpdHJhcnkgaGlnaCBudW1iZXIgaWYgYWN0dWFsIG51bWJlciBpcyB1bmtub3duLlxuICAgKi9cbiAgcm93Q291bnQ6IF9yZWFjdC5Qcm9wVHlwZXMubnVtYmVyLmlzUmVxdWlyZWQsXG5cbiAgLyoqXG4gICAqIFRocmVzaG9sZCBhdCB3aGljaCB0byBwcmUtZmV0Y2ggZGF0YS5cbiAgICogQSB0aHJlc2hvbGQgWCBtZWFucyB0aGF0IGRhdGEgd2lsbCBzdGFydCBsb2FkaW5nIHdoZW4gYSB1c2VyIHNjcm9sbHMgd2l0aGluIFggcm93cy5cbiAgICogVGhpcyB2YWx1ZSBkZWZhdWx0cyB0byAxNS5cbiAgICovXG4gIHRocmVzaG9sZDogX3JlYWN0LlByb3BUeXBlcy5udW1iZXIuaXNSZXF1aXJlZFxufTtcbkluZmluaXRlTG9hZGVyLmRlZmF1bHRQcm9wcyA9IHtcbiAgbWluaW11bUJhdGNoU2l6ZTogMTAsXG4gIHJvd0NvdW50OiAwLFxuICB0aHJlc2hvbGQ6IDE1XG59O1xuZXhwb3J0cy5kZWZhdWx0ID0gSW5maW5pdGVMb2FkZXI7XG5mdW5jdGlvbiBpc1JhbmdlVmlzaWJsZShfcmVmMikge1xuICB2YXIgbGFzdFJlbmRlcmVkU3RhcnRJbmRleCA9IF9yZWYyLmxhc3RSZW5kZXJlZFN0YXJ0SW5kZXg7XG4gIHZhciBsYXN0UmVuZGVyZWRTdG9wSW5kZXggPSBfcmVmMi5sYXN0UmVuZGVyZWRTdG9wSW5kZXg7XG4gIHZhciBzdGFydEluZGV4ID0gX3JlZjIuc3RhcnRJbmRleDtcbiAgdmFyIHN0b3BJbmRleCA9IF9yZWYyLnN0b3BJbmRleDtcblxuICByZXR1cm4gIShzdGFydEluZGV4ID4gbGFzdFJlbmRlcmVkU3RvcEluZGV4IHx8IHN0b3BJbmRleCA8IGxhc3RSZW5kZXJlZFN0YXJ0SW5kZXgpO1xufVxuXG4vKipcbiAqIFJldHVybnMgYWxsIG9mIHRoZSByYW5nZXMgd2l0aGluIGEgbGFyZ2VyIHJhbmdlIHRoYXQgY29udGFpbiB1bmxvYWRlZCByb3dzLlxuICovXG5mdW5jdGlvbiBzY2FuRm9yVW5sb2FkZWRSYW5nZXMoX3JlZjMpIHtcbiAgdmFyIGlzUm93TG9hZGVkID0gX3JlZjMuaXNSb3dMb2FkZWQ7XG4gIHZhciBtaW5pbXVtQmF0Y2hTaXplID0gX3JlZjMubWluaW11bUJhdGNoU2l6ZTtcbiAgdmFyIHJvd0NvdW50ID0gX3JlZjMucm93Q291bnQ7XG4gIHZhciBzdGFydEluZGV4ID0gX3JlZjMuc3RhcnRJbmRleDtcbiAgdmFyIHN0b3BJbmRleCA9IF9yZWYzLnN0b3BJbmRleDtcblxuICB2YXIgdW5sb2FkZWRSYW5nZXMgPSBbXTtcblxuICB2YXIgcmFuZ2VTdGFydEluZGV4ID0gbnVsbDtcbiAgdmFyIHJhbmdlU3RvcEluZGV4ID0gbnVsbDtcblxuICBmb3IgKHZhciBpbmRleCA9IHN0YXJ0SW5kZXg7IGluZGV4IDw9IHN0b3BJbmRleDsgaW5kZXgrKykge1xuICAgIHZhciBsb2FkZWQgPSBpc1Jvd0xvYWRlZCh7IGluZGV4OiBpbmRleCB9KTtcblxuICAgIGlmICghbG9hZGVkKSB7XG4gICAgICByYW5nZVN0b3BJbmRleCA9IGluZGV4O1xuICAgICAgaWYgKHJhbmdlU3RhcnRJbmRleCA9PT0gbnVsbCkge1xuICAgICAgICByYW5nZVN0YXJ0SW5kZXggPSBpbmRleDtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHJhbmdlU3RvcEluZGV4ICE9PSBudWxsKSB7XG4gICAgICB1bmxvYWRlZFJhbmdlcy5wdXNoKHtcbiAgICAgICAgc3RhcnRJbmRleDogcmFuZ2VTdGFydEluZGV4LFxuICAgICAgICBzdG9wSW5kZXg6IHJhbmdlU3RvcEluZGV4XG4gICAgICB9KTtcblxuICAgICAgcmFuZ2VTdGFydEluZGV4ID0gcmFuZ2VTdG9wSW5kZXggPSBudWxsO1xuICAgIH1cbiAgfVxuXG4gIC8vIElmIDpyYW5nZVN0b3BJbmRleCBpcyBub3QgbnVsbCBpdCBtZWFucyB3ZSBoYXZlbid0IHJhbiBvdXQgb2YgdW5sb2FkZWQgcm93cy5cbiAgLy8gU2NhbiBmb3J3YXJkIHRvIHRyeSBmaWxsaW5nIG91ciA6bWluaW11bUJhdGNoU2l6ZS5cbiAgaWYgKHJhbmdlU3RvcEluZGV4ICE9PSBudWxsKSB7XG4gICAgdmFyIHBvdGVudGlhbFN0b3BJbmRleCA9IE1hdGgubWluKE1hdGgubWF4KHJhbmdlU3RvcEluZGV4LCByYW5nZVN0YXJ0SW5kZXggKyBtaW5pbXVtQmF0Y2hTaXplIC0gMSksIHJvd0NvdW50IC0gMSk7XG5cbiAgICBmb3IgKHZhciBfaW5kZXggPSByYW5nZVN0b3BJbmRleCArIDE7IF9pbmRleCA8PSBwb3RlbnRpYWxTdG9wSW5kZXg7IF9pbmRleCsrKSB7XG4gICAgICBpZiAoIWlzUm93TG9hZGVkKHsgaW5kZXg6IF9pbmRleCB9KSkge1xuICAgICAgICByYW5nZVN0b3BJbmRleCA9IF9pbmRleDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHVubG9hZGVkUmFuZ2VzLnB1c2goe1xuICAgICAgc3RhcnRJbmRleDogcmFuZ2VTdGFydEluZGV4LFxuICAgICAgc3RvcEluZGV4OiByYW5nZVN0b3BJbmRleFxuICAgIH0pO1xuICB9XG5cbiAgLy8gQ2hlY2sgdG8gc2VlIGlmIG91ciBmaXJzdCByYW5nZSBlbmRlZCBwcmVtYXR1cmVseS5cbiAgLy8gSW4gdGhpcyBjYXNlIHdlIHNob3VsZCBzY2FuIGJhY2t3YXJkcyB0byB0cnkgZmlsbGluZyBvdXIgOm1pbmltdW1CYXRjaFNpemUuXG4gIGlmICh1bmxvYWRlZFJhbmdlcy5sZW5ndGgpIHtcbiAgICB2YXIgZmlyc3RVbmxvYWRlZFJhbmdlID0gdW5sb2FkZWRSYW5nZXNbMF07XG5cbiAgICB3aGlsZSAoZmlyc3RVbmxvYWRlZFJhbmdlLnN0b3BJbmRleCAtIGZpcnN0VW5sb2FkZWRSYW5nZS5zdGFydEluZGV4ICsgMSA8IG1pbmltdW1CYXRjaFNpemUgJiYgZmlyc3RVbmxvYWRlZFJhbmdlLnN0YXJ0SW5kZXggPiAwKSB7XG4gICAgICB2YXIgX2luZGV4MiA9IGZpcnN0VW5sb2FkZWRSYW5nZS5zdGFydEluZGV4IC0gMTtcblxuICAgICAgaWYgKCFpc1Jvd0xvYWRlZCh7IGluZGV4OiBfaW5kZXgyIH0pKSB7XG4gICAgICAgIGZpcnN0VW5sb2FkZWRSYW5nZS5zdGFydEluZGV4ID0gX2luZGV4MjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB1bmxvYWRlZFJhbmdlcztcbn1cblxuLyoqXG4gKiBTaW5jZSBSViBjb21wb25lbnRzIHVzZSBzaGFsbG93Q29tcGFyZSB3ZSBuZWVkIHRvIGZvcmNlIGEgcmVuZGVyIChldmVuIHRob3VnaCBwcm9wcyBoYXZlbid0IGNoYW5nZWQpLlxuICogSG93ZXZlciBJbmZpbml0ZUxvYWRlciBtYXkgd3JhcCBhIEdyaWQgb3IgaXQgbWF5IHdyYXAgYSBGbGV4VGFibGUgb3IgVmlydHVhbFNjcm9sbC5cbiAqIEluIHRoZSBmaXJzdCBjYXNlIHRoZSBidWlsdC1pbiBSZWFjdCBmb3JjZVVwZGF0ZSgpIG1ldGhvZCBpcyBzdWZmaWNpZW50IHRvIGZvcmNlIGEgcmUtcmVuZGVyLFxuICogQnV0IGluIHRoZSBsYXR0ZXIgY2FzZXMgd2UgbmVlZCB0byB1c2UgdGhlIFJWLXNwZWNpZmljIGZvcmNlVXBkYXRlR3JpZCgpIG1ldGhvZC5cbiAqIEVsc2UgdGhlIGlubmVyIEdyaWQgd2lsbCBub3QgYmUgcmUtcmVuZGVyZWQgYW5kIHZpc3VhbHMgbWF5IGJlIHN0YWxlLlxuICovXG5mdW5jdGlvbiBmb3JjZVVwZGF0ZVJlYWN0VmlydHVhbGl6ZWRDb21wb25lbnQoY29tcG9uZW50KSB7XG4gIHR5cGVvZiBjb21wb25lbnQuZm9yY2VVcGRhdGVHcmlkID09PSAnZnVuY3Rpb24nID8gY29tcG9uZW50LmZvcmNlVXBkYXRlR3JpZCgpIDogY29tcG9uZW50LmZvcmNlVXBkYXRlKCk7XG59IiwiJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0cy5JbmZpbml0ZUxvYWRlciA9IGV4cG9ydHMuZGVmYXVsdCA9IHVuZGVmaW5lZDtcblxudmFyIF9JbmZpbml0ZUxvYWRlcjIgPSByZXF1aXJlKCcuL0luZmluaXRlTG9hZGVyJyk7XG5cbnZhciBfSW5maW5pdGVMb2FkZXIzID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfSW5maW5pdGVMb2FkZXIyKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgZGVmYXVsdDogb2JqIH07IH1cblxuZXhwb3J0cy5kZWZhdWx0ID0gX0luZmluaXRlTG9hZGVyMy5kZWZhdWx0O1xuZXhwb3J0cy5JbmZpbml0ZUxvYWRlciA9IF9JbmZpbml0ZUxvYWRlcjMuZGVmYXVsdDsiLCIndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSBmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoXCJ2YWx1ZVwiIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KCk7XG5cbnZhciBfcmVhY3QgPSByZXF1aXJlKCdyZWFjdCcpO1xuXG52YXIgX3JlYWN0QWRkb25zU2hhbGxvd0NvbXBhcmUgPSByZXF1aXJlKCdyZWFjdC1hZGRvbnMtc2hhbGxvdy1jb21wYXJlJyk7XG5cbnZhciBfcmVhY3RBZGRvbnNTaGFsbG93Q29tcGFyZTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9yZWFjdEFkZG9uc1NoYWxsb3dDb21wYXJlKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgZGVmYXVsdDogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uXCIpOyB9IH1cblxuZnVuY3Rpb24gX3Bvc3NpYmxlQ29uc3RydWN0b3JSZXR1cm4oc2VsZiwgY2FsbCkgeyBpZiAoIXNlbGYpIHsgdGhyb3cgbmV3IFJlZmVyZW5jZUVycm9yKFwidGhpcyBoYXNuJ3QgYmVlbiBpbml0aWFsaXNlZCAtIHN1cGVyKCkgaGFzbid0IGJlZW4gY2FsbGVkXCIpOyB9IHJldHVybiBjYWxsICYmICh0eXBlb2YgY2FsbCA9PT0gXCJvYmplY3RcIiB8fCB0eXBlb2YgY2FsbCA9PT0gXCJmdW5jdGlvblwiKSA/IGNhbGwgOiBzZWxmOyB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09IFwiZnVuY3Rpb25cIiAmJiBzdXBlckNsYXNzICE9PSBudWxsKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoXCJTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90IFwiICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBPYmplY3Quc2V0UHJvdG90eXBlT2YgPyBPYmplY3Quc2V0UHJvdG90eXBlT2Yoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIDogc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG4vKipcbiAqIEhPQyB0aGF0IHNpbXBsaWZpZXMgdGhlIHByb2Nlc3Mgb2Ygc3luY2hyb25pemluZyBzY3JvbGxpbmcgYmV0d2VlbiB0d28gb3IgbW9yZSB2aXJ0dWFsaXplZCBjb21wb25lbnRzLlxuICovXG52YXIgU2Nyb2xsU3luYyA9IGZ1bmN0aW9uIChfQ29tcG9uZW50KSB7XG4gIF9pbmhlcml0cyhTY3JvbGxTeW5jLCBfQ29tcG9uZW50KTtcblxuICBmdW5jdGlvbiBTY3JvbGxTeW5jKHByb3BzLCBjb250ZXh0KSB7XG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIFNjcm9sbFN5bmMpO1xuXG4gICAgdmFyIF90aGlzID0gX3Bvc3NpYmxlQ29uc3RydWN0b3JSZXR1cm4odGhpcywgKFNjcm9sbFN5bmMuX19wcm90b19fIHx8IE9iamVjdC5nZXRQcm90b3R5cGVPZihTY3JvbGxTeW5jKSkuY2FsbCh0aGlzLCBwcm9wcywgY29udGV4dCkpO1xuXG4gICAgX3RoaXMuc3RhdGUgPSB7XG4gICAgICBjbGllbnRIZWlnaHQ6IDAsXG4gICAgICBjbGllbnRXaWR0aDogMCxcbiAgICAgIHNjcm9sbEhlaWdodDogMCxcbiAgICAgIHNjcm9sbExlZnQ6IDAsXG4gICAgICBzY3JvbGxUb3A6IDAsXG4gICAgICBzY3JvbGxXaWR0aDogMFxuICAgIH07XG5cbiAgICBfdGhpcy5fb25TY3JvbGwgPSBfdGhpcy5fb25TY3JvbGwuYmluZChfdGhpcyk7XG4gICAgcmV0dXJuIF90aGlzO1xuICB9XG5cbiAgX2NyZWF0ZUNsYXNzKFNjcm9sbFN5bmMsIFt7XG4gICAga2V5OiAncmVuZGVyJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVuZGVyKCkge1xuICAgICAgdmFyIGNoaWxkcmVuID0gdGhpcy5wcm9wcy5jaGlsZHJlbjtcbiAgICAgIHZhciBfc3RhdGUgPSB0aGlzLnN0YXRlO1xuICAgICAgdmFyIGNsaWVudEhlaWdodCA9IF9zdGF0ZS5jbGllbnRIZWlnaHQ7XG4gICAgICB2YXIgY2xpZW50V2lkdGggPSBfc3RhdGUuY2xpZW50V2lkdGg7XG4gICAgICB2YXIgc2Nyb2xsSGVpZ2h0ID0gX3N0YXRlLnNjcm9sbEhlaWdodDtcbiAgICAgIHZhciBzY3JvbGxMZWZ0ID0gX3N0YXRlLnNjcm9sbExlZnQ7XG4gICAgICB2YXIgc2Nyb2xsVG9wID0gX3N0YXRlLnNjcm9sbFRvcDtcbiAgICAgIHZhciBzY3JvbGxXaWR0aCA9IF9zdGF0ZS5zY3JvbGxXaWR0aDtcblxuXG4gICAgICByZXR1cm4gY2hpbGRyZW4oe1xuICAgICAgICBjbGllbnRIZWlnaHQ6IGNsaWVudEhlaWdodCxcbiAgICAgICAgY2xpZW50V2lkdGg6IGNsaWVudFdpZHRoLFxuICAgICAgICBvblNjcm9sbDogdGhpcy5fb25TY3JvbGwsXG4gICAgICAgIHNjcm9sbEhlaWdodDogc2Nyb2xsSGVpZ2h0LFxuICAgICAgICBzY3JvbGxMZWZ0OiBzY3JvbGxMZWZ0LFxuICAgICAgICBzY3JvbGxUb3A6IHNjcm9sbFRvcCxcbiAgICAgICAgc2Nyb2xsV2lkdGg6IHNjcm9sbFdpZHRoXG4gICAgICB9KTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdzaG91bGRDb21wb25lbnRVcGRhdGUnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBzaG91bGRDb21wb25lbnRVcGRhdGUobmV4dFByb3BzLCBuZXh0U3RhdGUpIHtcbiAgICAgIHJldHVybiAoMCwgX3JlYWN0QWRkb25zU2hhbGxvd0NvbXBhcmUyLmRlZmF1bHQpKHRoaXMsIG5leHRQcm9wcywgbmV4dFN0YXRlKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25TY3JvbGwnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBfb25TY3JvbGwoX3JlZikge1xuICAgICAgdmFyIGNsaWVudEhlaWdodCA9IF9yZWYuY2xpZW50SGVpZ2h0O1xuICAgICAgdmFyIGNsaWVudFdpZHRoID0gX3JlZi5jbGllbnRXaWR0aDtcbiAgICAgIHZhciBzY3JvbGxIZWlnaHQgPSBfcmVmLnNjcm9sbEhlaWdodDtcbiAgICAgIHZhciBzY3JvbGxMZWZ0ID0gX3JlZi5zY3JvbGxMZWZ0O1xuICAgICAgdmFyIHNjcm9sbFRvcCA9IF9yZWYuc2Nyb2xsVG9wO1xuICAgICAgdmFyIHNjcm9sbFdpZHRoID0gX3JlZi5zY3JvbGxXaWR0aDtcblxuICAgICAgdGhpcy5zZXRTdGF0ZSh7IGNsaWVudEhlaWdodDogY2xpZW50SGVpZ2h0LCBjbGllbnRXaWR0aDogY2xpZW50V2lkdGgsIHNjcm9sbEhlaWdodDogc2Nyb2xsSGVpZ2h0LCBzY3JvbGxMZWZ0OiBzY3JvbGxMZWZ0LCBzY3JvbGxUb3A6IHNjcm9sbFRvcCwgc2Nyb2xsV2lkdGg6IHNjcm9sbFdpZHRoIH0pO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBTY3JvbGxTeW5jO1xufShfcmVhY3QuQ29tcG9uZW50KTtcblxuU2Nyb2xsU3luYy5wcm9wVHlwZXMgPSB7XG4gIC8qKlxuICAgKiBGdW5jdGlvbiByZXNwb25kaWJsZSBmb3IgcmVuZGVyaW5nIDIgb3IgbW9yZSB2aXJ0dWFsaXplZCBjb21wb25lbnRzLlxuICAgKiBUaGlzIGZ1bmN0aW9uIHNob3VsZCBpbXBsZW1lbnQgdGhlIGZvbGxvd2luZyBzaWduYXR1cmU6XG4gICAqICh7IG9uU2Nyb2xsLCBzY3JvbGxMZWZ0LCBzY3JvbGxUb3AgfSkgPT4gUHJvcFR5cGVzLmVsZW1lbnRcbiAgICovXG4gIGNoaWxkcmVuOiBfcmVhY3QuUHJvcFR5cGVzLmZ1bmMuaXNSZXF1aXJlZFxufTtcbmV4cG9ydHMuZGVmYXVsdCA9IFNjcm9sbFN5bmM7IiwiJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0cy5TY3JvbGxTeW5jID0gZXhwb3J0cy5kZWZhdWx0ID0gdW5kZWZpbmVkO1xuXG52YXIgX1Njcm9sbFN5bmMyID0gcmVxdWlyZSgnLi9TY3JvbGxTeW5jJyk7XG5cbnZhciBfU2Nyb2xsU3luYzMgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9TY3JvbGxTeW5jMik7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7IGRlZmF1bHQ6IG9iaiB9OyB9XG5cbmV4cG9ydHMuZGVmYXVsdCA9IF9TY3JvbGxTeW5jMy5kZWZhdWx0O1xuZXhwb3J0cy5TY3JvbGxTeW5jID0gX1Njcm9sbFN5bmMzLmRlZmF1bHQ7IiwiJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2V4dGVuZHMgPSBPYmplY3QuYXNzaWduIHx8IGZ1bmN0aW9uICh0YXJnZXQpIHsgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHsgdmFyIHNvdXJjZSA9IGFyZ3VtZW50c1tpXTsgZm9yICh2YXIga2V5IGluIHNvdXJjZSkgeyBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHNvdXJjZSwga2V5KSkgeyB0YXJnZXRba2V5XSA9IHNvdXJjZVtrZXldOyB9IH0gfSByZXR1cm4gdGFyZ2V0OyB9O1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKFwidmFsdWVcIiBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSgpO1xuXG52YXIgX0dyaWQgPSByZXF1aXJlKCcuLi9HcmlkJyk7XG5cbnZhciBfR3JpZDIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9HcmlkKTtcblxudmFyIF9yZWFjdCA9IHJlcXVpcmUoJ3JlYWN0Jyk7XG5cbnZhciBfcmVhY3QyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfcmVhY3QpO1xuXG52YXIgX2NsYXNzbmFtZXMgPSByZXF1aXJlKCdjbGFzc25hbWVzJyk7XG5cbnZhciBfY2xhc3NuYW1lczIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9jbGFzc25hbWVzKTtcblxudmFyIF9yZWFjdEFkZG9uc1NoYWxsb3dDb21wYXJlID0gcmVxdWlyZSgncmVhY3QtYWRkb25zLXNoYWxsb3ctY29tcGFyZScpO1xuXG52YXIgX3JlYWN0QWRkb25zU2hhbGxvd0NvbXBhcmUyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfcmVhY3RBZGRvbnNTaGFsbG93Q29tcGFyZSk7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7IGRlZmF1bHQ6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvblwiKTsgfSB9XG5cbmZ1bmN0aW9uIF9wb3NzaWJsZUNvbnN0cnVjdG9yUmV0dXJuKHNlbGYsIGNhbGwpIHsgaWYgKCFzZWxmKSB7IHRocm93IG5ldyBSZWZlcmVuY2VFcnJvcihcInRoaXMgaGFzbid0IGJlZW4gaW5pdGlhbGlzZWQgLSBzdXBlcigpIGhhc24ndCBiZWVuIGNhbGxlZFwiKTsgfSByZXR1cm4gY2FsbCAmJiAodHlwZW9mIGNhbGwgPT09IFwib2JqZWN0XCIgfHwgdHlwZW9mIGNhbGwgPT09IFwiZnVuY3Rpb25cIikgPyBjYWxsIDogc2VsZjsgfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSBcImZ1bmN0aW9uXCIgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCBcIiArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgT2JqZWN0LnNldFByb3RvdHlwZU9mID8gT2JqZWN0LnNldFByb3RvdHlwZU9mKHN1YkNsYXNzLCBzdXBlckNsYXNzKSA6IHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxuLyoqXG4gKiBJdCBpcyBpbmVmZmljaWVudCB0byBjcmVhdGUgYW5kIG1hbmFnZSBhIGxhcmdlIGxpc3Qgb2YgRE9NIGVsZW1lbnRzIHdpdGhpbiBhIHNjcm9sbGluZyBjb250YWluZXJcbiAqIGlmIG9ubHkgYSBmZXcgb2YgdGhvc2UgZWxlbWVudHMgYXJlIHZpc2libGUuIFRoZSBwcmltYXJ5IHB1cnBvc2Ugb2YgdGhpcyBjb21wb25lbnQgaXMgdG8gaW1wcm92ZVxuICogcGVyZm9ybWFuY2UgYnkgb25seSByZW5kZXJpbmcgdGhlIERPTSBub2RlcyB0aGF0IGEgdXNlciBpcyBhYmxlIHRvIHNlZSBiYXNlZCBvbiB0aGVpciBjdXJyZW50XG4gKiBzY3JvbGwgcG9zaXRpb24uXG4gKlxuICogVGhpcyBjb21wb25lbnQgcmVuZGVycyBhIHZpcnR1YWxpemVkIGxpc3Qgb2YgZWxlbWVudHMgd2l0aCBlaXRoZXIgZml4ZWQgb3IgZHluYW1pYyBoZWlnaHRzLlxuICovXG52YXIgVmlydHVhbFNjcm9sbCA9IGZ1bmN0aW9uIChfQ29tcG9uZW50KSB7XG4gIF9pbmhlcml0cyhWaXJ0dWFsU2Nyb2xsLCBfQ29tcG9uZW50KTtcblxuICBmdW5jdGlvbiBWaXJ0dWFsU2Nyb2xsKHByb3BzLCBjb250ZXh0KSB7XG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIFZpcnR1YWxTY3JvbGwpO1xuXG4gICAgdmFyIF90aGlzID0gX3Bvc3NpYmxlQ29uc3RydWN0b3JSZXR1cm4odGhpcywgKFZpcnR1YWxTY3JvbGwuX19wcm90b19fIHx8IE9iamVjdC5nZXRQcm90b3R5cGVPZihWaXJ0dWFsU2Nyb2xsKSkuY2FsbCh0aGlzLCBwcm9wcywgY29udGV4dCkpO1xuXG4gICAgX3RoaXMuX2NlbGxSZW5kZXJlciA9IF90aGlzLl9jZWxsUmVuZGVyZXIuYmluZChfdGhpcyk7XG4gICAgX3RoaXMuX2NyZWF0ZVJvd0NsYXNzTmFtZUdldHRlciA9IF90aGlzLl9jcmVhdGVSb3dDbGFzc05hbWVHZXR0ZXIuYmluZChfdGhpcyk7XG4gICAgX3RoaXMuX2NyZWF0ZVJvd1N0eWxlR2V0dGVyID0gX3RoaXMuX2NyZWF0ZVJvd1N0eWxlR2V0dGVyLmJpbmQoX3RoaXMpO1xuICAgIF90aGlzLl9vblNjcm9sbCA9IF90aGlzLl9vblNjcm9sbC5iaW5kKF90aGlzKTtcbiAgICBfdGhpcy5fb25TZWN0aW9uUmVuZGVyZWQgPSBfdGhpcy5fb25TZWN0aW9uUmVuZGVyZWQuYmluZChfdGhpcyk7XG4gICAgcmV0dXJuIF90aGlzO1xuICB9XG5cbiAgX2NyZWF0ZUNsYXNzKFZpcnR1YWxTY3JvbGwsIFt7XG4gICAga2V5OiAnZm9yY2VVcGRhdGVHcmlkJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gZm9yY2VVcGRhdGVHcmlkKCkge1xuICAgICAgdGhpcy5HcmlkLmZvcmNlVXBkYXRlKCk7XG4gICAgfVxuXG4gICAgLyoqIFNlZSBHcmlkI21lYXN1cmVBbGxDZWxscyAqL1xuXG4gIH0sIHtcbiAgICBrZXk6ICdtZWFzdXJlQWxsUm93cycsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIG1lYXN1cmVBbGxSb3dzKCkge1xuICAgICAgdGhpcy5HcmlkLm1lYXN1cmVBbGxDZWxscygpO1xuICAgIH1cblxuICAgIC8qKiBTZWUgR3JpZCNyZWNvbXB1dGVHcmlkU2l6ZSAqL1xuXG4gIH0sIHtcbiAgICBrZXk6ICdyZWNvbXB1dGVSb3dIZWlnaHRzJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVjb21wdXRlUm93SGVpZ2h0cygpIHtcbiAgICAgIHZhciBpbmRleCA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMCB8fCBhcmd1bWVudHNbMF0gPT09IHVuZGVmaW5lZCA/IDAgOiBhcmd1bWVudHNbMF07XG5cbiAgICAgIHRoaXMuR3JpZC5yZWNvbXB1dGVHcmlkU2l6ZSh7XG4gICAgICAgIHJvd0luZGV4OiBpbmRleFxuICAgICAgfSk7XG4gICAgICB0aGlzLmZvcmNlVXBkYXRlR3JpZCgpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ3JlbmRlcicsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJlbmRlcigpIHtcbiAgICAgIHZhciBfdGhpczIgPSB0aGlzO1xuXG4gICAgICB2YXIgX3Byb3BzID0gdGhpcy5wcm9wcztcbiAgICAgIHZhciBjbGFzc05hbWUgPSBfcHJvcHMuY2xhc3NOYW1lO1xuICAgICAgdmFyIG5vUm93c1JlbmRlcmVyID0gX3Byb3BzLm5vUm93c1JlbmRlcmVyO1xuICAgICAgdmFyIHNjcm9sbFRvSW5kZXggPSBfcHJvcHMuc2Nyb2xsVG9JbmRleDtcbiAgICAgIHZhciB3aWR0aCA9IF9wcm9wcy53aWR0aDtcblxuXG4gICAgICB2YXIgY2xhc3NOYW1lcyA9ICgwLCBfY2xhc3NuYW1lczIuZGVmYXVsdCkoJ1ZpcnR1YWxTY3JvbGwnLCBjbGFzc05hbWUpO1xuXG4gICAgICByZXR1cm4gX3JlYWN0Mi5kZWZhdWx0LmNyZWF0ZUVsZW1lbnQoX0dyaWQyLmRlZmF1bHQsIF9leHRlbmRzKHt9LCB0aGlzLnByb3BzLCB7XG4gICAgICAgIGF1dG9Db250YWluZXJXaWR0aDogdHJ1ZSxcbiAgICAgICAgY2VsbFJlbmRlcmVyOiB0aGlzLl9jZWxsUmVuZGVyZXIsXG4gICAgICAgIGNlbGxDbGFzc05hbWU6IHRoaXMuX2NyZWF0ZVJvd0NsYXNzTmFtZUdldHRlcigpLFxuICAgICAgICBjZWxsU3R5bGU6IHRoaXMuX2NyZWF0ZVJvd1N0eWxlR2V0dGVyKCksXG4gICAgICAgIGNsYXNzTmFtZTogY2xhc3NOYW1lcyxcbiAgICAgICAgY29sdW1uV2lkdGg6IHdpZHRoLFxuICAgICAgICBjb2x1bW5Db3VudDogMSxcbiAgICAgICAgbm9Db250ZW50UmVuZGVyZXI6IG5vUm93c1JlbmRlcmVyLFxuICAgICAgICBvblNjcm9sbDogdGhpcy5fb25TY3JvbGwsXG4gICAgICAgIG9uU2VjdGlvblJlbmRlcmVkOiB0aGlzLl9vblNlY3Rpb25SZW5kZXJlZCxcbiAgICAgICAgcmVmOiBmdW5jdGlvbiByZWYoX3JlZikge1xuICAgICAgICAgIF90aGlzMi5HcmlkID0gX3JlZjtcbiAgICAgICAgfSxcbiAgICAgICAgc2Nyb2xsVG9Sb3c6IHNjcm9sbFRvSW5kZXhcbiAgICAgIH0pKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdzaG91bGRDb21wb25lbnRVcGRhdGUnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBzaG91bGRDb21wb25lbnRVcGRhdGUobmV4dFByb3BzLCBuZXh0U3RhdGUpIHtcbiAgICAgIHJldHVybiAoMCwgX3JlYWN0QWRkb25zU2hhbGxvd0NvbXBhcmUyLmRlZmF1bHQpKHRoaXMsIG5leHRQcm9wcywgbmV4dFN0YXRlKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfY2VsbFJlbmRlcmVyJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gX2NlbGxSZW5kZXJlcihfcmVmMikge1xuICAgICAgdmFyIGNvbHVtbkluZGV4ID0gX3JlZjIuY29sdW1uSW5kZXg7XG4gICAgICB2YXIgaXNTY3JvbGxpbmcgPSBfcmVmMi5pc1Njcm9sbGluZztcbiAgICAgIHZhciByb3dJbmRleCA9IF9yZWYyLnJvd0luZGV4O1xuICAgICAgdmFyIHJvd1JlbmRlcmVyID0gdGhpcy5wcm9wcy5yb3dSZW5kZXJlcjtcblxuXG4gICAgICByZXR1cm4gcm93UmVuZGVyZXIoe1xuICAgICAgICBpbmRleDogcm93SW5kZXgsXG4gICAgICAgIGlzU2Nyb2xsaW5nOiBpc1Njcm9sbGluZ1xuICAgICAgfSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX2NyZWF0ZVJvd0NsYXNzTmFtZUdldHRlcicsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9jcmVhdGVSb3dDbGFzc05hbWVHZXR0ZXIoKSB7XG4gICAgICB2YXIgcm93Q2xhc3NOYW1lID0gdGhpcy5wcm9wcy5yb3dDbGFzc05hbWU7XG5cblxuICAgICAgcmV0dXJuIHJvd0NsYXNzTmFtZSBpbnN0YW5jZW9mIEZ1bmN0aW9uID8gZnVuY3Rpb24gKF9yZWYzKSB7XG4gICAgICAgIHZhciByb3dJbmRleCA9IF9yZWYzLnJvd0luZGV4O1xuICAgICAgICByZXR1cm4gcm93Q2xhc3NOYW1lKHsgaW5kZXg6IHJvd0luZGV4IH0pO1xuICAgICAgfSA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHJvd0NsYXNzTmFtZTtcbiAgICAgIH07XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX2NyZWF0ZVJvd1N0eWxlR2V0dGVyJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gX2NyZWF0ZVJvd1N0eWxlR2V0dGVyKCkge1xuICAgICAgdmFyIHJvd1N0eWxlID0gdGhpcy5wcm9wcy5yb3dTdHlsZTtcblxuXG4gICAgICB2YXIgd3JhcHBlZCA9IHJvd1N0eWxlIGluc3RhbmNlb2YgRnVuY3Rpb24gPyByb3dTdHlsZSA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHJvd1N0eWxlO1xuICAgICAgfTtcblxuICAgICAgLy8gRGVmYXVsdCB3aWR0aCB0byAxMDAlIHRvIHByZXZlbnQgbGlzdCByb3dzIGZyb20gZmxvd2luZyB1bmRlciB0aGUgdmVydGljYWwgc2Nyb2xsYmFyXG4gICAgICByZXR1cm4gZnVuY3Rpb24gKF9yZWY0KSB7XG4gICAgICAgIHZhciByb3dJbmRleCA9IF9yZWY0LnJvd0luZGV4O1xuICAgICAgICByZXR1cm4gX2V4dGVuZHMoe1xuICAgICAgICAgIHdpZHRoOiAnMTAwJSdcbiAgICAgICAgfSwgd3JhcHBlZCh7IGluZGV4OiByb3dJbmRleCB9KSk7XG4gICAgICB9O1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vblNjcm9sbCcsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vblNjcm9sbChfcmVmNSkge1xuICAgICAgdmFyIGNsaWVudEhlaWdodCA9IF9yZWY1LmNsaWVudEhlaWdodDtcbiAgICAgIHZhciBzY3JvbGxIZWlnaHQgPSBfcmVmNS5zY3JvbGxIZWlnaHQ7XG4gICAgICB2YXIgc2Nyb2xsVG9wID0gX3JlZjUuc2Nyb2xsVG9wO1xuICAgICAgdmFyIG9uU2Nyb2xsID0gdGhpcy5wcm9wcy5vblNjcm9sbDtcblxuXG4gICAgICBvblNjcm9sbCh7IGNsaWVudEhlaWdodDogY2xpZW50SGVpZ2h0LCBzY3JvbGxIZWlnaHQ6IHNjcm9sbEhlaWdodCwgc2Nyb2xsVG9wOiBzY3JvbGxUb3AgfSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uU2VjdGlvblJlbmRlcmVkJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uU2VjdGlvblJlbmRlcmVkKF9yZWY2KSB7XG4gICAgICB2YXIgcm93T3ZlcnNjYW5TdGFydEluZGV4ID0gX3JlZjYucm93T3ZlcnNjYW5TdGFydEluZGV4O1xuICAgICAgdmFyIHJvd092ZXJzY2FuU3RvcEluZGV4ID0gX3JlZjYucm93T3ZlcnNjYW5TdG9wSW5kZXg7XG4gICAgICB2YXIgcm93U3RhcnRJbmRleCA9IF9yZWY2LnJvd1N0YXJ0SW5kZXg7XG4gICAgICB2YXIgcm93U3RvcEluZGV4ID0gX3JlZjYucm93U3RvcEluZGV4O1xuICAgICAgdmFyIG9uUm93c1JlbmRlcmVkID0gdGhpcy5wcm9wcy5vblJvd3NSZW5kZXJlZDtcblxuXG4gICAgICBvblJvd3NSZW5kZXJlZCh7XG4gICAgICAgIG92ZXJzY2FuU3RhcnRJbmRleDogcm93T3ZlcnNjYW5TdGFydEluZGV4LFxuICAgICAgICBvdmVyc2NhblN0b3BJbmRleDogcm93T3ZlcnNjYW5TdG9wSW5kZXgsXG4gICAgICAgIHN0YXJ0SW5kZXg6IHJvd1N0YXJ0SW5kZXgsXG4gICAgICAgIHN0b3BJbmRleDogcm93U3RvcEluZGV4XG4gICAgICB9KTtcbiAgICB9XG4gIH1dKTtcblxuICByZXR1cm4gVmlydHVhbFNjcm9sbDtcbn0oX3JlYWN0LkNvbXBvbmVudCk7XG5cblZpcnR1YWxTY3JvbGwucHJvcFR5cGVzID0ge1xuICAnYXJpYS1sYWJlbCc6IF9yZWFjdC5Qcm9wVHlwZXMuc3RyaW5nLFxuXG4gIC8qKlxuICAgKiBSZW1vdmVzIGZpeGVkIGhlaWdodCBmcm9tIHRoZSBzY3JvbGxpbmdDb250YWluZXIgc28gdGhhdCB0aGUgdG90YWwgaGVpZ2h0XG4gICAqIG9mIHJvd3MgY2FuIHN0cmV0Y2ggdGhlIHdpbmRvdy4gSW50ZW5kZWQgZm9yIHVzZSB3aXRoIFdpbmRvd1Njcm9sbGVyXG4gICAqL1xuICBhdXRvSGVpZ2h0OiBfcmVhY3QuUHJvcFR5cGVzLmJvb2wsXG5cbiAgLyoqIE9wdGlvbmFsIENTUyBjbGFzcyBuYW1lICovXG4gIGNsYXNzTmFtZTogX3JlYWN0LlByb3BUeXBlcy5zdHJpbmcsXG5cbiAgLyoqXG4gICAqIFVzZWQgdG8gZXN0aW1hdGUgdGhlIHRvdGFsIGhlaWdodCBvZiBhIFZpcnR1YWxTY3JvbGwgYmVmb3JlIGFsbCBvZiBpdHMgcm93cyBoYXZlIGFjdHVhbGx5IGJlZW4gbWVhc3VyZWQuXG4gICAqIFRoZSBlc3RpbWF0ZWQgdG90YWwgaGVpZ2h0IGlzIGFkanVzdGVkIGFzIHJvd3MgYXJlIHJlbmRlcmVkLlxuICAgKi9cbiAgZXN0aW1hdGVkUm93U2l6ZTogX3JlYWN0LlByb3BUeXBlcy5udW1iZXIuaXNSZXF1aXJlZCxcblxuICAvKiogSGVpZ2h0IGNvbnN0cmFpbnQgZm9yIGxpc3QgKGRldGVybWluZXMgaG93IG1hbnkgYWN0dWFsIHJvd3MgYXJlIHJlbmRlcmVkKSAqL1xuICBoZWlnaHQ6IF9yZWFjdC5Qcm9wVHlwZXMubnVtYmVyLmlzUmVxdWlyZWQsXG5cbiAgLyoqIE9wdGlvbmFsIHJlbmRlcmVyIHRvIGJlIHVzZWQgaW4gcGxhY2Ugb2Ygcm93cyB3aGVuIHJvd0NvdW50IGlzIDAgKi9cbiAgbm9Sb3dzUmVuZGVyZXI6IF9yZWFjdC5Qcm9wVHlwZXMuZnVuYy5pc1JlcXVpcmVkLFxuXG4gIC8qKlxuICAgKiBDYWxsYmFjayBpbnZva2VkIHdpdGggaW5mb3JtYXRpb24gYWJvdXQgdGhlIHNsaWNlIG9mIHJvd3MgdGhhdCB3ZXJlIGp1c3QgcmVuZGVyZWQuXG4gICAqICh7IHN0YXJ0SW5kZXgsIHN0b3BJbmRleCB9KTogdm9pZFxuICAgKi9cbiAgb25Sb3dzUmVuZGVyZWQ6IF9yZWFjdC5Qcm9wVHlwZXMuZnVuYy5pc1JlcXVpcmVkLFxuXG4gIC8qKlxuICAgKiBOdW1iZXIgb2Ygcm93cyB0byByZW5kZXIgYWJvdmUvYmVsb3cgdGhlIHZpc2libGUgYm91bmRzIG9mIHRoZSBsaXN0LlxuICAgKiBUaGVzZSByb3dzIGNhbiBoZWxwIGZvciBzbW9vdGhlciBzY3JvbGxpbmcgb24gdG91Y2ggZGV2aWNlcy5cbiAgICovXG4gIG92ZXJzY2FuUm93Q291bnQ6IF9yZWFjdC5Qcm9wVHlwZXMubnVtYmVyLmlzUmVxdWlyZWQsXG5cbiAgLyoqXG4gICAqIENhbGxiYWNrIGludm9rZWQgd2hlbmV2ZXIgdGhlIHNjcm9sbCBvZmZzZXQgY2hhbmdlcyB3aXRoaW4gdGhlIGlubmVyIHNjcm9sbGFibGUgcmVnaW9uLlxuICAgKiBUaGlzIGNhbGxiYWNrIGNhbiBiZSB1c2VkIHRvIHN5bmMgc2Nyb2xsaW5nIGJldHdlZW4gbGlzdHMsIHRhYmxlcywgb3IgZ3JpZHMuXG4gICAqICh7IGNsaWVudEhlaWdodCwgc2Nyb2xsSGVpZ2h0LCBzY3JvbGxUb3AgfSk6IHZvaWRcbiAgICovXG4gIG9uU2Nyb2xsOiBfcmVhY3QuUHJvcFR5cGVzLmZ1bmMuaXNSZXF1aXJlZCxcblxuICAvKipcbiAgICogRWl0aGVyIGEgZml4ZWQgcm93IGhlaWdodCAobnVtYmVyKSBvciBhIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyB0aGUgaGVpZ2h0IG9mIGEgcm93IGdpdmVuIGl0cyBpbmRleC5cbiAgICogKHsgaW5kZXg6IG51bWJlciB9KTogbnVtYmVyXG4gICAqL1xuICByb3dIZWlnaHQ6IF9yZWFjdC5Qcm9wVHlwZXMub25lT2ZUeXBlKFtfcmVhY3QuUHJvcFR5cGVzLm51bWJlciwgX3JlYWN0LlByb3BUeXBlcy5mdW5jXSkuaXNSZXF1aXJlZCxcblxuICAvKiogUmVzcG9uc2JpbGUgZm9yIHJlbmRlcmluZyBhIHJvdyBnaXZlbiBhbiBpbmRleDsgKHsgaW5kZXg6IG51bWJlciB9KTogbm9kZSAqL1xuICByb3dSZW5kZXJlcjogX3JlYWN0LlByb3BUeXBlcy5mdW5jLmlzUmVxdWlyZWQsXG5cbiAgLyoqIE9wdGlvbmFsIGN1c3RvbSBDU1MgY2xhc3MgZm9yIGluZGl2aWR1YWwgcm93cyAqL1xuICByb3dDbGFzc05hbWU6IF9yZWFjdC5Qcm9wVHlwZXMub25lT2ZUeXBlKFtfcmVhY3QuUHJvcFR5cGVzLnN0cmluZywgX3JlYWN0LlByb3BUeXBlcy5mdW5jXSksXG5cbiAgLyoqIE51bWJlciBvZiByb3dzIGluIGxpc3QuICovXG4gIHJvd0NvdW50OiBfcmVhY3QuUHJvcFR5cGVzLm51bWJlci5pc1JlcXVpcmVkLFxuXG4gIC8qKiBPcHRpb25hbCBjdXN0b20gc3R5bGVzIGZvciBpbmRpdmlkdWFsIGNlbGxzICovXG4gIHJvd1N0eWxlOiBfcmVhY3QuUHJvcFR5cGVzLm9uZU9mVHlwZShbX3JlYWN0LlByb3BUeXBlcy5vYmplY3QsIF9yZWFjdC5Qcm9wVHlwZXMuZnVuY10pLFxuXG4gIC8qKiBTZWUgR3JpZCNzY3JvbGxUb0FsaWdubWVudCAqL1xuICBzY3JvbGxUb0FsaWdubWVudDogX3JlYWN0LlByb3BUeXBlcy5vbmVPZihbJ2F1dG8nLCAnZW5kJywgJ3N0YXJ0JywgJ2NlbnRlciddKS5pc1JlcXVpcmVkLFxuXG4gIC8qKiBSb3cgaW5kZXggdG8gZW5zdXJlIHZpc2libGUgKGJ5IGZvcmNlZnVsbHkgc2Nyb2xsaW5nIGlmIG5lY2Vzc2FyeSkgKi9cbiAgc2Nyb2xsVG9JbmRleDogX3JlYWN0LlByb3BUeXBlcy5udW1iZXIsXG5cbiAgLyoqIFZlcnRpY2FsIG9mZnNldC4gKi9cbiAgc2Nyb2xsVG9wOiBfcmVhY3QuUHJvcFR5cGVzLm51bWJlcixcblxuICAvKiogT3B0aW9uYWwgaW5saW5lIHN0eWxlICovXG4gIHN0eWxlOiBfcmVhY3QuUHJvcFR5cGVzLm9iamVjdCxcblxuICAvKiogVGFiIGluZGV4IGZvciBmb2N1cyAqL1xuICB0YWJJbmRleDogX3JlYWN0LlByb3BUeXBlcy5udW1iZXIsXG5cbiAgLyoqIFdpZHRoIG9mIGxpc3QgKi9cbiAgd2lkdGg6IF9yZWFjdC5Qcm9wVHlwZXMubnVtYmVyLmlzUmVxdWlyZWRcbn07XG5WaXJ0dWFsU2Nyb2xsLmRlZmF1bHRQcm9wcyA9IHtcbiAgZXN0aW1hdGVkUm93U2l6ZTogMzAsXG4gIG5vUm93c1JlbmRlcmVyOiBmdW5jdGlvbiBub1Jvd3NSZW5kZXJlcigpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfSxcbiAgb25Sb3dzUmVuZGVyZWQ6IGZ1bmN0aW9uIG9uUm93c1JlbmRlcmVkKCkge1xuICAgIHJldHVybiBudWxsO1xuICB9LFxuICBvblNjcm9sbDogZnVuY3Rpb24gb25TY3JvbGwoKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH0sXG4gIG92ZXJzY2FuUm93Q291bnQ6IDEwLFxuICBzY3JvbGxUb0FsaWdubWVudDogJ2F1dG8nLFxuICBzdHlsZToge31cbn07XG5leHBvcnRzLmRlZmF1bHQgPSBWaXJ0dWFsU2Nyb2xsOyIsIid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcbmV4cG9ydHMuVmlydHVhbFNjcm9sbCA9IGV4cG9ydHMuZGVmYXVsdCA9IHVuZGVmaW5lZDtcblxudmFyIF9WaXJ0dWFsU2Nyb2xsMiA9IHJlcXVpcmUoJy4vVmlydHVhbFNjcm9sbCcpO1xuXG52YXIgX1ZpcnR1YWxTY3JvbGwzID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfVmlydHVhbFNjcm9sbDIpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyBkZWZhdWx0OiBvYmogfTsgfVxuXG5leHBvcnRzLmRlZmF1bHQgPSBfVmlydHVhbFNjcm9sbDMuZGVmYXVsdDtcbmV4cG9ydHMuVmlydHVhbFNjcm9sbCA9IF9WaXJ0dWFsU2Nyb2xsMy5kZWZhdWx0OyIsIid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9jcmVhdGVDbGFzcyA9IGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmIChcInZhbHVlXCIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0oKTtcblxudmFyIF9yZWFjdCA9IHJlcXVpcmUoJ3JlYWN0Jyk7XG5cbnZhciBfcmVhY3QyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfcmVhY3QpO1xuXG52YXIgX3JlYWN0RG9tID0gcmVxdWlyZSgncmVhY3QtZG9tJyk7XG5cbnZhciBfcmVhY3REb20yID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfcmVhY3REb20pO1xuXG52YXIgX3JlYWN0QWRkb25zU2hhbGxvd0NvbXBhcmUgPSByZXF1aXJlKCdyZWFjdC1hZGRvbnMtc2hhbGxvdy1jb21wYXJlJyk7XG5cbnZhciBfcmVhY3RBZGRvbnNTaGFsbG93Q29tcGFyZTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9yZWFjdEFkZG9uc1NoYWxsb3dDb21wYXJlKTtcblxudmFyIF9yYWYgPSByZXF1aXJlKCdyYWYnKTtcblxudmFyIF9yYWYyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfcmFmKTtcblxudmFyIF9vblNjcm9sbCA9IHJlcXVpcmUoJy4vdXRpbHMvb25TY3JvbGwnKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgZGVmYXVsdDogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uXCIpOyB9IH1cblxuZnVuY3Rpb24gX3Bvc3NpYmxlQ29uc3RydWN0b3JSZXR1cm4oc2VsZiwgY2FsbCkgeyBpZiAoIXNlbGYpIHsgdGhyb3cgbmV3IFJlZmVyZW5jZUVycm9yKFwidGhpcyBoYXNuJ3QgYmVlbiBpbml0aWFsaXNlZCAtIHN1cGVyKCkgaGFzbid0IGJlZW4gY2FsbGVkXCIpOyB9IHJldHVybiBjYWxsICYmICh0eXBlb2YgY2FsbCA9PT0gXCJvYmplY3RcIiB8fCB0eXBlb2YgY2FsbCA9PT0gXCJmdW5jdGlvblwiKSA/IGNhbGwgOiBzZWxmOyB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09IFwiZnVuY3Rpb25cIiAmJiBzdXBlckNsYXNzICE9PSBudWxsKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoXCJTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90IFwiICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBPYmplY3Quc2V0UHJvdG90eXBlT2YgPyBPYmplY3Quc2V0UHJvdG90eXBlT2Yoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIDogc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG52YXIgV2luZG93U2Nyb2xsZXIgPSBmdW5jdGlvbiAoX0NvbXBvbmVudCkge1xuICBfaW5oZXJpdHMoV2luZG93U2Nyb2xsZXIsIF9Db21wb25lbnQpO1xuXG4gIGZ1bmN0aW9uIFdpbmRvd1Njcm9sbGVyKHByb3BzKSB7XG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIFdpbmRvd1Njcm9sbGVyKTtcblxuICAgIHZhciBfdGhpcyA9IF9wb3NzaWJsZUNvbnN0cnVjdG9yUmV0dXJuKHRoaXMsIChXaW5kb3dTY3JvbGxlci5fX3Byb3RvX18gfHwgT2JqZWN0LmdldFByb3RvdHlwZU9mKFdpbmRvd1Njcm9sbGVyKSkuY2FsbCh0aGlzLCBwcm9wcykpO1xuXG4gICAgdmFyIGhlaWdodCA9IHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnID8gd2luZG93LmlubmVySGVpZ2h0IDogMDtcblxuICAgIF90aGlzLnN0YXRlID0ge1xuICAgICAgaXNTY3JvbGxpbmc6IGZhbHNlLFxuICAgICAgaGVpZ2h0OiBoZWlnaHQsXG4gICAgICBzY3JvbGxUb3A6IDBcbiAgICB9O1xuXG4gICAgX3RoaXMuX29uU2Nyb2xsV2luZG93ID0gX3RoaXMuX29uU2Nyb2xsV2luZG93LmJpbmQoX3RoaXMpO1xuICAgIF90aGlzLl9vblJlc2l6ZVdpbmRvdyA9IF90aGlzLl9vblJlc2l6ZVdpbmRvdy5iaW5kKF90aGlzKTtcbiAgICBfdGhpcy5fZW5hYmxlUG9pbnRlckV2ZW50c0FmdGVyRGVsYXlDYWxsYmFjayA9IF90aGlzLl9lbmFibGVQb2ludGVyRXZlbnRzQWZ0ZXJEZWxheUNhbGxiYWNrLmJpbmQoX3RoaXMpO1xuICAgIHJldHVybiBfdGhpcztcbiAgfVxuXG4gIF9jcmVhdGVDbGFzcyhXaW5kb3dTY3JvbGxlciwgW3tcbiAgICBrZXk6ICdjb21wb25lbnREaWRNb3VudCcsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGNvbXBvbmVudERpZE1vdW50KCkge1xuICAgICAgdmFyIGhlaWdodCA9IHRoaXMuc3RhdGUuaGVpZ2h0O1xuXG4gICAgICAvLyBTdWJ0cmFjdCBkb2N1bWVudEVsZW1lbnQgdG9wIHRvIGhhbmRsZSBlZGdlLWNhc2Ugd2hlcmUgYSB1c2VyIGlzIG5hdmlnYXRpbmcgYmFjayAoaGlzdG9yeSkgZnJvbSBhbiBhbHJlYWR5LXNjcm9sbGVkIGJhZ2UuXG4gICAgICAvLyBJbiB0aGlzIGNhc2UgdGhlIGJvZHkncyB0b3AgcG9zaXRpb24gd2lsbCBiZSBhIG5lZ2F0aXZlIG51bWJlciBhbmQgdGhpcyBlbGVtZW50J3MgdG9wIHdpbGwgYmUgaW5jcmVhc2VkIChieSB0aGF0IGFtb3VudCkuXG5cbiAgICAgIHRoaXMuX3Bvc2l0aW9uRnJvbVRvcCA9IF9yZWFjdERvbTIuZGVmYXVsdC5maW5kRE9NTm9kZSh0aGlzKS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS50b3AgLSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkudG9wO1xuXG4gICAgICBpZiAoaGVpZ2h0ICE9PSB3aW5kb3cuaW5uZXJIZWlnaHQpIHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgaGVpZ2h0OiB3aW5kb3cuaW5uZXJIZWlnaHRcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgICgwLCBfb25TY3JvbGwucmVnaXN0ZXJTY3JvbGxMaXN0ZW5lcikodGhpcyk7XG4gICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigncmVzaXplJywgdGhpcy5fb25SZXNpemVXaW5kb3csIGZhbHNlKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdjb21wb25lbnRXaWxsVW5tb3VudCcsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGNvbXBvbmVudFdpbGxVbm1vdW50KCkge1xuICAgICAgKDAsIF9vblNjcm9sbC51bnJlZ2lzdGVyU2Nyb2xsTGlzdGVuZXIpKHRoaXMpO1xuXG4gICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcigncmVzaXplJywgdGhpcy5fb25SZXNpemVXaW5kb3csIGZhbHNlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGVzIHRoZSBzdGF0ZSBkdXJpbmcgdGhlIG5leHQgYW5pbWF0aW9uIGZyYW1lLlxuICAgICAqIFVzZSB0aGlzIG1ldGhvZCB0byBhdm9pZCBtdWx0aXBsZSByZW5kZXJzIGluIGEgc21hbGwgc3BhbiBvZiB0aW1lLlxuICAgICAqIFRoaXMgaGVscHMgcGVyZm9ybWFuY2UgZm9yIGJ1cnN0eSBldmVudHMgKGxpa2Ugb25TY3JvbGwpLlxuICAgICAqL1xuXG4gIH0sIHtcbiAgICBrZXk6ICdfc2V0TmV4dFN0YXRlJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gX3NldE5leHRTdGF0ZShzdGF0ZSkge1xuICAgICAgdmFyIF90aGlzMiA9IHRoaXM7XG5cbiAgICAgIGlmICh0aGlzLl9zZXROZXh0U3RhdGVBbmltYXRpb25GcmFtZUlkKSB7XG4gICAgICAgIF9yYWYyLmRlZmF1bHQuY2FuY2VsKHRoaXMuX3NldE5leHRTdGF0ZUFuaW1hdGlvbkZyYW1lSWQpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9zZXROZXh0U3RhdGVBbmltYXRpb25GcmFtZUlkID0gKDAsIF9yYWYyLmRlZmF1bHQpKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgX3RoaXMyLl9zZXROZXh0U3RhdGVBbmltYXRpb25GcmFtZUlkID0gbnVsbDtcbiAgICAgICAgX3RoaXMyLnNldFN0YXRlKHN0YXRlKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ3JlbmRlcicsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJlbmRlcigpIHtcbiAgICAgIHZhciBjaGlsZHJlbiA9IHRoaXMucHJvcHMuY2hpbGRyZW47XG4gICAgICB2YXIgX3N0YXRlID0gdGhpcy5zdGF0ZTtcbiAgICAgIHZhciBpc1Njcm9sbGluZyA9IF9zdGF0ZS5pc1Njcm9sbGluZztcbiAgICAgIHZhciBzY3JvbGxUb3AgPSBfc3RhdGUuc2Nyb2xsVG9wO1xuICAgICAgdmFyIGhlaWdodCA9IF9zdGF0ZS5oZWlnaHQ7XG5cblxuICAgICAgcmV0dXJuIF9yZWFjdDIuZGVmYXVsdC5jcmVhdGVFbGVtZW50KFxuICAgICAgICAnZGl2JyxcbiAgICAgICAgbnVsbCxcbiAgICAgICAgY2hpbGRyZW4oe1xuICAgICAgICAgIGhlaWdodDogaGVpZ2h0LFxuICAgICAgICAgIGlzU2Nyb2xsaW5nOiBpc1Njcm9sbGluZyxcbiAgICAgICAgICBzY3JvbGxUb3A6IHNjcm9sbFRvcFxuICAgICAgICB9KVxuICAgICAgKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdzaG91bGRDb21wb25lbnRVcGRhdGUnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBzaG91bGRDb21wb25lbnRVcGRhdGUobmV4dFByb3BzLCBuZXh0U3RhdGUpIHtcbiAgICAgIHJldHVybiAoMCwgX3JlYWN0QWRkb25zU2hhbGxvd0NvbXBhcmUyLmRlZmF1bHQpKHRoaXMsIG5leHRQcm9wcywgbmV4dFN0YXRlKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfZW5hYmxlUG9pbnRlckV2ZW50c0FmdGVyRGVsYXlDYWxsYmFjaycsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9lbmFibGVQb2ludGVyRXZlbnRzQWZ0ZXJEZWxheUNhbGxiYWNrKCkge1xuICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgIGlzU2Nyb2xsaW5nOiBmYWxzZVxuICAgICAgfSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uUmVzaXplV2luZG93JyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uUmVzaXplV2luZG93KGV2ZW50KSB7XG4gICAgICB2YXIgb25SZXNpemUgPSB0aGlzLnByb3BzLm9uUmVzaXplO1xuXG5cbiAgICAgIHZhciBoZWlnaHQgPSB3aW5kb3cuaW5uZXJIZWlnaHQgfHwgMDtcblxuICAgICAgdGhpcy5zZXRTdGF0ZSh7IGhlaWdodDogaGVpZ2h0IH0pO1xuXG4gICAgICBvblJlc2l6ZSh7IGhlaWdodDogaGVpZ2h0IH0pO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vblNjcm9sbFdpbmRvdycsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vblNjcm9sbFdpbmRvdyhldmVudCkge1xuICAgICAgdmFyIG9uU2Nyb2xsID0gdGhpcy5wcm9wcy5vblNjcm9sbDtcblxuICAgICAgLy8gSW4gSUUxMCsgc2Nyb2xsWSBpcyB1bmRlZmluZWQsIHNvIHdlIHJlcGxhY2UgdGhhdCB3aXRoIHRoZSBsYXR0ZXJcblxuICAgICAgdmFyIHNjcm9sbFkgPSAnc2Nyb2xsWScgaW4gd2luZG93ID8gd2luZG93LnNjcm9sbFkgOiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsVG9wO1xuXG4gICAgICB2YXIgc2Nyb2xsVG9wID0gTWF0aC5tYXgoMCwgc2Nyb2xsWSAtIHRoaXMuX3Bvc2l0aW9uRnJvbVRvcCk7XG5cbiAgICAgIHZhciBzdGF0ZSA9IHtcbiAgICAgICAgaXNTY3JvbGxpbmc6IHRydWUsXG4gICAgICAgIHNjcm9sbFRvcDogc2Nyb2xsVG9wXG4gICAgICB9O1xuXG4gICAgICBpZiAoIXRoaXMuc3RhdGUuaXNTY3JvbGxpbmcpIHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZShzdGF0ZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLl9zZXROZXh0U3RhdGUoc3RhdGUpO1xuICAgICAgfVxuXG4gICAgICBvblNjcm9sbCh7IHNjcm9sbFRvcDogc2Nyb2xsVG9wIH0pO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBXaW5kb3dTY3JvbGxlcjtcbn0oX3JlYWN0LkNvbXBvbmVudCk7XG5cbldpbmRvd1Njcm9sbGVyLnByb3BUeXBlcyA9IHtcbiAgLyoqXG4gICAqIEZ1bmN0aW9uIHJlc3BvbmRpYmxlIGZvciByZW5kZXJpbmcgY2hpbGRyZW4uXG4gICAqIFRoaXMgZnVuY3Rpb24gc2hvdWxkIGltcGxlbWVudCB0aGUgZm9sbG93aW5nIHNpZ25hdHVyZTpcbiAgICogKHsgaGVpZ2h0LCBzY3JvbGxUb3AgfSkgPT4gUHJvcFR5cGVzLmVsZW1lbnRcbiAgICovXG4gIGNoaWxkcmVuOiBfcmVhY3QuUHJvcFR5cGVzLmZ1bmMuaXNSZXF1aXJlZCxcblxuICAvKiogQ2FsbGJhY2sgdG8gYmUgaW52b2tlZCBvbi1yZXNpemU6ICh7IGhlaWdodCB9KSAqL1xuICBvblJlc2l6ZTogX3JlYWN0LlByb3BUeXBlcy5mdW5jLmlzUmVxdWlyZWQsXG5cbiAgLyoqIENhbGxiYWNrIHRvIGJlIGludm9rZWQgb24tc2Nyb2xsOiAoeyBzY3JvbGxUb3AgfSkgKi9cbiAgb25TY3JvbGw6IF9yZWFjdC5Qcm9wVHlwZXMuZnVuYy5pc1JlcXVpcmVkXG59O1xuV2luZG93U2Nyb2xsZXIuZGVmYXVsdFByb3BzID0ge1xuICBvblJlc2l6ZTogZnVuY3Rpb24gb25SZXNpemUoKSB7fSxcbiAgb25TY3JvbGw6IGZ1bmN0aW9uIG9uU2Nyb2xsKCkge31cbn07XG5leHBvcnRzLmRlZmF1bHQgPSBXaW5kb3dTY3JvbGxlcjsiLCIndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5leHBvcnRzLklTX1NDUk9MTElOR19USU1FT1VUID0gZXhwb3J0cy5XaW5kb3dTY3JvbGxlciA9IGV4cG9ydHMuZGVmYXVsdCA9IHVuZGVmaW5lZDtcblxudmFyIF9XaW5kb3dTY3JvbGxlcjIgPSByZXF1aXJlKCcuL1dpbmRvd1Njcm9sbGVyJyk7XG5cbnZhciBfV2luZG93U2Nyb2xsZXIzID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfV2luZG93U2Nyb2xsZXIyKTtcblxudmFyIF9vblNjcm9sbCA9IHJlcXVpcmUoJy4vdXRpbHMvb25TY3JvbGwnKTtcblxudmFyIF9vblNjcm9sbDIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9vblNjcm9sbCk7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7IGRlZmF1bHQ6IG9iaiB9OyB9XG5cbmV4cG9ydHMuZGVmYXVsdCA9IF9XaW5kb3dTY3JvbGxlcjMuZGVmYXVsdDtcbmV4cG9ydHMuV2luZG93U2Nyb2xsZXIgPSBfV2luZG93U2Nyb2xsZXIzLmRlZmF1bHQ7XG5leHBvcnRzLklTX1NDUk9MTElOR19USU1FT1VUID0gX29uU2Nyb2xsMi5kZWZhdWx0OyIsIid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcbmV4cG9ydHMucmVnaXN0ZXJTY3JvbGxMaXN0ZW5lciA9IHJlZ2lzdGVyU2Nyb2xsTGlzdGVuZXI7XG5leHBvcnRzLnVucmVnaXN0ZXJTY3JvbGxMaXN0ZW5lciA9IHVucmVnaXN0ZXJTY3JvbGxMaXN0ZW5lcjtcbnZhciBtb3VudGVkSW5zdGFuY2VzID0gW107XG52YXIgb3JpZ2luYWxCb2R5UG9pbnRlckV2ZW50cyA9IG51bGw7XG52YXIgZGlzYWJsZVBvaW50ZXJFdmVudHNUaW1lb3V0SWQgPSBudWxsO1xuXG4vKipcbiAqIFNwZWNpZmllcyB0aGUgbnVtYmVyIG9mIG1pbGlzZWNvbmRzIGR1cmluZyB3aGljaCB0byBkaXNhYmxlIHBvaW50ZXIgZXZlbnRzIHdoaWxlIGEgc2Nyb2xsIGlzIGluIHByb2dyZXNzLlxuICogVGhpcyBpbXByb3ZlcyBwZXJmb3JtYW5jZSBhbmQgbWFrZXMgc2Nyb2xsaW5nIHNtb290aGVyLlxuICovXG52YXIgSVNfU0NST0xMSU5HX1RJTUVPVVQgPSBleHBvcnRzLklTX1NDUk9MTElOR19USU1FT1VUID0gMTUwO1xuXG5mdW5jdGlvbiBlbmFibGVQb2ludGVyRXZlbnRzSWZEaXNhYmxlZCgpIHtcbiAgaWYgKGRpc2FibGVQb2ludGVyRXZlbnRzVGltZW91dElkKSB7XG4gICAgZGlzYWJsZVBvaW50ZXJFdmVudHNUaW1lb3V0SWQgPSBudWxsO1xuXG4gICAgZG9jdW1lbnQuYm9keS5zdHlsZS5wb2ludGVyRXZlbnRzID0gb3JpZ2luYWxCb2R5UG9pbnRlckV2ZW50cztcblxuICAgIG9yaWdpbmFsQm9keVBvaW50ZXJFdmVudHMgPSBudWxsO1xuICB9XG59XG5cbmZ1bmN0aW9uIGVuYWJsZVBvaW50ZXJFdmVudHNBZnRlckRlbGF5Q2FsbGJhY2soKSB7XG4gIGVuYWJsZVBvaW50ZXJFdmVudHNJZkRpc2FibGVkKCk7XG4gIG1vdW50ZWRJbnN0YW5jZXMuZm9yRWFjaChmdW5jdGlvbiAoY29tcG9uZW50KSB7XG4gICAgcmV0dXJuIGNvbXBvbmVudC5fZW5hYmxlUG9pbnRlckV2ZW50c0FmdGVyRGVsYXlDYWxsYmFjaygpO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gZW5hYmxlUG9pbnRlckV2ZW50c0FmdGVyRGVsYXkoKSB7XG4gIGlmIChkaXNhYmxlUG9pbnRlckV2ZW50c1RpbWVvdXRJZCkge1xuICAgIGNsZWFyVGltZW91dChkaXNhYmxlUG9pbnRlckV2ZW50c1RpbWVvdXRJZCk7XG4gIH1cblxuICBkaXNhYmxlUG9pbnRlckV2ZW50c1RpbWVvdXRJZCA9IHNldFRpbWVvdXQoZW5hYmxlUG9pbnRlckV2ZW50c0FmdGVyRGVsYXlDYWxsYmFjaywgSVNfU0NST0xMSU5HX1RJTUVPVVQpO1xufVxuXG5mdW5jdGlvbiBvblNjcm9sbFdpbmRvdyhldmVudCkge1xuICBpZiAob3JpZ2luYWxCb2R5UG9pbnRlckV2ZW50cyA9PSBudWxsKSB7XG4gICAgb3JpZ2luYWxCb2R5UG9pbnRlckV2ZW50cyA9IGRvY3VtZW50LmJvZHkuc3R5bGUucG9pbnRlckV2ZW50cztcblxuICAgIGRvY3VtZW50LmJvZHkuc3R5bGUucG9pbnRlckV2ZW50cyA9ICdub25lJztcblxuICAgIGVuYWJsZVBvaW50ZXJFdmVudHNBZnRlckRlbGF5KCk7XG4gIH1cbiAgbW91bnRlZEluc3RhbmNlcy5mb3JFYWNoKGZ1bmN0aW9uIChjb21wb25lbnQpIHtcbiAgICByZXR1cm4gY29tcG9uZW50Ll9vblNjcm9sbFdpbmRvdyhldmVudCk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiByZWdpc3RlclNjcm9sbExpc3RlbmVyKGNvbXBvbmVudCkge1xuICBpZiAoIW1vdW50ZWRJbnN0YW5jZXMubGVuZ3RoKSB7XG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIG9uU2Nyb2xsV2luZG93KTtcbiAgfVxuICBtb3VudGVkSW5zdGFuY2VzLnB1c2goY29tcG9uZW50KTtcbn1cblxuZnVuY3Rpb24gdW5yZWdpc3RlclNjcm9sbExpc3RlbmVyKGNvbXBvbmVudCkge1xuICBtb3VudGVkSW5zdGFuY2VzID0gbW91bnRlZEluc3RhbmNlcy5maWx0ZXIoZnVuY3Rpb24gKGMpIHtcbiAgICByZXR1cm4gYyAhPT0gY29tcG9uZW50O1xuICB9KTtcbiAgaWYgKCFtb3VudGVkSW5zdGFuY2VzLmxlbmd0aCkge1xuICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdzY3JvbGwnLCBvblNjcm9sbFdpbmRvdyk7XG4gICAgaWYgKGRpc2FibGVQb2ludGVyRXZlbnRzVGltZW91dElkKSB7XG4gICAgICBjbGVhclRpbWVvdXQoZGlzYWJsZVBvaW50ZXJFdmVudHNUaW1lb3V0SWQpO1xuICAgICAgZW5hYmxlUG9pbnRlckV2ZW50c0lmRGlzYWJsZWQoKTtcbiAgICB9XG4gIH1cbn0iLCIndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5cbnZhciBfQXJyb3dLZXlTdGVwcGVyID0gcmVxdWlyZSgnLi9BcnJvd0tleVN0ZXBwZXInKTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdBcnJvd0tleVN0ZXBwZXInLCB7XG4gIGVudW1lcmFibGU6IHRydWUsXG4gIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgIHJldHVybiBfQXJyb3dLZXlTdGVwcGVyLkFycm93S2V5U3RlcHBlcjtcbiAgfVxufSk7XG5cbnZhciBfQXV0b1NpemVyID0gcmVxdWlyZSgnLi9BdXRvU2l6ZXInKTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdBdXRvU2l6ZXInLCB7XG4gIGVudW1lcmFibGU6IHRydWUsXG4gIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgIHJldHVybiBfQXV0b1NpemVyLkF1dG9TaXplcjtcbiAgfVxufSk7XG5cbnZhciBfQ2VsbE1lYXN1cmVyID0gcmVxdWlyZSgnLi9DZWxsTWVhc3VyZXInKTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdDZWxsTWVhc3VyZXInLCB7XG4gIGVudW1lcmFibGU6IHRydWUsXG4gIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgIHJldHVybiBfQ2VsbE1lYXN1cmVyLkNlbGxNZWFzdXJlcjtcbiAgfVxufSk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ2RlZmF1bHRDZWxsTWVhc3VyZXJDZWxsU2l6ZUNhY2hlJywge1xuICBlbnVtZXJhYmxlOiB0cnVlLFxuICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICByZXR1cm4gX0NlbGxNZWFzdXJlci5kZWZhdWx0Q2VsbFNpemVDYWNoZTtcbiAgfVxufSk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ3VuaWZvcm1TaXplQ2VsbE1lYXN1cmVyQ2VsbFNpemVDYWNoZScsIHtcbiAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgcmV0dXJuIF9DZWxsTWVhc3VyZXIuZGVmYXVsdENlbGxTaXplQ2FjaGU7XG4gIH1cbn0pO1xuXG52YXIgX0NvbGxlY3Rpb24gPSByZXF1aXJlKCcuL0NvbGxlY3Rpb24nKTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdDb2xsZWN0aW9uJywge1xuICBlbnVtZXJhYmxlOiB0cnVlLFxuICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICByZXR1cm4gX0NvbGxlY3Rpb24uQ29sbGVjdGlvbjtcbiAgfVxufSk7XG5cbnZhciBfQ29sdW1uU2l6ZXIgPSByZXF1aXJlKCcuL0NvbHVtblNpemVyJyk7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnQ29sdW1uU2l6ZXInLCB7XG4gIGVudW1lcmFibGU6IHRydWUsXG4gIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgIHJldHVybiBfQ29sdW1uU2l6ZXIuQ29sdW1uU2l6ZXI7XG4gIH1cbn0pO1xuXG52YXIgX0ZsZXhUYWJsZSA9IHJlcXVpcmUoJy4vRmxleFRhYmxlJyk7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnZGVmYXVsdEZsZXhUYWJsZUNlbGxEYXRhR2V0dGVyJywge1xuICBlbnVtZXJhYmxlOiB0cnVlLFxuICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICByZXR1cm4gX0ZsZXhUYWJsZS5kZWZhdWx0Q2VsbERhdGFHZXR0ZXI7XG4gIH1cbn0pO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdkZWZhdWx0RmxleFRhYmxlQ2VsbFJlbmRlcmVyJywge1xuICBlbnVtZXJhYmxlOiB0cnVlLFxuICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICByZXR1cm4gX0ZsZXhUYWJsZS5kZWZhdWx0Q2VsbFJlbmRlcmVyO1xuICB9XG59KTtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnZGVmYXVsdEZsZXhUYWJsZUhlYWRlclJlbmRlcmVyJywge1xuICBlbnVtZXJhYmxlOiB0cnVlLFxuICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICByZXR1cm4gX0ZsZXhUYWJsZS5kZWZhdWx0SGVhZGVyUmVuZGVyZXI7XG4gIH1cbn0pO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdkZWZhdWx0RmxleFRhYmxlUm93UmVuZGVyZXInLCB7XG4gIGVudW1lcmFibGU6IHRydWUsXG4gIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgIHJldHVybiBfRmxleFRhYmxlLmRlZmF1bHRSb3dSZW5kZXJlcjtcbiAgfVxufSk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ0ZsZXhUYWJsZScsIHtcbiAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgcmV0dXJuIF9GbGV4VGFibGUuRmxleFRhYmxlO1xuICB9XG59KTtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnRmxleENvbHVtbicsIHtcbiAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgcmV0dXJuIF9GbGV4VGFibGUuRmxleENvbHVtbjtcbiAgfVxufSk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ1NvcnREaXJlY3Rpb24nLCB7XG4gIGVudW1lcmFibGU6IHRydWUsXG4gIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgIHJldHVybiBfRmxleFRhYmxlLlNvcnREaXJlY3Rpb247XG4gIH1cbn0pO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdTb3J0SW5kaWNhdG9yJywge1xuICBlbnVtZXJhYmxlOiB0cnVlLFxuICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICByZXR1cm4gX0ZsZXhUYWJsZS5Tb3J0SW5kaWNhdG9yO1xuICB9XG59KTtcblxudmFyIF9HcmlkID0gcmVxdWlyZSgnLi9HcmlkJyk7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnZGVmYXVsdENlbGxSYW5nZVJlbmRlcmVyJywge1xuICBlbnVtZXJhYmxlOiB0cnVlLFxuICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICByZXR1cm4gX0dyaWQuZGVmYXVsdENlbGxSYW5nZVJlbmRlcmVyO1xuICB9XG59KTtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnR3JpZCcsIHtcbiAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgcmV0dXJuIF9HcmlkLkdyaWQ7XG4gIH1cbn0pO1xuXG52YXIgX0luZmluaXRlTG9hZGVyID0gcmVxdWlyZSgnLi9JbmZpbml0ZUxvYWRlcicpO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ0luZmluaXRlTG9hZGVyJywge1xuICBlbnVtZXJhYmxlOiB0cnVlLFxuICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICByZXR1cm4gX0luZmluaXRlTG9hZGVyLkluZmluaXRlTG9hZGVyO1xuICB9XG59KTtcblxudmFyIF9TY3JvbGxTeW5jID0gcmVxdWlyZSgnLi9TY3JvbGxTeW5jJyk7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnU2Nyb2xsU3luYycsIHtcbiAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgcmV0dXJuIF9TY3JvbGxTeW5jLlNjcm9sbFN5bmM7XG4gIH1cbn0pO1xuXG52YXIgX1ZpcnR1YWxTY3JvbGwgPSByZXF1aXJlKCcuL1ZpcnR1YWxTY3JvbGwnKTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdWaXJ0dWFsU2Nyb2xsJywge1xuICBlbnVtZXJhYmxlOiB0cnVlLFxuICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICByZXR1cm4gX1ZpcnR1YWxTY3JvbGwuVmlydHVhbFNjcm9sbDtcbiAgfVxufSk7XG5cbnZhciBfV2luZG93U2Nyb2xsZXIgPSByZXF1aXJlKCcuL1dpbmRvd1Njcm9sbGVyJyk7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnV2luZG93U2Nyb2xsZXInLCB7XG4gIGVudW1lcmFibGU6IHRydWUsXG4gIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgIHJldHVybiBfV2luZG93U2Nyb2xsZXIuV2luZG93U2Nyb2xsZXI7XG4gIH1cbn0pOyIsIid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcbmV4cG9ydHMuZGVmYXVsdCA9IGNyZWF0ZUNhbGxiYWNrTWVtb2l6ZXI7XG4vKipcbiAqIEhlbHBlciB1dGlsaXR5IHRoYXQgdXBkYXRlcyB0aGUgc3BlY2lmaWVkIGNhbGxiYWNrIHdoZW5ldmVyIGFueSBvZiB0aGUgc3BlY2lmaWVkIGluZGljZXMgaGF2ZSBjaGFuZ2VkLlxuICovXG5mdW5jdGlvbiBjcmVhdGVDYWxsYmFja01lbW9pemVyKCkge1xuICB2YXIgcmVxdWlyZUFsbEtleXMgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDAgfHwgYXJndW1lbnRzWzBdID09PSB1bmRlZmluZWQgPyB0cnVlIDogYXJndW1lbnRzWzBdO1xuXG4gIHZhciBjYWNoZWRJbmRpY2VzID0ge307XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIChfcmVmKSB7XG4gICAgdmFyIGNhbGxiYWNrID0gX3JlZi5jYWxsYmFjaztcbiAgICB2YXIgaW5kaWNlcyA9IF9yZWYuaW5kaWNlcztcblxuICAgIHZhciBrZXlzID0gT2JqZWN0LmtleXMoaW5kaWNlcyk7XG4gICAgdmFyIGFsbEluaXRpYWxpemVkID0gIXJlcXVpcmVBbGxLZXlzIHx8IGtleXMuZXZlcnkoZnVuY3Rpb24gKGtleSkge1xuICAgICAgdmFyIHZhbHVlID0gaW5kaWNlc1trZXldO1xuICAgICAgcmV0dXJuIEFycmF5LmlzQXJyYXkodmFsdWUpID8gdmFsdWUubGVuZ3RoID4gMCA6IHZhbHVlID49IDA7XG4gICAgfSk7XG4gICAgdmFyIGluZGV4Q2hhbmdlZCA9IGtleXMubGVuZ3RoICE9PSBPYmplY3Qua2V5cyhjYWNoZWRJbmRpY2VzKS5sZW5ndGggfHwga2V5cy5zb21lKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgIHZhciBjYWNoZWRWYWx1ZSA9IGNhY2hlZEluZGljZXNba2V5XTtcbiAgICAgIHZhciB2YWx1ZSA9IGluZGljZXNba2V5XTtcblxuICAgICAgcmV0dXJuIEFycmF5LmlzQXJyYXkodmFsdWUpID8gY2FjaGVkVmFsdWUuam9pbignLCcpICE9PSB2YWx1ZS5qb2luKCcsJykgOiBjYWNoZWRWYWx1ZSAhPT0gdmFsdWU7XG4gICAgfSk7XG5cbiAgICBjYWNoZWRJbmRpY2VzID0gaW5kaWNlcztcblxuICAgIGlmIChhbGxJbml0aWFsaXplZCAmJiBpbmRleENoYW5nZWQpIHtcbiAgICAgIGNhbGxiYWNrKGluZGljZXMpO1xuICAgIH1cbiAgfTtcbn0iLCIndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5leHBvcnRzLmRlZmF1bHQgPSBnZXRVcGRhdGVkT2Zmc2V0Rm9ySW5kZXg7XG4vKipcbiAqIERldGVybWluZXMgYSBuZXcgb2Zmc2V0IHRoYXQgZW5zdXJlcyBhIGNlcnRhaW4gY2VsbCBpcyB2aXNpYmxlLCBnaXZlbiB0aGUgY3VycmVudCBvZmZzZXQuXG4gKiBJZiB0aGUgY2VsbCBpcyBhbHJlYWR5IHZpc2libGUgdGhlbiB0aGUgY3VycmVudCBvZmZzZXQgd2lsbCBiZSByZXR1cm5lZC5cbiAqIElmIHRoZSBjdXJyZW50IG9mZnNldCBpcyB0b28gZ3JlYXQgb3Igc21hbGwsIGl0IHdpbGwgYmUgYWRqdXN0ZWQganVzdCBlbm91Z2ggdG8gZW5zdXJlIHRoZSBzcGVjaWZpZWQgaW5kZXggaXMgdmlzaWJsZS5cbiAqXG4gKiBAcGFyYW0gYWxpZ24gRGVzaXJlZCBhbGlnbm1lbnQgd2l0aGluIGNvbnRhaW5lcjsgb25lIG9mIFwiYXV0b1wiIChkZWZhdWx0KSwgXCJzdGFydFwiLCBvciBcImVuZFwiXG4gKiBAcGFyYW0gY2VsbE9mZnNldCBPZmZzZXQgKHggb3IgeSkgcG9zaXRpb24gZm9yIGNlbGxcbiAqIEBwYXJhbSBjZWxsU2l6ZSBTaXplICh3aWR0aCBvciBoZWlnaHQpIG9mIGNlbGxcbiAqIEBwYXJhbSBjb250YWluZXJTaXplIFRvdGFsIHNpemUgKHdpZHRoIG9yIGhlaWdodCkgb2YgdGhlIGNvbnRhaW5lclxuICogQHBhcmFtIGN1cnJlbnRPZmZzZXQgQ29udGFpbmVyJ3MgY3VycmVudCAoeCBvciB5KSBvZmZzZXRcbiAqIEByZXR1cm4gT2Zmc2V0IHRvIHVzZSB0byBlbnN1cmUgdGhlIHNwZWNpZmllZCBjZWxsIGlzIHZpc2libGVcbiAqL1xuZnVuY3Rpb24gZ2V0VXBkYXRlZE9mZnNldEZvckluZGV4KF9yZWYpIHtcbiAgdmFyIF9yZWYkYWxpZ24gPSBfcmVmLmFsaWduO1xuICB2YXIgYWxpZ24gPSBfcmVmJGFsaWduID09PSB1bmRlZmluZWQgPyAnYXV0bycgOiBfcmVmJGFsaWduO1xuICB2YXIgY2VsbE9mZnNldCA9IF9yZWYuY2VsbE9mZnNldDtcbiAgdmFyIGNlbGxTaXplID0gX3JlZi5jZWxsU2l6ZTtcbiAgdmFyIGNvbnRhaW5lclNpemUgPSBfcmVmLmNvbnRhaW5lclNpemU7XG4gIHZhciBjdXJyZW50T2Zmc2V0ID0gX3JlZi5jdXJyZW50T2Zmc2V0O1xuXG4gIHZhciBtYXhPZmZzZXQgPSBjZWxsT2Zmc2V0O1xuICB2YXIgbWluT2Zmc2V0ID0gbWF4T2Zmc2V0IC0gY29udGFpbmVyU2l6ZSArIGNlbGxTaXplO1xuXG4gIHN3aXRjaCAoYWxpZ24pIHtcbiAgICBjYXNlICdzdGFydCc6XG4gICAgICByZXR1cm4gbWF4T2Zmc2V0O1xuICAgIGNhc2UgJ2VuZCc6XG4gICAgICByZXR1cm4gbWluT2Zmc2V0O1xuICAgIGNhc2UgJ2NlbnRlcic6XG4gICAgICByZXR1cm4gbWF4T2Zmc2V0IC0gKGNvbnRhaW5lclNpemUgLSBjZWxsU2l6ZSkgLyAyO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gTWF0aC5tYXgobWluT2Zmc2V0LCBNYXRoLm1pbihtYXhPZmZzZXQsIGN1cnJlbnRPZmZzZXQpKTtcbiAgfVxufSIsIid1c2Ugc3RyaWN0JztcblxuLyoqXG4qIERldGVjdCBFbGVtZW50IFJlc2l6ZS5cbiogRm9ya2VkIGluIG9yZGVyIHRvIGd1YXJkIGFnYWluc3QgdW5zYWZlICd3aW5kb3cnIGFuZCAnZG9jdW1lbnQnIHJlZmVyZW5jZXMuXG4qXG4qIGh0dHBzOi8vZ2l0aHViLmNvbS9zZGVjaW1hL2phdmFzY3JpcHQtZGV0ZWN0LWVsZW1lbnQtcmVzaXplXG4qIFNlYmFzdGlhbiBEZWNpbWFcbipcbiogdmVyc2lvbjogMC41LjNcbioqL1xuXG4vLyBDaGVjayBgZG9jdW1lbnRgIGFuZCBgd2luZG93YCBpbiBjYXNlIG9mIHNlcnZlci1zaWRlIHJlbmRlcmluZ1xudmFyIF93aW5kb3c7XG5pZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgX3dpbmRvdyA9IHdpbmRvdztcbn0gZWxzZSBpZiAodHlwZW9mIHNlbGYgIT09ICd1bmRlZmluZWQnKSB7XG4gIF93aW5kb3cgPSBzZWxmO1xufSBlbHNlIHtcbiAgX3dpbmRvdyA9IHVuZGVmaW5lZDtcbn1cblxudmFyIGF0dGFjaEV2ZW50ID0gdHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJyAmJiBkb2N1bWVudC5hdHRhY2hFdmVudDtcbnZhciBzdHlsZXNDcmVhdGVkID0gZmFsc2U7XG5cbmlmICghYXR0YWNoRXZlbnQpIHtcbiAgdmFyIHJlcXVlc3RGcmFtZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgcmFmID0gX3dpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUgfHwgX3dpbmRvdy5tb3pSZXF1ZXN0QW5pbWF0aW9uRnJhbWUgfHwgX3dpbmRvdy53ZWJraXRSZXF1ZXN0QW5pbWF0aW9uRnJhbWUgfHwgZnVuY3Rpb24gKGZuKSB7XG4gICAgICByZXR1cm4gX3dpbmRvdy5zZXRUaW1lb3V0KGZuLCAyMCk7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGZuKSB7XG4gICAgICByZXR1cm4gcmFmKGZuKTtcbiAgICB9O1xuICB9KCk7XG5cbiAgdmFyIGNhbmNlbEZyYW1lID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBjYW5jZWwgPSBfd2luZG93LmNhbmNlbEFuaW1hdGlvbkZyYW1lIHx8IF93aW5kb3cubW96Q2FuY2VsQW5pbWF0aW9uRnJhbWUgfHwgX3dpbmRvdy53ZWJraXRDYW5jZWxBbmltYXRpb25GcmFtZSB8fCBfd2luZG93LmNsZWFyVGltZW91dDtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGlkKSB7XG4gICAgICByZXR1cm4gY2FuY2VsKGlkKTtcbiAgICB9O1xuICB9KCk7XG5cbiAgdmFyIHJlc2V0VHJpZ2dlcnMgPSBmdW5jdGlvbiByZXNldFRyaWdnZXJzKGVsZW1lbnQpIHtcbiAgICB2YXIgdHJpZ2dlcnMgPSBlbGVtZW50Ll9fcmVzaXplVHJpZ2dlcnNfXyxcbiAgICAgICAgZXhwYW5kID0gdHJpZ2dlcnMuZmlyc3RFbGVtZW50Q2hpbGQsXG4gICAgICAgIGNvbnRyYWN0ID0gdHJpZ2dlcnMubGFzdEVsZW1lbnRDaGlsZCxcbiAgICAgICAgZXhwYW5kQ2hpbGQgPSBleHBhbmQuZmlyc3RFbGVtZW50Q2hpbGQ7XG4gICAgY29udHJhY3Quc2Nyb2xsTGVmdCA9IGNvbnRyYWN0LnNjcm9sbFdpZHRoO1xuICAgIGNvbnRyYWN0LnNjcm9sbFRvcCA9IGNvbnRyYWN0LnNjcm9sbEhlaWdodDtcbiAgICBleHBhbmRDaGlsZC5zdHlsZS53aWR0aCA9IGV4cGFuZC5vZmZzZXRXaWR0aCArIDEgKyAncHgnO1xuICAgIGV4cGFuZENoaWxkLnN0eWxlLmhlaWdodCA9IGV4cGFuZC5vZmZzZXRIZWlnaHQgKyAxICsgJ3B4JztcbiAgICBleHBhbmQuc2Nyb2xsTGVmdCA9IGV4cGFuZC5zY3JvbGxXaWR0aDtcbiAgICBleHBhbmQuc2Nyb2xsVG9wID0gZXhwYW5kLnNjcm9sbEhlaWdodDtcbiAgfTtcblxuICB2YXIgY2hlY2tUcmlnZ2VycyA9IGZ1bmN0aW9uIGNoZWNrVHJpZ2dlcnMoZWxlbWVudCkge1xuICAgIHJldHVybiBlbGVtZW50Lm9mZnNldFdpZHRoICE9IGVsZW1lbnQuX19yZXNpemVMYXN0X18ud2lkdGggfHwgZWxlbWVudC5vZmZzZXRIZWlnaHQgIT0gZWxlbWVudC5fX3Jlc2l6ZUxhc3RfXy5oZWlnaHQ7XG4gIH07XG5cbiAgdmFyIHNjcm9sbExpc3RlbmVyID0gZnVuY3Rpb24gc2Nyb2xsTGlzdGVuZXIoZSkge1xuICAgIHZhciBlbGVtZW50ID0gdGhpcztcbiAgICByZXNldFRyaWdnZXJzKHRoaXMpO1xuICAgIGlmICh0aGlzLl9fcmVzaXplUkFGX18pIGNhbmNlbEZyYW1lKHRoaXMuX19yZXNpemVSQUZfXyk7XG4gICAgdGhpcy5fX3Jlc2l6ZVJBRl9fID0gcmVxdWVzdEZyYW1lKGZ1bmN0aW9uICgpIHtcbiAgICAgIGlmIChjaGVja1RyaWdnZXJzKGVsZW1lbnQpKSB7XG4gICAgICAgIGVsZW1lbnQuX19yZXNpemVMYXN0X18ud2lkdGggPSBlbGVtZW50Lm9mZnNldFdpZHRoO1xuICAgICAgICBlbGVtZW50Ll9fcmVzaXplTGFzdF9fLmhlaWdodCA9IGVsZW1lbnQub2Zmc2V0SGVpZ2h0O1xuICAgICAgICBlbGVtZW50Ll9fcmVzaXplTGlzdGVuZXJzX18uZm9yRWFjaChmdW5jdGlvbiAoZm4pIHtcbiAgICAgICAgICBmbi5jYWxsKGVsZW1lbnQsIGUpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfTtcblxuICAvKiBEZXRlY3QgQ1NTIEFuaW1hdGlvbnMgc3VwcG9ydCB0byBkZXRlY3QgZWxlbWVudCBkaXNwbGF5L3JlLWF0dGFjaCAqL1xuICB2YXIgYW5pbWF0aW9uID0gZmFsc2UsXG4gICAgICBhbmltYXRpb25zdHJpbmcgPSAnYW5pbWF0aW9uJyxcbiAgICAgIGtleWZyYW1lcHJlZml4ID0gJycsXG4gICAgICBhbmltYXRpb25zdGFydGV2ZW50ID0gJ2FuaW1hdGlvbnN0YXJ0JyxcbiAgICAgIGRvbVByZWZpeGVzID0gJ1dlYmtpdCBNb3ogTyBtcycuc3BsaXQoJyAnKSxcbiAgICAgIHN0YXJ0RXZlbnRzID0gJ3dlYmtpdEFuaW1hdGlvblN0YXJ0IGFuaW1hdGlvbnN0YXJ0IG9BbmltYXRpb25TdGFydCBNU0FuaW1hdGlvblN0YXJ0Jy5zcGxpdCgnICcpLFxuICAgICAgcGZ4ID0gJyc7XG4gIHtcbiAgICB2YXIgZWxtID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZmFrZWVsZW1lbnQnKTtcbiAgICBpZiAoZWxtLnN0eWxlLmFuaW1hdGlvbk5hbWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgYW5pbWF0aW9uID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAoYW5pbWF0aW9uID09PSBmYWxzZSkge1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBkb21QcmVmaXhlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAoZWxtLnN0eWxlW2RvbVByZWZpeGVzW2ldICsgJ0FuaW1hdGlvbk5hbWUnXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgcGZ4ID0gZG9tUHJlZml4ZXNbaV07XG4gICAgICAgICAgYW5pbWF0aW9uc3RyaW5nID0gcGZ4ICsgJ0FuaW1hdGlvbic7XG4gICAgICAgICAga2V5ZnJhbWVwcmVmaXggPSAnLScgKyBwZngudG9Mb3dlckNhc2UoKSArICctJztcbiAgICAgICAgICBhbmltYXRpb25zdGFydGV2ZW50ID0gc3RhcnRFdmVudHNbaV07XG4gICAgICAgICAgYW5pbWF0aW9uID0gdHJ1ZTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHZhciBhbmltYXRpb25OYW1lID0gJ3Jlc2l6ZWFuaW0nO1xuICB2YXIgYW5pbWF0aW9uS2V5ZnJhbWVzID0gJ0AnICsga2V5ZnJhbWVwcmVmaXggKyAna2V5ZnJhbWVzICcgKyBhbmltYXRpb25OYW1lICsgJyB7IGZyb20geyBvcGFjaXR5OiAwOyB9IHRvIHsgb3BhY2l0eTogMDsgfSB9ICc7XG4gIHZhciBhbmltYXRpb25TdHlsZSA9IGtleWZyYW1lcHJlZml4ICsgJ2FuaW1hdGlvbjogMW1zICcgKyBhbmltYXRpb25OYW1lICsgJzsgJztcbn1cblxudmFyIGNyZWF0ZVN0eWxlcyA9IGZ1bmN0aW9uIGNyZWF0ZVN0eWxlcygpIHtcbiAgaWYgKCFzdHlsZXNDcmVhdGVkKSB7XG4gICAgLy9vcGFjaXR5OjAgd29ya3MgYXJvdW5kIGEgY2hyb21lIGJ1ZyBodHRwczovL2NvZGUuZ29vZ2xlLmNvbS9wL2Nocm9taXVtL2lzc3Vlcy9kZXRhaWw/aWQ9Mjg2MzYwXG4gICAgdmFyIGNzcyA9IChhbmltYXRpb25LZXlmcmFtZXMgPyBhbmltYXRpb25LZXlmcmFtZXMgOiAnJykgKyAnLnJlc2l6ZS10cmlnZ2VycyB7ICcgKyAoYW5pbWF0aW9uU3R5bGUgPyBhbmltYXRpb25TdHlsZSA6ICcnKSArICd2aXNpYmlsaXR5OiBoaWRkZW47IG9wYWNpdHk6IDA7IH0gJyArICcucmVzaXplLXRyaWdnZXJzLCAucmVzaXplLXRyaWdnZXJzID4gZGl2LCAuY29udHJhY3QtdHJpZ2dlcjpiZWZvcmUgeyBjb250ZW50OiBcXFwiIFxcXCI7IGRpc3BsYXk6IGJsb2NrOyBwb3NpdGlvbjogYWJzb2x1dGU7IHRvcDogMDsgbGVmdDogMDsgaGVpZ2h0OiAxMDAlOyB3aWR0aDogMTAwJTsgb3ZlcmZsb3c6IGhpZGRlbjsgfSAucmVzaXplLXRyaWdnZXJzID4gZGl2IHsgYmFja2dyb3VuZDogI2VlZTsgb3ZlcmZsb3c6IGF1dG87IH0gLmNvbnRyYWN0LXRyaWdnZXI6YmVmb3JlIHsgd2lkdGg6IDIwMCU7IGhlaWdodDogMjAwJTsgfScsXG4gICAgICAgIGhlYWQgPSBkb2N1bWVudC5oZWFkIHx8IGRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCdoZWFkJylbMF0sXG4gICAgICAgIHN0eWxlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3R5bGUnKTtcblxuICAgIHN0eWxlLnR5cGUgPSAndGV4dC9jc3MnO1xuICAgIGlmIChzdHlsZS5zdHlsZVNoZWV0KSB7XG4gICAgICBzdHlsZS5zdHlsZVNoZWV0LmNzc1RleHQgPSBjc3M7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN0eWxlLmFwcGVuZENoaWxkKGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKGNzcykpO1xuICAgIH1cblxuICAgIGhlYWQuYXBwZW5kQ2hpbGQoc3R5bGUpO1xuICAgIHN0eWxlc0NyZWF0ZWQgPSB0cnVlO1xuICB9XG59O1xuXG52YXIgYWRkUmVzaXplTGlzdGVuZXIgPSBmdW5jdGlvbiBhZGRSZXNpemVMaXN0ZW5lcihlbGVtZW50LCBmbikge1xuICBpZiAoYXR0YWNoRXZlbnQpIGVsZW1lbnQuYXR0YWNoRXZlbnQoJ29ucmVzaXplJywgZm4pO2Vsc2Uge1xuICAgIGlmICghZWxlbWVudC5fX3Jlc2l6ZVRyaWdnZXJzX18pIHtcbiAgICAgIGlmIChnZXRDb21wdXRlZFN0eWxlKGVsZW1lbnQpLnBvc2l0aW9uID09ICdzdGF0aWMnKSBlbGVtZW50LnN0eWxlLnBvc2l0aW9uID0gJ3JlbGF0aXZlJztcbiAgICAgIGNyZWF0ZVN0eWxlcygpO1xuICAgICAgZWxlbWVudC5fX3Jlc2l6ZUxhc3RfXyA9IHt9O1xuICAgICAgZWxlbWVudC5fX3Jlc2l6ZUxpc3RlbmVyc19fID0gW107XG4gICAgICAoZWxlbWVudC5fX3Jlc2l6ZVRyaWdnZXJzX18gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSkuY2xhc3NOYW1lID0gJ3Jlc2l6ZS10cmlnZ2Vycyc7XG4gICAgICBlbGVtZW50Ll9fcmVzaXplVHJpZ2dlcnNfXy5pbm5lckhUTUwgPSAnPGRpdiBjbGFzcz1cImV4cGFuZC10cmlnZ2VyXCI+PGRpdj48L2Rpdj48L2Rpdj4nICsgJzxkaXYgY2xhc3M9XCJjb250cmFjdC10cmlnZ2VyXCI+PC9kaXY+JztcbiAgICAgIGVsZW1lbnQuYXBwZW5kQ2hpbGQoZWxlbWVudC5fX3Jlc2l6ZVRyaWdnZXJzX18pO1xuICAgICAgcmVzZXRUcmlnZ2VycyhlbGVtZW50KTtcbiAgICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgc2Nyb2xsTGlzdGVuZXIsIHRydWUpO1xuXG4gICAgICAvKiBMaXN0ZW4gZm9yIGEgY3NzIGFuaW1hdGlvbiB0byBkZXRlY3QgZWxlbWVudCBkaXNwbGF5L3JlLWF0dGFjaCAqL1xuICAgICAgYW5pbWF0aW9uc3RhcnRldmVudCAmJiBlbGVtZW50Ll9fcmVzaXplVHJpZ2dlcnNfXy5hZGRFdmVudExpc3RlbmVyKGFuaW1hdGlvbnN0YXJ0ZXZlbnQsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGlmIChlLmFuaW1hdGlvbk5hbWUgPT0gYW5pbWF0aW9uTmFtZSkgcmVzZXRUcmlnZ2VycyhlbGVtZW50KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICBlbGVtZW50Ll9fcmVzaXplTGlzdGVuZXJzX18ucHVzaChmbik7XG4gIH1cbn07XG5cbnZhciByZW1vdmVSZXNpemVMaXN0ZW5lciA9IGZ1bmN0aW9uIHJlbW92ZVJlc2l6ZUxpc3RlbmVyKGVsZW1lbnQsIGZuKSB7XG4gIGlmIChhdHRhY2hFdmVudCkgZWxlbWVudC5kZXRhY2hFdmVudCgnb25yZXNpemUnLCBmbik7ZWxzZSB7XG4gICAgZWxlbWVudC5fX3Jlc2l6ZUxpc3RlbmVyc19fLnNwbGljZShlbGVtZW50Ll9fcmVzaXplTGlzdGVuZXJzX18uaW5kZXhPZihmbiksIDEpO1xuICAgIGlmICghZWxlbWVudC5fX3Jlc2l6ZUxpc3RlbmVyc19fLmxlbmd0aCkge1xuICAgICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdzY3JvbGwnLCBzY3JvbGxMaXN0ZW5lciwgdHJ1ZSk7XG4gICAgICBlbGVtZW50Ll9fcmVzaXplVHJpZ2dlcnNfXyA9ICFlbGVtZW50LnJlbW92ZUNoaWxkKGVsZW1lbnQuX19yZXNpemVUcmlnZ2Vyc19fKTtcbiAgICB9XG4gIH1cbn07XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICBhZGRSZXNpemVMaXN0ZW5lcjogYWRkUmVzaXplTGlzdGVuZXIsXG4gIHJlbW92ZVJlc2l6ZUxpc3RlbmVyOiByZW1vdmVSZXNpemVMaXN0ZW5lclxufTsiLCIndXNlIHN0cmljdCc7XG5tb2R1bGUuZXhwb3J0cyA9ICEhKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmIHdpbmRvdy5kb2N1bWVudCAmJiB3aW5kb3cuZG9jdW1lbnQuY3JlYXRlRWxlbWVudCk7IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgY2FuVXNlRE9NID0gcmVxdWlyZSgnLi9pbkRPTScpO1xuXG52YXIgc2l6ZTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAocmVjYWxjKSB7XG4gIGlmICghc2l6ZSB8fCByZWNhbGMpIHtcbiAgICBpZiAoY2FuVXNlRE9NKSB7XG4gICAgICB2YXIgc2Nyb2xsRGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG5cbiAgICAgIHNjcm9sbERpdi5zdHlsZS5wb3NpdGlvbiA9ICdhYnNvbHV0ZSc7XG4gICAgICBzY3JvbGxEaXYuc3R5bGUudG9wID0gJy05OTk5cHgnO1xuICAgICAgc2Nyb2xsRGl2LnN0eWxlLndpZHRoID0gJzUwcHgnO1xuICAgICAgc2Nyb2xsRGl2LnN0eWxlLmhlaWdodCA9ICc1MHB4JztcbiAgICAgIHNjcm9sbERpdi5zdHlsZS5vdmVyZmxvdyA9ICdzY3JvbGwnO1xuXG4gICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHNjcm9sbERpdik7XG4gICAgICBzaXplID0gc2Nyb2xsRGl2Lm9mZnNldFdpZHRoIC0gc2Nyb2xsRGl2LmNsaWVudFdpZHRoO1xuICAgICAgZG9jdW1lbnQuYm9keS5yZW1vdmVDaGlsZChzY3JvbGxEaXYpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBzaXplO1xufTsiLCJ2YXIgbm93ID0gcmVxdWlyZSgncGVyZm9ybWFuY2Utbm93JylcbiAgLCByb290ID0gdHlwZW9mIHdpbmRvdyA9PT0gJ3VuZGVmaW5lZCcgPyBnbG9iYWwgOiB3aW5kb3dcbiAgLCB2ZW5kb3JzID0gWydtb3onLCAnd2Via2l0J11cbiAgLCBzdWZmaXggPSAnQW5pbWF0aW9uRnJhbWUnXG4gICwgcmFmID0gcm9vdFsncmVxdWVzdCcgKyBzdWZmaXhdXG4gICwgY2FmID0gcm9vdFsnY2FuY2VsJyArIHN1ZmZpeF0gfHwgcm9vdFsnY2FuY2VsUmVxdWVzdCcgKyBzdWZmaXhdXG5cbmZvcih2YXIgaSA9IDA7ICFyYWYgJiYgaSA8IHZlbmRvcnMubGVuZ3RoOyBpKyspIHtcbiAgcmFmID0gcm9vdFt2ZW5kb3JzW2ldICsgJ1JlcXVlc3QnICsgc3VmZml4XVxuICBjYWYgPSByb290W3ZlbmRvcnNbaV0gKyAnQ2FuY2VsJyArIHN1ZmZpeF1cbiAgICAgIHx8IHJvb3RbdmVuZG9yc1tpXSArICdDYW5jZWxSZXF1ZXN0JyArIHN1ZmZpeF1cbn1cblxuLy8gU29tZSB2ZXJzaW9ucyBvZiBGRiBoYXZlIHJBRiBidXQgbm90IGNBRlxuaWYoIXJhZiB8fCAhY2FmKSB7XG4gIHZhciBsYXN0ID0gMFxuICAgICwgaWQgPSAwXG4gICAgLCBxdWV1ZSA9IFtdXG4gICAgLCBmcmFtZUR1cmF0aW9uID0gMTAwMCAvIDYwXG5cbiAgcmFmID0gZnVuY3Rpb24oY2FsbGJhY2spIHtcbiAgICBpZihxdWV1ZS5sZW5ndGggPT09IDApIHtcbiAgICAgIHZhciBfbm93ID0gbm93KClcbiAgICAgICAgLCBuZXh0ID0gTWF0aC5tYXgoMCwgZnJhbWVEdXJhdGlvbiAtIChfbm93IC0gbGFzdCkpXG4gICAgICBsYXN0ID0gbmV4dCArIF9ub3dcbiAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBjcCA9IHF1ZXVlLnNsaWNlKDApXG4gICAgICAgIC8vIENsZWFyIHF1ZXVlIGhlcmUgdG8gcHJldmVudFxuICAgICAgICAvLyBjYWxsYmFja3MgZnJvbSBhcHBlbmRpbmcgbGlzdGVuZXJzXG4gICAgICAgIC8vIHRvIHRoZSBjdXJyZW50IGZyYW1lJ3MgcXVldWVcbiAgICAgICAgcXVldWUubGVuZ3RoID0gMFxuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgY3AubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBpZighY3BbaV0uY2FuY2VsbGVkKSB7XG4gICAgICAgICAgICB0cnl7XG4gICAgICAgICAgICAgIGNwW2ldLmNhbGxiYWNrKGxhc3QpXG4gICAgICAgICAgICB9IGNhdGNoKGUpIHtcbiAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHsgdGhyb3cgZSB9LCAwKVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSwgTWF0aC5yb3VuZChuZXh0KSlcbiAgICB9XG4gICAgcXVldWUucHVzaCh7XG4gICAgICBoYW5kbGU6ICsraWQsXG4gICAgICBjYWxsYmFjazogY2FsbGJhY2ssXG4gICAgICBjYW5jZWxsZWQ6IGZhbHNlXG4gICAgfSlcbiAgICByZXR1cm4gaWRcbiAgfVxuXG4gIGNhZiA9IGZ1bmN0aW9uKGhhbmRsZSkge1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBxdWV1ZS5sZW5ndGg7IGkrKykge1xuICAgICAgaWYocXVldWVbaV0uaGFuZGxlID09PSBoYW5kbGUpIHtcbiAgICAgICAgcXVldWVbaV0uY2FuY2VsbGVkID0gdHJ1ZVxuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGZuKSB7XG4gIC8vIFdyYXAgaW4gYSBuZXcgZnVuY3Rpb24gdG8gcHJldmVudFxuICAvLyBgY2FuY2VsYCBwb3RlbnRpYWxseSBiZWluZyBhc3NpZ25lZFxuICAvLyB0byB0aGUgbmF0aXZlIHJBRiBmdW5jdGlvblxuICByZXR1cm4gcmFmLmNhbGwocm9vdCwgZm4pXG59XG5tb2R1bGUuZXhwb3J0cy5jYW5jZWwgPSBmdW5jdGlvbigpIHtcbiAgY2FmLmFwcGx5KHJvb3QsIGFyZ3VtZW50cylcbn1cbm1vZHVsZS5leHBvcnRzLnBvbHlmaWxsID0gZnVuY3Rpb24oKSB7XG4gIHJvb3QucmVxdWVzdEFuaW1hdGlvbkZyYW1lID0gcmFmXG4gIHJvb3QuY2FuY2VsQW5pbWF0aW9uRnJhbWUgPSBjYWZcbn1cbiIsIi8vIEdlbmVyYXRlZCBieSBDb2ZmZWVTY3JpcHQgMS4xMi4yXG4oZnVuY3Rpb24oKSB7XG4gIHZhciBnZXROYW5vU2Vjb25kcywgaHJ0aW1lLCBsb2FkVGltZSwgbW9kdWxlTG9hZFRpbWUsIG5vZGVMb2FkVGltZSwgdXBUaW1lO1xuXG4gIGlmICgodHlwZW9mIHBlcmZvcm1hbmNlICE9PSBcInVuZGVmaW5lZFwiICYmIHBlcmZvcm1hbmNlICE9PSBudWxsKSAmJiBwZXJmb3JtYW5jZS5ub3cpIHtcbiAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHBlcmZvcm1hbmNlLm5vdygpO1xuICAgIH07XG4gIH0gZWxzZSBpZiAoKHR5cGVvZiBwcm9jZXNzICE9PSBcInVuZGVmaW5lZFwiICYmIHByb2Nlc3MgIT09IG51bGwpICYmIHByb2Nlc3MuaHJ0aW1lKSB7XG4gICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiAoZ2V0TmFub1NlY29uZHMoKSAtIG5vZGVMb2FkVGltZSkgLyAxZTY7XG4gICAgfTtcbiAgICBocnRpbWUgPSBwcm9jZXNzLmhydGltZTtcbiAgICBnZXROYW5vU2Vjb25kcyA9IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGhyO1xuICAgICAgaHIgPSBocnRpbWUoKTtcbiAgICAgIHJldHVybiBoclswXSAqIDFlOSArIGhyWzFdO1xuICAgIH07XG4gICAgbW9kdWxlTG9hZFRpbWUgPSBnZXROYW5vU2Vjb25kcygpO1xuICAgIHVwVGltZSA9IHByb2Nlc3MudXB0aW1lKCkgKiAxZTk7XG4gICAgbm9kZUxvYWRUaW1lID0gbW9kdWxlTG9hZFRpbWUgLSB1cFRpbWU7XG4gIH0gZWxzZSBpZiAoRGF0ZS5ub3cpIHtcbiAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIERhdGUubm93KCkgLSBsb2FkVGltZTtcbiAgICB9O1xuICAgIGxvYWRUaW1lID0gRGF0ZS5ub3coKTtcbiAgfSBlbHNlIHtcbiAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIG5ldyBEYXRlKCkuZ2V0VGltZSgpIC0gbG9hZFRpbWU7XG4gICAgfTtcbiAgICBsb2FkVGltZSA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICB9XG5cbn0pLmNhbGwodGhpcyk7XG5cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXBlcmZvcm1hbmNlLW5vdy5qcy5tYXBcbiJdfQ== diff --git a/examples/dist/bundle.js b/examples/dist/bundle.js index ad9809313a..3248f69c1c 100644 --- a/examples/dist/bundle.js +++ b/examples/dist/bundle.js @@ -13,8 +13,6 @@ var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_ag function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } -function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } @@ -98,16 +96,13 @@ var Async = (function (_Component) { } } }, { - key: 'componentWillUpdate', - value: function componentWillUpdate(nextProps, nextState) { - var _this = this; - - var propertiesToSync = ['options']; - propertiesToSync.forEach(function (prop) { - if (_this.props[prop] !== nextProps[prop]) { - _this.setState(_defineProperty({}, prop, nextProps[prop])); - } - }); + key: 'componentWillReceiveProps', + value: function componentWillReceiveProps(nextProps) { + if (nextProps.options !== this.props.options) { + this.setState({ + options: nextProps.options + }); + } } }, { key: 'clearOptions', @@ -117,7 +112,7 @@ var Async = (function (_Component) { }, { key: 'loadOptions', value: function loadOptions(inputValue) { - var _this2 = this; + var _this = this; var loadOptions = this.props.loadOptions; @@ -132,8 +127,8 @@ var Async = (function (_Component) { } var callback = function callback(error, data) { - if (callback === _this2._callback) { - _this2._callback = null; + if (callback === _this._callback) { + _this._callback = null; var options = data && data.options || []; @@ -141,7 +136,7 @@ var Async = (function (_Component) { cache[inputValue] = options; } - _this2.setState({ + _this.setState({ isLoading: false, options: options }); @@ -165,8 +160,6 @@ var Async = (function (_Component) { isLoading: true }); } - - return inputValue; } }, { key: '_onInputChange', @@ -176,19 +169,24 @@ var Async = (function (_Component) { var ignoreCase = _props.ignoreCase; var onInputChange = _props.onInputChange; + var transformedInputValue = inputValue; + if (ignoreAccents) { - inputValue = (0, _utilsStripDiacritics2['default'])(inputValue); + transformedInputValue = (0, _utilsStripDiacritics2['default'])(transformedInputValue); } if (ignoreCase) { - inputValue = inputValue.toLowerCase(); + transformedInputValue = transformedInputValue.toLowerCase(); } if (onInputChange) { - onInputChange(inputValue); + onInputChange(transformedInputValue); } - return this.loadOptions(inputValue); + this.loadOptions(transformedInputValue); + + // Return the original input value to avoid modifying the user's view of the input while typing. + return inputValue; } }, { key: 'inputValue', @@ -225,7 +223,7 @@ var Async = (function (_Component) { }, { key: 'render', value: function render() { - var _this3 = this; + var _this2 = this; var _props3 = this.props; var children = _props3.children; @@ -240,13 +238,13 @@ var Async = (function (_Component) { placeholder: isLoading ? loadingPlaceholder : placeholder, options: isLoading && loadingPlaceholder ? [] : options, ref: function ref(_ref) { - return _this3.select = _ref; + return _this2.select = _ref; }, onChange: function onChange(newValues) { - if (_this3.props.multi && _this3.props.value && newValues.length > _this3.props.value.length) { - _this3.clearOptions(); + if (_this2.props.multi && _this2.props.value && newValues.length > _this2.props.value.length) { + _this2.clearOptions(); } - _this3.props.onChange(newValues); + _this2.props.onChange(newValues); } }; @@ -270,25 +268,37 @@ function defaultChildren(props) { } module.exports = exports['default']; -},{"./Select":"react-select","./utils/stripDiacritics":10,"prop-types":undefined,"react":undefined}],2:[function(require,module,exports){ +},{"./Select":5,"./utils/stripDiacritics":11,"prop-types":undefined,"react":undefined}],2:[function(require,module,exports){ 'use strict'; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; +var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + +var _get = function get(_x2, _x3, _x4) { var _again = true; _function: while (_again) { var object = _x2, property = _x3, receiver = _x4; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x2 = parent; _x3 = property; _x4 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } -var _react = require('react'); +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } -var _react2 = _interopRequireDefault(_react); +function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } -var _createReactClass = require('create-react-class'); +var _react = require('react'); -var _createReactClass2 = _interopRequireDefault(_createReactClass); +var _react2 = _interopRequireDefault(_react); var _Select = require('./Select'); var _Select2 = _interopRequireDefault(_Select); +var _Async = require('./Async'); + +var _Async2 = _interopRequireDefault(_Async); + +var _Creatable = require('./Creatable'); + +var _Creatable2 = _interopRequireDefault(_Creatable); + function reduce(obj) { var props = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; @@ -299,60 +309,78 @@ function reduce(obj) { }, props); } -var AsyncCreatable = (0, _createReactClass2['default'])({ - displayName: 'AsyncCreatableSelect', - - focus: function focus() { - this.select.focus(); - }, +var AsyncCreatableSelect = (function (_React$Component) { + _inherits(AsyncCreatableSelect, _React$Component); - render: function render() { - var _this = this; + function AsyncCreatableSelect() { + _classCallCheck(this, AsyncCreatableSelect); - return _react2['default'].createElement( - _Select2['default'].Async, - this.props, - function (asyncProps) { - return _react2['default'].createElement( - _Select2['default'].Creatable, - _this.props, - function (creatableProps) { - return _react2['default'].createElement(_Select2['default'], _extends({}, reduce(asyncProps, reduce(creatableProps, {})), { - onInputChange: function (input) { - creatableProps.onInputChange(input); - return asyncProps.onInputChange(input); - }, - ref: function (ref) { - _this.select = ref; - creatableProps.ref(ref); - asyncProps.ref(ref); - } - })); - } - ); - } - ); + _get(Object.getPrototypeOf(AsyncCreatableSelect.prototype), 'constructor', this).apply(this, arguments); } -}); -module.exports = AsyncCreatable; + _createClass(AsyncCreatableSelect, [{ + key: 'focus', + value: function focus() { + this.select.focus(); + } + }, { + key: 'render', + value: function render() { + var _this = this; + + return _react2['default'].createElement( + _Async2['default'], + this.props, + function (asyncProps) { + return _react2['default'].createElement( + _Creatable2['default'], + _this.props, + function (creatableProps) { + return _react2['default'].createElement(_Select2['default'], _extends({}, reduce(asyncProps, reduce(creatableProps, {})), { + onInputChange: function (input) { + creatableProps.onInputChange(input); + return asyncProps.onInputChange(input); + }, + ref: function (ref) { + _this.select = ref; + creatableProps.ref(ref); + asyncProps.ref(ref); + } + })); + } + ); + } + ); + } + }]); + + return AsyncCreatableSelect; +})(_react2['default'].Component); -},{"./Select":"react-select","create-react-class":undefined,"react":undefined}],3:[function(require,module,exports){ +; + +module.exports = AsyncCreatableSelect; + +},{"./Async":1,"./Creatable":3,"./Select":5,"react":undefined}],3:[function(require,module,exports){ 'use strict'; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; +var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + +var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } -var _react = require('react'); +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } -var _react2 = _interopRequireDefault(_react); +function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } -var _createReactClass = require('create-react-class'); +var _react = require('react'); -var _createReactClass2 = _interopRequireDefault(_createReactClass); +var _react2 = _interopRequireDefault(_react); var _propTypes = require('prop-types'); @@ -370,249 +398,210 @@ var _utilsDefaultMenuRenderer = require('./utils/defaultMenuRenderer'); var _utilsDefaultMenuRenderer2 = _interopRequireDefault(_utilsDefaultMenuRenderer); -var Creatable = (0, _createReactClass2['default'])({ - displayName: 'CreatableSelect', - - propTypes: { - // Child function responsible for creating the inner Select component - // This component can be used to compose HOCs (eg Creatable and Async) - // (props: Object): PropTypes.element - children: _propTypes2['default'].func, - - // See Select.propTypes.filterOptions - filterOptions: _propTypes2['default'].any, - - // Searches for any matching option within the set of options. - // This function prevents duplicate options from being created. - // ({ option: Object, options: Array, labelKey: string, valueKey: string }): boolean - isOptionUnique: _propTypes2['default'].func, - - // Determines if the current input text represents a valid option. - // ({ label: string }): boolean - isValidNewOption: _propTypes2['default'].func, - - // See Select.propTypes.menuRenderer - menuRenderer: _propTypes2['default'].any, - - // Factory to create new option. - // ({ label: string, labelKey: string, valueKey: string }): Object - newOptionCreator: _propTypes2['default'].func, - - // input change handler: function (inputValue) {} - onInputChange: _propTypes2['default'].func, - - // input keyDown handler: function (event) {} - onInputKeyDown: _propTypes2['default'].func, - - // new option click handler: function (option) {} - onNewOptionClick: _propTypes2['default'].func, - - // See Select.propTypes.options - options: _propTypes2['default'].array, - - // Creates prompt/placeholder option text. - // (filterText: string): string - promptTextCreator: _propTypes2['default'].func, - - // Decides if a keyDown event (eg its `keyCode`) should result in the creation of a new option. - shouldKeyDownEventCreateNewOption: _propTypes2['default'].func - }, - - // Default prop methods - statics: { - isOptionUnique: isOptionUnique, - isValidNewOption: isValidNewOption, - newOptionCreator: newOptionCreator, - promptTextCreator: promptTextCreator, - shouldKeyDownEventCreateNewOption: shouldKeyDownEventCreateNewOption - }, - - getDefaultProps: function getDefaultProps() { - return { - filterOptions: _utilsDefaultFilterOptions2['default'], - isOptionUnique: isOptionUnique, - isValidNewOption: isValidNewOption, - menuRenderer: _utilsDefaultMenuRenderer2['default'], - newOptionCreator: newOptionCreator, - promptTextCreator: promptTextCreator, - shouldKeyDownEventCreateNewOption: shouldKeyDownEventCreateNewOption - }; - }, - - createNewOption: function createNewOption() { - var _props = this.props; - var isValidNewOption = _props.isValidNewOption; - var newOptionCreator = _props.newOptionCreator; - var onNewOptionClick = _props.onNewOptionClick; - var _props$options = _props.options; - var options = _props$options === undefined ? [] : _props$options; - var shouldKeyDownEventCreateNewOption = _props.shouldKeyDownEventCreateNewOption; - - if (isValidNewOption({ label: this.inputValue })) { - var option = newOptionCreator({ label: this.inputValue, labelKey: this.labelKey, valueKey: this.valueKey }); - var _isOptionUnique = this.isOptionUnique({ option: option }); - - // Don't add the same option twice. - if (_isOptionUnique) { - if (onNewOptionClick) { - onNewOptionClick(option); - } else { - options.unshift(option); - - this.select.selectValue(option); - } - } - } - }, +var CreatableSelect = (function (_React$Component) { + _inherits(CreatableSelect, _React$Component); - filterOptions: function filterOptions() { - var _props2 = this.props; - var filterOptions = _props2.filterOptions; - var isValidNewOption = _props2.isValidNewOption; - var options = _props2.options; - var promptTextCreator = _props2.promptTextCreator; + function CreatableSelect(props, context) { + _classCallCheck(this, CreatableSelect); - // TRICKY Check currently selected options as well. - // Don't display a create-prompt for a value that's selected. - // This covers async edge-cases where a newly-created Option isn't yet in the async-loaded array. - var excludeOptions = arguments[2] || []; + _get(Object.getPrototypeOf(CreatableSelect.prototype), 'constructor', this).call(this, props, context); - var filteredOptions = filterOptions.apply(undefined, arguments) || []; + this.filterOptions = this.filterOptions.bind(this); + this.menuRenderer = this.menuRenderer.bind(this); + this.onInputKeyDown = this.onInputKeyDown.bind(this); + this.onInputChange = this.onInputChange.bind(this); + this.onOptionSelect = this.onOptionSelect.bind(this); + } - if (isValidNewOption({ label: this.inputValue })) { - var _newOptionCreator = this.props.newOptionCreator; + _createClass(CreatableSelect, [{ + key: 'createNewOption', + value: function createNewOption() { + var _props = this.props; + var isValidNewOption = _props.isValidNewOption; + var newOptionCreator = _props.newOptionCreator; + var onNewOptionClick = _props.onNewOptionClick; + var _props$options = _props.options; + var options = _props$options === undefined ? [] : _props$options; + var shouldKeyDownEventCreateNewOption = _props.shouldKeyDownEventCreateNewOption; + + if (isValidNewOption({ label: this.inputValue })) { + var option = newOptionCreator({ label: this.inputValue, labelKey: this.labelKey, valueKey: this.valueKey }); + var _isOptionUnique = this.isOptionUnique({ option: option }); + + // Don't add the same option twice. + if (_isOptionUnique) { + if (onNewOptionClick) { + onNewOptionClick(option); + } else { + options.unshift(option); + + this.select.selectValue(option); + } + } + } + } + }, { + key: 'filterOptions', + value: function filterOptions() { + var _props2 = this.props; + var filterOptions = _props2.filterOptions; + var isValidNewOption = _props2.isValidNewOption; + var options = _props2.options; + var promptTextCreator = _props2.promptTextCreator; - var option = _newOptionCreator({ - label: this.inputValue, - labelKey: this.labelKey, - valueKey: this.valueKey - }); + // TRICKY Check currently selected options as well. + // Don't display a create-prompt for a value that's selected. + // This covers async edge-cases where a newly-created Option isn't yet in the async-loaded array. + var excludeOptions = arguments[2] || []; - // TRICKY Compare to all options (not just filtered options) in case option has already been selected). - // For multi-selects, this would remove it from the filtered list. - var _isOptionUnique2 = this.isOptionUnique({ - option: option, - options: excludeOptions.concat(filteredOptions) - }); + var filteredOptions = filterOptions.apply(undefined, arguments) || []; - if (_isOptionUnique2) { - var _prompt = promptTextCreator(this.inputValue); + if (isValidNewOption({ label: this.inputValue })) { + var _newOptionCreator = this.props.newOptionCreator; - this._createPlaceholderOption = _newOptionCreator({ - label: _prompt, + var option = _newOptionCreator({ + label: this.inputValue, labelKey: this.labelKey, valueKey: this.valueKey }); - filteredOptions.unshift(this._createPlaceholderOption); - } - } - - return filteredOptions; - }, + // TRICKY Compare to all options (not just filtered options) in case option has already been selected). + // For multi-selects, this would remove it from the filtered list. + var _isOptionUnique2 = this.isOptionUnique({ + option: option, + options: excludeOptions.concat(filteredOptions) + }); - isOptionUnique: function isOptionUnique(_ref2) { - var option = _ref2.option; - var options = _ref2.options; - var isOptionUnique = this.props.isOptionUnique; + if (_isOptionUnique2) { + var _prompt = promptTextCreator(this.inputValue); - options = options || this.select.filterOptions(); + this._createPlaceholderOption = _newOptionCreator({ + label: _prompt, + labelKey: this.labelKey, + valueKey: this.valueKey + }); - return isOptionUnique({ - labelKey: this.labelKey, - option: option, - options: options, - valueKey: this.valueKey - }); - }, + filteredOptions.unshift(this._createPlaceholderOption); + } + } - menuRenderer: function menuRenderer(params) { - var menuRenderer = this.props.menuRenderer; + return filteredOptions; + } + }, { + key: 'isOptionUnique', + value: function isOptionUnique(_ref2) { + var option = _ref2.option; + var options = _ref2.options; + var isOptionUnique = this.props.isOptionUnique; - return menuRenderer(_extends({}, params, { - onSelect: this.onOptionSelect, - selectValue: this.onOptionSelect - })); - }, + options = options || this.select.filterOptions(); - onInputChange: function onInputChange(input) { - var onInputChange = this.props.onInputChange; + return isOptionUnique({ + labelKey: this.labelKey, + option: option, + options: options, + valueKey: this.valueKey + }); + } + }, { + key: 'menuRenderer', + value: function menuRenderer(params) { + var menuRenderer = this.props.menuRenderer; - if (onInputChange) { - onInputChange(input); + return menuRenderer(_extends({}, params, { + onSelect: this.onOptionSelect, + selectValue: this.onOptionSelect + })); } + }, { + key: 'onInputChange', + value: function onInputChange(input) { + var onInputChange = this.props.onInputChange; - // This value may be needed in between Select mounts (when this.select is null) - this.inputValue = input; - }, + if (onInputChange) { + onInputChange(input); + } - onInputKeyDown: function onInputKeyDown(event) { - var _props3 = this.props; - var shouldKeyDownEventCreateNewOption = _props3.shouldKeyDownEventCreateNewOption; - var onInputKeyDown = _props3.onInputKeyDown; + // This value may be needed in between Select mounts (when this.select is null) + this.inputValue = input; + } + }, { + key: 'onInputKeyDown', + value: function onInputKeyDown(event) { + var _props3 = this.props; + var shouldKeyDownEventCreateNewOption = _props3.shouldKeyDownEventCreateNewOption; + var onInputKeyDown = _props3.onInputKeyDown; - var focusedOption = this.select.getFocusedOption(); + var focusedOption = this.select.getFocusedOption(); - if (focusedOption && focusedOption === this._createPlaceholderOption && shouldKeyDownEventCreateNewOption({ keyCode: event.keyCode })) { - this.createNewOption(); + if (focusedOption && focusedOption === this._createPlaceholderOption && shouldKeyDownEventCreateNewOption({ keyCode: event.keyCode })) { + this.createNewOption(); - // Prevent decorated Select from doing anything additional with this keyDown event - event.preventDefault(); - } else if (onInputKeyDown) { - onInputKeyDown(event); + // Prevent decorated Select from doing anything additional with this keyDown event + event.preventDefault(); + } else if (onInputKeyDown) { + onInputKeyDown(event); + } } - }, - - onOptionSelect: function onOptionSelect(option, event) { - if (option === this._createPlaceholderOption) { - this.createNewOption(); - } else { - this.select.selectValue(option); + }, { + key: 'onOptionSelect', + value: function onOptionSelect(option, event) { + if (option === this._createPlaceholderOption) { + this.createNewOption(); + } else { + this.select.selectValue(option); + } + } + }, { + key: 'focus', + value: function focus() { + this.select.focus(); } - }, + }, { + key: 'render', + value: function render() { + var _this = this; - focus: function focus() { - this.select.focus(); - }, + var _props4 = this.props; + var newOptionCreator = _props4.newOptionCreator; + var shouldKeyDownEventCreateNewOption = _props4.shouldKeyDownEventCreateNewOption; - render: function render() { - var _this = this; + var restProps = _objectWithoutProperties(_props4, ['newOptionCreator', 'shouldKeyDownEventCreateNewOption']); - var _props4 = this.props; - var newOptionCreator = _props4.newOptionCreator; - var shouldKeyDownEventCreateNewOption = _props4.shouldKeyDownEventCreateNewOption; + var children = this.props.children; - var restProps = _objectWithoutProperties(_props4, ['newOptionCreator', 'shouldKeyDownEventCreateNewOption']); + // We can't use destructuring default values to set the children, + // because it won't apply work if `children` is null. A falsy check is + // more reliable in real world use-cases. + if (!children) { + children = defaultChildren; + } - var children = this.props.children; + var props = _extends({}, restProps, { + allowCreate: true, + filterOptions: this.filterOptions, + menuRenderer: this.menuRenderer, + onInputChange: this.onInputChange, + onInputKeyDown: this.onInputKeyDown, + ref: function ref(_ref) { + _this.select = _ref; - // We can't use destructuring default values to set the children, - // because it won't apply work if `children` is null. A falsy check is - // more reliable in real world use-cases. - if (!children) { - children = defaultChildren; - } + // These values may be needed in between Select mounts (when this.select is null) + if (_ref) { + _this.labelKey = _ref.props.labelKey; + _this.valueKey = _ref.props.valueKey; + } + } + }); - var props = _extends({}, restProps, { - allowCreate: true, - filterOptions: this.filterOptions, - menuRenderer: this.menuRenderer, - onInputChange: this.onInputChange, - onInputKeyDown: this.onInputKeyDown, - ref: function ref(_ref) { - _this.select = _ref; + return children(props); + } + }]); - // These values may be needed in between Select mounts (when this.select is null) - if (_ref) { - _this.labelKey = _ref.props.labelKey; - _this.valueKey = _ref.props.valueKey; - } - } - }); + return CreatableSelect; +})(_react2['default'].Component); - return children(props); - } -}); +; function defaultChildren(props) { return _react2['default'].createElement(_Select2['default'], props); @@ -665,139 +654,86 @@ function shouldKeyDownEventCreateNewOption(_ref6) { return false; }; -module.exports = Creatable; +// Default prop methods +CreatableSelect.isOptionUnique = isOptionUnique; +CreatableSelect.isValidNewOption = isValidNewOption; +CreatableSelect.newOptionCreator = newOptionCreator; +CreatableSelect.promptTextCreator = promptTextCreator; +CreatableSelect.shouldKeyDownEventCreateNewOption = shouldKeyDownEventCreateNewOption; + +CreatableSelect.defaultProps = { + filterOptions: _utilsDefaultFilterOptions2['default'], + isOptionUnique: isOptionUnique, + isValidNewOption: isValidNewOption, + menuRenderer: _utilsDefaultMenuRenderer2['default'], + newOptionCreator: newOptionCreator, + promptTextCreator: promptTextCreator, + shouldKeyDownEventCreateNewOption: shouldKeyDownEventCreateNewOption +}; -},{"./Select":"react-select","./utils/defaultFilterOptions":8,"./utils/defaultMenuRenderer":9,"create-react-class":undefined,"prop-types":undefined,"react":undefined}],4:[function(require,module,exports){ -'use strict'; +CreatableSelect.propTypes = { + // Child function responsible for creating the inner Select component + // This component can be used to compose HOCs (eg Creatable and Async) + // (props: Object): PropTypes.element + children: _propTypes2['default'].func, -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + // See Select.propTypes.filterOptions + filterOptions: _propTypes2['default'].any, -var _react = require('react'); + // Searches for any matching option within the set of options. + // This function prevents duplicate options from being created. + // ({ option: Object, options: Array, labelKey: string, valueKey: string }): boolean + isOptionUnique: _propTypes2['default'].func, -var _react2 = _interopRequireDefault(_react); + // Determines if the current input text represents a valid option. + // ({ label: string }): boolean + isValidNewOption: _propTypes2['default'].func, -var _createReactClass = require('create-react-class'); + // See Select.propTypes.menuRenderer + menuRenderer: _propTypes2['default'].any, -var _createReactClass2 = _interopRequireDefault(_createReactClass); + // Factory to create new option. + // ({ label: string, labelKey: string, valueKey: string }): Object + newOptionCreator: _propTypes2['default'].func, -var _propTypes = require('prop-types'); + // input change handler: function (inputValue) {} + onInputChange: _propTypes2['default'].func, -var _propTypes2 = _interopRequireDefault(_propTypes); + // input keyDown handler: function (event) {} + onInputKeyDown: _propTypes2['default'].func, -var _classnames = require('classnames'); + // new option click handler: function (option) {} + onNewOptionClick: _propTypes2['default'].func, -var _classnames2 = _interopRequireDefault(_classnames); + // See Select.propTypes.options + options: _propTypes2['default'].array, -var Option = (0, _createReactClass2['default'])({ - propTypes: { - children: _propTypes2['default'].node, - className: _propTypes2['default'].string, // className (based on mouse position) - instancePrefix: _propTypes2['default'].string.isRequired, // unique prefix for the ids (used for aria) - isDisabled: _propTypes2['default'].bool, // the option is disabled - isFocused: _propTypes2['default'].bool, // the option is focused - isSelected: _propTypes2['default'].bool, // the option is selected - onFocus: _propTypes2['default'].func, // method to handle mouseEnter on option element - onSelect: _propTypes2['default'].func, // method to handle click on option element - onUnfocus: _propTypes2['default'].func, // method to handle mouseLeave on option element - option: _propTypes2['default'].object.isRequired, // object that is base for that option - optionIndex: _propTypes2['default'].number }, - // index of the option, used to generate unique ids for aria - blockEvent: function blockEvent(event) { - event.preventDefault(); - event.stopPropagation(); - if (event.target.tagName !== 'A' || !('href' in event.target)) { - return; - } - if (event.target.target) { - window.open(event.target.href, event.target.target); - } else { - window.location.href = event.target.href; - } - }, - - handleMouseDown: function handleMouseDown(event) { - event.preventDefault(); - event.stopPropagation(); - this.props.onSelect(this.props.option, event); - }, - - handleMouseEnter: function handleMouseEnter(event) { - this.onFocus(event); - }, - - handleMouseMove: function handleMouseMove(event) { - this.onFocus(event); - }, - - handleTouchEnd: function handleTouchEnd(event) { - // Check if the view is being dragged, In this case - // we don't want to fire the click event (because the user only wants to scroll) - if (this.dragging) return; - - this.handleMouseDown(event); - }, - - handleTouchMove: function handleTouchMove(event) { - // Set a flag that the view is being dragged - this.dragging = true; - }, - - handleTouchStart: function handleTouchStart(event) { - // Set a flag that the view is not being dragged - this.dragging = false; - }, - - onFocus: function onFocus(event) { - if (!this.props.isFocused) { - this.props.onFocus(this.props.option, event); - } - }, - render: function render() { - var _props = this.props; - var option = _props.option; - var instancePrefix = _props.instancePrefix; - var optionIndex = _props.optionIndex; - - var className = (0, _classnames2['default'])(this.props.className, option.className); - - return option.disabled ? _react2['default'].createElement( - 'div', - { className: className, - onMouseDown: this.blockEvent, - onClick: this.blockEvent }, - this.props.children - ) : _react2['default'].createElement( - 'div', - { className: className, - style: option.style, - role: 'option', - onMouseDown: this.handleMouseDown, - onMouseEnter: this.handleMouseEnter, - onMouseMove: this.handleMouseMove, - onTouchStart: this.handleTouchStart, - onTouchMove: this.handleTouchMove, - onTouchEnd: this.handleTouchEnd, - id: instancePrefix + '-option-' + optionIndex, - title: option.title }, - this.props.children - ); - } -}); + // Creates prompt/placeholder option text. + // (filterText: string): string + promptTextCreator: _propTypes2['default'].func, -module.exports = Option; + // Decides if a keyDown event (eg its `keyCode`) should result in the creation of a new option. + shouldKeyDownEventCreateNewOption: _propTypes2['default'].func +}; + +module.exports = CreatableSelect; -},{"classnames":undefined,"create-react-class":undefined,"prop-types":undefined,"react":undefined}],5:[function(require,module,exports){ +},{"./Select":5,"./utils/defaultFilterOptions":9,"./utils/defaultMenuRenderer":10,"prop-types":undefined,"react":undefined}],4:[function(require,module,exports){ 'use strict'; +var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + +var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } -var _react = require('react'); +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } -var _react2 = _interopRequireDefault(_react); +function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } -var _createReactClass = require('create-react-class'); +var _react = require('react'); -var _createReactClass2 = _interopRequireDefault(_createReactClass); +var _react2 = _interopRequireDefault(_react); var _propTypes = require('prop-types'); @@ -807,299 +743,168 @@ var _classnames = require('classnames'); var _classnames2 = _interopRequireDefault(_classnames); -var Value = (0, _createReactClass2['default'])({ +var Option = (function (_React$Component) { + _inherits(Option, _React$Component); - displayName: 'Value', + function Option(props) { + _classCallCheck(this, Option); - propTypes: { - children: _propTypes2['default'].node, - disabled: _propTypes2['default'].bool, // disabled prop passed to ReactSelect - id: _propTypes2['default'].string, // Unique id for the value - used for aria - onClick: _propTypes2['default'].func, // method to handle click on value label - onRemove: _propTypes2['default'].func, // method to handle removal of the value - value: _propTypes2['default'].object.isRequired }, + _get(Object.getPrototypeOf(Option.prototype), 'constructor', this).call(this, props); - // the option object for this value - handleMouseDown: function handleMouseDown(event) { - if (event.type === 'mousedown' && event.button !== 0) { - return; - } - if (this.props.onClick) { + this.handleMouseDown = this.handleMouseDown.bind(this); + this.handleMouseEnter = this.handleMouseEnter.bind(this); + this.handleMouseMove = this.handleMouseMove.bind(this); + this.handleTouchStart = this.handleTouchStart.bind(this); + this.onFocus = this.onFocus.bind(this); + } + + _createClass(Option, [{ + key: 'blockEvent', + value: function blockEvent(event) { + event.preventDefault(); event.stopPropagation(); - this.props.onClick(this.props.value, event); - return; + if (event.target.tagName !== 'A' || !('href' in event.target)) { + return; + } + if (event.target.target) { + window.open(event.target.href, event.target.target); + } else { + window.location.href = event.target.href; + } } - if (this.props.value.href) { + }, { + key: 'handleMouseDown', + value: function handleMouseDown(event) { + event.preventDefault(); event.stopPropagation(); + this.props.onSelect(this.props.option, event); } - }, - - onRemove: function onRemove(event) { - event.preventDefault(); - event.stopPropagation(); - this.props.onRemove(this.props.value); - }, - - handleTouchEndRemove: function handleTouchEndRemove(event) { - // Check if the view is being dragged, In this case - // we don't want to fire the click event (because the user only wants to scroll) - if (this.dragging) return; + }, { + key: 'handleMouseEnter', + value: function handleMouseEnter(event) { + this.onFocus(event); + } + }, { + key: 'handleMouseMove', + value: function handleMouseMove(event) { + this.onFocus(event); + } + }, { + key: 'handleTouchEnd', + value: function handleTouchEnd(event) { + // Check if the view is being dragged, In this case + // we don't want to fire the click event (because the user only wants to scroll) + if (this.dragging) return; - // Fire the mouse events - this.onRemove(event); - }, + this.handleMouseDown(event); + } + }, { + key: 'handleTouchMove', + value: function handleTouchMove(event) { + // Set a flag that the view is being dragged + this.dragging = true; + } + }, { + key: 'handleTouchStart', + value: function handleTouchStart(event) { + // Set a flag that the view is not being dragged + this.dragging = false; + } + }, { + key: 'onFocus', + value: function onFocus(event) { + if (!this.props.isFocused) { + this.props.onFocus(this.props.option, event); + } + } + }, { + key: 'render', + value: function render() { + var _props = this.props; + var option = _props.option; + var instancePrefix = _props.instancePrefix; + var optionIndex = _props.optionIndex; - handleTouchMove: function handleTouchMove(event) { - // Set a flag that the view is being dragged - this.dragging = true; - }, + var className = (0, _classnames2['default'])(this.props.className, option.className); - handleTouchStart: function handleTouchStart(event) { - // Set a flag that the view is not being dragged - this.dragging = false; - }, + return option.disabled ? _react2['default'].createElement( + 'div', + { className: className, + onMouseDown: this.blockEvent, + onClick: this.blockEvent }, + this.props.children + ) : _react2['default'].createElement( + 'div', + { className: className, + style: option.style, + role: 'option', + onMouseDown: this.handleMouseDown, + onMouseEnter: this.handleMouseEnter, + onMouseMove: this.handleMouseMove, + onTouchStart: this.handleTouchStart, + onTouchMove: this.handleTouchMove, + onTouchEnd: this.handleTouchEnd, + id: instancePrefix + '-option-' + optionIndex, + title: option.title }, + this.props.children + ); + } + }]); - renderRemoveIcon: function renderRemoveIcon() { - if (this.props.disabled || !this.props.onRemove) return; - return _react2['default'].createElement( - 'span', - { className: 'Select-value-icon', - 'aria-hidden': 'true', - onMouseDown: this.onRemove, - onTouchEnd: this.handleTouchEndRemove, - onTouchStart: this.handleTouchStart, - onTouchMove: this.handleTouchMove }, - '×' - ); - }, - - renderLabel: function renderLabel() { - var className = 'Select-value-label'; - return this.props.onClick || this.props.value.href ? _react2['default'].createElement( - 'a', - { className: className, href: this.props.value.href, target: this.props.value.target, onMouseDown: this.handleMouseDown, onTouchEnd: this.handleMouseDown }, - this.props.children - ) : _react2['default'].createElement( - 'span', - { className: className, role: 'option', 'aria-selected': 'true', id: this.props.id }, - this.props.children - ); - }, + return Option; +})(_react2['default'].Component); - render: function render() { - return _react2['default'].createElement( - 'div', - { className: (0, _classnames2['default'])('Select-value', this.props.value.className), - style: this.props.value.style, - title: this.props.value.title - }, - this.renderRemoveIcon(), - this.renderLabel() - ); - } +; -}); +Option.propTypes = { + children: _propTypes2['default'].node, + className: _propTypes2['default'].string, // className (based on mouse position) + instancePrefix: _propTypes2['default'].string.isRequired, // unique prefix for the ids (used for aria) + isDisabled: _propTypes2['default'].bool, // the option is disabled + isFocused: _propTypes2['default'].bool, // the option is focused + isSelected: _propTypes2['default'].bool, // the option is selected + onFocus: _propTypes2['default'].func, // method to handle mouseEnter on option element + onSelect: _propTypes2['default'].func, // method to handle click on option element + onUnfocus: _propTypes2['default'].func, // method to handle mouseLeave on option element + option: _propTypes2['default'].object.isRequired, // object that is base for that option + optionIndex: _propTypes2['default'].number }; + +// index of the option, used to generate unique ids for aria +module.exports = Option; -module.exports = Value; +},{"classnames":undefined,"prop-types":undefined,"react":undefined}],5:[function(require,module,exports){ +/*! + Copyright (c) 2016 Jed Watson. + Licensed under the MIT License (MIT), see + http://jedwatson.github.io/react-select +*/ -},{"classnames":undefined,"create-react-class":undefined,"prop-types":undefined,"react":undefined}],6:[function(require,module,exports){ -"use strict"; +'use strict'; -Object.defineProperty(exports, "__esModule", { +Object.defineProperty(exports, '__esModule', { value: true }); -exports["default"] = arrowRenderer; -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } - -var _react = require('react'); +var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); -var _react2 = _interopRequireDefault(_react); +var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; -function arrowRenderer(_ref) { - var onMouseDown = _ref.onMouseDown; +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - return _react2["default"].createElement("span", { - className: "Select-arrow", - onMouseDown: onMouseDown - }); -} +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } -; -module.exports = exports["default"]; +function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } -},{"react":undefined}],7:[function(require,module,exports){ -'use strict'; +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } -Object.defineProperty(exports, '__esModule', { - value: true -}); -exports['default'] = clearRenderer; +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } +function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var _react = require('react'); var _react2 = _interopRequireDefault(_react); -function clearRenderer() { - return _react2['default'].createElement('span', { - className: 'Select-clear', - dangerouslySetInnerHTML: { __html: '×' } - }); -} - -; -module.exports = exports['default']; - -},{"react":undefined}],8:[function(require,module,exports){ -'use strict'; - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - -var _stripDiacritics = require('./stripDiacritics'); - -var _stripDiacritics2 = _interopRequireDefault(_stripDiacritics); - -function filterOptions(options, filterValue, excludeOptions, props) { - var _this = this; - - if (props.ignoreAccents) { - filterValue = (0, _stripDiacritics2['default'])(filterValue); - } - - if (props.ignoreCase) { - filterValue = filterValue.toLowerCase(); - } - - if (excludeOptions) excludeOptions = excludeOptions.map(function (i) { - return i[props.valueKey]; - }); - - return options.filter(function (option) { - if (excludeOptions && excludeOptions.indexOf(option[props.valueKey]) > -1) return false; - if (props.filterOption) return props.filterOption.call(_this, option, filterValue); - if (!filterValue) return true; - var valueTest = String(option[props.valueKey]); - var labelTest = String(option[props.labelKey]); - if (props.ignoreAccents) { - if (props.matchProp !== 'label') valueTest = (0, _stripDiacritics2['default'])(valueTest); - if (props.matchProp !== 'value') labelTest = (0, _stripDiacritics2['default'])(labelTest); - } - if (props.ignoreCase) { - if (props.matchProp !== 'label') valueTest = valueTest.toLowerCase(); - if (props.matchProp !== 'value') labelTest = labelTest.toLowerCase(); - } - return props.matchPos === 'start' ? props.matchProp !== 'label' && valueTest.substr(0, filterValue.length) === filterValue || props.matchProp !== 'value' && labelTest.substr(0, filterValue.length) === filterValue : props.matchProp !== 'label' && valueTest.indexOf(filterValue) >= 0 || props.matchProp !== 'value' && labelTest.indexOf(filterValue) >= 0; - }); -} - -module.exports = filterOptions; - -},{"./stripDiacritics":10}],9:[function(require,module,exports){ -'use strict'; - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - -var _classnames = require('classnames'); - -var _classnames2 = _interopRequireDefault(_classnames); - -var _react = require('react'); - -var _react2 = _interopRequireDefault(_react); - -function menuRenderer(_ref) { - var focusedOption = _ref.focusedOption; - var instancePrefix = _ref.instancePrefix; - var labelKey = _ref.labelKey; - var onFocus = _ref.onFocus; - var onSelect = _ref.onSelect; - var optionClassName = _ref.optionClassName; - var optionComponent = _ref.optionComponent; - var optionRenderer = _ref.optionRenderer; - var options = _ref.options; - var valueArray = _ref.valueArray; - var valueKey = _ref.valueKey; - var onOptionRef = _ref.onOptionRef; - - var Option = optionComponent; - - return options.map(function (option, i) { - var isSelected = valueArray && valueArray.indexOf(option) > -1; - var isFocused = option === focusedOption; - var optionClass = (0, _classnames2['default'])(optionClassName, { - 'Select-option': true, - 'is-selected': isSelected, - 'is-focused': isFocused, - 'is-disabled': option.disabled - }); - - return _react2['default'].createElement( - Option, - { - className: optionClass, - instancePrefix: instancePrefix, - isDisabled: option.disabled, - isFocused: isFocused, - isSelected: isSelected, - key: 'option-' + i + '-' + option[valueKey], - onFocus: onFocus, - onSelect: onSelect, - option: option, - optionIndex: i, - ref: function (ref) { - onOptionRef(ref, isFocused); - } - }, - optionRenderer(option, i) - ); - }); -} - -module.exports = menuRenderer; - -},{"classnames":undefined,"react":undefined}],10:[function(require,module,exports){ -'use strict'; - -var map = [{ 'base': 'A', 'letters': /[\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F]/g }, { 'base': 'AA', 'letters': /[\uA732]/g }, { 'base': 'AE', 'letters': /[\u00C6\u01FC\u01E2]/g }, { 'base': 'AO', 'letters': /[\uA734]/g }, { 'base': 'AU', 'letters': /[\uA736]/g }, { 'base': 'AV', 'letters': /[\uA738\uA73A]/g }, { 'base': 'AY', 'letters': /[\uA73C]/g }, { 'base': 'B', 'letters': /[\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181]/g }, { 'base': 'C', 'letters': /[\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E]/g }, { 'base': 'D', 'letters': /[\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779]/g }, { 'base': 'DZ', 'letters': /[\u01F1\u01C4]/g }, { 'base': 'Dz', 'letters': /[\u01F2\u01C5]/g }, { 'base': 'E', 'letters': /[\u0045\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E]/g }, { 'base': 'F', 'letters': /[\u0046\u24BB\uFF26\u1E1E\u0191\uA77B]/g }, { 'base': 'G', 'letters': /[\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E]/g }, { 'base': 'H', 'letters': /[\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D]/g }, { 'base': 'I', 'letters': /[\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197]/g }, { 'base': 'J', 'letters': /[\u004A\u24BF\uFF2A\u0134\u0248]/g }, { 'base': 'K', 'letters': /[\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2]/g }, { 'base': 'L', 'letters': /[\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780]/g }, { 'base': 'LJ', 'letters': /[\u01C7]/g }, { 'base': 'Lj', 'letters': /[\u01C8]/g }, { 'base': 'M', 'letters': /[\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C]/g }, { 'base': 'N', 'letters': /[\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4]/g }, { 'base': 'NJ', 'letters': /[\u01CA]/g }, { 'base': 'Nj', 'letters': /[\u01CB]/g }, { 'base': 'O', 'letters': /[\u004F\u24C4\uFF2F\u00D2\u00D3\u00D4\u1ED2\u1ED0\u1ED6\u1ED4\u00D5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\u00D6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\u00D8\u01FE\u0186\u019F\uA74A\uA74C]/g }, { 'base': 'OI', 'letters': /[\u01A2]/g }, { 'base': 'OO', 'letters': /[\uA74E]/g }, { 'base': 'OU', 'letters': /[\u0222]/g }, { 'base': 'P', 'letters': /[\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754]/g }, { 'base': 'Q', 'letters': /[\u0051\u24C6\uFF31\uA756\uA758\u024A]/g }, { 'base': 'R', 'letters': /[\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782]/g }, { 'base': 'S', 'letters': /[\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784]/g }, { 'base': 'T', 'letters': /[\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786]/g }, { 'base': 'TZ', 'letters': /[\uA728]/g }, { 'base': 'U', 'letters': /[\u0055\u24CA\uFF35\u00D9\u00DA\u00DB\u0168\u1E78\u016A\u1E7A\u016C\u00DC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244]/g }, { 'base': 'V', 'letters': /[\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245]/g }, { 'base': 'VY', 'letters': /[\uA760]/g }, { 'base': 'W', 'letters': /[\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72]/g }, { 'base': 'X', 'letters': /[\u0058\u24CD\uFF38\u1E8A\u1E8C]/g }, { 'base': 'Y', 'letters': /[\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE]/g }, { 'base': 'Z', 'letters': /[\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762]/g }, { 'base': 'a', 'letters': /[\u0061\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u00E4\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250]/g }, { 'base': 'aa', 'letters': /[\uA733]/g }, { 'base': 'ae', 'letters': /[\u00E6\u01FD\u01E3]/g }, { 'base': 'ao', 'letters': /[\uA735]/g }, { 'base': 'au', 'letters': /[\uA737]/g }, { 'base': 'av', 'letters': /[\uA739\uA73B]/g }, { 'base': 'ay', 'letters': /[\uA73D]/g }, { 'base': 'b', 'letters': /[\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253]/g }, { 'base': 'c', 'letters': /[\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184]/g }, { 'base': 'd', 'letters': /[\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A]/g }, { 'base': 'dz', 'letters': /[\u01F3\u01C6]/g }, { 'base': 'e', 'letters': /[\u0065\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD]/g }, { 'base': 'f', 'letters': /[\u0066\u24D5\uFF46\u1E1F\u0192\uA77C]/g }, { 'base': 'g', 'letters': /[\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F]/g }, { 'base': 'h', 'letters': /[\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265]/g }, { 'base': 'hv', 'letters': /[\u0195]/g }, { 'base': 'i', 'letters': /[\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131]/g }, { 'base': 'j', 'letters': /[\u006A\u24D9\uFF4A\u0135\u01F0\u0249]/g }, { 'base': 'k', 'letters': /[\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3]/g }, { 'base': 'l', 'letters': /[\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747]/g }, { 'base': 'lj', 'letters': /[\u01C9]/g }, { 'base': 'm', 'letters': /[\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F]/g }, { 'base': 'n', 'letters': /[\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5]/g }, { 'base': 'nj', 'letters': /[\u01CC]/g }, { 'base': 'o', 'letters': /[\u006F\u24DE\uFF4F\u00F2\u00F3\u00F4\u1ED3\u1ED1\u1ED7\u1ED5\u00F5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\u00F6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\u00F8\u01FF\u0254\uA74B\uA74D\u0275]/g }, { 'base': 'oi', 'letters': /[\u01A3]/g }, { 'base': 'ou', 'letters': /[\u0223]/g }, { 'base': 'oo', 'letters': /[\uA74F]/g }, { 'base': 'p', 'letters': /[\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755]/g }, { 'base': 'q', 'letters': /[\u0071\u24E0\uFF51\u024B\uA757\uA759]/g }, { 'base': 'r', 'letters': /[\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783]/g }, { 'base': 's', 'letters': /[\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B]/g }, { 'base': 't', 'letters': /[\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787]/g }, { 'base': 'tz', 'letters': /[\uA729]/g }, { 'base': 'u', 'letters': /[\u0075\u24E4\uFF55\u00F9\u00FA\u00FB\u0169\u1E79\u016B\u1E7B\u016D\u00FC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289]/g }, { 'base': 'v', 'letters': /[\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C]/g }, { 'base': 'vy', 'letters': /[\uA761]/g }, { 'base': 'w', 'letters': /[\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73]/g }, { 'base': 'x', 'letters': /[\u0078\u24E7\uFF58\u1E8B\u1E8D]/g }, { 'base': 'y', 'letters': /[\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF]/g }, { 'base': 'z', 'letters': /[\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763]/g }]; - -module.exports = function stripDiacritics(str) { - for (var i = 0; i < map.length; i++) { - str = str.replace(map[i].letters, map[i].base); - } - return str; -}; - -},{}],"react-select":[function(require,module,exports){ -/*! - Copyright (c) 2016 Jed Watson. - Licensed under the MIT License (MIT), see - http://jedwatson.github.io/react-select -*/ - -'use strict'; - -Object.defineProperty(exports, '__esModule', { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - -function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } - -function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } - -var _react = require('react'); - -var _react2 = _interopRequireDefault(_react); - -var _createReactClass = require('create-react-class'); - -var _createReactClass2 = _interopRequireDefault(_createReactClass); - var _propTypes = require('prop-types'); var _propTypes2 = _interopRequireDefault(_propTypes); @@ -1132,18 +937,6 @@ var _utilsDefaultClearRenderer = require('./utils/defaultClearRenderer'); var _utilsDefaultClearRenderer2 = _interopRequireDefault(_utilsDefaultClearRenderer); -var _Async = require('./Async'); - -var _Async2 = _interopRequireDefault(_Async); - -var _AsyncCreatable = require('./AsyncCreatable'); - -var _AsyncCreatable2 = _interopRequireDefault(_AsyncCreatable); - -var _Creatable = require('./Creatable'); - -var _Creatable2 = _interopRequireDefault(_Creatable); - var _Option = require('./Option'); var _Option2 = _interopRequireDefault(_Option); @@ -1169,1150 +962,1619 @@ var stringOrNode = _propTypes2['default'].oneOfType([_propTypes2['default'].stri var instanceId = 1; -var Select = (0, _createReactClass2['default'])({ - - displayName: 'Select', - - propTypes: { - addLabelText: _propTypes2['default'].string, // placeholder displayed when you want to add a label on a multi-value input - 'aria-describedby': _propTypes2['default'].string, // HTML ID(s) of element(s) that should be used to describe this input (for assistive tech) - 'aria-label': _propTypes2['default'].string, // Aria label (for assistive tech) - 'aria-labelledby': _propTypes2['default'].string, // HTML ID of an element that should be used as the label (for assistive tech) - arrowRenderer: _propTypes2['default'].func, // Create drop-down caret element - autoBlur: _propTypes2['default'].bool, // automatically blur the component when an option is selected - autofocus: _propTypes2['default'].bool, // autofocus the component on mount - autosize: _propTypes2['default'].bool, // whether to enable autosizing or not - backspaceRemoves: _propTypes2['default'].bool, // whether backspace removes an item if there is no text input - backspaceToRemoveMessage: _propTypes2['default'].string, // Message to use for screenreaders to press backspace to remove the current item - {label} is replaced with the item label - className: _propTypes2['default'].string, // className for the outer element - clearAllText: stringOrNode, // title for the "clear" control when multi: true - clearRenderer: _propTypes2['default'].func, // create clearable x element - clearValueText: stringOrNode, // title for the "clear" control - clearable: _propTypes2['default'].bool, // should it be possible to reset value - deleteRemoves: _propTypes2['default'].bool, // whether backspace removes an item if there is no text input - delimiter: _propTypes2['default'].string, // delimiter to use to join multiple values for the hidden field value - disabled: _propTypes2['default'].bool, // whether the Select is disabled or not - escapeClearsValue: _propTypes2['default'].bool, // whether escape clears the value when the menu is closed - filterOption: _propTypes2['default'].func, // method to filter a single option (option, filterString) - filterOptions: _propTypes2['default'].any, // boolean to enable default filtering or function to filter the options array ([options], filterString, [values]) - ignoreAccents: _propTypes2['default'].bool, // whether to strip diacritics when filtering - ignoreCase: _propTypes2['default'].bool, // whether to perform case-insensitive filtering - inputProps: _propTypes2['default'].object, // custom attributes for the Input - inputRenderer: _propTypes2['default'].func, // returns a custom input component - instanceId: _propTypes2['default'].string, // set the components instanceId - isLoading: _propTypes2['default'].bool, // whether the Select is loading externally or not (such as options being loaded) - joinValues: _propTypes2['default'].bool, // joins multiple values into a single form field with the delimiter (legacy mode) - labelKey: _propTypes2['default'].string, // path of the label value in option objects - matchPos: _propTypes2['default'].string, // (any|start) match the start or entire string when filtering - matchProp: _propTypes2['default'].string, // (any|label|value) which option property to filter on - menuBuffer: _propTypes2['default'].number, // optional buffer (in px) between the bottom of the viewport and the bottom of the menu - menuContainerStyle: _propTypes2['default'].object, // optional style to apply to the menu container - menuRenderer: _propTypes2['default'].func, // renders a custom menu with options - menuStyle: _propTypes2['default'].object, // optional style to apply to the menu - multi: _propTypes2['default'].bool, // multi-value input - name: _propTypes2['default'].string, // generates a hidden tag with this field name for html forms - noResultsText: stringOrNode, // placeholder displayed when there are no matching search results - onBlur: _propTypes2['default'].func, // onBlur handler: function (event) {} - onBlurResetsInput: _propTypes2['default'].bool, // whether input is cleared on blur - onChange: _propTypes2['default'].func, // onChange handler: function (newValue) {} - onClose: _propTypes2['default'].func, // fires when the menu is closed - onCloseResetsInput: _propTypes2['default'].bool, // whether input is cleared when menu is closed through the arrow - onFocus: _propTypes2['default'].func, // onFocus handler: function (event) {} - onInputChange: _propTypes2['default'].func, // onInputChange handler: function (inputValue) {} - onInputKeyDown: _propTypes2['default'].func, // input keyDown handler: function (event) {} - onMenuScrollToBottom: _propTypes2['default'].func, // fires when the menu is scrolled to the bottom; can be used to paginate options - onOpen: _propTypes2['default'].func, // fires when the menu is opened - onValueClick: _propTypes2['default'].func, // onClick handler for value labels: function (value, event) {} - openAfterFocus: _propTypes2['default'].bool, // boolean to enable opening dropdown when focused - openOnFocus: _propTypes2['default'].bool, // always open options menu on focus - optionClassName: _propTypes2['default'].string, // additional class(es) to apply to the