-
Notifications
You must be signed in to change notification settings - Fork 209
/
F-NAScan.py
371 lines (362 loc) · 142 KB
/
F-NAScan.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
#coding:utf-8
#author:wolf@future-sec
import getopt,sys,Queue,threading,socket,struct,urllib2,time,os,re,json,base64,cgi,array,ssl
queue = Queue.Queue()
mutex = threading.Lock()
timeout = 10
port_list = []
re_data = {}
port_data = {}
statistics = {}
try:
_create_unverified_https_context = ssl._create_unverified_context
except AttributeError:
pass
else:
ssl._create_default_https_context = _create_unverified_https_context
class UnicodeStreamFilter:
def __init__(self, target):
self.target = target
self.encoding = 'utf-8'
self.errors = 'replace'
self.encode_to = self.target.encoding
def write(self, s):
if type(s) == str:
s = s.decode("utf-8")
s = s.encode(self.encode_to, self.errors).decode(self.encode_to)
self.target.write(s)
if sys.stdout.encoding == 'cp936':
sys.stdout = UnicodeStreamFilter(sys.stdout)
class SendPingThr(threading.Thread):
def __init__(self, ipPool, icmpPacket, icmpSocket, timeout=3):
threading.Thread.__init__(self)
self.Sock = icmpSocket
self.ipPool = ipPool
self.packet = icmpPacket
self.timeout = timeout
self.Sock.settimeout(timeout + 1)
def run(self):
time.sleep(0.01)
for ip in self.ipPool:
try:
self.Sock.sendto(self.packet, (ip, 0))
except socket.timeout:
break
time.sleep(self.timeout)
class Nscan:
def __init__(self, timeout=3):
self.timeout = timeout
self.__data = struct.pack('d', time.time())
self.__id = os.getpid()
@property
def __icmpSocket(self):
Sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.getprotobyname("icmp"))
return Sock
def __inCksum(self, packet):
if len(packet) & 1:
packet = packet + '\0'
words = array.array('h', packet)
sum = 0
for word in words:
sum += (word & 0xffff)
sum = (sum >> 16) + (sum & 0xffff)
sum = sum + (sum >> 16)
return (~sum) & 0xffff
@property
def __icmpPacket(self):
header = struct.pack('bbHHh', 8, 0, 0, self.__id, 0)
packet = header + self.__data
chkSum = self.__inCksum(packet)
header = struct.pack('bbHHh', 8, 0, chkSum, self.__id, 0)
return header + self.__data
def mPing(self, ipPool):
Sock = self.__icmpSocket
Sock.settimeout(self.timeout)
packet = self.__icmpPacket
recvFroms = set()
sendThr = SendPingThr(ipPool, packet, Sock, self.timeout)
sendThr.start()
while True:
try:
ac_ip = Sock.recvfrom(1024)[1][0]
if ac_ip not in recvFroms:
log("active",ac_ip,0)
recvFroms.add(ac_ip)
except Exception:
pass
finally:
if not sendThr.isAlive():
break
return recvFroms & ipPool
def get_ac_ip(ip_list):
try:
s = Nscan()
ipPool = set(ip_list)
return s.mPing(ipPool)
except:
print 'The current user permissions unable to send icmp packets'
return ip_list
class ThreadNum(threading.Thread):
def __init__(self,queue):
threading.Thread.__init__(self)
self.queue = queue
def run(self):
while True:
try:
if queue.empty():break
queue_task = self.queue.get()
except:
break
try:
task_host,task_port = queue_task.split(":")
data = scan_port(task_host,task_port)
if data:
if data <> 'NULL':
port_data[task_host + ":" + task_port] = urllib2.quote(data)
server_type = server_discern(task_host,task_port,data)
if not server_type:
h_server,title = get_web_info(task_host,task_port)
if title or h_server:server_type = 'web ' + title
if server_type:log('server',task_host,task_port,server_type.strip())
except Exception,e:
continue
def get_code(header,html):
try:
m = re.search(r'<meta.*?charset\=(.*?)"(>| |\/)',html, flags=re.I)
if m:
return m.group(1).replace('"','')
except:
pass
try:
if header.has_key('Content-Type'):
Content_Type = header['Content-Type']
m = re.search(r'.*?charset\=(.*?)(;|$)',Content_Type,flags=re.I)
if m:return m.group(1)
except:
pass
def get_web_info(host,port):
h_server,h_xpb,title_str,html = '','','',''
try:
info = urllib2.urlopen("http://%s:%s"%(host,port),timeout=timeout)
html = info.read()
header = info.headers
except urllib2.HTTPError,e:
header = e.headers
except Exception,e:
return False,False
if not header:return False,False
try:
html_code = get_code(header,html).strip()
if html_code and len(html_code) < 12:
html = html.decode(html_code).encode('utf-8')
except:
pass
try:
port_data[host + ":" + str(port)] = urllib2.quote(str(header) + "\r\n\r\n" + cgi.escape(html))
title = re.search(r'<title>(.*?)</title>', html, flags=re.I|re.M)
if title:title_str=title.group(1)
except Exception,e:
pass
return str(header),title_str
def scan_port(host,port):
try:
socket.setdefaulttimeout(timeout/2)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((str(host),int(port)))
log('portscan',host,port)
except Exception,e:
return False
try:
data = sock.recv(512)
sock.close()
if len(data) > 2:
return data
else:
return 'NULL'
except Exception,e:
return 'NULL'
def log(scan_type,host,port,info=''):
mutex.acquire()
try:
time_str = time.strftime('%X', time.localtime(time.time()))
if scan_type == 'portscan':
print "[%s] %s:%d open"%(time_str,host,int(port))
try:
re_data[host].append(port)
except KeyError:
re_data[host]=[]
re_data[host].append(port)
elif scan_type == 'server':
print "[%s] %s:%d is %s"%(time_str,host,int(port),str(info))
try:
server = info.split(" ")[0].replace("(default)","")
statistics[server] += 1
except KeyError:
statistics[server] = 1
re_data[host].remove(port)
re_data[host].append(str(port) + " " + str(info))
elif scan_type == 'active':
print "[%s] %s active"%(time_str,host)
except Exception,e:
pass
mutex.release()
def read_config(config_type):
if config_type == 'server_info':
mark_list=[]
try:
config_file = open('server_info.ini','r')
for mark in config_file:
name,port,reg = mark.strip().split("|",2)
mark_list.append([name,port,reg])
config_file.close()
return mark_list
except:
print 'Configuration file read failed'
exit()
def server_discern(host,port,data):
server = ''
for mark_info in mark_list:
try:
name,default_port,reg = mark_info
if int(default_port) == int(port):server = name+"(default)"
if reg and data <> 'NULL':
matchObj = re.search(reg,data,re.I|re.M)
if matchObj:server = name
if server:
return server
except Exception,e:
continue
return server
def get_ip_list(ip):
ip_list = []
iptonum = lambda x:sum([256**j*int(i) for j,i in enumerate(x.split('.')[::-1])])
numtoip = lambda x: '.'.join([str(x/(256**i)%256) for i in range(3,-1,-1)])
if '-' in ip:
ip_range = ip.split('-')
ip_start = long(iptonum(ip_range[0]))
ip_end = long(iptonum(ip_range[1]))
ip_count = ip_end - ip_start
if ip_count >= 0 and ip_count <= 65536:
for ip_num in range(ip_start,ip_end+1):
ip_list.append(numtoip(ip_num))
else:
print '-h wrong format'
elif '.ini' in ip:
ip_config = open(ip,'r')
for ip in ip_config:
ip_list.extend(get_ip_list(ip.strip()))
ip_config.close()
else:
ip_split=ip.split('.')
net = len(ip_split)
if net == 2:
for b in range(1,255):
for c in range(1,255):
ip = "%s.%s.%d.%d"%(ip_split[0],ip_split[1],b,c)
ip_list.append(ip)
elif net == 3:
for c in range(1,255):
ip = "%s.%s.%s.%d"%(ip_split[0],ip_split[1],ip_split[2],c)
ip_list.append(ip)
elif net ==4:
ip_list.append(ip)
else:
print "-h wrong format"
return ip_list
def get_port_list(port):
port_list = []
if '.ini' in port:
port_config = open(port,'r')
for port in port_config:
port_list.append(port.strip())
port_config.close()
else:
port_list = port.split(',')
return port_list
def write_result():
re_json = []
re_array = {}
td = ''
try:
ip_list = re_data.keys()
ip_list.sort()
for ip_str in ip_list:
port_array = []
for port_str in re_data[ip_str]:
port_array.append({"name":port_str,"url":"javascript:view('%s');"%(ip_str + ":" + port_str.split(" ")[0])})
ip_array = {"name":ip_str,"submenu":port_array}
if re_array.has_key(ip_str[0:ip_str.rindex('.')]+'.*'):
re_array[ip_str[0:ip_str.rindex('.')]+'.*'].append(ip_array)
else:
re_array[ip_str[0:ip_str.rindex('.')]+'.*']=[]
re_array[ip_str[0:ip_str.rindex('.')]+'.*'].append(ip_array)
for ip_c in re_array:
re_json.append({"name":ip_c,'submenu':re_array[ip_c]})
for server in statistics:
td += "<tr><td align='center'>%s</td><td align='center'>%d</td></tr>"%(server,statistics[server])
td_html = "<table><tr><th>Service</th><th>Count</th></tr>" + td + "</table>"
if re_json:
mo_html = base64.b64decode("PCFkb2N0eXBlIGh0bWw+CjxodG1sPgoJPGhlYWQ+Cgk8bWV0YSBjaGFyc2V0PSJVVEYtOCI+Cgk8dGl0bGU+572R57uc6LWE5Lqn5L+h5oGv5YiX6KGoPC90aXRsZT4KIAk8c3R5bGUgdHlwZT0idGV4dC9jc3MiPgoJCS53cmFwLW1lbnV7b3ZlcmZsb3cteDpoaWRkZW47b3ZlcmZsb3cteTphdXRvO21pbi13aWR0aDoyNSU7bWF4LXdpZHRoOjM1JTtiYWNrZ3JvdW5kOiNmNmY2ZjY7Zm9udDoxMnB4LzEuNSBUYWhvbWEsQXJpYWwsc2Fucy1zZXJpZjtmbG9hdDpsZWZ0O21hcmdpbjoxMHB4fS53cmFwLW1lbnUgdWx7bGlzdC1zdHlsZTpub25lO21hcmdpbjowO3BhZGRpbmc6MH0ud3JhcC1tZW51IHVsIGxpe3RleHQtaW5kZW50OjNlbTt3aGl0ZS1zcGFjZTpub3dyYXB9LndyYXAtbWVudSB1bCBsaSBoMntjdXJzb3I6cG9pbnRlcjtoZWlnaHQ6MTAwJTt3aWR0aDoxMDAlO21hcmdpbjowIDAgMXB4IDA7Zm9udDoxMnB4LzMxcHggJ+Wui+S9kyc7Y29sb3I6I2ZmZjtiYWNrZ3JvdW5kOiNhZGFkYWR9LndyYXAtbWVudSB1bCBsaSBhe2Rpc3BsYXk6YmxvY2s7b3V0bGluZTowO2hlaWdodDoyNXB4O2xpbmUtaGVpZ2h0OjI1cHg7bWFyZ2luOjFweCAwO2NvbG9yOiMxYTM4NWM7dGV4dC1kZWNvcmF0aW9uOm5vbmV9LndyYXAtbWVudSB1bCBsaSBpbWd7bWFyZ2luLXJpZ2h0OjEwcHg7bWFyZ2luLWxlZnQ6LTE3cHg7bWFyZ2luLXRvcDo5cHg7d2lkdGg6N3B4O2hlaWdodDo3cHg7YmFja2dyb3VuZC1pbWFnZTp1cmwoZGF0YTppbWFnZS9naWY7YmFzZTY0LFIwbEdPRGxoQndBT0FMTU1BRXlFcFVxRXFVbUVwa21GcVVxRnAwbUVwRW1EcVVpRXBraUZwRXVEcGtlRHAwYUZwdi8vL3dBQUFBQUFBQUFBQUNIL0MxaE5VQ0JFWVhSaFdFMVFQRDk0Y0dGamEyVjBJR0psWjJsdVBTTHZ1NzhpSUdsa1BTSlhOVTB3VFhCRFpXaHBTSHB5WlZONlRsUmplbXRqT1dRaVB6NGdQSGc2ZUcxd2JXVjBZU0I0Yld4dWN6cDRQU0poWkc5aVpUcHVjenB0WlhSaEx5SWdlRHA0YlhCMGF6MGlRV1J2WW1VZ1dFMVFJRU52Y21VZ05TNHdMV013TmpBZ05qRXVNVE0wTnpjM0xDQXlNREV3THpBeUx6RXlMVEUzT2pNeU9qQXdJQ0FnSUNBZ0lDQWlQaUE4Y21SbU9sSkVSaUI0Yld4dWN6cHlaR1k5SW1oMGRIQTZMeTkzZDNjdWR6TXViM0puTHpFNU9Ua3ZNREl2TWpJdGNtUm1MWE41Ym5SaGVDMXVjeU1pUGlBOGNtUm1Pa1JsYzJOeWFYQjBhVzl1SUhKa1pqcGhZbTkxZEQwaUlpQjRiV3h1Y3pwNGJYQTlJbWgwZEhBNkx5OXVjeTVoWkc5aVpTNWpiMjB2ZUdGd0x6RXVNQzhpSUhodGJHNXpPbmh0Y0UxTlBTSm9kSFJ3T2k4dmJuTXVZV1J2WW1VdVkyOXRMM2hoY0M4eExqQXZiVzB2SWlCNGJXeHVjenB6ZEZKbFpqMGlhSFIwY0RvdkwyNXpMbUZrYjJKbExtTnZiUzk0WVhBdk1TNHdMM05VZVhCbEwxSmxjMjkxY21ObFVtVm1JeUlnZUcxd09rTnlaV0YwYjNKVWIyOXNQU0pCWkc5aVpTQlFhRzkwYjNOb2IzQWdRMU0xSUZkcGJtUnZkM01pSUhodGNFMU5Pa2x1YzNSaGJtTmxTVVE5SW5odGNDNXBhV1E2UlVFM01UUTFSamN5TkVKQ01URkZNamhCT1RjNFEwUXhRVEk1UmtJeE9UVWlJSGh0Y0UxTk9rUnZZM1Z0Wlc1MFNVUTlJbmh0Y0M1a2FXUTZSVUUzTVRRMVJqZ3lORUpDTVRGRk1qaEJPVGM0UTBReFFUSTVSa0l4T1RVaVBpQThlRzF3VFUwNlJHVnlhWFpsWkVaeWIyMGdjM1JTWldZNmFXNXpkR0Z1WTJWSlJEMGllRzF3TG1scFpEcEZRVGN4TkRWR05USTBRa0l4TVVVeU9FRTVOemhEUkRGQk1qbEdRakU1TlNJZ2MzUlNaV1k2Wkc5amRXMWxiblJKUkQwaWVHMXdMbVJwWkRwRlFUY3hORFZHTmpJMFFrSXhNVVV5T0VFNU56aERSREZCTWpsR1FqRTVOU0l2UGlBOEwzSmtaanBFWlhOamNtbHdkR2x2Ymo0Z1BDOXlaR1k2VWtSR1BpQThMM2c2ZUcxd2JXVjBZVDRnUEQ5NGNHRmphMlYwSUdWdVpEMGljaUkvUGdILy92MzgrL3I1K1BmMjlmVHo4dkh3Nys3dDdPdnE2ZWpuNXVYazQrTGg0Ti9lM2R6YjJ0blkxOWJWMU5QUzBkRFB6czNNeThySnlNZkd4Y1REd3NIQXY3Njl2THU2dWJpM3RyVzBzN0t4c0srdXJheXJxcW1vcDZhbHBLT2lvYUNmbnAyY201cVptSmVXbFpTVGtwR1FqNDZOakl1S2lZaUhob1dFZzRLQmdIOStmWHg3ZW5sNGQzWjFkSE55Y1hCdmJtMXNhMnBwYUdkbVpXUmpZbUZnWDE1ZFhGdGFXVmhYVmxWVVUxSlJVRTlPVFV4TFNrbElSMFpGUkVOQ1FVQS9QajA4T3pvNU9EYzJOVFF6TWpFd0x5NHRMQ3NxS1NnbkppVWtJeUloSUI4ZUhSd2JHaGtZRnhZVkZCTVNFUkFQRGcwTUN3b0pDQWNHQlFRREFnRUFBQ0g1QkFFQUFBd0FMQUFBQUFBSEFBNEFRQVFma0VrZ3E3VWcxM0hDelZRVk1vUVNKSUJCaU9NRXNsY2NGNEt3SU5aUVJRQTcpO2JvcmRlcjowfS53cmFwLW1lbnUgdWwgbGkgaW1nLnVuZm9sZHtiYWNrZ3JvdW5kLXBvc2l0aW9uOjAgLTlweH0ud3JhcC1tZW51IHVsIGxpIGE6aG92ZXJ7YmFja2dyb3VuZC1jb2xvcjojY2NjO2JhY2tncm91bmQtaW1hZ2U6bm9uZX0ud3JhcC1kYXRhe292ZXJmbG93OmF1dG87bWluLWhlaWdodDo1MDBweDttaW4td2lkdGg6NDAlO21heC13aWR0aDo2MCU7YmFja2dyb3VuZDojZjZmNmY2O2ZvbnQ6MTJweC8xLjUgVGFob21hLEFyaWFsLHNhbnMtc2VyaWY7ZmxvYXQ6bGVmdDttYXJnaW46MTBweDtwYWRkaW5nOjEwcHggNXB4IDE1cHggMjBweH0KCTwvc3R5bGU+Cgk8c2NyaXB0PgoJKGZ1bmN0aW9uKGUsdCl7dmFyIG4scixpPXR5cGVvZiB0LG89ZS5kb2N1bWVudCxhPWUubG9jYXRpb24scz1lLmpRdWVyeSx1PWUuJCxsPXt9LGM9W10scD0iMS45LjEiLGY9Yy5jb25jYXQsZD1jLnB1c2gsaD1jLnNsaWNlLGc9Yy5pbmRleE9mLG09bC50b1N0cmluZyx5PWwuaGFzT3duUHJvcGVydHksdj1wLnRyaW0sYj1mdW5jdGlvbihlLHQpe3JldHVybiBuZXcgYi5mbi5pbml0KGUsdCxyKX0seD0vWystXT8oPzpcZCpcLnwpXGQrKD86W2VFXVsrLV0/XGQrfCkvLnNvdXJjZSx3PS9cUysvZyxUPS9eW1xzXHVGRUZGXHhBMF0rfFtcc1x1RkVGRlx4QTBdKyQvZyxOPS9eKD86KDxbXHdcV10rPilbXj5dKnwjKFtcdy1dKikpJC8sQz0vXjwoXHcrKVxzKlwvPz4oPzo8XC9cMT58KSQvLGs9L15bXF0sOnt9XHNdKiQvLEU9Lyg/Ol58OnwsKSg/OlxzKlxbKSsvZyxTPS9cXCg/OlsiXFxcL2JmbnJ0XXx1W1xkYS1mQS1GXXs0fSkvZyxBPS8iW14iXFxcclxuXSoifHRydWV8ZmFsc2V8bnVsbHwtPyg/OlxkK1wufClcZCsoPzpbZUVdWystXT9cZCt8KS9nLGo9L14tbXMtLyxEPS8tKFtcZGEtel0pL2dpLEw9ZnVuY3Rpb24oZSx0KXtyZXR1cm4gdC50b1VwcGVyQ2FzZSgpfSxIPWZ1bmN0aW9uKGUpeyhvLmFkZEV2ZW50TGlzdGVuZXJ8fCJsb2FkIj09PWUudHlwZXx8ImNvbXBsZXRlIj09PW8ucmVhZHlTdGF0ZSkmJihxKCksYi5yZWFkeSgpKX0scT1mdW5jdGlvbigpe28uYWRkRXZlbnRMaXN0ZW5lcj8oby5yZW1vdmVFdmVudExpc3RlbmVyKCJET01Db250ZW50TG9hZGVkIixILCExKSxlLnJlbW92ZUV2ZW50TGlzdGVuZXIoImxvYWQiLEgsITEpKTooby5kZXRhY2hFdmVudCgib25yZWFkeXN0YXRlY2hhbmdlIixIKSxlLmRldGFjaEV2ZW50KCJvbmxvYWQiLEgpKX07Yi5mbj1iLnByb3RvdHlwZT17anF1ZXJ5OnAsY29uc3RydWN0b3I6Yixpbml0OmZ1bmN0aW9uKGUsbixyKXt2YXIgaSxhO2lmKCFlKXJldHVybiB0aGlzO2lmKCJzdHJpbmciPT10eXBlb2YgZSl7aWYoaT0iPCI9PT1lLmNoYXJBdCgwKSYmIj4iPT09ZS5jaGFyQXQoZS5sZW5ndGgtMSkmJmUubGVuZ3RoPj0zP1tudWxsLGUsbnVsbF06Ti5leGVjKGUpLCFpfHwhaVsxXSYmbilyZXR1cm4hbnx8bi5qcXVlcnk/KG58fHIpLmZpbmQoZSk6dGhpcy5jb25zdHJ1Y3RvcihuKS5maW5kKGUpO2lmKGlbMV0pe2lmKG49biBpbnN0YW5jZW9mIGI/blswXTpuLGIubWVyZ2UodGhpcyxiLnBhcnNlSFRNTChpWzFdLG4mJm4ubm9kZVR5cGU/bi5vd25lckRvY3VtZW50fHxuOm8sITApKSxDLnRlc3QoaVsxXSkmJmIuaXNQbGFpbk9iamVjdChuKSlmb3IoaSBpbiBuKWIuaXNGdW5jdGlvbih0aGlzW2ldKT90aGlzW2ldKG5baV0pOnRoaXMuYXR0cihpLG5baV0pO3JldHVybiB0aGlzfWlmKGE9by5nZXRFbGVtZW50QnlJZChpWzJdKSxhJiZhLnBhcmVudE5vZGUpe2lmKGEuaWQhPT1pWzJdKXJldHVybiByLmZpbmQoZSk7dGhpcy5sZW5ndGg9MSx0aGlzWzBdPWF9cmV0dXJuIHRoaXMuY29udGV4dD1vLHRoaXMuc2VsZWN0b3I9ZSx0aGlzfXJldHVybiBlLm5vZGVUeXBlPyh0aGlzLmNvbnRleHQ9dGhpc1swXT1lLHRoaXMubGVuZ3RoPTEsdGhpcyk6Yi5pc0Z1bmN0aW9uKGUpP3IucmVhZHkoZSk6KGUuc2VsZWN0b3IhPT10JiYodGhpcy5zZWxlY3Rvcj1lLnNlbGVjdG9yLHRoaXMuY29udGV4dD1lLmNvbnRleHQpLGIubWFrZUFycmF5KGUsdGhpcykpfSxzZWxlY3RvcjoiIixsZW5ndGg6MCxzaXplOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMubGVuZ3RofSx0b0FycmF5OmZ1bmN0aW9uKCl7cmV0dXJuIGguY2FsbCh0aGlzKX0sZ2V0OmZ1bmN0aW9uKGUpe3JldHVybiBudWxsPT1lP3RoaXMudG9BcnJheSgpOjA+ZT90aGlzW3RoaXMubGVuZ3RoK2VdOnRoaXNbZV19LHB1c2hTdGFjazpmdW5jdGlvbihlKXt2YXIgdD1iLm1lcmdlKHRoaXMuY29uc3RydWN0b3IoKSxlKTtyZXR1cm4gdC5wcmV2T2JqZWN0PXRoaXMsdC5jb250ZXh0PXRoaXMuY29udGV4dCx0fSxlYWNoOmZ1bmN0aW9uKGUsdCl7cmV0dXJuIGIuZWFjaCh0aGlzLGUsdCl9LHJlYWR5OmZ1bmN0aW9uKGUpe3JldHVybiBiLnJlYWR5LnByb21pc2UoKS5kb25lKGUpLHRoaXN9LHNsaWNlOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMucHVzaFN0YWNrKGguYXBwbHkodGhpcyxhcmd1bWVudHMpKX0sZmlyc3Q6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5lcSgwKX0sbGFzdDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmVxKC0xKX0sZXE6ZnVuY3Rpb24oZSl7dmFyIHQ9dGhpcy5sZW5ndGgsbj0rZSsoMD5lP3Q6MCk7cmV0dXJuIHRoaXMucHVzaFN0YWNrKG4+PTAmJnQ+bj9bdGhpc1tuXV06W10pfSxtYXA6ZnVuY3Rpb24oZSl7cmV0dXJuIHRoaXMucHVzaFN0YWNrKGIubWFwKHRoaXMsZnVuY3Rpb24odCxuKXtyZXR1cm4gZS5jYWxsKHQsbix0KX0pKX0sZW5kOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMucHJldk9iamVjdHx8dGhpcy5jb25zdHJ1Y3RvcihudWxsKX0scHVzaDpkLHNvcnQ6W10uc29ydCxzcGxpY2U6W10uc3BsaWNlfSxiLmZuLmluaXQucHJvdG90eXBlPWIuZm4sYi5leHRlbmQ9Yi5mbi5leHRlbmQ9ZnVuY3Rpb24oKXt2YXIgZSxuLHIsaSxvLGEscz1hcmd1bWVudHNbMF18fHt9LHU9MSxsPWFyZ3VtZW50cy5sZW5ndGgsYz0hMTtmb3IoImJvb2xlYW4iPT10eXBlb2YgcyYmKGM9cyxzPWFyZ3VtZW50c1sxXXx8e30sdT0yKSwib2JqZWN0Ij09dHlwZW9mIHN8fGIuaXNGdW5jdGlvbihzKXx8KHM9e30pLGw9PT11JiYocz10aGlzLC0tdSk7bD51O3UrKylpZihudWxsIT0obz1hcmd1bWVudHNbdV0pKWZvcihpIGluIG8pZT1zW2ldLHI9b1tpXSxzIT09ciYmKGMmJnImJihiLmlzUGxhaW5PYmplY3Qocil8fChuPWIuaXNBcnJheShyKSkpPyhuPyhuPSExLGE9ZSYmYi5pc0FycmF5KGUpP2U6W10pOmE9ZSYmYi5pc1BsYWluT2JqZWN0KGUpP2U6e30sc1tpXT1iLmV4dGVuZChjLGEscikpOnIhPT10JiYoc1tpXT1yKSk7cmV0dXJuIHN9LGIuZXh0ZW5kKHtub0NvbmZsaWN0OmZ1bmN0aW9uKHQpe3JldHVybiBlLiQ9PT1iJiYoZS4kPXUpLHQmJmUualF1ZXJ5PT09YiYmKGUualF1ZXJ5PXMpLGJ9LGlzUmVhZHk6ITEscmVhZHlXYWl0OjEsaG9sZFJlYWR5OmZ1bmN0aW9uKGUpe2U/Yi5yZWFkeVdhaXQrKzpiLnJlYWR5KCEwKX0scmVhZHk6ZnVuY3Rpb24oZSl7aWYoZT09PSEwPyEtLWIucmVhZHlXYWl0OiFiLmlzUmVhZHkpe2lmKCFvLmJvZHkpcmV0dXJuIHNldFRpbWVvdXQoYi5yZWFkeSk7Yi5pc1JlYWR5PSEwLGUhPT0hMCYmLS1iLnJlYWR5V2FpdD4wfHwobi5yZXNvbHZlV2l0aChvLFtiXSksYi5mbi50cmlnZ2VyJiZiKG8pLnRyaWdnZXIoInJlYWR5Iikub2ZmKCJyZWFkeSIpKX19LGlzRnVuY3Rpb246ZnVuY3Rpb24oZSl7cmV0dXJuImZ1bmN0aW9uIj09PWIudHlwZShlKX0saXNBcnJheTpBcnJheS5pc0FycmF5fHxmdW5jdGlvbihlKXtyZXR1cm4iYXJyYXkiPT09Yi50eXBlKGUpfSxpc1dpbmRvdzpmdW5jdGlvbihlKXtyZXR1cm4gbnVsbCE9ZSYmZT09ZS53aW5kb3d9LGlzTnVtZXJpYzpmdW5jdGlvbihlKXtyZXR1cm4haXNOYU4ocGFyc2VGbG9hdChlKSkmJmlzRmluaXRlKGUpfSx0eXBlOmZ1bmN0aW9uKGUpe3JldHVybiBudWxsPT1lP2UrIiI6Im9iamVjdCI9PXR5cGVvZiBlfHwiZnVuY3Rpb24iPT10eXBlb2YgZT9sW20uY2FsbChlKV18fCJvYmplY3QiOnR5cGVvZiBlfSxpc1BsYWluT2JqZWN0OmZ1bmN0aW9uKGUpe2lmKCFlfHwib2JqZWN0IiE9PWIudHlwZShlKXx8ZS5ub2RlVHlwZXx8Yi5pc1dpbmRvdyhlKSlyZXR1cm4hMTt0cnl7aWYoZS5jb25zdHJ1Y3RvciYmIXkuY2FsbChlLCJjb25zdHJ1Y3RvciIpJiYheS5jYWxsKGUuY29uc3RydWN0b3IucHJvdG90eXBlLCJpc1Byb3RvdHlwZU9mIikpcmV0dXJuITF9Y2F0Y2gobil7cmV0dXJuITF9dmFyIHI7Zm9yKHIgaW4gZSk7cmV0dXJuIHI9PT10fHx5LmNhbGwoZSxyKX0saXNFbXB0eU9iamVjdDpmdW5jdGlvbihlKXt2YXIgdDtmb3IodCBpbiBlKXJldHVybiExO3JldHVybiEwfSxlcnJvcjpmdW5jdGlvbihlKXt0aHJvdyBFcnJvcihlKX0scGFyc2VIVE1MOmZ1bmN0aW9uKGUsdCxuKXtpZighZXx8InN0cmluZyIhPXR5cGVvZiBlKXJldHVybiBudWxsOyJib29sZWFuIj09dHlwZW9mIHQmJihuPXQsdD0hMSksdD10fHxvO3ZhciByPUMuZXhlYyhlKSxpPSFuJiZbXTtyZXR1cm4gcj9bdC5jcmVhdGVFbGVtZW50KHJbMV0pXToocj1iLmJ1aWxkRnJhZ21lbnQoW2VdLHQsaSksaSYmYihpKS5yZW1vdmUoKSxiLm1lcmdlKFtdLHIuY2hpbGROb2RlcykpfSxwYXJzZUpTT046ZnVuY3Rpb24obil7cmV0dXJuIGUuSlNPTiYmZS5KU09OLnBhcnNlP2UuSlNPTi5wYXJzZShuKTpudWxsPT09bj9uOiJzdHJpbmciPT10eXBlb2YgbiYmKG49Yi50cmltKG4pLG4mJmsudGVzdChuLnJlcGxhY2UoUywiQCIpLnJlcGxhY2UoQSwiXSIpLnJlcGxhY2UoRSwiIikpKT9GdW5jdGlvbigicmV0dXJuICIrbikoKTooYi5lcnJvcigiSW52YWxpZCBKU09OOiAiK24pLHQpfSxwYXJzZVhNTDpmdW5jdGlvbihuKXt2YXIgcixpO2lmKCFufHwic3RyaW5nIiE9dHlwZW9mIG4pcmV0dXJuIG51bGw7dHJ5e2UuRE9NUGFyc2VyPyhpPW5ldyBET01QYXJzZXIscj1pLnBhcnNlRnJvbVN0cmluZyhuLCJ0ZXh0L3htbCIpKToocj1uZXcgQWN0aXZlWE9iamVjdCgiTWljcm9zb2Z0LlhNTERPTSIpLHIuYXN5bmM9ImZhbHNlIixyLmxvYWRYTUwobikpfWNhdGNoKG8pe3I9dH1yZXR1cm4gciYmci5kb2N1bWVudEVsZW1lbnQmJiFyLmdldEVsZW1lbnRzQnlUYWdOYW1lKCJwYXJzZXJlcnJvciIpLmxlbmd0aHx8Yi5lcnJvcigiSW52YWxpZCBYTUw6ICIrbikscn0sbm9vcDpmdW5jdGlvbigpe30sZ2xvYmFsRXZhbDpmdW5jdGlvbih0KXt0JiZiLnRyaW0odCkmJihlLmV4ZWNTY3JpcHR8fGZ1bmN0aW9uKHQpe2UuZXZhbC5jYWxsKGUsdCl9KSh0KX0sY2FtZWxDYXNlOmZ1bmN0aW9uKGUpe3JldHVybiBlLnJlcGxhY2UoaiwibXMtIikucmVwbGFjZShELEwpfSxub2RlTmFtZTpmdW5jdGlvbihlLHQpe3JldHVybiBlLm5vZGVOYW1lJiZlLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCk9PT10LnRvTG93ZXJDYXNlKCl9LGVhY2g6ZnVuY3Rpb24oZSx0LG4pe3ZhciByLGk9MCxvPWUubGVuZ3RoLGE9TShlKTtpZihuKXtpZihhKXtmb3IoO28+aTtpKyspaWYocj10LmFwcGx5KGVbaV0sbikscj09PSExKWJyZWFrfWVsc2UgZm9yKGkgaW4gZSlpZihyPXQuYXBwbHkoZVtpXSxuKSxyPT09ITEpYnJlYWt9ZWxzZSBpZihhKXtmb3IoO28+aTtpKyspaWYocj10LmNhbGwoZVtpXSxpLGVbaV0pLHI9PT0hMSlicmVha31lbHNlIGZvcihpIGluIGUpaWYocj10LmNhbGwoZVtpXSxpLGVbaV0pLHI9PT0hMSlicmVhaztyZXR1cm4gZX0sdHJpbTp2JiYhdi5jYWxsKCJcdWZlZmZcdTAwYTAiKT9mdW5jdGlvbihlKXtyZXR1cm4gbnVsbD09ZT8iIjp2LmNhbGwoZSl9OmZ1bmN0aW9uKGUpe3JldHVybiBudWxsPT1lPyIiOihlKyIiKS5yZXBsYWNlKFQsIiIpfSxtYWtlQXJyYXk6ZnVuY3Rpb24oZSx0KXt2YXIgbj10fHxbXTtyZXR1cm4gbnVsbCE9ZSYmKE0oT2JqZWN0KGUpKT9iLm1lcmdlKG4sInN0cmluZyI9PXR5cGVvZiBlP1tlXTplKTpkLmNhbGwobixlKSksbn0saW5BcnJheTpmdW5jdGlvbihlLHQsbil7dmFyIHI7aWYodCl7aWYoZylyZXR1cm4gZy5jYWxsKHQsZSxuKTtmb3Iocj10Lmxlbmd0aCxuPW4/MD5uP01hdGgubWF4KDAscituKTpuOjA7cj5uO24rKylpZihuIGluIHQmJnRbbl09PT1lKXJldHVybiBufXJldHVybi0xfSxtZXJnZTpmdW5jdGlvbihlLG4pe3ZhciByPW4ubGVuZ3RoLGk9ZS5sZW5ndGgsbz0wO2lmKCJudW1iZXIiPT10eXBlb2Ygcilmb3IoO3I+bztvKyspZVtpKytdPW5bb107ZWxzZSB3aGlsZShuW29dIT09dCllW2krK109bltvKytdO3JldHVybiBlLmxlbmd0aD1pLGV9LGdyZXA6ZnVuY3Rpb24oZSx0LG4pe3ZhciByLGk9W10sbz0wLGE9ZS5sZW5ndGg7Zm9yKG49ISFuO2E+bztvKyspcj0hIXQoZVtvXSxvKSxuIT09ciYmaS5wdXNoKGVbb10pO3JldHVybiBpfSxtYXA6ZnVuY3Rpb24oZSx0LG4pe3ZhciByLGk9MCxvPWUubGVuZ3RoLGE9TShlKSxzPVtdO2lmKGEpZm9yKDtvPmk7aSsrKXI9dChlW2ldLGksbiksbnVsbCE9ciYmKHNbcy5sZW5ndGhdPXIpO2Vsc2UgZm9yKGkgaW4gZSlyPXQoZVtpXSxpLG4pLG51bGwhPXImJihzW3MubGVuZ3RoXT1yKTtyZXR1cm4gZi5hcHBseShbXSxzKX0sZ3VpZDoxLHByb3h5OmZ1bmN0aW9uKGUsbil7dmFyIHIsaSxvO3JldHVybiJzdHJpbmciPT10eXBlb2YgbiYmKG89ZVtuXSxuPWUsZT1vKSxiLmlzRnVuY3Rpb24oZSk/KHI9aC5jYWxsKGFyZ3VtZW50cywyKSxpPWZ1bmN0aW9uKCl7cmV0dXJuIGUuYXBwbHkobnx8dGhpcyxyLmNvbmNhdChoLmNhbGwoYXJndW1lbnRzKSkpfSxpLmd1aWQ9ZS5ndWlkPWUuZ3VpZHx8Yi5ndWlkKyssaSk6dH0sYWNjZXNzOmZ1bmN0aW9uKGUsbixyLGksbyxhLHMpe3ZhciB1PTAsbD1lLmxlbmd0aCxjPW51bGw9PXI7aWYoIm9iamVjdCI9PT1iLnR5cGUocikpe289ITA7Zm9yKHUgaW4gciliLmFjY2VzcyhlLG4sdSxyW3VdLCEwLGEscyl9ZWxzZSBpZihpIT09dCYmKG89ITAsYi5pc0Z1bmN0aW9uKGkpfHwocz0hMCksYyYmKHM/KG4uY2FsbChlLGkpLG49bnVsbCk6KGM9bixuPWZ1bmN0aW9uKGUsdCxuKXtyZXR1cm4gYy5jYWxsKGIoZSksbil9KSksbikpZm9yKDtsPnU7dSsrKW4oZVt1XSxyLHM/aTppLmNhbGwoZVt1XSx1LG4oZVt1XSxyKSkpO3JldHVybiBvP2U6Yz9uLmNhbGwoZSk6bD9uKGVbMF0scik6YX0sbm93OmZ1bmN0aW9uKCl7cmV0dXJuKG5ldyBEYXRlKS5nZXRUaW1lKCl9fSksYi5yZWFkeS5wcm9taXNlPWZ1bmN0aW9uKHQpe2lmKCFuKWlmKG49Yi5EZWZlcnJlZCgpLCJjb21wbGV0ZSI9PT1vLnJlYWR5U3RhdGUpc2V0VGltZW91dChiLnJlYWR5KTtlbHNlIGlmKG8uYWRkRXZlbnRMaXN0ZW5lcilvLmFkZEV2ZW50TGlzdGVuZXIoIkRPTUNvbnRlbnRMb2FkZWQiLEgsITEpLGUuYWRkRXZlbnRMaXN0ZW5lcigibG9hZCIsSCwhMSk7ZWxzZXtvLmF0dGFjaEV2ZW50KCJvbnJlYWR5c3RhdGVjaGFuZ2UiLEgpLGUuYXR0YWNoRXZlbnQoIm9ubG9hZCIsSCk7dmFyIHI9ITE7dHJ5e3I9bnVsbD09ZS5mcmFtZUVsZW1lbnQmJm8uZG9jdW1lbnRFbGVtZW50fWNhdGNoKGkpe31yJiZyLmRvU2Nyb2xsJiZmdW5jdGlvbiBhKCl7aWYoIWIuaXNSZWFkeSl7dHJ5e3IuZG9TY3JvbGwoImxlZnQiKX1jYXRjaChlKXtyZXR1cm4gc2V0VGltZW91dChhLDUwKX1xKCksYi5yZWFkeSgpfX0oKX1yZXR1cm4gbi5wcm9taXNlKHQpfSxiLmVhY2goIkJvb2xlYW4gTnVtYmVyIFN0cmluZyBGdW5jdGlvbiBBcnJheSBEYXRlIFJlZ0V4cCBPYmplY3QgRXJyb3IiLnNwbGl0KCIgIiksZnVuY3Rpb24oZSx0KXtsWyJbb2JqZWN0ICIrdCsiXSJdPXQudG9Mb3dlckNhc2UoKX0pO2Z1bmN0aW9uIE0oZSl7dmFyIHQ9ZS5sZW5ndGgsbj1iLnR5cGUoZSk7cmV0dXJuIGIuaXNXaW5kb3coZSk/ITE6MT09PWUubm9kZVR5cGUmJnQ/ITA6ImFycmF5Ij09PW58fCJmdW5jdGlvbiIhPT1uJiYoMD09PXR8fCJudW1iZXIiPT10eXBlb2YgdCYmdD4wJiZ0LTEgaW4gZSl9cj1iKG8pO3ZhciBfPXt9O2Z1bmN0aW9uIEYoZSl7dmFyIHQ9X1tlXT17fTtyZXR1cm4gYi5lYWNoKGUubWF0Y2godyl8fFtdLGZ1bmN0aW9uKGUsbil7dFtuXT0hMH0pLHR9Yi5DYWxsYmFja3M9ZnVuY3Rpb24oZSl7ZT0ic3RyaW5nIj09dHlwZW9mIGU/X1tlXXx8RihlKTpiLmV4dGVuZCh7fSxlKTt2YXIgbixyLGksbyxhLHMsdT1bXSxsPSFlLm9uY2UmJltdLGM9ZnVuY3Rpb24odCl7Zm9yKHI9ZS5tZW1vcnkmJnQsaT0hMCxhPXN8fDAscz0wLG89dS5sZW5ndGgsbj0hMDt1JiZvPmE7YSsrKWlmKHVbYV0uYXBwbHkodFswXSx0WzFdKT09PSExJiZlLnN0b3BPbkZhbHNlKXtyPSExO2JyZWFrfW49ITEsdSYmKGw/bC5sZW5ndGgmJmMobC5zaGlmdCgpKTpyP3U9W106cC5kaXNhYmxlKCkpfSxwPXthZGQ6ZnVuY3Rpb24oKXtpZih1KXt2YXIgdD11Lmxlbmd0aDsoZnVuY3Rpb24gaSh0KXtiLmVhY2godCxmdW5jdGlvbih0LG4pe3ZhciByPWIudHlwZShuKTsiZnVuY3Rpb24iPT09cj9lLnVuaXF1ZSYmcC5oYXMobil8fHUucHVzaChuKTpuJiZuLmxlbmd0aCYmInN0cmluZyIhPT1yJiZpKG4pfSl9KShhcmd1bWVudHMpLG4/bz11Lmxlbmd0aDpyJiYocz10LGMocikpfXJldHVybiB0aGlzfSxyZW1vdmU6ZnVuY3Rpb24oKXtyZXR1cm4gdSYmYi5lYWNoKGFyZ3VtZW50cyxmdW5jdGlvbihlLHQpe3ZhciByO3doaWxlKChyPWIuaW5BcnJheSh0LHUscikpPi0xKXUuc3BsaWNlKHIsMSksbiYmKG8+PXImJm8tLSxhPj1yJiZhLS0pfSksdGhpc30saGFzOmZ1bmN0aW9uKGUpe3JldHVybiBlP2IuaW5BcnJheShlLHUpPi0xOiEoIXV8fCF1Lmxlbmd0aCl9LGVtcHR5OmZ1bmN0aW9uKCl7cmV0dXJuIHU9W10sdGhpc30sZGlzYWJsZTpmdW5jdGlvbigpe3JldHVybiB1PWw9cj10LHRoaXN9LGRpc2FibGVkOmZ1bmN0aW9uKCl7cmV0dXJuIXV9LGxvY2s6ZnVuY3Rpb24oKXtyZXR1cm4gbD10LHJ8fHAuZGlzYWJsZSgpLHRoaXN9LGxvY2tlZDpmdW5jdGlvbigpe3JldHVybiFsfSxmaXJlV2l0aDpmdW5jdGlvbihlLHQpe3JldHVybiB0PXR8fFtdLHQ9W2UsdC5zbGljZT90LnNsaWNlKCk6dF0sIXV8fGkmJiFsfHwobj9sLnB1c2godCk6Yyh0KSksdGhpc30sZmlyZTpmdW5jdGlvbigpe3JldHVybiBwLmZpcmVXaXRoKHRoaXMsYXJndW1lbnRzKSx0aGlzfSxmaXJlZDpmdW5jdGlvbigpe3JldHVybiEhaX19O3JldHVybiBwfSxiLmV4dGVuZCh7RGVmZXJyZWQ6ZnVuY3Rpb24oZSl7dmFyIHQ9W1sicmVzb2x2ZSIsImRvbmUiLGIuQ2FsbGJhY2tzKCJvbmNlIG1lbW9yeSIpLCJyZXNvbHZlZCJdLFsicmVqZWN0IiwiZmFpbCIsYi5DYWxsYmFja3MoIm9uY2UgbWVtb3J5IiksInJlamVjdGVkIl0sWyJub3RpZnkiLCJwcm9ncmVzcyIsYi5DYWxsYmFja3MoIm1lbW9yeSIpXV0sbj0icGVuZGluZyIscj17c3RhdGU6ZnVuY3Rpb24oKXtyZXR1cm4gbn0sYWx3YXlzOmZ1bmN0aW9uKCl7cmV0dXJuIGkuZG9uZShhcmd1bWVudHMpLmZhaWwoYXJndW1lbnRzKSx0aGlzfSx0aGVuOmZ1bmN0aW9uKCl7dmFyIGU9YXJndW1lbnRzO3JldHVybiBiLkRlZmVycmVkKGZ1bmN0aW9uKG4pe2IuZWFjaCh0LGZ1bmN0aW9uKHQsbyl7dmFyIGE9b1swXSxzPWIuaXNGdW5jdGlvbihlW3RdKSYmZVt0XTtpW29bMV1dKGZ1bmN0aW9uKCl7dmFyIGU9cyYmcy5hcHBseSh0aGlzLGFyZ3VtZW50cyk7ZSYmYi5pc0Z1bmN0aW9uKGUucHJvbWlzZSk/ZS5wcm9taXNlKCkuZG9uZShuLnJlc29sdmUpLmZhaWwobi5yZWplY3QpLnByb2dyZXNzKG4ubm90aWZ5KTpuW2ErIldpdGgiXSh0aGlzPT09cj9uLnByb21pc2UoKTp0aGlzLHM/W2VdOmFyZ3VtZW50cyl9KX0pLGU9bnVsbH0pLnByb21pc2UoKX0scHJvbWlzZTpmdW5jdGlvbihlKXtyZXR1cm4gbnVsbCE9ZT9iLmV4dGVuZChlLHIpOnJ9fSxpPXt9O3JldHVybiByLnBpcGU9ci50aGVuLGIuZWFjaCh0LGZ1bmN0aW9uKGUsbyl7dmFyIGE9b1syXSxzPW9bM107cltvWzFdXT1hLmFkZCxzJiZhLmFkZChmdW5jdGlvbigpe249c30sdFsxXmVdWzJdLmRpc2FibGUsdFsyXVsyXS5sb2NrKSxpW29bMF1dPWZ1bmN0aW9uKCl7cmV0dXJuIGlbb1swXSsiV2l0aCJdKHRoaXM9PT1pP3I6dGhpcyxhcmd1bWVudHMpLHRoaXN9LGlbb1swXSsiV2l0aCJdPWEuZmlyZVdpdGh9KSxyLnByb21pc2UoaSksZSYmZS5jYWxsKGksaSksaX0sd2hlbjpmdW5jdGlvbihlKXt2YXIgdD0wLG49aC5jYWxsKGFyZ3VtZW50cykscj1uLmxlbmd0aCxpPTEhPT1yfHxlJiZiLmlzRnVuY3Rpb24oZS5wcm9taXNlKT9yOjAsbz0xPT09aT9lOmIuRGVmZXJyZWQoKSxhPWZ1bmN0aW9uKGUsdCxuKXtyZXR1cm4gZnVuY3Rpb24ocil7dFtlXT10aGlzLG5bZV09YXJndW1lbnRzLmxlbmd0aD4xP2guY2FsbChhcmd1bWVudHMpOnIsbj09PXM/by5ub3RpZnlXaXRoKHQsbik6LS1pfHxvLnJlc29sdmVXaXRoKHQsbil9fSxzLHUsbDtpZihyPjEpZm9yKHM9QXJyYXkociksdT1BcnJheShyKSxsPUFycmF5KHIpO3I+dDt0Kyspblt0XSYmYi5pc0Z1bmN0aW9uKG5bdF0ucHJvbWlzZSk/blt0XS5wcm9taXNlKCkuZG9uZShhKHQsbCxuKSkuZmFpbChvLnJlamVjdCkucHJvZ3Jlc3MoYSh0LHUscykpOi0taTtyZXR1cm4gaXx8by5yZXNvbHZlV2l0aChsLG4pLG8ucHJvbWlzZSgpfX0pLGIuc3VwcG9ydD1mdW5jdGlvbigpe3ZhciB0LG4scixhLHMsdSxsLGMscCxmLGQ9by5jcmVhdGVFbGVtZW50KCJkaXYiKTtpZihkLnNldEF0dHJpYnV0ZSgiY2xhc3NOYW1lIiwidCIpLGQuaW5uZXJIVE1MPSIgIDxsaW5rLz48dGFibGU+PC90YWJsZT48YSBocmVmPScvYSc+YTwvYT48aW5wdXQgdHlwZT0nY2hlY2tib3gnLz4iLG49ZC5nZXRFbGVtZW50c0J5VGFnTmFtZSgiKiIpLHI9ZC5nZXRFbGVtZW50c0J5VGFnTmFtZSgiYSIpWzBdLCFufHwhcnx8IW4ubGVuZ3RoKXJldHVybnt9O3M9by5jcmVhdGVFbGVtZW50KCJzZWxlY3QiKSxsPXMuYXBwZW5kQ2hpbGQoby5jcmVhdGVFbGVtZW50KCJvcHRpb24iKSksYT1kLmdldEVsZW1lbnRzQnlUYWdOYW1lKCJpbnB1dCIpWzBdLHIuc3R5bGUuY3NzVGV4dD0idG9wOjFweDtmbG9hdDpsZWZ0O29wYWNpdHk6LjUiLHQ9e2dldFNldEF0dHJpYnV0ZToidCIhPT1kLmNsYXNzTmFtZSxsZWFkaW5nV2hpdGVzcGFjZTozPT09ZC5maXJzdENoaWxkLm5vZGVUeXBlLHRib2R5OiFkLmdldEVsZW1lbnRzQnlUYWdOYW1lKCJ0Ym9keSIpLmxlbmd0aCxodG1sU2VyaWFsaXplOiEhZC5nZXRFbGVtZW50c0J5VGFnTmFtZSgibGluayIpLmxlbmd0aCxzdHlsZTovdG9wLy50ZXN0KHIuZ2V0QXR0cmlidXRlKCJzdHlsZSIpKSxocmVmTm9ybWFsaXplZDoiL2EiPT09ci5nZXRBdHRyaWJ1dGUoImhyZWYiKSxvcGFjaXR5Oi9eMC41Ly50ZXN0KHIuc3R5bGUub3BhY2l0eSksY3NzRmxvYXQ6ISFyLnN0eWxlLmNzc0Zsb2F0LGNoZWNrT246ISFhLnZhbHVlLG9wdFNlbGVjdGVkOmwuc2VsZWN0ZWQsZW5jdHlwZTohIW8uY3JlYXRlRWxlbWVudCgiZm9ybSIpLmVuY3R5cGUsaHRtbDVDbG9uZToiPDpuYXY+PC86bmF2PiIhPT1vLmNyZWF0ZUVsZW1lbnQoIm5hdiIpLmNsb25lTm9kZSghMCkub3V0ZXJIVE1MLGJveE1vZGVsOiJDU1MxQ29tcGF0Ij09PW8uY29tcGF0TW9kZSxkZWxldGVFeHBhbmRvOiEwLG5vQ2xvbmVFdmVudDohMCxpbmxpbmVCbG9ja05lZWRzTGF5b3V0OiExLHNocmlua1dyYXBCbG9ja3M6ITEscmVsaWFibGVNYXJnaW5SaWdodDohMCxib3hTaXppbmdSZWxpYWJsZTohMCxwaXhlbFBvc2l0aW9uOiExfSxhLmNoZWNrZWQ9ITAsdC5ub0Nsb25lQ2hlY2tlZD1hLmNsb25lTm9kZSghMCkuY2hlY2tlZCxzLmRpc2FibGVkPSEwLHQub3B0RGlzYWJsZWQ9IWwuZGlzYWJsZWQ7dHJ5e2RlbGV0ZSBkLnRlc3R9Y2F0Y2goaCl7dC5kZWxldGVFeHBhbmRvPSExfWE9by5jcmVhdGVFbGVtZW50KCJpbnB1dCIpLGEuc2V0QXR0cmlidXRlKCJ2YWx1ZSIsIiIpLHQuaW5wdXQ9IiI9PT1hLmdldEF0dHJpYnV0ZSgidmFsdWUiKSxhLnZhbHVlPSJ0IixhLnNldEF0dHJpYnV0ZSgidHlwZSIsInJhZGlvIiksdC5yYWRpb1ZhbHVlPSJ0Ij09PWEudmFsdWUsYS5zZXRBdHRyaWJ1dGUoImNoZWNrZWQiLCJ0IiksYS5zZXRBdHRyaWJ1dGUoIm5hbWUiLCJ0IiksdT1vLmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKSx1LmFwcGVuZENoaWxkKGEpLHQuYXBwZW5kQ2hlY2tlZD1hLmNoZWNrZWQsdC5jaGVja0Nsb25lPXUuY2xvbmVOb2RlKCEwKS5jbG9uZU5vZGUoITApLmxhc3RDaGlsZC5jaGVja2VkLGQuYXR0YWNoRXZlbnQmJihkLmF0dGFjaEV2ZW50KCJvbmNsaWNrIixmdW5jdGlvbigpe3Qubm9DbG9uZUV2ZW50PSExfSksZC5jbG9uZU5vZGUoITApLmNsaWNrKCkpO2ZvcihmIGlue3N1Ym1pdDohMCxjaGFuZ2U6ITAsZm9jdXNpbjohMH0pZC5zZXRBdHRyaWJ1dGUoYz0ib24iK2YsInQiKSx0W2YrIkJ1YmJsZXMiXT1jIGluIGV8fGQuYXR0cmlidXRlc1tjXS5leHBhbmRvPT09ITE7cmV0dXJuIGQuc3R5bGUuYmFja2dyb3VuZENsaXA9ImNvbnRlbnQtYm94IixkLmNsb25lTm9kZSghMCkuc3R5bGUuYmFja2dyb3VuZENsaXA9IiIsdC5jbGVhckNsb25lU3R5bGU9ImNvbnRlbnQtYm94Ij09PWQuc3R5bGUuYmFja2dyb3VuZENsaXAsYihmdW5jdGlvbigpe3ZhciBuLHIsYSxzPSJwYWRkaW5nOjA7bWFyZ2luOjA7Ym9yZGVyOjA7ZGlzcGxheTpibG9jaztib3gtc2l6aW5nOmNvbnRlbnQtYm94Oy1tb3otYm94LXNpemluZzpjb250ZW50LWJveDstd2Via2l0LWJveC1zaXppbmc6Y29udGVudC1ib3g7Iix1PW8uZ2V0RWxlbWVudHNCeVRhZ05hbWUoImJvZHkiKVswXTt1JiYobj1vLmNyZWF0ZUVsZW1lbnQoImRpdiIpLG4uc3R5bGUuY3NzVGV4dD0iYm9yZGVyOjA7d2lkdGg6MDtoZWlnaHQ6MDtwb3NpdGlvbjphYnNvbHV0ZTt0b3A6MDtsZWZ0Oi05OTk5cHg7bWFyZ2luLXRvcDoxcHgiLHUuYXBwZW5kQ2hpbGQobikuYXBwZW5kQ2hpbGQoZCksZC5pbm5lckhUTUw9Ijx0YWJsZT48dHI+PHRkPjwvdGQ+PHRkPnQ8L3RkPjwvdHI+PC90YWJsZT4iLGE9ZC5nZXRFbGVtZW50c0J5VGFnTmFtZSgidGQiKSxhWzBdLnN0eWxlLmNzc1RleHQ9InBhZGRpbmc6MDttYXJnaW46MDtib3JkZXI6MDtkaXNwbGF5Om5vbmUiLHA9MD09PWFbMF0ub2Zmc2V0SGVpZ2h0LGFbMF0uc3R5bGUuZGlzcGxheT0iIixhWzFdLnN0eWxlLmRpc3BsYXk9Im5vbmUiLHQucmVsaWFibGVIaWRkZW5PZmZzZXRzPXAmJjA9PT1hWzBdLm9mZnNldEhlaWdodCxkLmlubmVySFRNTD0iIixkLnN0eWxlLmNzc1RleHQ9ImJveC1zaXppbmc6Ym9yZGVyLWJveDstbW96LWJveC1zaXppbmc6Ym9yZGVyLWJveDstd2Via2l0LWJveC1zaXppbmc6Ym9yZGVyLWJveDtwYWRkaW5nOjFweDtib3JkZXI6MXB4O2Rpc3BsYXk6YmxvY2s7d2lkdGg6NHB4O21hcmdpbi10b3A6MSU7cG9zaXRpb246YWJzb2x1dGU7dG9wOjElOyIsdC5ib3hTaXppbmc9ND09PWQub2Zmc2V0V2lkdGgsdC5kb2VzTm90SW5jbHVkZU1hcmdpbkluQm9keU9mZnNldD0xIT09dS5vZmZzZXRUb3AsZS5nZXRDb21wdXRlZFN0eWxlJiYodC5waXhlbFBvc2l0aW9uPSIxJSIhPT0oZS5nZXRDb21wdXRlZFN0eWxlKGQsbnVsbCl8fHt9KS50b3AsdC5ib3hTaXppbmdSZWxpYWJsZT0iNHB4Ij09PShlLmdldENvbXB1dGVkU3R5bGUoZCxudWxsKXx8e3dpZHRoOiI0cHgifSkud2lkdGgscj1kLmFwcGVuZENoaWxkKG8uY3JlYXRlRWxlbWVudCgiZGl2IikpLHIuc3R5bGUuY3NzVGV4dD1kLnN0eWxlLmNzc1RleHQ9cyxyLnN0eWxlLm1hcmdpblJpZ2h0PXIuc3R5bGUud2lkdGg9IjAiLGQuc3R5bGUud2lkdGg9IjFweCIsdC5yZWxpYWJsZU1hcmdpblJpZ2h0PSFwYXJzZUZsb2F0KChlLmdldENvbXB1dGVkU3R5bGUocixudWxsKXx8e30pLm1hcmdpblJpZ2h0KSksdHlwZW9mIGQuc3R5bGUuem9vbSE9PWkmJihkLmlubmVySFRNTD0iIixkLnN0eWxlLmNzc1RleHQ9cysid2lkdGg6MXB4O3BhZGRpbmc6MXB4O2Rpc3BsYXk6aW5saW5lO3pvb206MSIsdC5pbmxpbmVCbG9ja05lZWRzTGF5b3V0PTM9PT1kLm9mZnNldFdpZHRoLGQuc3R5bGUuZGlzcGxheT0iYmxvY2siLGQuaW5uZXJIVE1MPSI8ZGl2PjwvZGl2PiIsZC5maXJzdENoaWxkLnN0eWxlLndpZHRoPSI1cHgiLHQuc2hyaW5rV3JhcEJsb2Nrcz0zIT09ZC5vZmZzZXRXaWR0aCx0LmlubGluZUJsb2NrTmVlZHNMYXlvdXQmJih1LnN0eWxlLnpvb209MSkpLHUucmVtb3ZlQ2hpbGQobiksbj1kPWE9cj1udWxsKX0pLG49cz11PWw9cj1hPW51bGwsdH0oKTt2YXIgTz0vKD86XHtbXHNcU10qXH18XFtbXHNcU10qXF0pJC8sQj0vKFtBLVpdKS9nO2Z1bmN0aW9uIFAoZSxuLHIsaSl7aWYoYi5hY2NlcHREYXRhKGUpKXt2YXIgbyxhLHM9Yi5leHBhbmRvLHU9InN0cmluZyI9PXR5cGVvZiBuLGw9ZS5ub2RlVHlwZSxwPWw/Yi5jYWNoZTplLGY9bD9lW3NdOmVbc10mJnM7aWYoZiYmcFtmXSYmKGl8fHBbZl0uZGF0YSl8fCF1fHxyIT09dClyZXR1cm4gZnx8KGw/ZVtzXT1mPWMucG9wKCl8fGIuZ3VpZCsrOmY9cykscFtmXXx8KHBbZl09e30sbHx8KHBbZl0udG9KU09OPWIubm9vcCkpLCgib2JqZWN0Ij09dHlwZW9mIG58fCJmdW5jdGlvbiI9PXR5cGVvZiBuKSYmKGk/cFtmXT1iLmV4dGVuZChwW2ZdLG4pOnBbZl0uZGF0YT1iLmV4dGVuZChwW2ZdLmRhdGEsbikpLG89cFtmXSxpfHwoby5kYXRhfHwoby5kYXRhPXt9KSxvPW8uZGF0YSksciE9PXQmJihvW2IuY2FtZWxDYXNlKG4pXT1yKSx1PyhhPW9bbl0sbnVsbD09YSYmKGE9b1tiLmNhbWVsQ2FzZShuKV0pKTphPW8sYX19ZnVuY3Rpb24gUihlLHQsbil7aWYoYi5hY2NlcHREYXRhKGUpKXt2YXIgcixpLG8sYT1lLm5vZGVUeXBlLHM9YT9iLmNhY2hlOmUsdT1hP2VbYi5leHBhbmRvXTpiLmV4cGFuZG87aWYoc1t1XSl7aWYodCYmKG89bj9zW3VdOnNbdV0uZGF0YSkpe2IuaXNBcnJheSh0KT90PXQuY29uY2F0KGIubWFwKHQsYi5jYW1lbENhc2UpKTp0IGluIG8/dD1bdF06KHQ9Yi5jYW1lbENhc2UodCksdD10IGluIG8/W3RdOnQuc3BsaXQoIiAiKSk7Zm9yKHI9MCxpPXQubGVuZ3RoO2k+cjtyKyspZGVsZXRlIG9bdFtyXV07aWYoIShuPyQ6Yi5pc0VtcHR5T2JqZWN0KShvKSlyZXR1cm59KG58fChkZWxldGUgc1t1XS5kYXRhLCQoc1t1XSkpKSYmKGE/Yi5jbGVhbkRhdGEoW2VdLCEwKTpiLnN1cHBvcnQuZGVsZXRlRXhwYW5kb3x8cyE9cy53aW5kb3c/ZGVsZXRlIHNbdV06c1t1XT1udWxsKX19fWIuZXh0ZW5kKHtjYWNoZTp7fSxleHBhbmRvOiJqUXVlcnkiKyhwK01hdGgucmFuZG9tKCkpLnJlcGxhY2UoL1xEL2csIiIpLG5vRGF0YTp7ZW1iZWQ6ITAsb2JqZWN0OiJjbHNpZDpEMjdDREI2RS1BRTZELTExY2YtOTZCOC00NDQ1NTM1NDAwMDAiLGFwcGxldDohMH0saGFzRGF0YTpmdW5jdGlvbihlKXtyZXR1cm4gZT1lLm5vZGVUeXBlP2IuY2FjaGVbZVtiLmV4cGFuZG9dXTplW2IuZXhwYW5kb10sISFlJiYhJChlKX0sZGF0YTpmdW5jdGlvbihlLHQsbil7cmV0dXJuIFAoZSx0LG4pfSxyZW1vdmVEYXRhOmZ1bmN0aW9uKGUsdCl7cmV0dXJuIFIoZSx0KX0sX2RhdGE6ZnVuY3Rpb24oZSx0LG4pe3JldHVybiBQKGUsdCxuLCEwKX0sX3JlbW92ZURhdGE6ZnVuY3Rpb24oZSx0KXtyZXR1cm4gUihlLHQsITApfSxhY2NlcHREYXRhOmZ1bmN0aW9uKGUpe2lmKGUubm9kZVR5cGUmJjEhPT1lLm5vZGVUeXBlJiY5IT09ZS5ub2RlVHlwZSlyZXR1cm4hMTt2YXIgdD1lLm5vZGVOYW1lJiZiLm5vRGF0YVtlLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCldO3JldHVybiF0fHx0IT09ITAmJmUuZ2V0QXR0cmlidXRlKCJjbGFzc2lkIik9PT10fX0pLGIuZm4uZXh0ZW5kKHtkYXRhOmZ1bmN0aW9uKGUsbil7dmFyIHIsaSxvPXRoaXNbMF0sYT0wLHM9bnVsbDtpZihlPT09dCl7aWYodGhpcy5sZW5ndGgmJihzPWIuZGF0YShvKSwxPT09by5ub2RlVHlwZSYmIWIuX2RhdGEobywicGFyc2VkQXR0cnMiKSkpe2ZvcihyPW8uYXR0cmlidXRlcztyLmxlbmd0aD5hO2ErKylpPXJbYV0ubmFtZSxpLmluZGV4T2YoImRhdGEtIil8fChpPWIuY2FtZWxDYXNlKGkuc2xpY2UoNSkpLFcobyxpLHNbaV0pKTtiLl9kYXRhKG8sInBhcnNlZEF0dHJzIiwhMCl9cmV0dXJuIHN9cmV0dXJuIm9iamVjdCI9PXR5cGVvZiBlP3RoaXMuZWFjaChmdW5jdGlvbigpe2IuZGF0YSh0aGlzLGUpfSk6Yi5hY2Nlc3ModGhpcyxmdW5jdGlvbihuKXtyZXR1cm4gbj09PXQ/bz9XKG8sZSxiLmRhdGEobyxlKSk6bnVsbDoodGhpcy5lYWNoKGZ1bmN0aW9uKCl7Yi5kYXRhKHRoaXMsZSxuKX0pLHQpfSxudWxsLG4sYXJndW1lbnRzLmxlbmd0aD4xLG51bGwsITApfSxyZW1vdmVEYXRhOmZ1bmN0aW9uKGUpe3JldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oKXtiLnJlbW92ZURhdGEodGhpcyxlKX0pfX0pO2Z1bmN0aW9uIFcoZSxuLHIpe2lmKHI9PT10JiYxPT09ZS5ub2RlVHlwZSl7dmFyIGk9ImRhdGEtIituLnJlcGxhY2UoQiwiLSQxIikudG9Mb3dlckNhc2UoKTtpZihyPWUuZ2V0QXR0cmlidXRlKGkpLCJzdHJpbmciPT10eXBlb2Ygcil7dHJ5e3I9InRydWUiPT09cj8hMDoiZmFsc2UiPT09cj8hMToibnVsbCI9PT1yP251bGw6K3IrIiI9PT1yPytyOk8udGVzdChyKT9iLnBhcnNlSlNPTihyKTpyfWNhdGNoKG8pe31iLmRhdGEoZSxuLHIpfWVsc2Ugcj10fXJldHVybiByfWZ1bmN0aW9uICQoZSl7dmFyIHQ7Zm9yKHQgaW4gZSlpZigoImRhdGEiIT09dHx8IWIuaXNFbXB0eU9iamVjdChlW3RdKSkmJiJ0b0pTT04iIT09dClyZXR1cm4hMTtyZXR1cm4hMH1iLmV4dGVuZCh7cXVldWU6ZnVuY3Rpb24oZSxuLHIpe3ZhciBpO3JldHVybiBlPyhuPShufHwiZngiKSsicXVldWUiLGk9Yi5fZGF0YShlLG4pLHImJighaXx8Yi5pc0FycmF5KHIpP2k9Yi5fZGF0YShlLG4sYi5tYWtlQXJyYXkocikpOmkucHVzaChyKSksaXx8W10pOnR9LGRlcXVldWU6ZnVuY3Rpb24oZSx0KXt0PXR8fCJmeCI7dmFyIG49Yi5xdWV1ZShlLHQpLHI9bi5sZW5ndGgsaT1uLnNoaWZ0KCksbz1iLl9xdWV1ZUhvb2tzKGUsdCksYT1mdW5jdGlvbigpe2IuZGVxdWV1ZShlLHQpfTsiaW5wcm9ncmVzcyI9PT1pJiYoaT1uLnNoaWZ0KCksci0tKSxvLmN1cj1pLGkmJigiZngiPT09dCYmbi51bnNoaWZ0KCJpbnByb2dyZXNzIiksZGVsZXRlIG8uc3RvcCxpLmNhbGwoZSxhLG8pKSwhciYmbyYmby5lbXB0eS5maXJlKCl9LF9xdWV1ZUhvb2tzOmZ1bmN0aW9uKGUsdCl7dmFyIG49dCsicXVldWVIb29rcyI7cmV0dXJuIGIuX2RhdGEoZSxuKXx8Yi5fZGF0YShlLG4se2VtcHR5OmIuQ2FsbGJhY2tzKCJvbmNlIG1lbW9yeSIpLmFkZChmdW5jdGlvbigpe2IuX3JlbW92ZURhdGEoZSx0KyJxdWV1ZSIpLGIuX3JlbW92ZURhdGEoZSxuKX0pfSl9fSksYi5mbi5leHRlbmQoe3F1ZXVlOmZ1bmN0aW9uKGUsbil7dmFyIHI9MjtyZXR1cm4ic3RyaW5nIiE9dHlwZW9mIGUmJihuPWUsZT0iZngiLHItLSkscj5hcmd1bWVudHMubGVuZ3RoP2IucXVldWUodGhpc1swXSxlKTpuPT09dD90aGlzOnRoaXMuZWFjaChmdW5jdGlvbigpe3ZhciB0PWIucXVldWUodGhpcyxlLG4pO2IuX3F1ZXVlSG9va3ModGhpcyxlKSwiZngiPT09ZSYmImlucHJvZ3Jlc3MiIT09dFswXSYmYi5kZXF1ZXVlKHRoaXMsZSl9KX0sZGVxdWV1ZTpmdW5jdGlvbihlKXtyZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uKCl7Yi5kZXF1ZXVlKHRoaXMsZSl9KX0sZGVsYXk6ZnVuY3Rpb24oZSx0KXtyZXR1cm4gZT1iLmZ4P2IuZnguc3BlZWRzW2VdfHxlOmUsdD10fHwiZngiLHRoaXMucXVldWUodCxmdW5jdGlvbih0LG4pe3ZhciByPXNldFRpbWVvdXQodCxlKTtuLnN0b3A9ZnVuY3Rpb24oKXtjbGVhclRpbWVvdXQocil9fSl9LGNsZWFyUXVldWU6ZnVuY3Rpb24oZSl7cmV0dXJuIHRoaXMucXVldWUoZXx8ImZ4IixbXSl9LHByb21pc2U6ZnVuY3Rpb24oZSxuKXt2YXIgcixpPTEsbz1iLkRlZmVycmVkKCksYT10aGlzLHM9dGhpcy5sZW5ndGgsdT1mdW5jdGlvbigpey0taXx8by5yZXNvbHZlV2l0aChhLFthXSl9OyJzdHJpbmciIT10eXBlb2YgZSYmKG49ZSxlPXQpLGU9ZXx8ImZ4Ijt3aGlsZShzLS0pcj1iLl9kYXRhKGFbc10sZSsicXVldWVIb29rcyIpLHImJnIuZW1wdHkmJihpKyssci5lbXB0eS5hZGQodSkpO3JldHVybiB1KCksby5wcm9taXNlKG4pfX0pO3ZhciBJLHosWD0vW1x0XHJcbl0vZyxVPS9cci9nLFY9L14oPzppbnB1dHxzZWxlY3R8dGV4dGFyZWF8YnV0dG9ufG9iamVjdCkkL2ksWT0vXig/OmF8YXJlYSkkL2ksSj0vXig/OmNoZWNrZWR8c2VsZWN0ZWR8YXV0b2ZvY3VzfGF1dG9wbGF5fGFzeW5jfGNvbnRyb2xzfGRlZmVyfGRpc2FibGVkfGhpZGRlbnxsb29wfG11bHRpcGxlfG9wZW58cmVhZG9ubHl8cmVxdWlyZWR8c2NvcGVkKSQvaSxHPS9eKD86Y2hlY2tlZHxzZWxlY3RlZCkkL2ksUT1iLnN1cHBvcnQuZ2V0U2V0QXR0cmlidXRlLEs9Yi5zdXBwb3J0LmlucHV0O2IuZm4uZXh0ZW5kKHthdHRyOmZ1bmN0aW9uKGUsdCl7cmV0dXJuIGIuYWNjZXNzKHRoaXMsYi5hdHRyLGUsdCxhcmd1bWVudHMubGVuZ3RoPjEpfSxyZW1vdmVBdHRyOmZ1bmN0aW9uKGUpe3JldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oKXtiLnJlbW92ZUF0dHIodGhpcyxlKX0pfSxwcm9wOmZ1bmN0aW9uKGUsdCl7cmV0dXJuIGIuYWNjZXNzKHRoaXMsYi5wcm9wLGUsdCxhcmd1bWVudHMubGVuZ3RoPjEpfSxyZW1vdmVQcm9wOmZ1bmN0aW9uKGUpe3JldHVybiBlPWIucHJvcEZpeFtlXXx8ZSx0aGlzLmVhY2goZnVuY3Rpb24oKXt0cnl7dGhpc1tlXT10LGRlbGV0ZSB0aGlzW2VdfWNhdGNoKG4pe319KX0sYWRkQ2xhc3M6ZnVuY3Rpb24oZSl7dmFyIHQsbixyLGksbyxhPTAscz10aGlzLmxlbmd0aCx1PSJzdHJpbmciPT10eXBlb2YgZSYmZTtpZihiLmlzRnVuY3Rpb24oZSkpcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbih0KXtiKHRoaXMpLmFkZENsYXNzKGUuY2FsbCh0aGlzLHQsdGhpcy5jbGFzc05hbWUpKX0pO2lmKHUpZm9yKHQ9KGV8fCIiKS5tYXRjaCh3KXx8W107cz5hO2ErKylpZihuPXRoaXNbYV0scj0xPT09bi5ub2RlVHlwZSYmKG4uY2xhc3NOYW1lPygiICIrbi5jbGFzc05hbWUrIiAiKS5yZXBsYWNlKFgsIiAiKToiICIpKXtvPTA7d2hpbGUoaT10W28rK10pMD5yLmluZGV4T2YoIiAiK2krIiAiKSYmKHIrPWkrIiAiKTtuLmNsYXNzTmFtZT1iLnRyaW0ocil9cmV0dXJuIHRoaXN9LHJlbW92ZUNsYXNzOmZ1bmN0aW9uKGUpe3ZhciB0LG4scixpLG8sYT0wLHM9dGhpcy5sZW5ndGgsdT0wPT09YXJndW1lbnRzLmxlbmd0aHx8InN0cmluZyI9PXR5cGVvZiBlJiZlO2lmKGIuaXNGdW5jdGlvbihlKSlyZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uKHQpe2IodGhpcykucmVtb3ZlQ2xhc3MoZS5jYWxsKHRoaXMsdCx0aGlzLmNsYXNzTmFtZSkpfSk7aWYodSlmb3IodD0oZXx8IiIpLm1hdGNoKHcpfHxbXTtzPmE7YSsrKWlmKG49dGhpc1thXSxyPTE9PT1uLm5vZGVUeXBlJiYobi5jbGFzc05hbWU/KCIgIituLmNsYXNzTmFtZSsiICIpLnJlcGxhY2UoWCwiICIpOiIiKSl7bz0wO3doaWxlKGk9dFtvKytdKXdoaWxlKHIuaW5kZXhPZigiICIraSsiICIpPj0wKXI9ci5yZXBsYWNlKCIgIitpKyIgIiwiICIpO24uY2xhc3NOYW1lPWU/Yi50cmltKHIpOiIifXJldHVybiB0aGlzfSx0b2dnbGVDbGFzczpmdW5jdGlvbihlLHQpe3ZhciBuPXR5cGVvZiBlLHI9ImJvb2xlYW4iPT10eXBlb2YgdDtyZXR1cm4gYi5pc0Z1bmN0aW9uKGUpP3RoaXMuZWFjaChmdW5jdGlvbihuKXtiKHRoaXMpLnRvZ2dsZUNsYXNzKGUuY2FsbCh0aGlzLG4sdGhpcy5jbGFzc05hbWUsdCksdCl9KTp0aGlzLmVhY2goZnVuY3Rpb24oKXtpZigic3RyaW5nIj09PW4pe3ZhciBvLGE9MCxzPWIodGhpcyksdT10LGw9ZS5tYXRjaCh3KXx8W107d2hpbGUobz1sW2ErK10pdT1yP3U6IXMuaGFzQ2xhc3Mobyksc1t1PyJhZGRDbGFzcyI6InJlbW92ZUNsYXNzIl0obyl9ZWxzZShuPT09aXx8ImJvb2xlYW4iPT09bikmJih0aGlzLmNsYXNzTmFtZSYmYi5fZGF0YSh0aGlzLCJfX2NsYXNzTmFtZV9fIix0aGlzLmNsYXNzTmFtZSksdGhpcy5jbGFzc05hbWU9dGhpcy5jbGFzc05hbWV8fGU9PT0hMT8iIjpiLl9kYXRhKHRoaXMsIl9fY2xhc3NOYW1lX18iKXx8IiIpfSl9LGhhc0NsYXNzOmZ1bmN0aW9uKGUpe3ZhciB0PSIgIitlKyIgIixuPTAscj10aGlzLmxlbmd0aDtmb3IoO3I+bjtuKyspaWYoMT09PXRoaXNbbl0ubm9kZVR5cGUmJigiICIrdGhpc1tuXS5jbGFzc05hbWUrIiAiKS5yZXBsYWNlKFgsIiAiKS5pbmRleE9mKHQpPj0wKXJldHVybiEwO3JldHVybiExfSx2YWw6ZnVuY3Rpb24oZSl7dmFyIG4scixpLG89dGhpc1swXTt7aWYoYXJndW1lbnRzLmxlbmd0aClyZXR1cm4gaT1iLmlzRnVuY3Rpb24oZSksdGhpcy5lYWNoKGZ1bmN0aW9uKG4pe3ZhciBvLGE9Yih0aGlzKTsxPT09dGhpcy5ub2RlVHlwZSYmKG89aT9lLmNhbGwodGhpcyxuLGEudmFsKCkpOmUsbnVsbD09bz9vPSIiOiJudW1iZXIiPT10eXBlb2Ygbz9vKz0iIjpiLmlzQXJyYXkobykmJihvPWIubWFwKG8sZnVuY3Rpb24oZSl7cmV0dXJuIG51bGw9PWU/IiI6ZSsiIn0pKSxyPWIudmFsSG9va3NbdGhpcy50eXBlXXx8Yi52YWxIb29rc1t0aGlzLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCldLHImJiJzZXQiaW4gciYmci5zZXQodGhpcyxvLCJ2YWx1ZSIpIT09dHx8KHRoaXMudmFsdWU9bykpfSk7aWYobylyZXR1cm4gcj1iLnZhbEhvb2tzW28udHlwZV18fGIudmFsSG9va3Nbby5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpXSxyJiYiZ2V0ImluIHImJihuPXIuZ2V0KG8sInZhbHVlIikpIT09dD9uOihuPW8udmFsdWUsInN0cmluZyI9PXR5cGVvZiBuP24ucmVwbGFjZShVLCIiKTpudWxsPT1uPyIiOm4pfX19KSxiLmV4dGVuZCh7dmFsSG9va3M6e29wdGlvbjp7Z2V0OmZ1bmN0aW9uKGUpe3ZhciB0PWUuYXR0cmlidXRlcy52YWx1ZTtyZXR1cm4hdHx8dC5zcGVjaWZpZWQ/ZS52YWx1ZTplLnRleHR9fSxzZWxlY3Q6e2dldDpmdW5jdGlvbihlKXt2YXIgdCxuLHI9ZS5vcHRpb25zLGk9ZS5zZWxlY3RlZEluZGV4LG89InNlbGVjdC1vbmUiPT09ZS50eXBlfHwwPmksYT1vP251bGw6W10scz1vP2krMTpyLmxlbmd0aCx1PTA+aT9zOm8/aTowO2Zvcig7cz51O3UrKylpZihuPXJbdV0sISghbi5zZWxlY3RlZCYmdSE9PWl8fChiLnN1cHBvcnQub3B0RGlzYWJsZWQ/bi5kaXNhYmxlZDpudWxsIT09bi5nZXRBdHRyaWJ1dGUoImRpc2FibGVkIikpfHxuLnBhcmVudE5vZGUuZGlzYWJsZWQmJmIubm9kZU5hbWUobi5wYXJlbnROb2RlLCJvcHRncm91cCIpKSl7aWYodD1iKG4pLnZhbCgpLG8pcmV0dXJuIHQ7YS5wdXNoKHQpfXJldHVybiBhfSxzZXQ6ZnVuY3Rpb24oZSx0KXt2YXIgbj1iLm1ha2VBcnJheSh0KTtyZXR1cm4gYihlKS5maW5kKCJvcHRpb24iKS5lYWNoKGZ1bmN0aW9uKCl7dGhpcy5zZWxlY3RlZD1iLmluQXJyYXkoYih0aGlzKS52YWwoKSxuKT49MH0pLG4ubGVuZ3RofHwoZS5zZWxlY3RlZEluZGV4PS0xKSxufX19LGF0dHI6ZnVuY3Rpb24oZSxuLHIpe3ZhciBvLGEscyx1PWUubm9kZVR5cGU7aWYoZSYmMyE9PXUmJjghPT11JiYyIT09dSlyZXR1cm4gdHlwZW9mIGUuZ2V0QXR0cmlidXRlPT09aT9iLnByb3AoZSxuLHIpOihhPTEhPT11fHwhYi5pc1hNTERvYyhlKSxhJiYobj1uLnRvTG93ZXJDYXNlKCksbz1iLmF0dHJIb29rc1tuXXx8KEoudGVzdChuKT96OkkpKSxyPT09dD9vJiZhJiYiZ2V0ImluIG8mJm51bGwhPT0ocz1vLmdldChlLG4pKT9zOih0eXBlb2YgZS5nZXRBdHRyaWJ1dGUhPT1pJiYocz1lLmdldEF0dHJpYnV0ZShuKSksbnVsbD09cz90OnMpOm51bGwhPT1yP28mJmEmJiJzZXQiaW4gbyYmKHM9by5zZXQoZSxyLG4pKSE9PXQ/czooZS5zZXRBdHRyaWJ1dGUobixyKyIiKSxyKTooYi5yZW1vdmVBdHRyKGUsbiksdCkpfSxyZW1vdmVBdHRyOmZ1bmN0aW9uKGUsdCl7dmFyIG4scixpPTAsbz10JiZ0Lm1hdGNoKHcpO2lmKG8mJjE9PT1lLm5vZGVUeXBlKXdoaWxlKG49b1tpKytdKXI9Yi5wcm9wRml4W25dfHxuLEoudGVzdChuKT8hUSYmRy50ZXN0KG4pP2VbYi5jYW1lbENhc2UoImRlZmF1bHQtIituKV09ZVtyXT0hMTplW3JdPSExOmIuYXR0cihlLG4sIiIpLGUucmVtb3ZlQXR0cmlidXRlKFE/bjpyKX0sYXR0ckhvb2tzOnt0eXBlOntzZXQ6ZnVuY3Rpb24oZSx0KXtpZighYi5zdXBwb3J0LnJhZGlvVmFsdWUmJiJyYWRpbyI9PT10JiZiLm5vZGVOYW1lKGUsImlucHV0Iikpe3ZhciBuPWUudmFsdWU7cmV0dXJuIGUuc2V0QXR0cmlidXRlKCJ0eXBlIix0KSxuJiYoZS52YWx1ZT1uKSx0fX19fSxwcm9wRml4Ont0YWJpbmRleDoidGFiSW5kZXgiLHJlYWRvbmx5OiJyZWFkT25seSIsImZvciI6Imh0bWxGb3IiLCJjbGFzcyI6ImNsYXNzTmFtZSIsbWF4bGVuZ3RoOiJtYXhMZW5ndGgiLGNlbGxzcGFjaW5nOiJjZWxsU3BhY2luZyIsY2VsbHBhZGRpbmc6ImNlbGxQYWRkaW5nIixyb3dzcGFuOiJyb3dTcGFuIixjb2xzcGFuOiJjb2xTcGFuIix1c2VtYXA6InVzZU1hcCIsZnJhbWVib3JkZXI6ImZyYW1lQm9yZGVyIixjb250ZW50ZWRpdGFibGU6ImNvbnRlbnRFZGl0YWJsZSJ9LHByb3A6ZnVuY3Rpb24oZSxuLHIpe3ZhciBpLG8sYSxzPWUubm9kZVR5cGU7aWYoZSYmMyE9PXMmJjghPT1zJiYyIT09cylyZXR1cm4gYT0xIT09c3x8IWIuaXNYTUxEb2MoZSksYSYmKG49Yi5wcm9wRml4W25dfHxuLG89Yi5wcm9wSG9va3Nbbl0pLHIhPT10P28mJiJzZXQiaW4gbyYmKGk9by5zZXQoZSxyLG4pKSE9PXQ/aTplW25dPXI6byYmImdldCJpbiBvJiZudWxsIT09KGk9by5nZXQoZSxuKSk/aTplW25dfSxwcm9wSG9va3M6e3RhYkluZGV4OntnZXQ6ZnVuY3Rpb24oZSl7dmFyIG49ZS5nZXRBdHRyaWJ1dGVOb2RlKCJ0YWJpbmRleCIpO3JldHVybiBuJiZuLnNwZWNpZmllZD9wYXJzZUludChuLnZhbHVlLDEwKTpWLnRlc3QoZS5ub2RlTmFtZSl8fFkudGVzdChlLm5vZGVOYW1lKSYmZS5ocmVmPzA6dH19fX0pLHo9e2dldDpmdW5jdGlvbihlLG4pe3ZhciByPWIucHJvcChlLG4pLGk9ImJvb2xlYW4iPT10eXBlb2YgciYmZS5nZXRBdHRyaWJ1dGUobiksbz0iYm9vbGVhbiI9PXR5cGVvZiByP0smJlE/bnVsbCE9aTpHLnRlc3Qobik/ZVtiLmNhbWVsQ2FzZSgiZGVmYXVsdC0iK24pXTohIWk6ZS5nZXRBdHRyaWJ1dGVOb2RlKG4pO3JldHVybiBvJiZvLnZhbHVlIT09ITE/bi50b0xvd2VyQ2FzZSgpOnR9LHNldDpmdW5jdGlvbihlLHQsbil7cmV0dXJuIHQ9PT0hMT9iLnJlbW92ZUF0dHIoZSxuKTpLJiZRfHwhRy50ZXN0KG4pP2Uuc2V0QXR0cmlidXRlKCFRJiZiLnByb3BGaXhbbl18fG4sbik6ZVtiLmNhbWVsQ2FzZSgiZGVmYXVsdC0iK24pXT1lW25dPSEwLG59fSxLJiZRfHwoYi5hdHRySG9va3MudmFsdWU9e2dldDpmdW5jdGlvbihlLG4pe3ZhciByPWUuZ2V0QXR0cmlidXRlTm9kZShuKTtyZXR1cm4gYi5ub2RlTmFtZShlLCJpbnB1dCIpP2UuZGVmYXVsdFZhbHVlOnImJnIuc3BlY2lmaWVkP3IudmFsdWU6dH0sc2V0OmZ1bmN0aW9uKGUsbixyKXtyZXR1cm4gYi5ub2RlTmFtZShlLCJpbnB1dCIpPyhlLmRlZmF1bHRWYWx1ZT1uLHQpOkkmJkkuc2V0KGUsbixyKX19KSxRfHwoST1iLnZhbEhvb2tzLmJ1dHRvbj17Z2V0OmZ1bmN0aW9uKGUsbil7dmFyIHI9ZS5nZXRBdHRyaWJ1dGVOb2RlKG4pO3JldHVybiByJiYoImlkIj09PW58fCJuYW1lIj09PW58fCJjb29yZHMiPT09bj8iIiE9PXIudmFsdWU6ci5zcGVjaWZpZWQpP3IudmFsdWU6dH0sc2V0OmZ1bmN0aW9uKGUsbixyKXt2YXIgaT1lLmdldEF0dHJpYnV0ZU5vZGUocik7cmV0dXJuIGl8fGUuc2V0QXR0cmlidXRlTm9kZShpPWUub3duZXJEb2N1bWVudC5jcmVhdGVBdHRyaWJ1dGUocikpLGkudmFsdWU9bis9IiIsInZhbHVlIj09PXJ8fG49PT1lLmdldEF0dHJpYnV0ZShyKT9uOnR9fSxiLmF0dHJIb29rcy5jb250ZW50ZWRpdGFibGU9e2dldDpJLmdldCxzZXQ6ZnVuY3Rpb24oZSx0LG4pe0kuc2V0KGUsIiI9PT10PyExOnQsbil9fSxiLmVhY2goWyJ3aWR0aCIsImhlaWdodCJdLGZ1bmN0aW9uKGUsbil7Yi5hdHRySG9va3Nbbl09Yi5leHRlbmQoYi5hdHRySG9va3Nbbl0se3NldDpmdW5jdGlvbihlLHIpe3JldHVybiIiPT09cj8oZS5zZXRBdHRyaWJ1dGUobiwiYXV0byIpLHIpOnR9fSl9KSksYi5zdXBwb3J0LmhyZWZOb3JtYWxpemVkfHwoYi5lYWNoKFsiaHJlZiIsInNyYyIsIndpZHRoIiwiaGVpZ2h0Il0sZnVuY3Rpb24oZSxuKXtiLmF0dHJIb29rc1tuXT1iLmV4dGVuZChiLmF0dHJIb29rc1tuXSx7Z2V0OmZ1bmN0aW9uKGUpe3ZhciByPWUuZ2V0QXR0cmlidXRlKG4sMik7cmV0dXJuIG51bGw9PXI/dDpyfX0pfSksYi5lYWNoKFsiaHJlZiIsInNyYyJdLGZ1bmN0aW9uKGUsdCl7Yi5wcm9wSG9va3NbdF09e2dldDpmdW5jdGlvbihlKXtyZXR1cm4gZS5nZXRBdHRyaWJ1dGUodCw0KX19fSkpLGIuc3VwcG9ydC5zdHlsZXx8KGIuYXR0ckhvb2tzLnN0eWxlPXtnZXQ6ZnVuY3Rpb24oZSl7cmV0dXJuIGUuc3R5bGUuY3NzVGV4dHx8dH0sc2V0OmZ1bmN0aW9uKGUsdCl7cmV0dXJuIGUuc3R5bGUuY3NzVGV4dD10KyIifX0pLGIuc3VwcG9ydC5vcHRTZWxlY3RlZHx8KGIucHJvcEhvb2tzLnNlbGVjdGVkPWIuZXh0ZW5kKGIucHJvcEhvb2tzLnNlbGVjdGVkLHtnZXQ6ZnVuY3Rpb24oZSl7dmFyIHQ9ZS5wYXJlbnROb2RlO3JldHVybiB0JiYodC5zZWxlY3RlZEluZGV4LHQucGFyZW50Tm9kZSYmdC5wYXJlbnROb2RlLnNlbGVjdGVkSW5kZXgpLG51bGx9fSkpLGIuc3VwcG9ydC5lbmN0eXBlfHwoYi5wcm9wRml4LmVuY3R5cGU9ImVuY29kaW5nIiksYi5zdXBwb3J0LmNoZWNrT258fGIuZWFjaChbInJhZGlvIiwiY2hlY2tib3giXSxmdW5jdGlvbigpe2IudmFsSG9va3NbdGhpc109e2dldDpmdW5jdGlvbihlKXtyZXR1cm4gbnVsbD09PWUuZ2V0QXR0cmlidXRlKCJ2YWx1ZSIpPyJvbiI6ZS52YWx1ZX19fSksYi5lYWNoKFsicmFkaW8iLCJjaGVja2JveCJdLGZ1bmN0aW9uKCl7Yi52YWxIb29rc1t0aGlzXT1iLmV4dGVuZChiLnZhbEhvb2tzW3RoaXNdLHtzZXQ6ZnVuY3Rpb24oZSxuKXtyZXR1cm4gYi5pc0FycmF5KG4pP2UuY2hlY2tlZD1iLmluQXJyYXkoYihlKS52YWwoKSxuKT49MDp0fX0pfSk7dmFyIFo9L14oPzppbnB1dHxzZWxlY3R8dGV4dGFyZWEpJC9pLGV0PS9ea2V5Lyx0dD0vXig/Om1vdXNlfGNvbnRleHRtZW51KXxjbGljay8sbnQ9L14oPzpmb2N1c2luZm9jdXN8Zm9jdXNvdXRibHVyKSQvLHJ0PS9eKFteLl0qKSg/OlwuKC4rKXwpJC87ZnVuY3Rpb24gaXQoKXtyZXR1cm4hMH1mdW5jdGlvbiBvdCgpe3JldHVybiExfWIuZXZlbnQ9e2dsb2JhbDp7fSxhZGQ6ZnVuY3Rpb24oZSxuLHIsbyxhKXt2YXIgcyx1LGwsYyxwLGYsZCxoLGcsbSx5LHY9Yi5fZGF0YShlKTtpZih2KXtyLmhhbmRsZXImJihjPXIscj1jLmhhbmRsZXIsYT1jLnNlbGVjdG9yKSxyLmd1aWR8fChyLmd1aWQ9Yi5ndWlkKyspLCh1PXYuZXZlbnRzKXx8KHU9di5ldmVudHM9e30pLChmPXYuaGFuZGxlKXx8KGY9di5oYW5kbGU9ZnVuY3Rpb24oZSl7cmV0dXJuIHR5cGVvZiBiPT09aXx8ZSYmYi5ldmVudC50cmlnZ2VyZWQ9PT1lLnR5cGU/dDpiLmV2ZW50LmRpc3BhdGNoLmFwcGx5KGYuZWxlbSxhcmd1bWVudHMpfSxmLmVsZW09ZSksbj0obnx8IiIpLm1hdGNoKHcpfHxbIiJdLGw9bi5sZW5ndGg7d2hpbGUobC0tKXM9cnQuZXhlYyhuW2xdKXx8W10sZz15PXNbMV0sbT0oc1syXXx8IiIpLnNwbGl0KCIuIikuc29ydCgpLHA9Yi5ldmVudC5zcGVjaWFsW2ddfHx7fSxnPShhP3AuZGVsZWdhdGVUeXBlOnAuYmluZFR5cGUpfHxnLHA9Yi5ldmVudC5zcGVjaWFsW2ddfHx7fSxkPWIuZXh0ZW5kKHt0eXBlOmcsb3JpZ1R5cGU6eSxkYXRhOm8saGFuZGxlcjpyLGd1aWQ6ci5ndWlkLHNlbGVjdG9yOmEsbmVlZHNDb250ZXh0OmEmJmIuZXhwci5tYXRjaC5uZWVkc0NvbnRleHQudGVzdChhKSxuYW1lc3BhY2U6bS5qb2luKCIuIil9LGMpLChoPXVbZ10pfHwoaD11W2ddPVtdLGguZGVsZWdhdGVDb3VudD0wLHAuc2V0dXAmJnAuc2V0dXAuY2FsbChlLG8sbSxmKSE9PSExfHwoZS5hZGRFdmVudExpc3RlbmVyP2UuYWRkRXZlbnRMaXN0ZW5lcihnLGYsITEpOmUuYXR0YWNoRXZlbnQmJmUuYXR0YWNoRXZlbnQoIm9uIitnLGYpKSkscC5hZGQmJihwLmFkZC5jYWxsKGUsZCksZC5oYW5kbGVyLmd1aWR8fChkLmhhbmRsZXIuZ3VpZD1yLmd1aWQpKSxhP2guc3BsaWNlKGguZGVsZWdhdGVDb3VudCsrLDAsZCk6aC5wdXNoKGQpLGIuZXZlbnQuZ2xvYmFsW2ddPSEwO2U9bnVsbH19LHJlbW92ZTpmdW5jdGlvbihlLHQsbixyLGkpe3ZhciBvLGEscyx1LGwsYyxwLGYsZCxoLGcsbT1iLmhhc0RhdGEoZSkmJmIuX2RhdGEoZSk7aWYobSYmKGM9bS5ldmVudHMpKXt0PSh0fHwiIikubWF0Y2godyl8fFsiIl0sbD10Lmxlbmd0aDt3aGlsZShsLS0paWYocz1ydC5leGVjKHRbbF0pfHxbXSxkPWc9c1sxXSxoPShzWzJdfHwiIikuc3BsaXQoIi4iKS5zb3J0KCksZCl7cD1iLmV2ZW50LnNwZWNpYWxbZF18fHt9LGQ9KHI/cC5kZWxlZ2F0ZVR5cGU6cC5iaW5kVHlwZSl8fGQsZj1jW2RdfHxbXSxzPXNbMl0mJlJlZ0V4cCgiKF58XFwuKSIraC5qb2luKCJcXC4oPzouKlxcLnwpIikrIihcXC58JCkiKSx1PW89Zi5sZW5ndGg7d2hpbGUoby0tKWE9ZltvXSwhaSYmZyE9PWEub3JpZ1R5cGV8fG4mJm4uZ3VpZCE9PWEuZ3VpZHx8cyYmIXMudGVzdChhLm5hbWVzcGFjZSl8fHImJnIhPT1hLnNlbGVjdG9yJiYoIioqIiE9PXJ8fCFhLnNlbGVjdG9yKXx8KGYuc3BsaWNlKG8sMSksYS5zZWxlY3RvciYmZi5kZWxlZ2F0ZUNvdW50LS0scC5yZW1vdmUmJnAucmVtb3ZlLmNhbGwoZSxhKSk7dSYmIWYubGVuZ3RoJiYocC50ZWFyZG93biYmcC50ZWFyZG93bi5jYWxsKGUsaCxtLmhhbmRsZSkhPT0hMXx8Yi5yZW1vdmVFdmVudChlLGQsbS5oYW5kbGUpLGRlbGV0ZSBjW2RdKX1lbHNlIGZvcihkIGluIGMpYi5ldmVudC5yZW1vdmUoZSxkK3RbbF0sbixyLCEwKTtiLmlzRW1wdHlPYmplY3QoYykmJihkZWxldGUgbS5oYW5kbGUsYi5fcmVtb3ZlRGF0YShlLCJldmVudHMiKSl9fSx0cmlnZ2VyOmZ1bmN0aW9uKG4scixpLGEpe3ZhciBzLHUsbCxjLHAsZixkLGg9W2l8fG9dLGc9eS5jYWxsKG4sInR5cGUiKT9uLnR5cGU6bixtPXkuY2FsbChuLCJuYW1lc3BhY2UiKT9uLm5hbWVzcGFjZS5zcGxpdCgiLiIpOltdO2lmKGw9Zj1pPWl8fG8sMyE9PWkubm9kZVR5cGUmJjghPT1pLm5vZGVUeXBlJiYhbnQudGVzdChnK2IuZXZlbnQudHJpZ2dlcmVkKSYmKGcuaW5kZXhPZigiLiIpPj0wJiYobT1nLnNwbGl0KCIuIiksZz1tLnNoaWZ0KCksbS5zb3J0KCkpLHU9MD5nLmluZGV4T2YoIjoiKSYmIm9uIitnLG49bltiLmV4cGFuZG9dP246bmV3IGIuRXZlbnQoZywib2JqZWN0Ij09dHlwZW9mIG4mJm4pLG4uaXNUcmlnZ2VyPSEwLG4ubmFtZXNwYWNlPW0uam9pbigiLiIpLG4ubmFtZXNwYWNlX3JlPW4ubmFtZXNwYWNlP1JlZ0V4cCgiKF58XFwuKSIrbS5qb2luKCJcXC4oPzouKlxcLnwpIikrIihcXC58JCkiKTpudWxsLG4ucmVzdWx0PXQsbi50YXJnZXR8fChuLnRhcmdldD1pKSxyPW51bGw9PXI/W25dOmIubWFrZUFycmF5KHIsW25dKSxwPWIuZXZlbnQuc3BlY2lhbFtnXXx8e30sYXx8IXAudHJpZ2dlcnx8cC50cmlnZ2VyLmFwcGx5KGkscikhPT0hMSkpe2lmKCFhJiYhcC5ub0J1YmJsZSYmIWIuaXNXaW5kb3coaSkpe2ZvcihjPXAuZGVsZWdhdGVUeXBlfHxnLG50LnRlc3QoYytnKXx8KGw9bC5wYXJlbnROb2RlKTtsO2w9bC5wYXJlbnROb2RlKWgucHVzaChsKSxmPWw7Zj09PShpLm93bmVyRG9jdW1lbnR8fG8pJiZoLnB1c2goZi5kZWZhdWx0Vmlld3x8Zi5wYXJlbnRXaW5kb3d8fGUpfWQ9MDt3aGlsZSgobD1oW2QrK10pJiYhbi5pc1Byb3BhZ2F0aW9uU3RvcHBlZCgpKW4udHlwZT1kPjE/YzpwLmJpbmRUeXBlfHxnLHM9KGIuX2RhdGEobCwiZXZlbnRzIil8fHt9KVtuLnR5cGVdJiZiLl9kYXRhKGwsImhhbmRsZSIpLHMmJnMuYXBwbHkobCxyKSxzPXUmJmxbdV0scyYmYi5hY2NlcHREYXRhKGwpJiZzLmFwcGx5JiZzLmFwcGx5KGwscik9PT0hMSYmbi5wcmV2ZW50RGVmYXVsdCgpO2lmKG4udHlwZT1nLCEoYXx8bi5pc0RlZmF1bHRQcmV2ZW50ZWQoKXx8cC5fZGVmYXVsdCYmcC5fZGVmYXVsdC5hcHBseShpLm93bmVyRG9jdW1lbnQscikhPT0hMXx8ImNsaWNrIj09PWcmJmIubm9kZU5hbWUoaSwiYSIpfHwhYi5hY2NlcHREYXRhKGkpfHwhdXx8IWlbZ118fGIuaXNXaW5kb3coaSkpKXtmPWlbdV0sZiYmKGlbdV09bnVsbCksYi5ldmVudC50cmlnZ2VyZWQ9Zzt0cnl7aVtnXSgpfWNhdGNoKHYpe31iLmV2ZW50LnRyaWdnZXJlZD10LGYmJihpW3VdPWYpfXJldHVybiBuLnJlc3VsdH19LGRpc3BhdGNoOmZ1bmN0aW9uKGUpe2U9Yi5ldmVudC5maXgoZSk7dmFyIG4scixpLG8sYSxzPVtdLHU9aC5jYWxsKGFyZ3VtZW50cyksbD0oYi5fZGF0YSh0aGlzLCJldmVudHMiKXx8e30pW2UudHlwZV18fFtdLGM9Yi5ldmVudC5zcGVjaWFsW2UudHlwZV18fHt9O2lmKHVbMF09ZSxlLmRlbGVnYXRlVGFyZ2V0PXRoaXMsIWMucHJlRGlzcGF0Y2h8fGMucHJlRGlzcGF0Y2guY2FsbCh0aGlzLGUpIT09ITEpe3M9Yi5ldmVudC5oYW5kbGVycy5jYWxsKHRoaXMsZSxsKSxuPTA7d2hpbGUoKG89c1tuKytdKSYmIWUuaXNQcm9wYWdhdGlvblN0b3BwZWQoKSl7ZS5jdXJyZW50VGFyZ2V0PW8uZWxlbSxhPTA7d2hpbGUoKGk9by5oYW5kbGVyc1thKytdKSYmIWUuaXNJbW1lZGlhdGVQcm9wYWdhdGlvblN0b3BwZWQoKSkoIWUubmFtZXNwYWNlX3JlfHxlLm5hbWVzcGFjZV9yZS50ZXN0KGkubmFtZXNwYWNlKSkmJihlLmhhbmRsZU9iaj1pLGUuZGF0YT1pLmRhdGEscj0oKGIuZXZlbnQuc3BlY2lhbFtpLm9yaWdUeXBlXXx8e30pLmhhbmRsZXx8aS5oYW5kbGVyKS5hcHBseShvLmVsZW0sdSksciE9PXQmJihlLnJlc3VsdD1yKT09PSExJiYoZS5wcmV2ZW50RGVmYXVsdCgpLGUuc3RvcFByb3BhZ2F0aW9uKCkpKX1yZXR1cm4gYy5wb3N0RGlzcGF0Y2gmJmMucG9zdERpc3BhdGNoLmNhbGwodGhpcyxlKSxlLnJlc3VsdH19LGhhbmRsZXJzOmZ1bmN0aW9uKGUsbil7dmFyIHIsaSxvLGEscz1bXSx1PW4uZGVsZWdhdGVDb3VudCxsPWUudGFyZ2V0O2lmKHUmJmwubm9kZVR5cGUmJighZS5idXR0b258fCJjbGljayIhPT1lLnR5cGUpKWZvcig7bCE9dGhpcztsPWwucGFyZW50Tm9kZXx8dGhpcylpZigxPT09bC5ub2RlVHlwZSYmKGwuZGlzYWJsZWQhPT0hMHx8ImNsaWNrIiE9PWUudHlwZSkpe2ZvcihvPVtdLGE9MDt1PmE7YSsrKWk9blthXSxyPWkuc2VsZWN0b3IrIiAiLG9bcl09PT10JiYob1tyXT1pLm5lZWRzQ29udGV4dD9iKHIsdGhpcykuaW5kZXgobCk+PTA6Yi5maW5kKHIsdGhpcyxudWxsLFtsXSkubGVuZ3RoKSxvW3JdJiZvLnB1c2goaSk7by5sZW5ndGgmJnMucHVzaCh7ZWxlbTpsLGhhbmRsZXJzOm99KX1yZXR1cm4gbi5sZW5ndGg+dSYmcy5wdXNoKHtlbGVtOnRoaXMsaGFuZGxlcnM6bi5zbGljZSh1KX0pLHN9LGZpeDpmdW5jdGlvbihlKXtpZihlW2IuZXhwYW5kb10pcmV0dXJuIGU7dmFyIHQsbixyLGk9ZS50eXBlLGE9ZSxzPXRoaXMuZml4SG9va3NbaV07c3x8KHRoaXMuZml4SG9va3NbaV09cz10dC50ZXN0KGkpP3RoaXMubW91c2VIb29rczpldC50ZXN0KGkpP3RoaXMua2V5SG9va3M6e30pLHI9cy5wcm9wcz90aGlzLnByb3BzLmNvbmNhdChzLnByb3BzKTp0aGlzLnByb3BzLGU9bmV3IGIuRXZlbnQoYSksdD1yLmxlbmd0aDt3aGlsZSh0LS0pbj1yW3RdLGVbbl09YVtuXTtyZXR1cm4gZS50YXJnZXR8fChlLnRhcmdldD1hLnNyY0VsZW1lbnR8fG8pLDM9PT1lLnRhcmdldC5ub2RlVHlwZSYmKGUudGFyZ2V0PWUudGFyZ2V0LnBhcmVudE5vZGUpLGUubWV0YUtleT0hIWUubWV0YUtleSxzLmZpbHRlcj9zLmZpbHRlcihlLGEpOmV9LHByb3BzOiJhbHRLZXkgYnViYmxlcyBjYW5jZWxhYmxlIGN0cmxLZXkgY3VycmVudFRhcmdldCBldmVudFBoYXNlIG1ldGFLZXkgcmVsYXRlZFRhcmdldCBzaGlmdEtleSB0YXJnZXQgdGltZVN0YW1wIHZpZXcgd2hpY2giLnNwbGl0KCIgIiksZml4SG9va3M6e30sa2V5SG9va3M6e3Byb3BzOiJjaGFyIGNoYXJDb2RlIGtleSBrZXlDb2RlIi5zcGxpdCgiICIpLGZpbHRlcjpmdW5jdGlvbihlLHQpe3JldHVybiBudWxsPT1lLndoaWNoJiYoZS53aGljaD1udWxsIT10LmNoYXJDb2RlP3QuY2hhckNvZGU6dC5rZXlDb2RlKSxlfX0sbW91c2VIb29rczp7cHJvcHM6ImJ1dHRvbiBidXR0b25zIGNsaWVudFggY2xpZW50WSBmcm9tRWxlbWVudCBvZmZzZXRYIG9mZnNldFkgcGFnZVggcGFnZVkgc2NyZWVuWCBzY3JlZW5ZIHRvRWxlbWVudCIuc3BsaXQoIiAiKSxmaWx0ZXI6ZnVuY3Rpb24oZSxuKXt2YXIgcixpLGEscz1uLmJ1dHRvbix1PW4uZnJvbUVsZW1lbnQ7cmV0dXJuIG51bGw9PWUucGFnZVgmJm51bGwhPW4uY2xpZW50WCYmKGk9ZS50YXJnZXQub3duZXJEb2N1bWVudHx8byxhPWkuZG9jdW1lbnRFbGVtZW50LHI9aS5ib2R5LGUucGFnZVg9bi5jbGllbnRYKyhhJiZhLnNjcm9sbExlZnR8fHImJnIuc2Nyb2xsTGVmdHx8MCktKGEmJmEuY2xpZW50TGVmdHx8ciYmci5jbGllbnRMZWZ0fHwwKSxlLnBhZ2VZPW4uY2xpZW50WSsoYSYmYS5zY3JvbGxUb3B8fHImJnIuc2Nyb2xsVG9wfHwwKS0oYSYmYS5jbGllbnRUb3B8fHImJnIuY2xpZW50VG9wfHwwKSksIWUucmVsYXRlZFRhcmdldCYmdSYmKGUucmVsYXRlZFRhcmdldD11PT09ZS50YXJnZXQ/bi50b0VsZW1lbnQ6dSksZS53aGljaHx8cz09PXR8fChlLndoaWNoPTEmcz8xOjImcz8zOjQmcz8yOjApLGV9fSxzcGVjaWFsOntsb2FkOntub0J1YmJsZTohMH0sY2xpY2s6e3RyaWdnZXI6ZnVuY3Rpb24oKXtyZXR1cm4gYi5ub2RlTmFtZSh0aGlzLCJpbnB1dCIpJiYiY2hlY2tib3giPT09dGhpcy50eXBlJiZ0aGlzLmNsaWNrPyh0aGlzLmNsaWNrKCksITEpOnR9fSxmb2N1czp7dHJpZ2dlcjpmdW5jdGlvbigpe2lmKHRoaXMhPT1vLmFjdGl2ZUVsZW1lbnQmJnRoaXMuZm9jdXMpdHJ5e3JldHVybiB0aGlzLmZvY3VzKCksITF9Y2F0Y2goZSl7fX0sZGVsZWdhdGVUeXBlOiJmb2N1c2luIn0sYmx1cjp7dHJpZ2dlcjpmdW5jdGlvbigpe3JldHVybiB0aGlzPT09by5hY3RpdmVFbGVtZW50JiZ0aGlzLmJsdXI/KHRoaXMuYmx1cigpLCExKTp0fSxkZWxlZ2F0ZVR5cGU6ImZvY3Vzb3V0In0sYmVmb3JldW5sb2FkOntwb3N0RGlzcGF0Y2g6ZnVuY3Rpb24oZSl7ZS5yZXN1bHQhPT10JiYoZS5vcmlnaW5hbEV2ZW50LnJldHVyblZhbHVlPWUucmVzdWx0KX19fSxzaW11bGF0ZTpmdW5jdGlvbihlLHQsbixyKXt2YXIgaT1iLmV4dGVuZChuZXcgYi5FdmVudCxuLHt0eXBlOmUsaXNTaW11bGF0ZWQ6ITAsb3JpZ2luYWxFdmVudDp7fX0pO3I/Yi5ldmVudC50cmlnZ2VyKGksbnVsbCx0KTpiLmV2ZW50LmRpc3BhdGNoLmNhbGwodCxpKSxpLmlzRGVmYXVsdFByZXZlbnRlZCgpJiZuLnByZXZlbnREZWZhdWx0KCl9fSxiLnJlbW92ZUV2ZW50PW8ucmVtb3ZlRXZlbnRMaXN0ZW5lcj9mdW5jdGlvbihlLHQsbil7ZS5yZW1vdmVFdmVudExpc3RlbmVyJiZlLnJlbW92ZUV2ZW50TGlzdGVuZXIodCxuLCExKX06ZnVuY3Rpb24oZSx0LG4pe3ZhciByPSJvbiIrdDtlLmRldGFjaEV2ZW50JiYodHlwZW9mIGVbcl09PT1pJiYoZVtyXT1udWxsKSxlLmRldGFjaEV2ZW50KHIsbikpfSxiLkV2ZW50PWZ1bmN0aW9uKGUsbil7cmV0dXJuIHRoaXMgaW5zdGFuY2VvZiBiLkV2ZW50PyhlJiZlLnR5cGU/KHRoaXMub3JpZ2luYWxFdmVudD1lLHRoaXMudHlwZT1lLnR5cGUsdGhpcy5pc0RlZmF1bHRQcmV2ZW50ZWQ9ZS5kZWZhdWx0UHJldmVudGVkfHxlLnJldHVyblZhbHVlPT09ITF8fGUuZ2V0UHJldmVudERlZmF1bHQmJmUuZ2V0UHJldmVudERlZmF1bHQoKT9pdDpvdCk6dGhpcy50eXBlPWUsbiYmYi5leHRlbmQodGhpcyxuKSx0aGlzLnRpbWVTdGFtcD1lJiZlLnRpbWVTdGFtcHx8Yi5ub3coKSx0aGlzW2IuZXhwYW5kb109ITAsdCk6bmV3IGIuRXZlbnQoZSxuKX0sYi5FdmVudC5wcm90b3R5cGU9e2lzRGVmYXVsdFByZXZlbnRlZDpvdCxpc1Byb3BhZ2F0aW9uU3RvcHBlZDpvdCxpc0ltbWVkaWF0ZVByb3BhZ2F0aW9uU3RvcHBlZDpvdCxwcmV2ZW50RGVmYXVsdDpmdW5jdGlvbigpe3ZhciBlPXRoaXMub3JpZ2luYWxFdmVudDt0aGlzLmlzRGVmYXVsdFByZXZlbnRlZD1pdCxlJiYoZS5wcmV2ZW50RGVmYXVsdD9lLnByZXZlbnREZWZhdWx0KCk6ZS5yZXR1cm5WYWx1ZT0hMSl9LHN0b3BQcm9wYWdhdGlvbjpmdW5jdGlvbigpe3ZhciBlPXRoaXMub3JpZ2luYWxFdmVudDt0aGlzLmlzUHJvcGFnYXRpb25TdG9wcGVkPWl0LGUmJihlLnN0b3BQcm9wYWdhdGlvbiYmZS5zdG9wUHJvcGFnYXRpb24oKSxlLmNhbmNlbEJ1YmJsZT0hMCl9LHN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbjpmdW5jdGlvbigpe3RoaXMuaXNJbW1lZGlhdGVQcm9wYWdhdGlvblN0b3BwZWQ9aXQsdGhpcy5zdG9wUHJvcGFnYXRpb24oKX19LGIuZWFjaCh7bW91c2VlbnRlcjoibW91c2VvdmVyIixtb3VzZWxlYXZlOiJtb3VzZW91dCJ9LGZ1bmN0aW9uKGUsdCl7Yi5ldmVudC5zcGVjaWFsW2VdPXtkZWxlZ2F0ZVR5cGU6dCxiaW5kVHlwZTp0LGhhbmRsZTpmdW5jdGlvbihlKXt2YXIgbixyPXRoaXMsaT1lLnJlbGF0ZWRUYXJnZXQsbz1lLmhhbmRsZU9iajsKCXJldHVybighaXx8aSE9PXImJiFiLmNvbnRhaW5zKHIsaSkpJiYoZS50eXBlPW8ub3JpZ1R5cGUsbj1vLmhhbmRsZXIuYXBwbHkodGhpcyxhcmd1bWVudHMpLGUudHlwZT10KSxufX19KSxiLnN1cHBvcnQuc3VibWl0QnViYmxlc3x8KGIuZXZlbnQuc3BlY2lhbC5zdWJtaXQ9e3NldHVwOmZ1bmN0aW9uKCl7cmV0dXJuIGIubm9kZU5hbWUodGhpcywiZm9ybSIpPyExOihiLmV2ZW50LmFkZCh0aGlzLCJjbGljay5fc3VibWl0IGtleXByZXNzLl9zdWJtaXQiLGZ1bmN0aW9uKGUpe3ZhciBuPWUudGFyZ2V0LHI9Yi5ub2RlTmFtZShuLCJpbnB1dCIpfHxiLm5vZGVOYW1lKG4sImJ1dHRvbiIpP24uZm9ybTp0O3ImJiFiLl9kYXRhKHIsInN1Ym1pdEJ1YmJsZXMiKSYmKGIuZXZlbnQuYWRkKHIsInN1Ym1pdC5fc3VibWl0IixmdW5jdGlvbihlKXtlLl9zdWJtaXRfYnViYmxlPSEwfSksYi5fZGF0YShyLCJzdWJtaXRCdWJibGVzIiwhMCkpfSksdCl9LHBvc3REaXNwYXRjaDpmdW5jdGlvbihlKXtlLl9zdWJtaXRfYnViYmxlJiYoZGVsZXRlIGUuX3N1Ym1pdF9idWJibGUsdGhpcy5wYXJlbnROb2RlJiYhZS5pc1RyaWdnZXImJmIuZXZlbnQuc2ltdWxhdGUoInN1Ym1pdCIsdGhpcy5wYXJlbnROb2RlLGUsITApKX0sdGVhcmRvd246ZnVuY3Rpb24oKXtyZXR1cm4gYi5ub2RlTmFtZSh0aGlzLCJmb3JtIik/ITE6KGIuZXZlbnQucmVtb3ZlKHRoaXMsIi5fc3VibWl0IiksdCl9fSksYi5zdXBwb3J0LmNoYW5nZUJ1YmJsZXN8fChiLmV2ZW50LnNwZWNpYWwuY2hhbmdlPXtzZXR1cDpmdW5jdGlvbigpe3JldHVybiBaLnRlc3QodGhpcy5ub2RlTmFtZSk/KCgiY2hlY2tib3giPT09dGhpcy50eXBlfHwicmFkaW8iPT09dGhpcy50eXBlKSYmKGIuZXZlbnQuYWRkKHRoaXMsInByb3BlcnR5Y2hhbmdlLl9jaGFuZ2UiLGZ1bmN0aW9uKGUpeyJjaGVja2VkIj09PWUub3JpZ2luYWxFdmVudC5wcm9wZXJ0eU5hbWUmJih0aGlzLl9qdXN0X2NoYW5nZWQ9ITApfSksYi5ldmVudC5hZGQodGhpcywiY2xpY2suX2NoYW5nZSIsZnVuY3Rpb24oZSl7dGhpcy5fanVzdF9jaGFuZ2VkJiYhZS5pc1RyaWdnZXImJih0aGlzLl9qdXN0X2NoYW5nZWQ9ITEpLGIuZXZlbnQuc2ltdWxhdGUoImNoYW5nZSIsdGhpcyxlLCEwKX0pKSwhMSk6KGIuZXZlbnQuYWRkKHRoaXMsImJlZm9yZWFjdGl2YXRlLl9jaGFuZ2UiLGZ1bmN0aW9uKGUpe3ZhciB0PWUudGFyZ2V0O1oudGVzdCh0Lm5vZGVOYW1lKSYmIWIuX2RhdGEodCwiY2hhbmdlQnViYmxlcyIpJiYoYi5ldmVudC5hZGQodCwiY2hhbmdlLl9jaGFuZ2UiLGZ1bmN0aW9uKGUpeyF0aGlzLnBhcmVudE5vZGV8fGUuaXNTaW11bGF0ZWR8fGUuaXNUcmlnZ2VyfHxiLmV2ZW50LnNpbXVsYXRlKCJjaGFuZ2UiLHRoaXMucGFyZW50Tm9kZSxlLCEwKX0pLGIuX2RhdGEodCwiY2hhbmdlQnViYmxlcyIsITApKX0pLHQpfSxoYW5kbGU6ZnVuY3Rpb24oZSl7dmFyIG49ZS50YXJnZXQ7cmV0dXJuIHRoaXMhPT1ufHxlLmlzU2ltdWxhdGVkfHxlLmlzVHJpZ2dlcnx8InJhZGlvIiE9PW4udHlwZSYmImNoZWNrYm94IiE9PW4udHlwZT9lLmhhbmRsZU9iai5oYW5kbGVyLmFwcGx5KHRoaXMsYXJndW1lbnRzKTp0fSx0ZWFyZG93bjpmdW5jdGlvbigpe3JldHVybiBiLmV2ZW50LnJlbW92ZSh0aGlzLCIuX2NoYW5nZSIpLCFaLnRlc3QodGhpcy5ub2RlTmFtZSl9fSksYi5zdXBwb3J0LmZvY3VzaW5CdWJibGVzfHxiLmVhY2goe2ZvY3VzOiJmb2N1c2luIixibHVyOiJmb2N1c291dCJ9LGZ1bmN0aW9uKGUsdCl7dmFyIG49MCxyPWZ1bmN0aW9uKGUpe2IuZXZlbnQuc2ltdWxhdGUodCxlLnRhcmdldCxiLmV2ZW50LmZpeChlKSwhMCl9O2IuZXZlbnQuc3BlY2lhbFt0XT17c2V0dXA6ZnVuY3Rpb24oKXswPT09bisrJiZvLmFkZEV2ZW50TGlzdGVuZXIoZSxyLCEwKX0sdGVhcmRvd246ZnVuY3Rpb24oKXswPT09LS1uJiZvLnJlbW92ZUV2ZW50TGlzdGVuZXIoZSxyLCEwKX19fSksYi5mbi5leHRlbmQoe29uOmZ1bmN0aW9uKGUsbixyLGksbyl7dmFyIGEscztpZigib2JqZWN0Ij09dHlwZW9mIGUpeyJzdHJpbmciIT10eXBlb2YgbiYmKHI9cnx8bixuPXQpO2ZvcihhIGluIGUpdGhpcy5vbihhLG4scixlW2FdLG8pO3JldHVybiB0aGlzfWlmKG51bGw9PXImJm51bGw9PWk/KGk9bixyPW49dCk6bnVsbD09aSYmKCJzdHJpbmciPT10eXBlb2Ygbj8oaT1yLHI9dCk6KGk9cixyPW4sbj10KSksaT09PSExKWk9b3Q7ZWxzZSBpZighaSlyZXR1cm4gdGhpcztyZXR1cm4gMT09PW8mJihzPWksaT1mdW5jdGlvbihlKXtyZXR1cm4gYigpLm9mZihlKSxzLmFwcGx5KHRoaXMsYXJndW1lbnRzKX0saS5ndWlkPXMuZ3VpZHx8KHMuZ3VpZD1iLmd1aWQrKykpLHRoaXMuZWFjaChmdW5jdGlvbigpe2IuZXZlbnQuYWRkKHRoaXMsZSxpLHIsbil9KX0sb25lOmZ1bmN0aW9uKGUsdCxuLHIpe3JldHVybiB0aGlzLm9uKGUsdCxuLHIsMSl9LG9mZjpmdW5jdGlvbihlLG4scil7dmFyIGksbztpZihlJiZlLnByZXZlbnREZWZhdWx0JiZlLmhhbmRsZU9iailyZXR1cm4gaT1lLmhhbmRsZU9iaixiKGUuZGVsZWdhdGVUYXJnZXQpLm9mZihpLm5hbWVzcGFjZT9pLm9yaWdUeXBlKyIuIitpLm5hbWVzcGFjZTppLm9yaWdUeXBlLGkuc2VsZWN0b3IsaS5oYW5kbGVyKSx0aGlzO2lmKCJvYmplY3QiPT10eXBlb2YgZSl7Zm9yKG8gaW4gZSl0aGlzLm9mZihvLG4sZVtvXSk7cmV0dXJuIHRoaXN9cmV0dXJuKG49PT0hMXx8ImZ1bmN0aW9uIj09dHlwZW9mIG4pJiYocj1uLG49dCkscj09PSExJiYocj1vdCksdGhpcy5lYWNoKGZ1bmN0aW9uKCl7Yi5ldmVudC5yZW1vdmUodGhpcyxlLHIsbil9KX0sYmluZDpmdW5jdGlvbihlLHQsbil7cmV0dXJuIHRoaXMub24oZSxudWxsLHQsbil9LHVuYmluZDpmdW5jdGlvbihlLHQpe3JldHVybiB0aGlzLm9mZihlLG51bGwsdCl9LGRlbGVnYXRlOmZ1bmN0aW9uKGUsdCxuLHIpe3JldHVybiB0aGlzLm9uKHQsZSxuLHIpfSx1bmRlbGVnYXRlOmZ1bmN0aW9uKGUsdCxuKXtyZXR1cm4gMT09PWFyZ3VtZW50cy5sZW5ndGg/dGhpcy5vZmYoZSwiKioiKTp0aGlzLm9mZih0LGV8fCIqKiIsbil9LHRyaWdnZXI6ZnVuY3Rpb24oZSx0KXtyZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uKCl7Yi5ldmVudC50cmlnZ2VyKGUsdCx0aGlzKX0pfSx0cmlnZ2VySGFuZGxlcjpmdW5jdGlvbihlLG4pe3ZhciByPXRoaXNbMF07cmV0dXJuIHI/Yi5ldmVudC50cmlnZ2VyKGUsbixyLCEwKTp0fX0pLGZ1bmN0aW9uKGUsdCl7dmFyIG4scixpLG8sYSxzLHUsbCxjLHAsZixkLGgsZyxtLHksdix4PSJzaXp6bGUiKy1uZXcgRGF0ZSx3PWUuZG9jdW1lbnQsVD17fSxOPTAsQz0wLGs9aXQoKSxFPWl0KCksUz1pdCgpLEE9dHlwZW9mIHQsaj0xPDwzMSxEPVtdLEw9RC5wb3AsSD1ELnB1c2gscT1ELnNsaWNlLE09RC5pbmRleE9mfHxmdW5jdGlvbihlKXt2YXIgdD0wLG49dGhpcy5sZW5ndGg7Zm9yKDtuPnQ7dCsrKWlmKHRoaXNbdF09PT1lKXJldHVybiB0O3JldHVybi0xfSxfPSJbXFx4MjBcXHRcXHJcXG5cXGZdIixGPSIoPzpcXFxcLnxbXFx3LV18W15cXHgwMC1cXHhhMF0pKyIsTz1GLnJlcGxhY2UoInciLCJ3IyIpLEI9IihbKl4kfCF+XT89KSIsUD0iXFxbIitfKyIqKCIrRisiKSIrXysiKig/OiIrQitfKyIqKD86KFsnXCJdKSgoPzpcXFxcLnxbXlxcXFxdKSo/KVxcM3woIitPKyIpfCl8KSIrXysiKlxcXSIsUj0iOigiK0YrIikoPzpcXCgoKFsnXCJdKSgoPzpcXFxcLnxbXlxcXFxdKSo/KVxcM3woKD86XFxcXC58W15cXFxcKClbXFxdXXwiK1AucmVwbGFjZSgzLDgpKyIpKil8LiopXFwpfCkiLFc9UmVnRXhwKCJeIitfKyIrfCgoPzpefFteXFxcXF0pKD86XFxcXC4pKikiK18rIiskIiwiZyIpLCQ9UmVnRXhwKCJeIitfKyIqLCIrXysiKiIpLEk9UmVnRXhwKCJeIitfKyIqKFtcXHgyMFxcdFxcclxcblxcZj4rfl0pIitfKyIqIiksej1SZWdFeHAoUiksWD1SZWdFeHAoIl4iK08rIiQiKSxVPXtJRDpSZWdFeHAoIl4jKCIrRisiKSIpLENMQVNTOlJlZ0V4cCgiXlxcLigiK0YrIikiKSxOQU1FOlJlZ0V4cCgiXlxcW25hbWU9WydcIl0/KCIrRisiKVsnXCJdP1xcXSIpLFRBRzpSZWdFeHAoIl4oIitGLnJlcGxhY2UoInciLCJ3KiIpKyIpIiksQVRUUjpSZWdFeHAoIl4iK1ApLFBTRVVETzpSZWdFeHAoIl4iK1IpLENISUxEOlJlZ0V4cCgiXjoob25seXxmaXJzdHxsYXN0fG50aHxudGgtbGFzdCktKGNoaWxkfG9mLXR5cGUpKD86XFwoIitfKyIqKGV2ZW58b2RkfCgoWystXXwpKFxcZCopbnwpIitfKyIqKD86KFsrLV18KSIrXysiKihcXGQrKXwpKSIrXysiKlxcKXwpIiwiaSIpLG5lZWRzQ29udGV4dDpSZWdFeHAoIl4iK18rIipbPit+XXw6KGV2ZW58b2RkfGVxfGd0fGx0fG50aHxmaXJzdHxsYXN0KSg/OlxcKCIrXysiKigoPzotXFxkKT9cXGQqKSIrXysiKlxcKXwpKD89W14tXXwkKSIsImkiKX0sVj0vW1x4MjBcdFxyXG5cZl0qWyt+XS8sWT0vXltee10rXHtccypcW25hdGl2ZSBjb2RlLyxKPS9eKD86IyhbXHctXSspfChcdyspfFwuKFtcdy1dKykpJC8sRz0vXig/OmlucHV0fHNlbGVjdHx0ZXh0YXJlYXxidXR0b24pJC9pLFE9L15oXGQkL2ksSz0vJ3xcXC9nLFo9L1w9W1x4MjBcdFxyXG5cZl0qKFteJyJcXV0qKVtceDIwXHRcclxuXGZdKlxdL2csZXQ9L1xcKFtcZGEtZkEtRl17MSw2fVtceDIwXHRcclxuXGZdP3wuKS9nLHR0PWZ1bmN0aW9uKGUsdCl7dmFyIG49IjB4Iit0LTY1NTM2O3JldHVybiBuIT09bj90OjA+bj9TdHJpbmcuZnJvbUNoYXJDb2RlKG4rNjU1MzYpOlN0cmluZy5mcm9tQ2hhckNvZGUoNTUyOTZ8bj4+MTAsNTYzMjB8MTAyMyZuKX07dHJ5e3EuY2FsbCh3LmRvY3VtZW50RWxlbWVudC5jaGlsZE5vZGVzLDApWzBdLm5vZGVUeXBlfWNhdGNoKG50KXtxPWZ1bmN0aW9uKGUpe3ZhciB0LG49W107d2hpbGUodD10aGlzW2UrK10pbi5wdXNoKHQpO3JldHVybiBufX1mdW5jdGlvbiBydChlKXtyZXR1cm4gWS50ZXN0KGUrIiIpfWZ1bmN0aW9uIGl0KCl7dmFyIGUsdD1bXTtyZXR1cm4gZT1mdW5jdGlvbihuLHIpe3JldHVybiB0LnB1c2gobis9IiAiKT5pLmNhY2hlTGVuZ3RoJiZkZWxldGUgZVt0LnNoaWZ0KCldLGVbbl09cn19ZnVuY3Rpb24gb3QoZSl7cmV0dXJuIGVbeF09ITAsZX1mdW5jdGlvbiBhdChlKXt2YXIgdD1wLmNyZWF0ZUVsZW1lbnQoImRpdiIpO3RyeXtyZXR1cm4gZSh0KX1jYXRjaChuKXtyZXR1cm4hMX1maW5hbGx5e3Q9bnVsbH19ZnVuY3Rpb24gc3QoZSx0LG4scil7dmFyIGksbyxhLHMsdSxsLGYsZyxtLHY7aWYoKHQ/dC5vd25lckRvY3VtZW50fHx0OncpIT09cCYmYyh0KSx0PXR8fHAsbj1ufHxbXSwhZXx8InN0cmluZyIhPXR5cGVvZiBlKXJldHVybiBuO2lmKDEhPT0ocz10Lm5vZGVUeXBlKSYmOSE9PXMpcmV0dXJuW107aWYoIWQmJiFyKXtpZihpPUouZXhlYyhlKSlpZihhPWlbMV0pe2lmKDk9PT1zKXtpZihvPXQuZ2V0RWxlbWVudEJ5SWQoYSksIW98fCFvLnBhcmVudE5vZGUpcmV0dXJuIG47aWYoby5pZD09PWEpcmV0dXJuIG4ucHVzaChvKSxufWVsc2UgaWYodC5vd25lckRvY3VtZW50JiYobz10Lm93bmVyRG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoYSkpJiZ5KHQsbykmJm8uaWQ9PT1hKXJldHVybiBuLnB1c2gobyksbn1lbHNle2lmKGlbMl0pcmV0dXJuIEguYXBwbHkobixxLmNhbGwodC5nZXRFbGVtZW50c0J5VGFnTmFtZShlKSwwKSksbjtpZigoYT1pWzNdKSYmVC5nZXRCeUNsYXNzTmFtZSYmdC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKXJldHVybiBILmFwcGx5KG4scS5jYWxsKHQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShhKSwwKSksbn1pZihULnFzYSYmIWgudGVzdChlKSl7aWYoZj0hMCxnPXgsbT10LHY9OT09PXMmJmUsMT09PXMmJiJvYmplY3QiIT09dC5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpKXtsPWZ0KGUpLChmPXQuZ2V0QXR0cmlidXRlKCJpZCIpKT9nPWYucmVwbGFjZShLLCJcXCQmIik6dC5zZXRBdHRyaWJ1dGUoImlkIixnKSxnPSJbaWQ9JyIrZysiJ10gIix1PWwubGVuZ3RoO3doaWxlKHUtLSlsW3VdPWcrZHQobFt1XSk7bT1WLnRlc3QoZSkmJnQucGFyZW50Tm9kZXx8dCx2PWwuam9pbigiLCIpfWlmKHYpdHJ5e3JldHVybiBILmFwcGx5KG4scS5jYWxsKG0ucXVlcnlTZWxlY3RvckFsbCh2KSwwKSksbn1jYXRjaChiKXt9ZmluYWxseXtmfHx0LnJlbW92ZUF0dHJpYnV0ZSgiaWQiKX19fXJldHVybiB3dChlLnJlcGxhY2UoVywiJDEiKSx0LG4scil9YT1zdC5pc1hNTD1mdW5jdGlvbihlKXt2YXIgdD1lJiYoZS5vd25lckRvY3VtZW50fHxlKS5kb2N1bWVudEVsZW1lbnQ7cmV0dXJuIHQ/IkhUTUwiIT09dC5ub2RlTmFtZTohMX0sYz1zdC5zZXREb2N1bWVudD1mdW5jdGlvbihlKXt2YXIgbj1lP2Uub3duZXJEb2N1bWVudHx8ZTp3O3JldHVybiBuIT09cCYmOT09PW4ubm9kZVR5cGUmJm4uZG9jdW1lbnRFbGVtZW50PyhwPW4sZj1uLmRvY3VtZW50RWxlbWVudCxkPWEobiksVC50YWdOYW1lTm9Db21tZW50cz1hdChmdW5jdGlvbihlKXtyZXR1cm4gZS5hcHBlbmRDaGlsZChuLmNyZWF0ZUNvbW1lbnQoIiIpKSwhZS5nZXRFbGVtZW50c0J5VGFnTmFtZSgiKiIpLmxlbmd0aH0pLFQuYXR0cmlidXRlcz1hdChmdW5jdGlvbihlKXtlLmlubmVySFRNTD0iPHNlbGVjdD48L3NlbGVjdD4iO3ZhciB0PXR5cGVvZiBlLmxhc3RDaGlsZC5nZXRBdHRyaWJ1dGUoIm11bHRpcGxlIik7cmV0dXJuImJvb2xlYW4iIT09dCYmInN0cmluZyIhPT10fSksVC5nZXRCeUNsYXNzTmFtZT1hdChmdW5jdGlvbihlKXtyZXR1cm4gZS5pbm5lckhUTUw9IjxkaXYgY2xhc3M9J2hpZGRlbiBlJz48L2Rpdj48ZGl2IGNsYXNzPSdoaWRkZW4nPjwvZGl2PiIsZS5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lJiZlLmdldEVsZW1lbnRzQnlDbGFzc05hbWUoImUiKS5sZW5ndGg/KGUubGFzdENoaWxkLmNsYXNzTmFtZT0iZSIsMj09PWUuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSgiZSIpLmxlbmd0aCk6ITF9KSxULmdldEJ5TmFtZT1hdChmdW5jdGlvbihlKXtlLmlkPXgrMCxlLmlubmVySFRNTD0iPGEgbmFtZT0nIit4KyInPjwvYT48ZGl2IG5hbWU9JyIreCsiJz48L2Rpdj4iLGYuaW5zZXJ0QmVmb3JlKGUsZi5maXJzdENoaWxkKTt2YXIgdD1uLmdldEVsZW1lbnRzQnlOYW1lJiZuLmdldEVsZW1lbnRzQnlOYW1lKHgpLmxlbmd0aD09PTIrbi5nZXRFbGVtZW50c0J5TmFtZSh4KzApLmxlbmd0aDtyZXR1cm4gVC5nZXRJZE5vdE5hbWU9IW4uZ2V0RWxlbWVudEJ5SWQoeCksZi5yZW1vdmVDaGlsZChlKSx0fSksaS5hdHRySGFuZGxlPWF0KGZ1bmN0aW9uKGUpe3JldHVybiBlLmlubmVySFRNTD0iPGEgaHJlZj0nIyc+PC9hPiIsZS5maXJzdENoaWxkJiZ0eXBlb2YgZS5maXJzdENoaWxkLmdldEF0dHJpYnV0ZSE9PUEmJiIjIj09PWUuZmlyc3RDaGlsZC5nZXRBdHRyaWJ1dGUoImhyZWYiKX0pP3t9OntocmVmOmZ1bmN0aW9uKGUpe3JldHVybiBlLmdldEF0dHJpYnV0ZSgiaHJlZiIsMil9LHR5cGU6ZnVuY3Rpb24oZSl7cmV0dXJuIGUuZ2V0QXR0cmlidXRlKCJ0eXBlIil9fSxULmdldElkTm90TmFtZT8oaS5maW5kLklEPWZ1bmN0aW9uKGUsdCl7aWYodHlwZW9mIHQuZ2V0RWxlbWVudEJ5SWQhPT1BJiYhZCl7dmFyIG49dC5nZXRFbGVtZW50QnlJZChlKTtyZXR1cm4gbiYmbi5wYXJlbnROb2RlP1tuXTpbXX19LGkuZmlsdGVyLklEPWZ1bmN0aW9uKGUpe3ZhciB0PWUucmVwbGFjZShldCx0dCk7cmV0dXJuIGZ1bmN0aW9uKGUpe3JldHVybiBlLmdldEF0dHJpYnV0ZSgiaWQiKT09PXR9fSk6KGkuZmluZC5JRD1mdW5jdGlvbihlLG4pe2lmKHR5cGVvZiBuLmdldEVsZW1lbnRCeUlkIT09QSYmIWQpe3ZhciByPW4uZ2V0RWxlbWVudEJ5SWQoZSk7cmV0dXJuIHI/ci5pZD09PWV8fHR5cGVvZiByLmdldEF0dHJpYnV0ZU5vZGUhPT1BJiZyLmdldEF0dHJpYnV0ZU5vZGUoImlkIikudmFsdWU9PT1lP1tyXTp0OltdfX0saS5maWx0ZXIuSUQ9ZnVuY3Rpb24oZSl7dmFyIHQ9ZS5yZXBsYWNlKGV0LHR0KTtyZXR1cm4gZnVuY3Rpb24oZSl7dmFyIG49dHlwZW9mIGUuZ2V0QXR0cmlidXRlTm9kZSE9PUEmJmUuZ2V0QXR0cmlidXRlTm9kZSgiaWQiKTtyZXR1cm4gbiYmbi52YWx1ZT09PXR9fSksaS5maW5kLlRBRz1ULnRhZ05hbWVOb0NvbW1lbnRzP2Z1bmN0aW9uKGUsbil7cmV0dXJuIHR5cGVvZiBuLmdldEVsZW1lbnRzQnlUYWdOYW1lIT09QT9uLmdldEVsZW1lbnRzQnlUYWdOYW1lKGUpOnR9OmZ1bmN0aW9uKGUsdCl7dmFyIG4scj1bXSxpPTAsbz10LmdldEVsZW1lbnRzQnlUYWdOYW1lKGUpO2lmKCIqIj09PWUpe3doaWxlKG49b1tpKytdKTE9PT1uLm5vZGVUeXBlJiZyLnB1c2gobik7cmV0dXJuIHJ9cmV0dXJuIG99LGkuZmluZC5OQU1FPVQuZ2V0QnlOYW1lJiZmdW5jdGlvbihlLG4pe3JldHVybiB0eXBlb2Ygbi5nZXRFbGVtZW50c0J5TmFtZSE9PUE/bi5nZXRFbGVtZW50c0J5TmFtZShuYW1lKTp0fSxpLmZpbmQuQ0xBU1M9VC5nZXRCeUNsYXNzTmFtZSYmZnVuY3Rpb24oZSxuKXtyZXR1cm4gdHlwZW9mIG4uZ2V0RWxlbWVudHNCeUNsYXNzTmFtZT09PUF8fGQ/dDpuLmdldEVsZW1lbnRzQnlDbGFzc05hbWUoZSl9LGc9W10saD1bIjpmb2N1cyJdLChULnFzYT1ydChuLnF1ZXJ5U2VsZWN0b3JBbGwpKSYmKGF0KGZ1bmN0aW9uKGUpe2UuaW5uZXJIVE1MPSI8c2VsZWN0PjxvcHRpb24gc2VsZWN0ZWQ9Jyc+PC9vcHRpb24+PC9zZWxlY3Q+IixlLnF1ZXJ5U2VsZWN0b3JBbGwoIltzZWxlY3RlZF0iKS5sZW5ndGh8fGgucHVzaCgiXFxbIitfKyIqKD86Y2hlY2tlZHxkaXNhYmxlZHxpc21hcHxtdWx0aXBsZXxyZWFkb25seXxzZWxlY3RlZHx2YWx1ZSkiKSxlLnF1ZXJ5U2VsZWN0b3JBbGwoIjpjaGVja2VkIikubGVuZ3RofHxoLnB1c2goIjpjaGVja2VkIil9KSxhdChmdW5jdGlvbihlKXtlLmlubmVySFRNTD0iPGlucHV0IHR5cGU9J2hpZGRlbicgaT0nJy8+IixlLnF1ZXJ5U2VsZWN0b3JBbGwoIltpXj0nJ10iKS5sZW5ndGgmJmgucHVzaCgiWypeJF09IitfKyIqKD86XCJcInwnJykiKSxlLnF1ZXJ5U2VsZWN0b3JBbGwoIjplbmFibGVkIikubGVuZ3RofHxoLnB1c2goIjplbmFibGVkIiwiOmRpc2FibGVkIiksZS5xdWVyeVNlbGVjdG9yQWxsKCIqLDp4IiksaC5wdXNoKCIsLio6Iil9KSksKFQubWF0Y2hlc1NlbGVjdG9yPXJ0KG09Zi5tYXRjaGVzU2VsZWN0b3J8fGYubW96TWF0Y2hlc1NlbGVjdG9yfHxmLndlYmtpdE1hdGNoZXNTZWxlY3Rvcnx8Zi5vTWF0Y2hlc1NlbGVjdG9yfHxmLm1zTWF0Y2hlc1NlbGVjdG9yKSkmJmF0KGZ1bmN0aW9uKGUpe1QuZGlzY29ubmVjdGVkTWF0Y2g9bS5jYWxsKGUsImRpdiIpLG0uY2FsbChlLCJbcyE9JyddOngiKSxnLnB1c2goIiE9IixSKX0pLGg9UmVnRXhwKGguam9pbigifCIpKSxnPVJlZ0V4cChnLmpvaW4oInwiKSkseT1ydChmLmNvbnRhaW5zKXx8Zi5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbj9mdW5jdGlvbihlLHQpe3ZhciBuPTk9PT1lLm5vZGVUeXBlP2UuZG9jdW1lbnRFbGVtZW50OmUscj10JiZ0LnBhcmVudE5vZGU7cmV0dXJuIGU9PT1yfHwhKCFyfHwxIT09ci5ub2RlVHlwZXx8IShuLmNvbnRhaW5zP24uY29udGFpbnMocik6ZS5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbiYmMTYmZS5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbihyKSkpfTpmdW5jdGlvbihlLHQpe2lmKHQpd2hpbGUodD10LnBhcmVudE5vZGUpaWYodD09PWUpcmV0dXJuITA7cmV0dXJuITF9LHY9Zi5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbj9mdW5jdGlvbihlLHQpe3ZhciByO3JldHVybiBlPT09dD8odT0hMCwwKToocj10LmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uJiZlLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uJiZlLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uKHQpKT8xJnJ8fGUucGFyZW50Tm9kZSYmMTE9PT1lLnBhcmVudE5vZGUubm9kZVR5cGU/ZT09PW58fHkodyxlKT8tMTp0PT09bnx8eSh3LHQpPzE6MDo0JnI/LTE6MTplLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uPy0xOjF9OmZ1bmN0aW9uKGUsdCl7dmFyIHIsaT0wLG89ZS5wYXJlbnROb2RlLGE9dC5wYXJlbnROb2RlLHM9W2VdLGw9W3RdO2lmKGU9PT10KXJldHVybiB1PSEwLDA7aWYoIW98fCFhKXJldHVybiBlPT09bj8tMTp0PT09bj8xOm8/LTE6YT8xOjA7aWYobz09PWEpcmV0dXJuIHV0KGUsdCk7cj1lO3doaWxlKHI9ci5wYXJlbnROb2RlKXMudW5zaGlmdChyKTtyPXQ7d2hpbGUocj1yLnBhcmVudE5vZGUpbC51bnNoaWZ0KHIpO3doaWxlKHNbaV09PT1sW2ldKWkrKztyZXR1cm4gaT91dChzW2ldLGxbaV0pOnNbaV09PT13Py0xOmxbaV09PT13PzE6MH0sdT0hMSxbMCwwXS5zb3J0KHYpLFQuZGV0ZWN0RHVwbGljYXRlcz11LHApOnB9LHN0Lm1hdGNoZXM9ZnVuY3Rpb24oZSx0KXtyZXR1cm4gc3QoZSxudWxsLG51bGwsdCl9LHN0Lm1hdGNoZXNTZWxlY3Rvcj1mdW5jdGlvbihlLHQpe2lmKChlLm93bmVyRG9jdW1lbnR8fGUpIT09cCYmYyhlKSx0PXQucmVwbGFjZShaLCI9JyQxJ10iKSwhKCFULm1hdGNoZXNTZWxlY3Rvcnx8ZHx8ZyYmZy50ZXN0KHQpfHxoLnRlc3QodCkpKXRyeXt2YXIgbj1tLmNhbGwoZSx0KTtpZihufHxULmRpc2Nvbm5lY3RlZE1hdGNofHxlLmRvY3VtZW50JiYxMSE9PWUuZG9jdW1lbnQubm9kZVR5cGUpcmV0dXJuIG59Y2F0Y2gocil7fXJldHVybiBzdCh0LHAsbnVsbCxbZV0pLmxlbmd0aD4wfSxzdC5jb250YWlucz1mdW5jdGlvbihlLHQpe3JldHVybihlLm93bmVyRG9jdW1lbnR8fGUpIT09cCYmYyhlKSx5KGUsdCl9LHN0LmF0dHI9ZnVuY3Rpb24oZSx0KXt2YXIgbjtyZXR1cm4oZS5vd25lckRvY3VtZW50fHxlKSE9PXAmJmMoZSksZHx8KHQ9dC50b0xvd2VyQ2FzZSgpKSwobj1pLmF0dHJIYW5kbGVbdF0pP24oZSk6ZHx8VC5hdHRyaWJ1dGVzP2UuZ2V0QXR0cmlidXRlKHQpOigobj1lLmdldEF0dHJpYnV0ZU5vZGUodCkpfHxlLmdldEF0dHJpYnV0ZSh0KSkmJmVbdF09PT0hMD90Om4mJm4uc3BlY2lmaWVkP24udmFsdWU6bnVsbH0sc3QuZXJyb3I9ZnVuY3Rpb24oZSl7dGhyb3cgRXJyb3IoIlN5bnRheCBlcnJvciwgdW5yZWNvZ25pemVkIGV4cHJlc3Npb246ICIrZSl9LHN0LnVuaXF1ZVNvcnQ9ZnVuY3Rpb24oZSl7dmFyIHQsbj1bXSxyPTEsaT0wO2lmKHU9IVQuZGV0ZWN0RHVwbGljYXRlcyxlLnNvcnQodiksdSl7Zm9yKDt0PWVbcl07cisrKXQ9PT1lW3ItMV0mJihpPW4ucHVzaChyKSk7d2hpbGUoaS0tKWUuc3BsaWNlKG5baV0sMSl9cmV0dXJuIGV9O2Z1bmN0aW9uIHV0KGUsdCl7dmFyIG49dCYmZSxyPW4mJih+dC5zb3VyY2VJbmRleHx8aiktKH5lLnNvdXJjZUluZGV4fHxqKTtpZihyKXJldHVybiByO2lmKG4pd2hpbGUobj1uLm5leHRTaWJsaW5nKWlmKG49PT10KXJldHVybi0xO3JldHVybiBlPzE6LTF9ZnVuY3Rpb24gbHQoZSl7cmV0dXJuIGZ1bmN0aW9uKHQpe3ZhciBuPXQubm9kZU5hbWUudG9Mb3dlckNhc2UoKTtyZXR1cm4iaW5wdXQiPT09biYmdC50eXBlPT09ZX19ZnVuY3Rpb24gY3QoZSl7cmV0dXJuIGZ1bmN0aW9uKHQpe3ZhciBuPXQubm9kZU5hbWUudG9Mb3dlckNhc2UoKTtyZXR1cm4oImlucHV0Ij09PW58fCJidXR0b24iPT09bikmJnQudHlwZT09PWV9fWZ1bmN0aW9uIHB0KGUpe3JldHVybiBvdChmdW5jdGlvbih0KXtyZXR1cm4gdD0rdCxvdChmdW5jdGlvbihuLHIpe3ZhciBpLG89ZShbXSxuLmxlbmd0aCx0KSxhPW8ubGVuZ3RoO3doaWxlKGEtLSluW2k9b1thXV0mJihuW2ldPSEocltpXT1uW2ldKSl9KX0pfW89c3QuZ2V0VGV4dD1mdW5jdGlvbihlKXt2YXIgdCxuPSIiLHI9MCxpPWUubm9kZVR5cGU7aWYoaSl7aWYoMT09PWl8fDk9PT1pfHwxMT09PWkpe2lmKCJzdHJpbmciPT10eXBlb2YgZS50ZXh0Q29udGVudClyZXR1cm4gZS50ZXh0Q29udGVudDtmb3IoZT1lLmZpcnN0Q2hpbGQ7ZTtlPWUubmV4dFNpYmxpbmcpbis9byhlKX1lbHNlIGlmKDM9PT1pfHw0PT09aSlyZXR1cm4gZS5ub2RlVmFsdWV9ZWxzZSBmb3IoO3Q9ZVtyXTtyKyspbis9byh0KTtyZXR1cm4gbn0saT1zdC5zZWxlY3RvcnM9e2NhY2hlTGVuZ3RoOjUwLGNyZWF0ZVBzZXVkbzpvdCxtYXRjaDpVLGZpbmQ6e30scmVsYXRpdmU6eyI+Ijp7ZGlyOiJwYXJlbnROb2RlIixmaXJzdDohMH0sIiAiOntkaXI6InBhcmVudE5vZGUifSwiKyI6e2RpcjoicHJldmlvdXNTaWJsaW5nIixmaXJzdDohMH0sIn4iOntkaXI6InByZXZpb3VzU2libGluZyJ9fSxwcmVGaWx0ZXI6e0FUVFI6ZnVuY3Rpb24oZSl7cmV0dXJuIGVbMV09ZVsxXS5yZXBsYWNlKGV0LHR0KSxlWzNdPShlWzRdfHxlWzVdfHwiIikucmVwbGFjZShldCx0dCksIn49Ij09PWVbMl0mJihlWzNdPSIgIitlWzNdKyIgIiksZS5zbGljZSgwLDQpfSxDSElMRDpmdW5jdGlvbihlKXtyZXR1cm4gZVsxXT1lWzFdLnRvTG93ZXJDYXNlKCksIm50aCI9PT1lWzFdLnNsaWNlKDAsMyk/KGVbM118fHN0LmVycm9yKGVbMF0pLGVbNF09KyhlWzRdP2VbNV0rKGVbNl18fDEpOjIqKCJldmVuIj09PWVbM118fCJvZGQiPT09ZVszXSkpLGVbNV09KyhlWzddK2VbOF18fCJvZGQiPT09ZVszXSkpOmVbM10mJnN0LmVycm9yKGVbMF0pLGV9LFBTRVVETzpmdW5jdGlvbihlKXt2YXIgdCxuPSFlWzVdJiZlWzJdO3JldHVybiBVLkNISUxELnRlc3QoZVswXSk/bnVsbDooZVs0XT9lWzJdPWVbNF06biYmei50ZXN0KG4pJiYodD1mdChuLCEwKSkmJih0PW4uaW5kZXhPZigiKSIsbi5sZW5ndGgtdCktbi5sZW5ndGgpJiYoZVswXT1lWzBdLnNsaWNlKDAsdCksZVsyXT1uLnNsaWNlKDAsdCkpLGUuc2xpY2UoMCwzKSl9fSxmaWx0ZXI6e1RBRzpmdW5jdGlvbihlKXtyZXR1cm4iKiI9PT1lP2Z1bmN0aW9uKCl7cmV0dXJuITB9OihlPWUucmVwbGFjZShldCx0dCkudG9Mb3dlckNhc2UoKSxmdW5jdGlvbih0KXtyZXR1cm4gdC5ub2RlTmFtZSYmdC5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpPT09ZX0pfSxDTEFTUzpmdW5jdGlvbihlKXt2YXIgdD1rW2UrIiAiXTtyZXR1cm4gdHx8KHQ9UmVnRXhwKCIoXnwiK18rIikiK2UrIigiK18rInwkKSIpKSYmayhlLGZ1bmN0aW9uKGUpe3JldHVybiB0LnRlc3QoZS5jbGFzc05hbWV8fHR5cGVvZiBlLmdldEF0dHJpYnV0ZSE9PUEmJmUuZ2V0QXR0cmlidXRlKCJjbGFzcyIpfHwiIil9KX0sQVRUUjpmdW5jdGlvbihlLHQsbil7cmV0dXJuIGZ1bmN0aW9uKHIpe3ZhciBpPXN0LmF0dHIocixlKTtyZXR1cm4gbnVsbD09aT8iIT0iPT09dDp0PyhpKz0iIiwiPSI9PT10P2k9PT1uOiIhPSI9PT10P2khPT1uOiJePSI9PT10P24mJjA9PT1pLmluZGV4T2Yobik6Iio9Ij09PXQ/biYmaS5pbmRleE9mKG4pPi0xOiIkPSI9PT10P24mJmkuc2xpY2UoLW4ubGVuZ3RoKT09PW46In49Ij09PXQ/KCIgIitpKyIgIikuaW5kZXhPZihuKT4tMToifD0iPT09dD9pPT09bnx8aS5zbGljZSgwLG4ubGVuZ3RoKzEpPT09bisiLSI6ITEpOiEwfX0sQ0hJTEQ6ZnVuY3Rpb24oZSx0LG4scixpKXt2YXIgbz0ibnRoIiE9PWUuc2xpY2UoMCwzKSxhPSJsYXN0IiE9PWUuc2xpY2UoLTQpLHM9Im9mLXR5cGUiPT09dDtyZXR1cm4gMT09PXImJjA9PT1pP2Z1bmN0aW9uKGUpe3JldHVybiEhZS5wYXJlbnROb2RlfTpmdW5jdGlvbih0LG4sdSl7dmFyIGwsYyxwLGYsZCxoLGc9byE9PWE/Im5leHRTaWJsaW5nIjoicHJldmlvdXNTaWJsaW5nIixtPXQucGFyZW50Tm9kZSx5PXMmJnQubm9kZU5hbWUudG9Mb3dlckNhc2UoKSx2PSF1JiYhcztpZihtKXtpZihvKXt3aGlsZShnKXtwPXQ7d2hpbGUocD1wW2ddKWlmKHM/cC5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpPT09eToxPT09cC5ub2RlVHlwZSlyZXR1cm4hMTtoPWc9Im9ubHkiPT09ZSYmIWgmJiJuZXh0U2libGluZyJ9cmV0dXJuITB9aWYoaD1bYT9tLmZpcnN0Q2hpbGQ6bS5sYXN0Q2hpbGRdLGEmJnYpe2M9bVt4XXx8KG1beF09e30pLGw9Y1tlXXx8W10sZD1sWzBdPT09TiYmbFsxXSxmPWxbMF09PT1OJiZsWzJdLHA9ZCYmbS5jaGlsZE5vZGVzW2RdO3doaWxlKHA9KytkJiZwJiZwW2ddfHwoZj1kPTApfHxoLnBvcCgpKWlmKDE9PT1wLm5vZGVUeXBlJiYrK2YmJnA9PT10KXtjW2VdPVtOLGQsZl07YnJlYWt9fWVsc2UgaWYodiYmKGw9KHRbeF18fCh0W3hdPXt9KSlbZV0pJiZsWzBdPT09TilmPWxbMV07ZWxzZSB3aGlsZShwPSsrZCYmcCYmcFtnXXx8KGY9ZD0wKXx8aC5wb3AoKSlpZigocz9wLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCk9PT15OjE9PT1wLm5vZGVUeXBlKSYmKytmJiYodiYmKChwW3hdfHwocFt4XT17fSkpW2VdPVtOLGZdKSxwPT09dCkpYnJlYWs7cmV0dXJuIGYtPWksZj09PXJ8fDA9PT1mJXImJmYvcj49MH19fSxQU0VVRE86ZnVuY3Rpb24oZSx0KXt2YXIgbixyPWkucHNldWRvc1tlXXx8aS5zZXRGaWx0ZXJzW2UudG9Mb3dlckNhc2UoKV18fHN0LmVycm9yKCJ1bnN1cHBvcnRlZCBwc2V1ZG86ICIrZSk7cmV0dXJuIHJbeF0/cih0KTpyLmxlbmd0aD4xPyhuPVtlLGUsIiIsdF0saS5zZXRGaWx0ZXJzLmhhc093blByb3BlcnR5KGUudG9Mb3dlckNhc2UoKSk/b3QoZnVuY3Rpb24oZSxuKXt2YXIgaSxvPXIoZSx0KSxhPW8ubGVuZ3RoO3doaWxlKGEtLSlpPU0uY2FsbChlLG9bYV0pLGVbaV09IShuW2ldPW9bYV0pfSk6ZnVuY3Rpb24oZSl7cmV0dXJuIHIoZSwwLG4pfSk6cn19LHBzZXVkb3M6e25vdDpvdChmdW5jdGlvbihlKXt2YXIgdD1bXSxuPVtdLHI9cyhlLnJlcGxhY2UoVywiJDEiKSk7cmV0dXJuIHJbeF0/b3QoZnVuY3Rpb24oZSx0LG4saSl7dmFyIG8sYT1yKGUsbnVsbCxpLFtdKSxzPWUubGVuZ3RoO3doaWxlKHMtLSkobz1hW3NdKSYmKGVbc109ISh0W3NdPW8pKX0pOmZ1bmN0aW9uKGUsaSxvKXtyZXR1cm4gdFswXT1lLHIodCxudWxsLG8sbiksIW4ucG9wKCl9fSksaGFzOm90KGZ1bmN0aW9uKGUpe3JldHVybiBmdW5jdGlvbih0KXtyZXR1cm4gc3QoZSx0KS5sZW5ndGg+MH19KSxjb250YWluczpvdChmdW5jdGlvbihlKXtyZXR1cm4gZnVuY3Rpb24odCl7cmV0dXJuKHQudGV4dENvbnRlbnR8fHQuaW5uZXJUZXh0fHxvKHQpKS5pbmRleE9mKGUpPi0xfX0pLGxhbmc6b3QoZnVuY3Rpb24oZSl7cmV0dXJuIFgudGVzdChlfHwiIil8fHN0LmVycm9yKCJ1bnN1cHBvcnRlZCBsYW5nOiAiK2UpLGU9ZS5yZXBsYWNlKGV0LHR0KS50b0xvd2VyQ2FzZSgpLGZ1bmN0aW9uKHQpe3ZhciBuO2RvIGlmKG49ZD90LmdldEF0dHJpYnV0ZSgieG1sOmxhbmciKXx8dC5nZXRBdHRyaWJ1dGUoImxhbmciKTp0LmxhbmcpcmV0dXJuIG49bi50b0xvd2VyQ2FzZSgpLG49PT1lfHwwPT09bi5pbmRleE9mKGUrIi0iKTt3aGlsZSgodD10LnBhcmVudE5vZGUpJiYxPT09dC5ub2RlVHlwZSk7cmV0dXJuITF9fSksdGFyZ2V0OmZ1bmN0aW9uKHQpe3ZhciBuPWUubG9jYXRpb24mJmUubG9jYXRpb24uaGFzaDtyZXR1cm4gbiYmbi5zbGljZSgxKT09PXQuaWR9LHJvb3Q6ZnVuY3Rpb24oZSl7cmV0dXJuIGU9PT1mfSxmb2N1czpmdW5jdGlvbihlKXtyZXR1cm4gZT09PXAuYWN0aXZlRWxlbWVudCYmKCFwLmhhc0ZvY3VzfHxwLmhhc0ZvY3VzKCkpJiYhIShlLnR5cGV8fGUuaHJlZnx8fmUudGFiSW5kZXgpfSxlbmFibGVkOmZ1bmN0aW9uKGUpe3JldHVybiBlLmRpc2FibGVkPT09ITF9LGRpc2FibGVkOmZ1bmN0aW9uKGUpe3JldHVybiBlLmRpc2FibGVkPT09ITB9LGNoZWNrZWQ6ZnVuY3Rpb24oZSl7dmFyIHQ9ZS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpO3JldHVybiJpbnB1dCI9PT10JiYhIWUuY2hlY2tlZHx8Im9wdGlvbiI9PT10JiYhIWUuc2VsZWN0ZWR9LHNlbGVjdGVkOmZ1bmN0aW9uKGUpe3JldHVybiBlLnBhcmVudE5vZGUmJmUucGFyZW50Tm9kZS5zZWxlY3RlZEluZGV4LGUuc2VsZWN0ZWQ9PT0hMH0sZW1wdHk6ZnVuY3Rpb24oZSl7Zm9yKGU9ZS5maXJzdENoaWxkO2U7ZT1lLm5leHRTaWJsaW5nKWlmKGUubm9kZU5hbWU+IkAifHwzPT09ZS5ub2RlVHlwZXx8ND09PWUubm9kZVR5cGUpcmV0dXJuITE7cmV0dXJuITB9LHBhcmVudDpmdW5jdGlvbihlKXtyZXR1cm4haS5wc2V1ZG9zLmVtcHR5KGUpfSxoZWFkZXI6ZnVuY3Rpb24oZSl7cmV0dXJuIFEudGVzdChlLm5vZGVOYW1lKX0saW5wdXQ6ZnVuY3Rpb24oZSl7cmV0dXJuIEcudGVzdChlLm5vZGVOYW1lKX0sYnV0dG9uOmZ1bmN0aW9uKGUpe3ZhciB0PWUubm9kZU5hbWUudG9Mb3dlckNhc2UoKTtyZXR1cm4iaW5wdXQiPT09dCYmImJ1dHRvbiI9PT1lLnR5cGV8fCJidXR0b24iPT09dH0sdGV4dDpmdW5jdGlvbihlKXt2YXIgdDtyZXR1cm4iaW5wdXQiPT09ZS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpJiYidGV4dCI9PT1lLnR5cGUmJihudWxsPT0odD1lLmdldEF0dHJpYnV0ZSgidHlwZSIpKXx8dC50b0xvd2VyQ2FzZSgpPT09ZS50eXBlKX0sZmlyc3Q6cHQoZnVuY3Rpb24oKXtyZXR1cm5bMF19KSxsYXN0OnB0KGZ1bmN0aW9uKGUsdCl7cmV0dXJuW3QtMV19KSxlcTpwdChmdW5jdGlvbihlLHQsbil7cmV0dXJuWzA+bj9uK3Q6bl19KSxldmVuOnB0KGZ1bmN0aW9uKGUsdCl7dmFyIG49MDtmb3IoO3Q+bjtuKz0yKWUucHVzaChuKTtyZXR1cm4gZX0pLG9kZDpwdChmdW5jdGlvbihlLHQpe3ZhciBuPTE7Zm9yKDt0Pm47bis9MillLnB1c2gobik7cmV0dXJuIGV9KSxsdDpwdChmdW5jdGlvbihlLHQsbil7dmFyIHI9MD5uP24rdDpuO2Zvcig7LS1yPj0wOyllLnB1c2gocik7cmV0dXJuIGV9KSxndDpwdChmdW5jdGlvbihlLHQsbil7dmFyIHI9MD5uP24rdDpuO2Zvcig7dD4rK3I7KWUucHVzaChyKTtyZXR1cm4gZX0pfX07Zm9yKG4gaW57cmFkaW86ITAsY2hlY2tib3g6ITAsZmlsZTohMCxwYXNzd29yZDohMCxpbWFnZTohMH0paS5wc2V1ZG9zW25dPWx0KG4pO2ZvcihuIGlue3N1Ym1pdDohMCxyZXNldDohMH0paS5wc2V1ZG9zW25dPWN0KG4pO2Z1bmN0aW9uIGZ0KGUsdCl7dmFyIG4scixvLGEscyx1LGwsYz1FW2UrIiAiXTtpZihjKXJldHVybiB0PzA6Yy5zbGljZSgwKTtzPWUsdT1bXSxsPWkucHJlRmlsdGVyO3doaWxlKHMpeyghbnx8KHI9JC5leGVjKHMpKSkmJihyJiYocz1zLnNsaWNlKHJbMF0ubGVuZ3RoKXx8cyksdS5wdXNoKG89W10pKSxuPSExLChyPUkuZXhlYyhzKSkmJihuPXIuc2hpZnQoKSxvLnB1c2goe3ZhbHVlOm4sdHlwZTpyWzBdLnJlcGxhY2UoVywiICIpfSkscz1zLnNsaWNlKG4ubGVuZ3RoKSk7Zm9yKGEgaW4gaS5maWx0ZXIpIShyPVVbYV0uZXhlYyhzKSl8fGxbYV0mJiEocj1sW2FdKHIpKXx8KG49ci5zaGlmdCgpLG8ucHVzaCh7dmFsdWU6bix0eXBlOmEsbWF0Y2hlczpyfSkscz1zLnNsaWNlKG4ubGVuZ3RoKSk7aWYoIW4pYnJlYWt9cmV0dXJuIHQ/cy5sZW5ndGg6cz9zdC5lcnJvcihlKTpFKGUsdSkuc2xpY2UoMCl9ZnVuY3Rpb24gZHQoZSl7dmFyIHQ9MCxuPWUubGVuZ3RoLHI9IiI7Zm9yKDtuPnQ7dCsrKXIrPWVbdF0udmFsdWU7cmV0dXJuIHJ9ZnVuY3Rpb24gaHQoZSx0LG4pe3ZhciBpPXQuZGlyLG89biYmInBhcmVudE5vZGUiPT09aSxhPUMrKztyZXR1cm4gdC5maXJzdD9mdW5jdGlvbih0LG4scil7d2hpbGUodD10W2ldKWlmKDE9PT10Lm5vZGVUeXBlfHxvKXJldHVybiBlKHQsbixyKX06ZnVuY3Rpb24odCxuLHMpe3ZhciB1LGwsYyxwPU4rIiAiK2E7aWYocyl7d2hpbGUodD10W2ldKWlmKCgxPT09dC5ub2RlVHlwZXx8bykmJmUodCxuLHMpKXJldHVybiEwfWVsc2Ugd2hpbGUodD10W2ldKWlmKDE9PT10Lm5vZGVUeXBlfHxvKWlmKGM9dFt4XXx8KHRbeF09e30pLChsPWNbaV0pJiZsWzBdPT09cCl7aWYoKHU9bFsxXSk9PT0hMHx8dT09PXIpcmV0dXJuIHU9PT0hMH1lbHNlIGlmKGw9Y1tpXT1bcF0sbFsxXT1lKHQsbixzKXx8cixsWzFdPT09ITApcmV0dXJuITB9fWZ1bmN0aW9uIGd0KGUpe3JldHVybiBlLmxlbmd0aD4xP2Z1bmN0aW9uKHQsbixyKXt2YXIgaT1lLmxlbmd0aDt3aGlsZShpLS0paWYoIWVbaV0odCxuLHIpKXJldHVybiExO3JldHVybiEwfTplWzBdfWZ1bmN0aW9uIG10KGUsdCxuLHIsaSl7dmFyIG8sYT1bXSxzPTAsdT1lLmxlbmd0aCxsPW51bGwhPXQ7Zm9yKDt1PnM7cysrKShvPWVbc10pJiYoIW58fG4obyxyLGkpKSYmKGEucHVzaChvKSxsJiZ0LnB1c2gocykpO3JldHVybiBhfWZ1bmN0aW9uIHl0KGUsdCxuLHIsaSxvKXtyZXR1cm4gciYmIXJbeF0mJihyPXl0KHIpKSxpJiYhaVt4XSYmKGk9eXQoaSxvKSksb3QoZnVuY3Rpb24obyxhLHMsdSl7dmFyIGwsYyxwLGY9W10sZD1bXSxoPWEubGVuZ3RoLGc9b3x8eHQodHx8IioiLHMubm9kZVR5cGU/W3NdOnMsW10pLG09IWV8fCFvJiZ0P2c6bXQoZyxmLGUscyx1KSx5PW4/aXx8KG8/ZTpofHxyKT9bXTphOm07aWYobiYmbihtLHkscyx1KSxyKXtsPW10KHksZCkscihsLFtdLHMsdSksYz1sLmxlbmd0aDt3aGlsZShjLS0pKHA9bFtjXSkmJih5W2RbY11dPSEobVtkW2NdXT1wKSl9aWYobyl7aWYoaXx8ZSl7aWYoaSl7bD1bXSxjPXkubGVuZ3RoO3doaWxlKGMtLSkocD15W2NdKSYmbC5wdXNoKG1bY109cCk7aShudWxsLHk9W10sbCx1KX1jPXkubGVuZ3RoO3doaWxlKGMtLSkocD15W2NdKSYmKGw9aT9NLmNhbGwobyxwKTpmW2NdKT4tMSYmKG9bbF09IShhW2xdPXApKX19ZWxzZSB5PW10KHk9PT1hP3kuc3BsaWNlKGgseS5sZW5ndGgpOnkpLGk/aShudWxsLGEseSx1KTpILmFwcGx5KGEseSl9KX1mdW5jdGlvbiB2dChlKXt2YXIgdCxuLHIsbz1lLmxlbmd0aCxhPWkucmVsYXRpdmVbZVswXS50eXBlXSxzPWF8fGkucmVsYXRpdmVbIiAiXSx1PWE/MTowLGM9aHQoZnVuY3Rpb24oZSl7cmV0dXJuIGU9PT10fSxzLCEwKSxwPWh0KGZ1bmN0aW9uKGUpe3JldHVybiBNLmNhbGwodCxlKT4tMX0scywhMCksZj1bZnVuY3Rpb24oZSxuLHIpe3JldHVybiFhJiYocnx8biE9PWwpfHwoKHQ9bikubm9kZVR5cGU/YyhlLG4scik6cChlLG4scikpfV07Zm9yKDtvPnU7dSsrKWlmKG49aS5yZWxhdGl2ZVtlW3VdLnR5cGVdKWY9W2h0KGd0KGYpLG4pXTtlbHNle2lmKG49aS5maWx0ZXJbZVt1XS50eXBlXS5hcHBseShudWxsLGVbdV0ubWF0Y2hlcyksblt4XSl7Zm9yKHI9Kyt1O28+cjtyKyspaWYoaS5yZWxhdGl2ZVtlW3JdLnR5cGVdKWJyZWFrO3JldHVybiB5dCh1PjEmJmd0KGYpLHU+MSYmZHQoZS5zbGljZSgwLHUtMSkpLnJlcGxhY2UoVywiJDEiKSxuLHI+dSYmdnQoZS5zbGljZSh1LHIpKSxvPnImJnZ0KGU9ZS5zbGljZShyKSksbz5yJiZkdChlKSl9Zi5wdXNoKG4pfXJldHVybiBndChmKX1mdW5jdGlvbiBidChlLHQpe3ZhciBuPTAsbz10Lmxlbmd0aD4wLGE9ZS5sZW5ndGg+MCxzPWZ1bmN0aW9uKHMsdSxjLGYsZCl7dmFyIGgsZyxtLHk9W10sdj0wLGI9IjAiLHg9cyYmW10sdz1udWxsIT1kLFQ9bCxDPXN8fGEmJmkuZmluZC5UQUcoIioiLGQmJnUucGFyZW50Tm9kZXx8dSksaz1OKz1udWxsPT1UPzE6TWF0aC5yYW5kb20oKXx8LjE7Zm9yKHcmJihsPXUhPT1wJiZ1LHI9bik7bnVsbCE9KGg9Q1tiXSk7YisrKXtpZihhJiZoKXtnPTA7d2hpbGUobT1lW2crK10paWYobShoLHUsYykpe2YucHVzaChoKTticmVha313JiYoTj1rLHI9KytuKX1vJiYoKGg9IW0mJmgpJiZ2LS0scyYmeC5wdXNoKGgpKX1pZih2Kz1iLG8mJmIhPT12KXtnPTA7d2hpbGUobT10W2crK10pbSh4LHksdSxjKTtpZihzKXtpZih2PjApd2hpbGUoYi0tKXhbYl18fHlbYl18fCh5W2JdPUwuY2FsbChmKSk7eT1tdCh5KX1ILmFwcGx5KGYseSksdyYmIXMmJnkubGVuZ3RoPjAmJnYrdC5sZW5ndGg+MSYmc3QudW5pcXVlU29ydChmKX1yZXR1cm4gdyYmKE49ayxsPVQpLHh9O3JldHVybiBvP290KHMpOnN9cz1zdC5jb21waWxlPWZ1bmN0aW9uKGUsdCl7dmFyIG4scj1bXSxpPVtdLG89U1tlKyIgIl07aWYoIW8pe3R8fCh0PWZ0KGUpKSxuPXQubGVuZ3RoO3doaWxlKG4tLSlvPXZ0KHRbbl0pLG9beF0/ci5wdXNoKG8pOmkucHVzaChvKTtvPVMoZSxidChpLHIpKX1yZXR1cm4gb307ZnVuY3Rpb24geHQoZSx0LG4pe3ZhciByPTAsaT10Lmxlbmd0aDtmb3IoO2k+cjtyKyspc3QoZSx0W3JdLG4pO3JldHVybiBufWZ1bmN0aW9uIHd0KGUsdCxuLHIpe3ZhciBvLGEsdSxsLGMscD1mdChlKTtpZighciYmMT09PXAubGVuZ3RoKXtpZihhPXBbMF09cFswXS5zbGljZSgwKSxhLmxlbmd0aD4yJiYiSUQiPT09KHU9YVswXSkudHlwZSYmOT09PXQubm9kZVR5cGUmJiFkJiZpLnJlbGF0aXZlW2FbMV0udHlwZV0pe2lmKHQ9aS5maW5kLklEKHUubWF0Y2hlc1swXS5yZXBsYWNlKGV0LHR0KSx0KVswXSwhdClyZXR1cm4gbjtlPWUuc2xpY2UoYS5zaGlmdCgpLnZhbHVlLmxlbmd0aCl9bz1VLm5lZWRzQ29udGV4dC50ZXN0KGUpPzA6YS5sZW5ndGg7d2hpbGUoby0tKXtpZih1PWFbb10saS5yZWxhdGl2ZVtsPXUudHlwZV0pYnJlYWs7aWYoKGM9aS5maW5kW2xdKSYmKHI9Yyh1Lm1hdGNoZXNbMF0ucmVwbGFjZShldCx0dCksVi50ZXN0KGFbMF0udHlwZSkmJnQucGFyZW50Tm9kZXx8dCkpKXtpZihhLnNwbGljZShvLDEpLGU9ci5sZW5ndGgmJmR0KGEpLCFlKXJldHVybiBILmFwcGx5KG4scS5jYWxsKHIsMCkpLG47YnJlYWt9fX1yZXR1cm4gcyhlLHApKHIsdCxkLG4sVi50ZXN0KGUpKSxufWkucHNldWRvcy5udGg9aS5wc2V1ZG9zLmVxO2Z1bmN0aW9uIFR0KCl7fWkuZmlsdGVycz1UdC5wcm90b3R5cGU9aS5wc2V1ZG9zLGkuc2V0RmlsdGVycz1uZXcgVHQsYygpLHN0LmF0dHI9Yi5hdHRyLGIuZmluZD1zdCxiLmV4cHI9c3Quc2VsZWN0b3JzLGIuZXhwclsiOiJdPWIuZXhwci5wc2V1ZG9zLGIudW5pcXVlPXN0LnVuaXF1ZVNvcnQsYi50ZXh0PXN0LmdldFRleHQsYi5pc1hNTERvYz1zdC5pc1hNTCxiLmNvbnRhaW5zPXN0LmNvbnRhaW5zfShlKTt2YXIgYXQ9L1VudGlsJC8sc3Q9L14oPzpwYXJlbnRzfHByZXYoPzpVbnRpbHxBbGwpKS8sdXQ9L14uW146I1xbXC4sXSokLyxsdD1iLmV4cHIubWF0Y2gubmVlZHNDb250ZXh0LGN0PXtjaGlsZHJlbjohMCxjb250ZW50czohMCxuZXh0OiEwLHByZXY6ITB9O2IuZm4uZXh0ZW5kKHtmaW5kOmZ1bmN0aW9uKGUpe3ZhciB0LG4scixpPXRoaXMubGVuZ3RoO2lmKCJzdHJpbmciIT10eXBlb2YgZSlyZXR1cm4gcj10aGlzLHRoaXMucHVzaFN0YWNrKGIoZSkuZmlsdGVyKGZ1bmN0aW9uKCl7Zm9yKHQ9MDtpPnQ7dCsrKWlmKGIuY29udGFpbnMoclt0XSx0aGlzKSlyZXR1cm4hMH0pKTtmb3Iobj1bXSx0PTA7aT50O3QrKyliLmZpbmQoZSx0aGlzW3RdLG4pO3JldHVybiBuPXRoaXMucHVzaFN0YWNrKGk+MT9iLnVuaXF1ZShuKTpuKSxuLnNlbGVjdG9yPSh0aGlzLnNlbGVjdG9yP3RoaXMuc2VsZWN0b3IrIiAiOiIiKStlLG59LGhhczpmdW5jdGlvbihlKXt2YXIgdCxuPWIoZSx0aGlzKSxyPW4ubGVuZ3RoO3JldHVybiB0aGlzLmZpbHRlcihmdW5jdGlvbigpe2Zvcih0PTA7cj50O3QrKylpZihiLmNvbnRhaW5zKHRoaXMsblt0XSkpcmV0dXJuITB9KX0sbm90OmZ1bmN0aW9uKGUpe3JldHVybiB0aGlzLnB1c2hTdGFjayhmdCh0aGlzLGUsITEpKX0sZmlsdGVyOmZ1bmN0aW9uKGUpe3JldHVybiB0aGlzLnB1c2hTdGFjayhmdCh0aGlzLGUsITApKX0saXM6ZnVuY3Rpb24oZSl7cmV0dXJuISFlJiYoInN0cmluZyI9PXR5cGVvZiBlP2x0LnRlc3QoZSk/YihlLHRoaXMuY29udGV4dCkuaW5kZXgodGhpc1swXSk+PTA6Yi5maWx0ZXIoZSx0aGlzKS5sZW5ndGg+MDp0aGlzLmZpbHRlcihlKS5sZW5ndGg+MCl9LGNsb3Nlc3Q6ZnVuY3Rpb24oZSx0KXt2YXIgbixyPTAsaT10aGlzLmxlbmd0aCxvPVtdLGE9bHQudGVzdChlKXx8InN0cmluZyIhPXR5cGVvZiBlP2IoZSx0fHx0aGlzLmNvbnRleHQpOjA7Zm9yKDtpPnI7cisrKXtuPXRoaXNbcl07d2hpbGUobiYmbi5vd25lckRvY3VtZW50JiZuIT09dCYmMTEhPT1uLm5vZGVUeXBlKXtpZihhP2EuaW5kZXgobik+LTE6Yi5maW5kLm1hdGNoZXNTZWxlY3RvcihuLGUpKXtvLnB1c2gobik7YnJlYWt9bj1uLnBhcmVudE5vZGV9fXJldHVybiB0aGlzLnB1c2hTdGFjayhvLmxlbmd0aD4xP2IudW5pcXVlKG8pOm8pfSxpbmRleDpmdW5jdGlvbihlKXtyZXR1cm4gZT8ic3RyaW5nIj09dHlwZW9mIGU/Yi5pbkFycmF5KHRoaXNbMF0sYihlKSk6Yi5pbkFycmF5KGUuanF1ZXJ5P2VbMF06ZSx0aGlzKTp0aGlzWzBdJiZ0aGlzWzBdLnBhcmVudE5vZGU/dGhpcy5maXJzdCgpLnByZXZBbGwoKS5sZW5ndGg6LTF9LGFkZDpmdW5jdGlvbihlLHQpe3ZhciBuPSJzdHJpbmciPT10eXBlb2YgZT9iKGUsdCk6Yi5tYWtlQXJyYXkoZSYmZS5ub2RlVHlwZT9bZV06ZSkscj1iLm1lcmdlKHRoaXMuZ2V0KCksbik7cmV0dXJuIHRoaXMucHVzaFN0YWNrKGIudW5pcXVlKHIpKX0sYWRkQmFjazpmdW5jdGlvbihlKXtyZXR1cm4gdGhpcy5hZGQobnVsbD09ZT90aGlzLnByZXZPYmplY3Q6dGhpcy5wcmV2T2JqZWN0LmZpbHRlcihlKSl9fSksYi5mbi5hbmRTZWxmPWIuZm4uYWRkQmFjaztmdW5jdGlvbiBwdChlLHQpe2RvIGU9ZVt0XTt3aGlsZShlJiYxIT09ZS5ub2RlVHlwZSk7cmV0dXJuIGV9Yi5lYWNoKHtwYXJlbnQ6ZnVuY3Rpb24oZSl7dmFyIHQ9ZS5wYXJlbnROb2RlO3JldHVybiB0JiYxMSE9PXQubm9kZVR5cGU/dDpudWxsfSxwYXJlbnRzOmZ1bmN0aW9uKGUpe3JldHVybiBiLmRpcihlLCJwYXJlbnROb2RlIil9LHBhcmVudHNVbnRpbDpmdW5jdGlvbihlLHQsbil7cmV0dXJuIGIuZGlyKGUsInBhcmVudE5vZGUiLG4pfSxuZXh0OmZ1bmN0aW9uKGUpe3JldHVybiBwdChlLCJuZXh0U2libGluZyIpfSxwcmV2OmZ1bmN0aW9uKGUpe3JldHVybiBwdChlLCJwcmV2aW91c1NpYmxpbmciKX0sbmV4dEFsbDpmdW5jdGlvbihlKXtyZXR1cm4gYi5kaXIoZSwibmV4dFNpYmxpbmciKX0scHJldkFsbDpmdW5jdGlvbihlKXtyZXR1cm4gYi5kaXIoZSwicHJldmlvdXNTaWJsaW5nIil9LG5leHRVbnRpbDpmdW5jdGlvbihlLHQsbil7cmV0dXJuIGIuZGlyKGUsIm5leHRTaWJsaW5nIixuKX0scHJldlVudGlsOmZ1bmN0aW9uKGUsdCxuKXtyZXR1cm4gYi5kaXIoZSwicHJldmlvdXNTaWJsaW5nIixuKX0sc2libGluZ3M6ZnVuY3Rpb24oZSl7cmV0dXJuIGIuc2libGluZygoZS5wYXJlbnROb2RlfHx7fSkuZmlyc3RDaGlsZCxlKX0sY2hpbGRyZW46ZnVuY3Rpb24oZSl7cmV0dXJuIGIuc2libGluZyhlLmZpcnN0Q2hpbGQpfSxjb250ZW50czpmdW5jdGlvbihlKXtyZXR1cm4gYi5ub2RlTmFtZShlLCJpZnJhbWUiKT9lLmNvbnRlbnREb2N1bWVudHx8ZS5jb250ZW50V2luZG93LmRvY3VtZW50OmIubWVyZ2UoW10sZS5jaGlsZE5vZGVzKX19LGZ1bmN0aW9uKGUsdCl7Yi5mbltlXT1mdW5jdGlvbihuLHIpe3ZhciBpPWIubWFwKHRoaXMsdCxuKTtyZXR1cm4gYXQudGVzdChlKXx8KHI9biksciYmInN0cmluZyI9PXR5cGVvZiByJiYoaT1iLmZpbHRlcihyLGkpKSxpPXRoaXMubGVuZ3RoPjEmJiFjdFtlXT9iLnVuaXF1ZShpKTppLHRoaXMubGVuZ3RoPjEmJnN0LnRlc3QoZSkmJihpPWkucmV2ZXJzZSgpKSx0aGlzLnB1c2hTdGFjayhpKX19KSxiLmV4dGVuZCh7ZmlsdGVyOmZ1bmN0aW9uKGUsdCxuKXtyZXR1cm4gbiYmKGU9Ijpub3QoIitlKyIpIiksMT09PXQubGVuZ3RoP2IuZmluZC5tYXRjaGVzU2VsZWN0b3IodFswXSxlKT9bdFswXV06W106Yi5maW5kLm1hdGNoZXMoZSx0KX0sZGlyOmZ1bmN0aW9uKGUsbixyKXt2YXIgaT1bXSxvPWVbbl07d2hpbGUobyYmOSE9PW8ubm9kZVR5cGUmJihyPT09dHx8MSE9PW8ubm9kZVR5cGV8fCFiKG8pLmlzKHIpKSkxPT09by5ub2RlVHlwZSYmaS5wdXNoKG8pLG89b1tuXTtyZXR1cm4gaX0sc2libGluZzpmdW5jdGlvbihlLHQpe3ZhciBuPVtdO2Zvcig7ZTtlPWUubmV4dFNpYmxpbmcpMT09PWUubm9kZVR5cGUmJmUhPT10JiZuLnB1c2goZSk7cmV0dXJuIG59fSk7ZnVuY3Rpb24gZnQoZSx0LG4pe2lmKHQ9dHx8MCxiLmlzRnVuY3Rpb24odCkpcmV0dXJuIGIuZ3JlcChlLGZ1bmN0aW9uKGUscil7dmFyIGk9ISF0LmNhbGwoZSxyLGUpO3JldHVybiBpPT09bn0pO2lmKHQubm9kZVR5cGUpcmV0dXJuIGIuZ3JlcChlLGZ1bmN0aW9uKGUpe3JldHVybiBlPT09dD09PW59KTtpZigic3RyaW5nIj09dHlwZW9mIHQpe3ZhciByPWIuZ3JlcChlLGZ1bmN0aW9uKGUpe3JldHVybiAxPT09ZS5ub2RlVHlwZX0pO2lmKHV0LnRlc3QodCkpcmV0dXJuIGIuZmlsdGVyKHQsciwhbik7dD1iLmZpbHRlcih0LHIpfXJldHVybiBiLmdyZXAoZSxmdW5jdGlvbihlKXtyZXR1cm4gYi5pbkFycmF5KGUsdCk+PTA9PT1ufSl9ZnVuY3Rpb24gZHQoZSl7dmFyIHQ9aHQuc3BsaXQoInwiKSxuPWUuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpO2lmKG4uY3JlYXRlRWxlbWVudCl3aGlsZSh0Lmxlbmd0aCluLmNyZWF0ZUVsZW1lbnQodC5wb3AoKSk7cmV0dXJuIG59dmFyIGh0PSJhYmJyfGFydGljbGV8YXNpZGV8YXVkaW98YmRpfGNhbnZhc3xkYXRhfGRhdGFsaXN0fGRldGFpbHN8ZmlnY2FwdGlvbnxmaWd1cmV8Zm9vdGVyfGhlYWRlcnxoZ3JvdXB8bWFya3xtZXRlcnxuYXZ8b3V0cHV0fHByb2dyZXNzfHNlY3Rpb258c3VtbWFyeXx0aW1lfHZpZGVvIixndD0vIGpRdWVyeVxkKz0iKD86bnVsbHxcZCspIi9nLG10PVJlZ0V4cCgiPCg/OiIraHQrIilbXFxzLz5dIiwiaSIpLHl0PS9eXHMrLyx2dD0vPCg/IWFyZWF8YnJ8Y29sfGVtYmVkfGhyfGltZ3xpbnB1dHxsaW5rfG1ldGF8cGFyYW0pKChbXHc6XSspW14+XSopXC8+L2dpLGJ0PS88KFtcdzpdKykvLHh0PS88dGJvZHkvaSx3dD0vPHwmIz9cdys7LyxUdD0vPCg/OnNjcmlwdHxzdHlsZXxsaW5rKS9pLE50PS9eKD86Y2hlY2tib3h8cmFkaW8pJC9pLEN0PS9jaGVja2VkXHMqKD86W149XXw9XHMqLmNoZWNrZWQuKS9pLGt0PS9eJHxcLyg/OmphdmF8ZWNtYSlzY3JpcHQvaSxFdD0vXnRydWVcLyguKikvLFN0PS9eXHMqPCEoPzpcW0NEQVRBXFt8LS0pfCg/OlxdXF18LS0pPlxzKiQvZyxBdD17b3B0aW9uOlsxLCI8c2VsZWN0IG11bHRpcGxlPSdtdWx0aXBsZSc+IiwiPC9zZWxlY3Q+Il0sbGVnZW5kOlsxLCI8ZmllbGRzZXQ+IiwiPC9maWVsZHNldD4iXSxhcmVhOlsxLCI8bWFwPiIsIjwvbWFwPiJdLHBhcmFtOlsxLCI8b2JqZWN0PiIsIjwvb2JqZWN0PiJdLHRoZWFkOlsxLCI8dGFibGU+IiwiPC90YWJsZT4iXSx0cjpbMiwiPHRhYmxlPjx0Ym9keT4iLCI8L3Rib2R5PjwvdGFibGU+Il0sY29sOlsyLCI8dGFibGU+PHRib2R5PjwvdGJvZHk+PGNvbGdyb3VwPiIsIjwvY29sZ3JvdXA+PC90YWJsZT4iXSx0ZDpbMywiPHRhYmxlPjx0Ym9keT48dHI+IiwiPC90cj48L3Rib2R5PjwvdGFibGU+Il0sX2RlZmF1bHQ6Yi5zdXBwb3J0Lmh0bWxTZXJpYWxpemU/WzAsIiIsIiJdOlsxLCJYPGRpdj4iLCI8L2Rpdj4iXX0sanQ9ZHQobyksRHQ9anQuYXBwZW5kQ2hpbGQoby5jcmVhdGVFbGVtZW50KCJkaXYiKSk7QXQub3B0Z3JvdXA9QXQub3B0aW9uLEF0LnRib2R5PUF0LnRmb290PUF0LmNvbGdyb3VwPUF0LmNhcHRpb249QXQudGhlYWQsQXQudGg9QXQudGQsYi5mbi5leHRlbmQoe3RleHQ6ZnVuY3Rpb24oZSl7cmV0dXJuIGIuYWNjZXNzKHRoaXMsZnVuY3Rpb24oZSl7cmV0dXJuIGU9PT10P2IudGV4dCh0aGlzKTp0aGlzLmVtcHR5KCkuYXBwZW5kKCh0aGlzWzBdJiZ0aGlzWzBdLm93bmVyRG9jdW1lbnR8fG8pLmNyZWF0ZVRleHROb2RlKGUpKX0sbnVsbCxlLGFyZ3VtZW50cy5sZW5ndGgpfSx3cmFwQWxsOmZ1bmN0aW9uKGUpe2lmKGIuaXNGdW5jdGlvbihlKSlyZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uKHQpe2IodGhpcykud3JhcEFsbChlLmNhbGwodGhpcyx0KSl9KTtpZih0aGlzWzBdKXt2YXIgdD1iKGUsdGhpc1swXS5vd25lckRvY3VtZW50KS5lcSgwKS5jbG9uZSghMCk7dGhpc1swXS5wYXJlbnROb2RlJiZ0Lmluc2VydEJlZm9yZSh0aGlzWzBdKSx0Lm1hcChmdW5jdGlvbigpe3ZhciBlPXRoaXM7d2hpbGUoZS5maXJzdENoaWxkJiYxPT09ZS5maXJzdENoaWxkLm5vZGVUeXBlKWU9ZS5maXJzdENoaWxkO3JldHVybiBlfSkuYXBwZW5kKHRoaXMpfXJldHVybiB0aGlzfSx3cmFwSW5uZXI6ZnVuY3Rpb24oZSl7cmV0dXJuIGIuaXNGdW5jdGlvbihlKT90aGlzLmVhY2goZnVuY3Rpb24odCl7Yih0aGlzKS53cmFwSW5uZXIoZS5jYWxsKHRoaXMsdCkpfSk6dGhpcy5lYWNoKGZ1bmN0aW9uKCl7dmFyIHQ9Yih0aGlzKSxuPXQuY29udGVudHMoKTtuLmxlbmd0aD9uLndyYXBBbGwoZSk6dC5hcHBlbmQoZSl9KX0sd3JhcDpmdW5jdGlvbihlKXt2YXIgdD1iLmlzRnVuY3Rpb24oZSk7cmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbihuKXtiKHRoaXMpLndyYXBBbGwodD9lLmNhbGwodGhpcyxuKTplKX0pfSx1bndyYXA6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5wYXJlbnQoKS5lYWNoKGZ1bmN0aW9uKCl7Yi5ub2RlTmFtZSh0aGlzLCJib2R5Iil8fGIodGhpcykucmVwbGFjZVdpdGgodGhpcy5jaGlsZE5vZGVzKX0pLmVuZCgpfSxhcHBlbmQ6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5kb21NYW5pcChhcmd1bWVudHMsITAsZnVuY3Rpb24oZSl7KDE9PT10aGlzLm5vZGVUeXBlfHwxMT09PXRoaXMubm9kZVR5cGV8fDk9PT10aGlzLm5vZGVUeXBlKSYmdGhpcy5hcHBlbmRDaGlsZChlKX0pfSxwcmVwZW5kOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZG9tTWFuaXAoYXJndW1lbnRzLCEwLGZ1bmN0aW9uKGUpeygxPT09dGhpcy5ub2RlVHlwZXx8MTE9PT10aGlzLm5vZGVUeXBlfHw5PT09dGhpcy5ub2RlVHlwZSkmJnRoaXMuaW5zZXJ0QmVmb3JlKGUsdGhpcy5maXJzdENoaWxkKX0pfSxiZWZvcmU6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5kb21NYW5pcChhcmd1bWVudHMsITEsZnVuY3Rpb24oZSl7dGhpcy5wYXJlbnROb2RlJiZ0aGlzLnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKGUsdGhpcyl9KX0sYWZ0ZXI6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5kb21NYW5pcChhcmd1bWVudHMsITEsZnVuY3Rpb24oZSl7dGhpcy5wYXJlbnROb2RlJiZ0aGlzLnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKGUsdGhpcy5uZXh0U2libGluZyl9KX0scmVtb3ZlOmZ1bmN0aW9uKGUsdCl7dmFyIG4scj0wO2Zvcig7bnVsbCE9KG49dGhpc1tyXSk7cisrKSghZXx8Yi5maWx0ZXIoZSxbbl0pLmxlbmd0aD4wKSYmKHR8fDEhPT1uLm5vZGVUeXBlfHxiLmNsZWFuRGF0YShPdChuKSksbi5wYXJlbnROb2RlJiYodCYmYi5jb250YWlucyhuLm93bmVyRG9jdW1lbnQsbikmJk10KE90KG4sInNjcmlwdCIpKSxuLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQobikpKTtyZXR1cm4gdGhpc30sZW1wdHk6ZnVuY3Rpb24oKXt2YXIgZSx0PTA7Zm9yKDtudWxsIT0oZT10aGlzW3RdKTt0KyspezE9PT1lLm5vZGVUeXBlJiZiLmNsZWFuRGF0YShPdChlLCExKSk7d2hpbGUoZS5maXJzdENoaWxkKWUucmVtb3ZlQ2hpbGQoZS5maXJzdENoaWxkKTtlLm9wdGlvbnMmJmIubm9kZU5hbWUoZSwic2VsZWN0IikmJihlLm9wdGlvbnMubGVuZ3RoPTApfXJldHVybiB0aGlzfSxjbG9uZTpmdW5jdGlvbihlLHQpe3JldHVybiBlPW51bGw9PWU/ITE6ZSx0PW51bGw9PXQ/ZTp0LHRoaXMubWFwKGZ1bmN0aW9uKCl7cmV0dXJuIGIuY2xvbmUodGhpcyxlLHQpfSl9LGh0bWw6ZnVuY3Rpb24oZSl7cmV0dXJuIGIuYWNjZXNzKHRoaXMsZnVuY3Rpb24oZSl7dmFyIG49dGhpc1swXXx8e30scj0wLGk9dGhpcy5sZW5ndGg7aWYoZT09PXQpcmV0dXJuIDE9PT1uLm5vZGVUeXBlP24uaW5uZXJIVE1MLnJlcGxhY2UoZ3QsIiIpOnQ7aWYoISgic3RyaW5nIiE9dHlwZW9mIGV8fFR0LnRlc3QoZSl8fCFiLnN1cHBvcnQuaHRtbFNlcmlhbGl6ZSYmbXQudGVzdChlKXx8IWIuc3VwcG9ydC5sZWFkaW5nV2hpdGVzcGFjZSYmeXQudGVzdChlKXx8QXRbKGJ0LmV4ZWMoZSl8fFsiIiwiIl0pWzFdLnRvTG93ZXJDYXNlKCldKSl7ZT1lLnJlcGxhY2UodnQsIjwkMT48LyQyPiIpO3RyeXtmb3IoO2k+cjtyKyspbj10aGlzW3JdfHx7fSwxPT09bi5ub2RlVHlwZSYmKGIuY2xlYW5EYXRhKE90KG4sITEpKSxuLmlubmVySFRNTD1lKTtuPTB9Y2F0Y2gobyl7fX1uJiZ0aGlzLmVtcHR5KCkuYXBwZW5kKGUpfSxudWxsLGUsYXJndW1lbnRzLmxlbmd0aCl9LHJlcGxhY2VXaXRoOmZ1bmN0aW9uKGUpe3ZhciB0PWIuaXNGdW5jdGlvbihlKTtyZXR1cm4gdHx8InN0cmluZyI9PXR5cGVvZiBlfHwoZT1iKGUpLm5vdCh0aGlzKS5kZXRhY2goKSksdGhpcy5kb21NYW5pcChbZV0sITAsZnVuY3Rpb24oZSl7dmFyIHQ9dGhpcy5uZXh0U2libGluZyxuPXRoaXMucGFyZW50Tm9kZTtuJiYoYih0aGlzKS5yZW1vdmUoKSxuLmluc2VydEJlZm9yZShlLHQpKX0pfSxkZXRhY2g6ZnVuY3Rpb24oZSl7cmV0dXJuIHRoaXMucmVtb3ZlKGUsITApfSxkb21NYW5pcDpmdW5jdGlvbihlLG4scil7ZT1mLmFwcGx5KFtdLGUpO3ZhciBpLG8sYSxzLHUsbCxjPTAscD10aGlzLmxlbmd0aCxkPXRoaXMsaD1wLTEsZz1lWzBdLG09Yi5pc0Z1bmN0aW9uKGcpO2lmKG18fCEoMT49cHx8InN0cmluZyIhPXR5cGVvZiBnfHxiLnN1cHBvcnQuY2hlY2tDbG9uZSkmJkN0LnRlc3QoZykpcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbihpKXt2YXIgbz1kLmVxKGkpO20mJihlWzBdPWcuY2FsbCh0aGlzLGksbj9vLmh0bWwoKTp0KSksby5kb21NYW5pcChlLG4scil9KTtpZihwJiYobD1iLmJ1aWxkRnJhZ21lbnQoZSx0aGlzWzBdLm93bmVyRG9jdW1lbnQsITEsdGhpcyksaT1sLmZpcnN0Q2hpbGQsMT09PWwuY2hpbGROb2Rlcy5sZW5ndGgmJihsPWkpLGkpKXtmb3Iobj1uJiZiLm5vZGVOYW1lKGksInRyIikscz1iLm1hcChPdChsLCJzY3JpcHQiKSxIdCksYT1zLmxlbmd0aDtwPmM7YysrKW89bCxjIT09aCYmKG89Yi5jbG9uZShvLCEwLCEwKSxhJiZiLm1lcmdlKHMsT3Qobywic2NyaXB0IikpKSxyLmNhbGwobiYmYi5ub2RlTmFtZSh0aGlzW2NdLCJ0YWJsZSIpP0x0KHRoaXNbY10sInRib2R5Iik6dGhpc1tjXSxvLGMpO2lmKGEpZm9yKHU9c1tzLmxlbmd0aC0xXS5vd25lckRvY3VtZW50LGIubWFwKHMscXQpLGM9MDthPmM7YysrKW89c1tjXSxrdC50ZXN0KG8udHlwZXx8IiIpJiYhYi5fZGF0YShvLCJnbG9iYWxFdmFsIikmJmIuY29udGFpbnModSxvKSYmKG8uc3JjP2IuYWpheCh7dXJsOm8uc3JjLHR5cGU6IkdFVCIsZGF0YVR5cGU6InNjcmlwdCIsYXN5bmM6ITEsZ2xvYmFsOiExLCJ0aHJvd3MiOiEwfSk6Yi5nbG9iYWxFdmFsKChvLnRleHR8fG8udGV4dENvbnRlbnR8fG8uaW5uZXJIVE1MfHwiIikucmVwbGFjZShTdCwiIikpKTtsPWk9bnVsbH1yZXR1cm4gdGhpc319KTtmdW5jdGlvbiBMdChlLHQpe3JldHVybiBlLmdldEVsZW1lbnRzQnlUYWdOYW1lKHQpWzBdfHxlLmFwcGVuZENoaWxkKGUub3duZXJEb2N1bWVudC5jcmVhdGVFbGVtZW50KHQpKX1mdW5jdGlvbiBIdChlKXt2YXIgdD1lLmdldEF0dHJpYnV0ZU5vZGUoInR5cGUiKTtyZXR1cm4gZS50eXBlPSh0JiZ0LnNwZWNpZmllZCkrIi8iK2UudHlwZSxlfWZ1bmN0aW9uIHF0KGUpe3ZhciB0PUV0LmV4ZWMoZS50eXBlKTtyZXR1cm4gdD9lLnR5cGU9dFsxXTplLnJlbW92ZUF0dHJpYnV0ZSgidHlwZSIpLGV9ZnVuY3Rpb24gTXQoZSx0KXt2YXIgbixyPTA7Zm9yKDtudWxsIT0obj1lW3JdKTtyKyspYi5fZGF0YShuLCJnbG9iYWxFdmFsIiwhdHx8Yi5fZGF0YSh0W3JdLCJnbG9iYWxFdmFsIikpfWZ1bmN0aW9uIF90KGUsdCl7aWYoMT09PXQubm9kZVR5cGUmJmIuaGFzRGF0YShlKSl7dmFyIG4scixpLG89Yi5fZGF0YShlKSxhPWIuX2RhdGEodCxvKSxzPW8uZXZlbnRzO2lmKHMpe2RlbGV0ZSBhLmhhbmRsZSxhLmV2ZW50cz17fTtmb3IobiBpbiBzKWZvcihyPTAsaT1zW25dLmxlbmd0aDtpPnI7cisrKWIuZXZlbnQuYWRkKHQsbixzW25dW3JdKX1hLmRhdGEmJihhLmRhdGE9Yi5leHRlbmQoe30sYS5kYXRhKSl9fWZ1bmN0aW9uIEZ0KGUsdCl7dmFyIG4scixpO2lmKDE9PT10Lm5vZGVUeXBlKXtpZihuPXQubm9kZU5hbWUudG9Mb3dlckNhc2UoKSwhYi5zdXBwb3J0Lm5vQ2xvbmVFdmVudCYmdFtiLmV4cGFuZG9dKXtpPWIuX2RhdGEodCk7Zm9yKHIgaW4gaS5ldmVudHMpYi5yZW1vdmVFdmVudCh0LHIsaS5oYW5kbGUpO3QucmVtb3ZlQXR0cmlidXRlKGIuZXhwYW5kbyl9InNjcmlwdCI9PT1uJiZ0LnRleHQhPT1lLnRleHQ/KEh0KHQpLnRleHQ9ZS50ZXh0LHF0KHQpKToib2JqZWN0Ij09PW4/KHQucGFyZW50Tm9kZSYmKHQub3V0ZXJIVE1MPWUub3V0ZXJIVE1MKSxiLnN1cHBvcnQuaHRtbDVDbG9uZSYmZS5pbm5lckhUTUwmJiFiLnRyaW0odC5pbm5lckhUTUwpJiYodC5pbm5lckhUTUw9ZS5pbm5lckhUTUwpKToiaW5wdXQiPT09biYmTnQudGVzdChlLnR5cGUpPyh0LmRlZmF1bHRDaGVja2VkPXQuY2hlY2tlZD1lLmNoZWNrZWQsdC52YWx1ZSE9PWUudmFsdWUmJih0LnZhbHVlPWUudmFsdWUpKToib3B0aW9uIj09PW4/dC5kZWZhdWx0U2VsZWN0ZWQ9dC5zZWxlY3RlZD1lLmRlZmF1bHRTZWxlY3RlZDooImlucHV0Ij09PW58fCJ0ZXh0YXJlYSI9PT1uKSYmKHQuZGVmYXVsdFZhbHVlPWUuZGVmYXVsdFZhbHVlKX19Yi5lYWNoKHthcHBlbmRUbzoiYXBwZW5kIixwcmVwZW5kVG86InByZXBlbmQiLGluc2VydEJlZm9yZToiYmVmb3JlIixpbnNlcnRBZnRlcjoiYWZ0ZXIiLHJlcGxhY2VBbGw6InJlcGxhY2VXaXRoIn0sZnVuY3Rpb24oZSx0KXtiLmZuW2VdPWZ1bmN0aW9uKGUpe3ZhciBuLHI9MCxpPVtdLG89YihlKSxhPW8ubGVuZ3RoLTE7Zm9yKDthPj1yO3IrKyluPXI9PT1hP3RoaXM6dGhpcy5jbG9uZSghMCksYihvW3JdKVt0XShuKSxkLmFwcGx5KGksbi5nZXQoKSk7cmV0dXJuIHRoaXMucHVzaFN0YWNrKGkpfX0pO2Z1bmN0aW9uIE90KGUsbil7dmFyIHIsbyxhPTAscz10eXBlb2YgZS5nZXRFbGVtZW50c0J5VGFnTmFtZSE9PWk/ZS5nZXRFbGVtZW50c0J5VGFnTmFtZShufHwiKiIpOnR5cGVvZiBlLnF1ZXJ5U2VsZWN0b3JBbGwhPT1pP2UucXVlcnlTZWxlY3RvckFsbChufHwiKiIpOnQ7aWYoIXMpZm9yKHM9W10scj1lLmNoaWxkTm9kZXN8fGU7bnVsbCE9KG89clthXSk7YSsrKSFufHxiLm5vZGVOYW1lKG8sbik/cy5wdXNoKG8pOmIubWVyZ2UocyxPdChvLG4pKTtyZXR1cm4gbj09PXR8fG4mJmIubm9kZU5hbWUoZSxuKT9iLm1lcmdlKFtlXSxzKTpzfWZ1bmN0aW9uIEJ0KGUpe050LnRlc3QoZS50eXBlKSYmKGUuZGVmYXVsdENoZWNrZWQ9ZS5jaGVja2VkKX1iLmV4dGVuZCh7Y2xvbmU6ZnVuY3Rpb24oZSx0LG4pe3ZhciByLGksbyxhLHMsdT1iLmNvbnRhaW5zKGUub3duZXJEb2N1bWVudCxlKTtpZihiLnN1cHBvcnQuaHRtbDVDbG9uZXx8Yi5pc1hNTERvYyhlKXx8IW10LnRlc3QoIjwiK2Uubm9kZU5hbWUrIj4iKT9vPWUuY2xvbmVOb2RlKCEwKTooRHQuaW5uZXJIVE1MPWUub3V0ZXJIVE1MLER0LnJlbW92ZUNoaWxkKG89RHQuZmlyc3RDaGlsZCkpLCEoYi5zdXBwb3J0Lm5vQ2xvbmVFdmVudCYmYi5zdXBwb3J0Lm5vQ2xvbmVDaGVja2VkfHwxIT09ZS5ub2RlVHlwZSYmMTEhPT1lLm5vZGVUeXBlfHxiLmlzWE1MRG9jKGUpKSlmb3Iocj1PdChvKSxzPU90KGUpLGE9MDtudWxsIT0oaT1zW2FdKTsrK2EpclthXSYmRnQoaSxyW2FdKTtpZih0KWlmKG4pZm9yKHM9c3x8T3QoZSkscj1yfHxPdChvKSxhPTA7bnVsbCE9KGk9c1thXSk7YSsrKV90KGksclthXSk7ZWxzZSBfdChlLG8pO3JldHVybiByPU90KG8sInNjcmlwdCIpLHIubGVuZ3RoPjAmJk10KHIsIXUmJk90KGUsInNjcmlwdCIpKSxyPXM9aT1udWxsLG99LGJ1aWxkRnJhZ21lbnQ6ZnVuY3Rpb24oZSx0LG4scil7dmFyIGksbyxhLHMsdSxsLGMscD1lLmxlbmd0aCxmPWR0KHQpLGQ9W10saD0wO2Zvcig7cD5oO2grKylpZihvPWVbaF0sb3x8MD09PW8paWYoIm9iamVjdCI9PT1iLnR5cGUobykpYi5tZXJnZShkLG8ubm9kZVR5cGU/W29dOm8pO2Vsc2UgaWYod3QudGVzdChvKSl7cz1zfHxmLmFwcGVuZENoaWxkKHQuY3JlYXRlRWxlbWVudCgiZGl2IikpLHU9KGJ0LmV4ZWMobyl8fFsiIiwiIl0pWzFdLnRvTG93ZXJDYXNlKCksYz1BdFt1XXx8QXQuX2RlZmF1bHQscy5pbm5lckhUTUw9Y1sxXStvLnJlcGxhY2UodnQsIjwkMT48LyQyPiIpK2NbMl0saT1jWzBdO3doaWxlKGktLSlzPXMubGFzdENoaWxkO2lmKCFiLnN1cHBvcnQubGVhZGluZ1doaXRlc3BhY2UmJnl0LnRlc3QobykmJmQucHVzaCh0LmNyZWF0ZVRleHROb2RlKHl0LmV4ZWMobylbMF0pKSwhYi5zdXBwb3J0LnRib2R5KXtvPSJ0YWJsZSIhPT11fHx4dC50ZXN0KG8pPyI8dGFibGU+IiE9PWNbMV18fHh0LnRlc3Qobyk/MDpzOnMuZmlyc3RDaGlsZCxpPW8mJm8uY2hpbGROb2Rlcy5sZW5ndGg7d2hpbGUoaS0tKWIubm9kZU5hbWUobD1vLmNoaWxkTm9kZXNbaV0sInRib2R5IikmJiFsLmNoaWxkTm9kZXMubGVuZ3RoJiZvLnJlbW92ZUNoaWxkKGwpCgl9Yi5tZXJnZShkLHMuY2hpbGROb2Rlcykscy50ZXh0Q29udGVudD0iIjt3aGlsZShzLmZpcnN0Q2hpbGQpcy5yZW1vdmVDaGlsZChzLmZpcnN0Q2hpbGQpO3M9Zi5sYXN0Q2hpbGR9ZWxzZSBkLnB1c2godC5jcmVhdGVUZXh0Tm9kZShvKSk7cyYmZi5yZW1vdmVDaGlsZChzKSxiLnN1cHBvcnQuYXBwZW5kQ2hlY2tlZHx8Yi5ncmVwKE90KGQsImlucHV0IiksQnQpLGg9MDt3aGlsZShvPWRbaCsrXSlpZigoIXJ8fC0xPT09Yi5pbkFycmF5KG8scikpJiYoYT1iLmNvbnRhaW5zKG8ub3duZXJEb2N1bWVudCxvKSxzPU90KGYuYXBwZW5kQ2hpbGQobyksInNjcmlwdCIpLGEmJk10KHMpLG4pKXtpPTA7d2hpbGUobz1zW2krK10pa3QudGVzdChvLnR5cGV8fCIiKSYmbi5wdXNoKG8pfXJldHVybiBzPW51bGwsZn0sY2xlYW5EYXRhOmZ1bmN0aW9uKGUsdCl7dmFyIG4scixvLGEscz0wLHU9Yi5leHBhbmRvLGw9Yi5jYWNoZSxwPWIuc3VwcG9ydC5kZWxldGVFeHBhbmRvLGY9Yi5ldmVudC5zcGVjaWFsO2Zvcig7bnVsbCE9KG49ZVtzXSk7cysrKWlmKCh0fHxiLmFjY2VwdERhdGEobikpJiYobz1uW3VdLGE9byYmbFtvXSkpe2lmKGEuZXZlbnRzKWZvcihyIGluIGEuZXZlbnRzKWZbcl0/Yi5ldmVudC5yZW1vdmUobixyKTpiLnJlbW92ZUV2ZW50KG4scixhLmhhbmRsZSk7bFtvXSYmKGRlbGV0ZSBsW29dLHA/ZGVsZXRlIG5bdV06dHlwZW9mIG4ucmVtb3ZlQXR0cmlidXRlIT09aT9uLnJlbW92ZUF0dHJpYnV0ZSh1KTpuW3VdPW51bGwsYy5wdXNoKG8pKX19fSk7dmFyIFB0LFJ0LFd0LCR0PS9hbHBoYVwoW14pXSpcKS9pLEl0PS9vcGFjaXR5XHMqPVxzKihbXildKikvLHp0PS9eKHRvcHxyaWdodHxib3R0b218bGVmdCkkLyxYdD0vXihub25lfHRhYmxlKD8hLWNbZWFdKS4rKS8sVXQ9L15tYXJnaW4vLFZ0PVJlZ0V4cCgiXigiK3grIikoLiopJCIsImkiKSxZdD1SZWdFeHAoIl4oIit4KyIpKD8hcHgpW2EteiVdKyQiLCJpIiksSnQ9UmVnRXhwKCJeKFsrLV0pPSgiK3grIikiLCJpIiksR3Q9e0JPRFk6ImJsb2NrIn0sUXQ9e3Bvc2l0aW9uOiJhYnNvbHV0ZSIsdmlzaWJpbGl0eToiaGlkZGVuIixkaXNwbGF5OiJibG9jayJ9LEt0PXtsZXR0ZXJTcGFjaW5nOjAsZm9udFdlaWdodDo0MDB9LFp0PVsiVG9wIiwiUmlnaHQiLCJCb3R0b20iLCJMZWZ0Il0sZW49WyJXZWJraXQiLCJPIiwiTW96IiwibXMiXTtmdW5jdGlvbiB0bihlLHQpe2lmKHQgaW4gZSlyZXR1cm4gdDt2YXIgbj10LmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpK3Quc2xpY2UoMSkscj10LGk9ZW4ubGVuZ3RoO3doaWxlKGktLSlpZih0PWVuW2ldK24sdCBpbiBlKXJldHVybiB0O3JldHVybiByfWZ1bmN0aW9uIG5uKGUsdCl7cmV0dXJuIGU9dHx8ZSwibm9uZSI9PT1iLmNzcyhlLCJkaXNwbGF5Iil8fCFiLmNvbnRhaW5zKGUub3duZXJEb2N1bWVudCxlKX1mdW5jdGlvbiBybihlLHQpe3ZhciBuLHIsaSxvPVtdLGE9MCxzPWUubGVuZ3RoO2Zvcig7cz5hO2ErKylyPWVbYV0sci5zdHlsZSYmKG9bYV09Yi5fZGF0YShyLCJvbGRkaXNwbGF5Iiksbj1yLnN0eWxlLmRpc3BsYXksdD8ob1thXXx8Im5vbmUiIT09bnx8KHIuc3R5bGUuZGlzcGxheT0iIiksIiI9PT1yLnN0eWxlLmRpc3BsYXkmJm5uKHIpJiYob1thXT1iLl9kYXRhKHIsIm9sZGRpc3BsYXkiLHVuKHIubm9kZU5hbWUpKSkpOm9bYV18fChpPW5uKHIpLChuJiYibm9uZSIhPT1ufHwhaSkmJmIuX2RhdGEociwib2xkZGlzcGxheSIsaT9uOmIuY3NzKHIsImRpc3BsYXkiKSkpKTtmb3IoYT0wO3M+YTthKyspcj1lW2FdLHIuc3R5bGUmJih0JiYibm9uZSIhPT1yLnN0eWxlLmRpc3BsYXkmJiIiIT09ci5zdHlsZS5kaXNwbGF5fHwoci5zdHlsZS5kaXNwbGF5PXQ/b1thXXx8IiI6Im5vbmUiKSk7cmV0dXJuIGV9Yi5mbi5leHRlbmQoe2NzczpmdW5jdGlvbihlLG4pe3JldHVybiBiLmFjY2Vzcyh0aGlzLGZ1bmN0aW9uKGUsbixyKXt2YXIgaSxvLGE9e30scz0wO2lmKGIuaXNBcnJheShuKSl7Zm9yKG89UnQoZSksaT1uLmxlbmd0aDtpPnM7cysrKWFbbltzXV09Yi5jc3MoZSxuW3NdLCExLG8pO3JldHVybiBhfXJldHVybiByIT09dD9iLnN0eWxlKGUsbixyKTpiLmNzcyhlLG4pfSxlLG4sYXJndW1lbnRzLmxlbmd0aD4xKX0sc2hvdzpmdW5jdGlvbigpe3JldHVybiBybih0aGlzLCEwKX0saGlkZTpmdW5jdGlvbigpe3JldHVybiBybih0aGlzKX0sdG9nZ2xlOmZ1bmN0aW9uKGUpe3ZhciB0PSJib29sZWFuIj09dHlwZW9mIGU7cmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbigpeyh0P2U6bm4odGhpcykpP2IodGhpcykuc2hvdygpOmIodGhpcykuaGlkZSgpfSl9fSksYi5leHRlbmQoe2Nzc0hvb2tzOntvcGFjaXR5OntnZXQ6ZnVuY3Rpb24oZSx0KXtpZih0KXt2YXIgbj1XdChlLCJvcGFjaXR5Iik7cmV0dXJuIiI9PT1uPyIxIjpufX19fSxjc3NOdW1iZXI6e2NvbHVtbkNvdW50OiEwLGZpbGxPcGFjaXR5OiEwLGZvbnRXZWlnaHQ6ITAsbGluZUhlaWdodDohMCxvcGFjaXR5OiEwLG9ycGhhbnM6ITAsd2lkb3dzOiEwLHpJbmRleDohMCx6b29tOiEwfSxjc3NQcm9wczp7ImZsb2F0IjpiLnN1cHBvcnQuY3NzRmxvYXQ/ImNzc0Zsb2F0Ijoic3R5bGVGbG9hdCJ9LHN0eWxlOmZ1bmN0aW9uKGUsbixyLGkpe2lmKGUmJjMhPT1lLm5vZGVUeXBlJiY4IT09ZS5ub2RlVHlwZSYmZS5zdHlsZSl7dmFyIG8sYSxzLHU9Yi5jYW1lbENhc2UobiksbD1lLnN0eWxlO2lmKG49Yi5jc3NQcm9wc1t1XXx8KGIuY3NzUHJvcHNbdV09dG4obCx1KSkscz1iLmNzc0hvb2tzW25dfHxiLmNzc0hvb2tzW3VdLHI9PT10KXJldHVybiBzJiYiZ2V0ImluIHMmJihvPXMuZ2V0KGUsITEsaSkpIT09dD9vOmxbbl07aWYoYT10eXBlb2Ygciwic3RyaW5nIj09PWEmJihvPUp0LmV4ZWMocikpJiYocj0ob1sxXSsxKSpvWzJdK3BhcnNlRmxvYXQoYi5jc3MoZSxuKSksYT0ibnVtYmVyIiksIShudWxsPT1yfHwibnVtYmVyIj09PWEmJmlzTmFOKHIpfHwoIm51bWJlciIhPT1hfHxiLmNzc051bWJlclt1XXx8KHIrPSJweCIpLGIuc3VwcG9ydC5jbGVhckNsb25lU3R5bGV8fCIiIT09cnx8MCE9PW4uaW5kZXhPZigiYmFja2dyb3VuZCIpfHwobFtuXT0iaW5oZXJpdCIpLHMmJiJzZXQiaW4gcyYmKHI9cy5zZXQoZSxyLGkpKT09PXQpKSl0cnl7bFtuXT1yfWNhdGNoKGMpe319fSxjc3M6ZnVuY3Rpb24oZSxuLHIsaSl7dmFyIG8sYSxzLHU9Yi5jYW1lbENhc2Uobik7cmV0dXJuIG49Yi5jc3NQcm9wc1t1XXx8KGIuY3NzUHJvcHNbdV09dG4oZS5zdHlsZSx1KSkscz1iLmNzc0hvb2tzW25dfHxiLmNzc0hvb2tzW3VdLHMmJiJnZXQiaW4gcyYmKGE9cy5nZXQoZSwhMCxyKSksYT09PXQmJihhPVd0KGUsbixpKSksIm5vcm1hbCI9PT1hJiZuIGluIEt0JiYoYT1LdFtuXSksIiI9PT1yfHxyPyhvPXBhcnNlRmxvYXQoYSkscj09PSEwfHxiLmlzTnVtZXJpYyhvKT9vfHwwOmEpOmF9LHN3YXA6ZnVuY3Rpb24oZSx0LG4scil7dmFyIGksbyxhPXt9O2ZvcihvIGluIHQpYVtvXT1lLnN0eWxlW29dLGUuc3R5bGVbb109dFtvXTtpPW4uYXBwbHkoZSxyfHxbXSk7Zm9yKG8gaW4gdCllLnN0eWxlW29dPWFbb107cmV0dXJuIGl9fSksZS5nZXRDb21wdXRlZFN0eWxlPyhSdD1mdW5jdGlvbih0KXtyZXR1cm4gZS5nZXRDb21wdXRlZFN0eWxlKHQsbnVsbCl9LFd0PWZ1bmN0aW9uKGUsbixyKXt2YXIgaSxvLGEscz1yfHxSdChlKSx1PXM/cy5nZXRQcm9wZXJ0eVZhbHVlKG4pfHxzW25dOnQsbD1lLnN0eWxlO3JldHVybiBzJiYoIiIhPT11fHxiLmNvbnRhaW5zKGUub3duZXJEb2N1bWVudCxlKXx8KHU9Yi5zdHlsZShlLG4pKSxZdC50ZXN0KHUpJiZVdC50ZXN0KG4pJiYoaT1sLndpZHRoLG89bC5taW5XaWR0aCxhPWwubWF4V2lkdGgsbC5taW5XaWR0aD1sLm1heFdpZHRoPWwud2lkdGg9dSx1PXMud2lkdGgsbC53aWR0aD1pLGwubWluV2lkdGg9byxsLm1heFdpZHRoPWEpKSx1fSk6by5kb2N1bWVudEVsZW1lbnQuY3VycmVudFN0eWxlJiYoUnQ9ZnVuY3Rpb24oZSl7cmV0dXJuIGUuY3VycmVudFN0eWxlfSxXdD1mdW5jdGlvbihlLG4scil7dmFyIGksbyxhLHM9cnx8UnQoZSksdT1zP3Nbbl06dCxsPWUuc3R5bGU7cmV0dXJuIG51bGw9PXUmJmwmJmxbbl0mJih1PWxbbl0pLFl0LnRlc3QodSkmJiF6dC50ZXN0KG4pJiYoaT1sLmxlZnQsbz1lLnJ1bnRpbWVTdHlsZSxhPW8mJm8ubGVmdCxhJiYoby5sZWZ0PWUuY3VycmVudFN0eWxlLmxlZnQpLGwubGVmdD0iZm9udFNpemUiPT09bj8iMWVtIjp1LHU9bC5waXhlbExlZnQrInB4IixsLmxlZnQ9aSxhJiYoby5sZWZ0PWEpKSwiIj09PXU/ImF1dG8iOnV9KTtmdW5jdGlvbiBvbihlLHQsbil7dmFyIHI9VnQuZXhlYyh0KTtyZXR1cm4gcj9NYXRoLm1heCgwLHJbMV0tKG58fDApKSsoclsyXXx8InB4Iik6dH1mdW5jdGlvbiBhbihlLHQsbixyLGkpe3ZhciBvPW49PT0ocj8iYm9yZGVyIjoiY29udGVudCIpPzQ6IndpZHRoIj09PXQ/MTowLGE9MDtmb3IoOzQ+bztvKz0yKSJtYXJnaW4iPT09biYmKGErPWIuY3NzKGUsbitadFtvXSwhMCxpKSkscj8oImNvbnRlbnQiPT09biYmKGEtPWIuY3NzKGUsInBhZGRpbmciK1p0W29dLCEwLGkpKSwibWFyZ2luIiE9PW4mJihhLT1iLmNzcyhlLCJib3JkZXIiK1p0W29dKyJXaWR0aCIsITAsaSkpKTooYSs9Yi5jc3MoZSwicGFkZGluZyIrWnRbb10sITAsaSksInBhZGRpbmciIT09biYmKGErPWIuY3NzKGUsImJvcmRlciIrWnRbb10rIldpZHRoIiwhMCxpKSkpO3JldHVybiBhfWZ1bmN0aW9uIHNuKGUsdCxuKXt2YXIgcj0hMCxpPSJ3aWR0aCI9PT10P2Uub2Zmc2V0V2lkdGg6ZS5vZmZzZXRIZWlnaHQsbz1SdChlKSxhPWIuc3VwcG9ydC5ib3hTaXppbmcmJiJib3JkZXItYm94Ij09PWIuY3NzKGUsImJveFNpemluZyIsITEsbyk7aWYoMD49aXx8bnVsbD09aSl7aWYoaT1XdChlLHQsbyksKDA+aXx8bnVsbD09aSkmJihpPWUuc3R5bGVbdF0pLFl0LnRlc3QoaSkpcmV0dXJuIGk7cj1hJiYoYi5zdXBwb3J0LmJveFNpemluZ1JlbGlhYmxlfHxpPT09ZS5zdHlsZVt0XSksaT1wYXJzZUZsb2F0KGkpfHwwfXJldHVybiBpK2FuKGUsdCxufHwoYT8iYm9yZGVyIjoiY29udGVudCIpLHIsbykrInB4In1mdW5jdGlvbiB1bihlKXt2YXIgdD1vLG49R3RbZV07cmV0dXJuIG58fChuPWxuKGUsdCksIm5vbmUiIT09biYmbnx8KFB0PShQdHx8YigiPGlmcmFtZSBmcmFtZWJvcmRlcj0nMCcgd2lkdGg9JzAnIGhlaWdodD0nMCcvPiIpLmNzcygiY3NzVGV4dCIsImRpc3BsYXk6YmxvY2sgIWltcG9ydGFudCIpKS5hcHBlbmRUbyh0LmRvY3VtZW50RWxlbWVudCksdD0oUHRbMF0uY29udGVudFdpbmRvd3x8UHRbMF0uY29udGVudERvY3VtZW50KS5kb2N1bWVudCx0LndyaXRlKCI8IWRvY3R5cGUgaHRtbD48aHRtbD48Ym9keT4iKSx0LmNsb3NlKCksbj1sbihlLHQpLFB0LmRldGFjaCgpKSxHdFtlXT1uKSxufWZ1bmN0aW9uIGxuKGUsdCl7dmFyIG49Yih0LmNyZWF0ZUVsZW1lbnQoZSkpLmFwcGVuZFRvKHQuYm9keSkscj1iLmNzcyhuWzBdLCJkaXNwbGF5Iik7cmV0dXJuIG4ucmVtb3ZlKCkscn1iLmVhY2goWyJoZWlnaHQiLCJ3aWR0aCJdLGZ1bmN0aW9uKGUsbil7Yi5jc3NIb29rc1tuXT17Z2V0OmZ1bmN0aW9uKGUscixpKXtyZXR1cm4gcj8wPT09ZS5vZmZzZXRXaWR0aCYmWHQudGVzdChiLmNzcyhlLCJkaXNwbGF5IikpP2Iuc3dhcChlLFF0LGZ1bmN0aW9uKCl7cmV0dXJuIHNuKGUsbixpKX0pOnNuKGUsbixpKTp0fSxzZXQ6ZnVuY3Rpb24oZSx0LHIpe3ZhciBpPXImJlJ0KGUpO3JldHVybiBvbihlLHQscj9hbihlLG4scixiLnN1cHBvcnQuYm94U2l6aW5nJiYiYm9yZGVyLWJveCI9PT1iLmNzcyhlLCJib3hTaXppbmciLCExLGkpLGkpOjApfX19KSxiLnN1cHBvcnQub3BhY2l0eXx8KGIuY3NzSG9va3Mub3BhY2l0eT17Z2V0OmZ1bmN0aW9uKGUsdCl7cmV0dXJuIEl0LnRlc3QoKHQmJmUuY3VycmVudFN0eWxlP2UuY3VycmVudFN0eWxlLmZpbHRlcjplLnN0eWxlLmZpbHRlcil8fCIiKT8uMDEqcGFyc2VGbG9hdChSZWdFeHAuJDEpKyIiOnQ/IjEiOiIifSxzZXQ6ZnVuY3Rpb24oZSx0KXt2YXIgbj1lLnN0eWxlLHI9ZS5jdXJyZW50U3R5bGUsaT1iLmlzTnVtZXJpYyh0KT8iYWxwaGEob3BhY2l0eT0iKzEwMCp0KyIpIjoiIixvPXImJnIuZmlsdGVyfHxuLmZpbHRlcnx8IiI7bi56b29tPTEsKHQ+PTF8fCIiPT09dCkmJiIiPT09Yi50cmltKG8ucmVwbGFjZSgkdCwiIikpJiZuLnJlbW92ZUF0dHJpYnV0ZSYmKG4ucmVtb3ZlQXR0cmlidXRlKCJmaWx0ZXIiKSwiIj09PXR8fHImJiFyLmZpbHRlcil8fChuLmZpbHRlcj0kdC50ZXN0KG8pP28ucmVwbGFjZSgkdCxpKTpvKyIgIitpKX19KSxiKGZ1bmN0aW9uKCl7Yi5zdXBwb3J0LnJlbGlhYmxlTWFyZ2luUmlnaHR8fChiLmNzc0hvb2tzLm1hcmdpblJpZ2h0PXtnZXQ6ZnVuY3Rpb24oZSxuKXtyZXR1cm4gbj9iLnN3YXAoZSx7ZGlzcGxheToiaW5saW5lLWJsb2NrIn0sV3QsW2UsIm1hcmdpblJpZ2h0Il0pOnR9fSksIWIuc3VwcG9ydC5waXhlbFBvc2l0aW9uJiZiLmZuLnBvc2l0aW9uJiZiLmVhY2goWyJ0b3AiLCJsZWZ0Il0sZnVuY3Rpb24oZSxuKXtiLmNzc0hvb2tzW25dPXtnZXQ6ZnVuY3Rpb24oZSxyKXtyZXR1cm4gcj8ocj1XdChlLG4pLFl0LnRlc3Qocik/YihlKS5wb3NpdGlvbigpW25dKyJweCI6cik6dH19fSl9KSxiLmV4cHImJmIuZXhwci5maWx0ZXJzJiYoYi5leHByLmZpbHRlcnMuaGlkZGVuPWZ1bmN0aW9uKGUpe3JldHVybiAwPj1lLm9mZnNldFdpZHRoJiYwPj1lLm9mZnNldEhlaWdodHx8IWIuc3VwcG9ydC5yZWxpYWJsZUhpZGRlbk9mZnNldHMmJiJub25lIj09PShlLnN0eWxlJiZlLnN0eWxlLmRpc3BsYXl8fGIuY3NzKGUsImRpc3BsYXkiKSl9LGIuZXhwci5maWx0ZXJzLnZpc2libGU9ZnVuY3Rpb24oZSl7cmV0dXJuIWIuZXhwci5maWx0ZXJzLmhpZGRlbihlKX0pLGIuZWFjaCh7bWFyZ2luOiIiLHBhZGRpbmc6IiIsYm9yZGVyOiJXaWR0aCJ9LGZ1bmN0aW9uKGUsdCl7Yi5jc3NIb29rc1tlK3RdPXtleHBhbmQ6ZnVuY3Rpb24obil7dmFyIHI9MCxpPXt9LG89InN0cmluZyI9PXR5cGVvZiBuP24uc3BsaXQoIiAiKTpbbl07Zm9yKDs0PnI7cisrKWlbZStadFtyXSt0XT1vW3JdfHxvW3ItMl18fG9bMF07cmV0dXJuIGl9fSxVdC50ZXN0KGUpfHwoYi5jc3NIb29rc1tlK3RdLnNldD1vbil9KTt2YXIgY249LyUyMC9nLHBuPS9cW1xdJC8sZm49L1xyP1xuL2csZG49L14oPzpzdWJtaXR8YnV0dG9ufGltYWdlfHJlc2V0fGZpbGUpJC9pLGhuPS9eKD86aW5wdXR8c2VsZWN0fHRleHRhcmVhfGtleWdlbikvaTtiLmZuLmV4dGVuZCh7c2VyaWFsaXplOmZ1bmN0aW9uKCl7cmV0dXJuIGIucGFyYW0odGhpcy5zZXJpYWxpemVBcnJheSgpKX0sc2VyaWFsaXplQXJyYXk6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5tYXAoZnVuY3Rpb24oKXt2YXIgZT1iLnByb3AodGhpcywiZWxlbWVudHMiKTtyZXR1cm4gZT9iLm1ha2VBcnJheShlKTp0aGlzfSkuZmlsdGVyKGZ1bmN0aW9uKCl7dmFyIGU9dGhpcy50eXBlO3JldHVybiB0aGlzLm5hbWUmJiFiKHRoaXMpLmlzKCI6ZGlzYWJsZWQiKSYmaG4udGVzdCh0aGlzLm5vZGVOYW1lKSYmIWRuLnRlc3QoZSkmJih0aGlzLmNoZWNrZWR8fCFOdC50ZXN0KGUpKX0pLm1hcChmdW5jdGlvbihlLHQpe3ZhciBuPWIodGhpcykudmFsKCk7cmV0dXJuIG51bGw9PW4/bnVsbDpiLmlzQXJyYXkobik/Yi5tYXAobixmdW5jdGlvbihlKXtyZXR1cm57bmFtZTp0Lm5hbWUsdmFsdWU6ZS5yZXBsYWNlKGZuLCJcclxuIil9fSk6e25hbWU6dC5uYW1lLHZhbHVlOm4ucmVwbGFjZShmbiwiXHJcbiIpfX0pLmdldCgpfX0pLGIucGFyYW09ZnVuY3Rpb24oZSxuKXt2YXIgcixpPVtdLG89ZnVuY3Rpb24oZSx0KXt0PWIuaXNGdW5jdGlvbih0KT90KCk6bnVsbD09dD8iIjp0LGlbaS5sZW5ndGhdPWVuY29kZVVSSUNvbXBvbmVudChlKSsiPSIrZW5jb2RlVVJJQ29tcG9uZW50KHQpfTtpZihuPT09dCYmKG49Yi5hamF4U2V0dGluZ3MmJmIuYWpheFNldHRpbmdzLnRyYWRpdGlvbmFsKSxiLmlzQXJyYXkoZSl8fGUuanF1ZXJ5JiYhYi5pc1BsYWluT2JqZWN0KGUpKWIuZWFjaChlLGZ1bmN0aW9uKCl7byh0aGlzLm5hbWUsdGhpcy52YWx1ZSl9KTtlbHNlIGZvcihyIGluIGUpZ24ocixlW3JdLG4sbyk7cmV0dXJuIGkuam9pbigiJiIpLnJlcGxhY2UoY24sIisiKX07ZnVuY3Rpb24gZ24oZSx0LG4scil7dmFyIGk7aWYoYi5pc0FycmF5KHQpKWIuZWFjaCh0LGZ1bmN0aW9uKHQsaSl7bnx8cG4udGVzdChlKT9yKGUsaSk6Z24oZSsiWyIrKCJvYmplY3QiPT10eXBlb2YgaT90OiIiKSsiXSIsaSxuLHIpfSk7ZWxzZSBpZihufHwib2JqZWN0IiE9PWIudHlwZSh0KSlyKGUsdCk7ZWxzZSBmb3IoaSBpbiB0KWduKGUrIlsiK2krIl0iLHRbaV0sbixyKX1iLmVhY2goImJsdXIgZm9jdXMgZm9jdXNpbiBmb2N1c291dCBsb2FkIHJlc2l6ZSBzY3JvbGwgdW5sb2FkIGNsaWNrIGRibGNsaWNrIG1vdXNlZG93biBtb3VzZXVwIG1vdXNlbW92ZSBtb3VzZW92ZXIgbW91c2VvdXQgbW91c2VlbnRlciBtb3VzZWxlYXZlIGNoYW5nZSBzZWxlY3Qgc3VibWl0IGtleWRvd24ga2V5cHJlc3Mga2V5dXAgZXJyb3IgY29udGV4dG1lbnUiLnNwbGl0KCIgIiksZnVuY3Rpb24oZSx0KXtiLmZuW3RdPWZ1bmN0aW9uKGUsbil7cmV0dXJuIGFyZ3VtZW50cy5sZW5ndGg+MD90aGlzLm9uKHQsbnVsbCxlLG4pOnRoaXMudHJpZ2dlcih0KX19KSxiLmZuLmhvdmVyPWZ1bmN0aW9uKGUsdCl7cmV0dXJuIHRoaXMubW91c2VlbnRlcihlKS5tb3VzZWxlYXZlKHR8fGUpfTt2YXIgbW4seW4sdm49Yi5ub3coKSxibj0vXD8vLHhuPS8jLiokLyx3bj0vKFs/Jl0pXz1bXiZdKi8sVG49L14oLio/KTpbIFx0XSooW15cclxuXSopXHI/JC9nbSxObj0vXig/OmFib3V0fGFwcHxhcHAtc3RvcmFnZXwuKy1leHRlbnNpb258ZmlsZXxyZXN8d2lkZ2V0KTokLyxDbj0vXig/OkdFVHxIRUFEKSQvLGtuPS9eXC9cLy8sRW49L14oW1x3ListXSs6KSg/OlwvXC8oW15cLz8jOl0qKSg/OjooXGQrKXwpfCkvLFNuPWIuZm4ubG9hZCxBbj17fSxqbj17fSxEbj0iKi8iLmNvbmNhdCgiKiIpO3RyeXt5bj1hLmhyZWZ9Y2F0Y2goTG4pe3luPW8uY3JlYXRlRWxlbWVudCgiYSIpLHluLmhyZWY9IiIseW49eW4uaHJlZn1tbj1Fbi5leGVjKHluLnRvTG93ZXJDYXNlKCkpfHxbXTtmdW5jdGlvbiBIbihlKXtyZXR1cm4gZnVuY3Rpb24odCxuKXsic3RyaW5nIiE9dHlwZW9mIHQmJihuPXQsdD0iKiIpO3ZhciByLGk9MCxvPXQudG9Mb3dlckNhc2UoKS5tYXRjaCh3KXx8W107aWYoYi5pc0Z1bmN0aW9uKG4pKXdoaWxlKHI9b1tpKytdKSIrIj09PXJbMF0/KHI9ci5zbGljZSgxKXx8IioiLChlW3JdPWVbcl18fFtdKS51bnNoaWZ0KG4pKTooZVtyXT1lW3JdfHxbXSkucHVzaChuKX19ZnVuY3Rpb24gcW4oZSxuLHIsaSl7dmFyIG89e30sYT1lPT09am47ZnVuY3Rpb24gcyh1KXt2YXIgbDtyZXR1cm4gb1t1XT0hMCxiLmVhY2goZVt1XXx8W10sZnVuY3Rpb24oZSx1KXt2YXIgYz11KG4scixpKTtyZXR1cm4ic3RyaW5nIiE9dHlwZW9mIGN8fGF8fG9bY10/YT8hKGw9Yyk6dDoobi5kYXRhVHlwZXMudW5zaGlmdChjKSxzKGMpLCExKX0pLGx9cmV0dXJuIHMobi5kYXRhVHlwZXNbMF0pfHwhb1siKiJdJiZzKCIqIil9ZnVuY3Rpb24gTW4oZSxuKXt2YXIgcixpLG89Yi5hamF4U2V0dGluZ3MuZmxhdE9wdGlvbnN8fHt9O2ZvcihpIGluIG4pbltpXSE9PXQmJigob1tpXT9lOnJ8fChyPXt9KSlbaV09bltpXSk7cmV0dXJuIHImJmIuZXh0ZW5kKCEwLGUsciksZX1iLmZuLmxvYWQ9ZnVuY3Rpb24oZSxuLHIpe2lmKCJzdHJpbmciIT10eXBlb2YgZSYmU24pcmV0dXJuIFNuLmFwcGx5KHRoaXMsYXJndW1lbnRzKTt2YXIgaSxvLGEscz10aGlzLHU9ZS5pbmRleE9mKCIgIik7cmV0dXJuIHU+PTAmJihpPWUuc2xpY2UodSxlLmxlbmd0aCksZT1lLnNsaWNlKDAsdSkpLGIuaXNGdW5jdGlvbihuKT8ocj1uLG49dCk6biYmIm9iamVjdCI9PXR5cGVvZiBuJiYoYT0iUE9TVCIpLHMubGVuZ3RoPjAmJmIuYWpheCh7dXJsOmUsdHlwZTphLGRhdGFUeXBlOiJodG1sIixkYXRhOm59KS5kb25lKGZ1bmN0aW9uKGUpe289YXJndW1lbnRzLHMuaHRtbChpP2IoIjxkaXY+IikuYXBwZW5kKGIucGFyc2VIVE1MKGUpKS5maW5kKGkpOmUpfSkuY29tcGxldGUociYmZnVuY3Rpb24oZSx0KXtzLmVhY2gocixvfHxbZS5yZXNwb25zZVRleHQsdCxlXSl9KSx0aGlzfSxiLmVhY2goWyJhamF4U3RhcnQiLCJhamF4U3RvcCIsImFqYXhDb21wbGV0ZSIsImFqYXhFcnJvciIsImFqYXhTdWNjZXNzIiwiYWpheFNlbmQiXSxmdW5jdGlvbihlLHQpe2IuZm5bdF09ZnVuY3Rpb24oZSl7cmV0dXJuIHRoaXMub24odCxlKX19KSxiLmVhY2goWyJnZXQiLCJwb3N0Il0sZnVuY3Rpb24oZSxuKXtiW25dPWZ1bmN0aW9uKGUscixpLG8pe3JldHVybiBiLmlzRnVuY3Rpb24ocikmJihvPW98fGksaT1yLHI9dCksYi5hamF4KHt1cmw6ZSx0eXBlOm4sZGF0YVR5cGU6byxkYXRhOnIsc3VjY2VzczppfSl9fSksYi5leHRlbmQoe2FjdGl2ZTowLGxhc3RNb2RpZmllZDp7fSxldGFnOnt9LGFqYXhTZXR0aW5nczp7dXJsOnluLHR5cGU6IkdFVCIsaXNMb2NhbDpObi50ZXN0KG1uWzFdKSxnbG9iYWw6ITAscHJvY2Vzc0RhdGE6ITAsYXN5bmM6ITAsY29udGVudFR5cGU6ImFwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZDsgY2hhcnNldD1VVEYtOCIsYWNjZXB0czp7IioiOkRuLHRleHQ6InRleHQvcGxhaW4iLGh0bWw6InRleHQvaHRtbCIseG1sOiJhcHBsaWNhdGlvbi94bWwsIHRleHQveG1sIixqc29uOiJhcHBsaWNhdGlvbi9qc29uLCB0ZXh0L2phdmFzY3JpcHQifSxjb250ZW50czp7eG1sOi94bWwvLGh0bWw6L2h0bWwvLGpzb246L2pzb24vfSxyZXNwb25zZUZpZWxkczp7eG1sOiJyZXNwb25zZVhNTCIsdGV4dDoicmVzcG9uc2VUZXh0In0sY29udmVydGVyczp7IiogdGV4dCI6ZS5TdHJpbmcsInRleHQgaHRtbCI6ITAsInRleHQganNvbiI6Yi5wYXJzZUpTT04sInRleHQgeG1sIjpiLnBhcnNlWE1MfSxmbGF0T3B0aW9uczp7dXJsOiEwLGNvbnRleHQ6ITB9fSxhamF4U2V0dXA6ZnVuY3Rpb24oZSx0KXtyZXR1cm4gdD9NbihNbihlLGIuYWpheFNldHRpbmdzKSx0KTpNbihiLmFqYXhTZXR0aW5ncyxlKX0sYWpheFByZWZpbHRlcjpIbihBbiksYWpheFRyYW5zcG9ydDpIbihqbiksYWpheDpmdW5jdGlvbihlLG4peyJvYmplY3QiPT10eXBlb2YgZSYmKG49ZSxlPXQpLG49bnx8e307dmFyIHIsaSxvLGEscyx1LGwsYyxwPWIuYWpheFNldHVwKHt9LG4pLGY9cC5jb250ZXh0fHxwLGQ9cC5jb250ZXh0JiYoZi5ub2RlVHlwZXx8Zi5qcXVlcnkpP2IoZik6Yi5ldmVudCxoPWIuRGVmZXJyZWQoKSxnPWIuQ2FsbGJhY2tzKCJvbmNlIG1lbW9yeSIpLG09cC5zdGF0dXNDb2RlfHx7fSx5PXt9LHY9e30seD0wLFQ9ImNhbmNlbGVkIixOPXtyZWFkeVN0YXRlOjAsZ2V0UmVzcG9uc2VIZWFkZXI6ZnVuY3Rpb24oZSl7dmFyIHQ7aWYoMj09PXgpe2lmKCFjKXtjPXt9O3doaWxlKHQ9VG4uZXhlYyhhKSljW3RbMV0udG9Mb3dlckNhc2UoKV09dFsyXX10PWNbZS50b0xvd2VyQ2FzZSgpXX1yZXR1cm4gbnVsbD09dD9udWxsOnR9LGdldEFsbFJlc3BvbnNlSGVhZGVyczpmdW5jdGlvbigpe3JldHVybiAyPT09eD9hOm51bGx9LHNldFJlcXVlc3RIZWFkZXI6ZnVuY3Rpb24oZSx0KXt2YXIgbj1lLnRvTG93ZXJDYXNlKCk7cmV0dXJuIHh8fChlPXZbbl09dltuXXx8ZSx5W2VdPXQpLHRoaXN9LG92ZXJyaWRlTWltZVR5cGU6ZnVuY3Rpb24oZSl7cmV0dXJuIHh8fChwLm1pbWVUeXBlPWUpLHRoaXN9LHN0YXR1c0NvZGU6ZnVuY3Rpb24oZSl7dmFyIHQ7aWYoZSlpZigyPngpZm9yKHQgaW4gZSltW3RdPVttW3RdLGVbdF1dO2Vsc2UgTi5hbHdheXMoZVtOLnN0YXR1c10pO3JldHVybiB0aGlzfSxhYm9ydDpmdW5jdGlvbihlKXt2YXIgdD1lfHxUO3JldHVybiBsJiZsLmFib3J0KHQpLGsoMCx0KSx0aGlzfX07aWYoaC5wcm9taXNlKE4pLmNvbXBsZXRlPWcuYWRkLE4uc3VjY2Vzcz1OLmRvbmUsTi5lcnJvcj1OLmZhaWwscC51cmw9KChlfHxwLnVybHx8eW4pKyIiKS5yZXBsYWNlKHhuLCIiKS5yZXBsYWNlKGtuLG1uWzFdKyIvLyIpLHAudHlwZT1uLm1ldGhvZHx8bi50eXBlfHxwLm1ldGhvZHx8cC50eXBlLHAuZGF0YVR5cGVzPWIudHJpbShwLmRhdGFUeXBlfHwiKiIpLnRvTG93ZXJDYXNlKCkubWF0Y2godyl8fFsiIl0sbnVsbD09cC5jcm9zc0RvbWFpbiYmKHI9RW4uZXhlYyhwLnVybC50b0xvd2VyQ2FzZSgpKSxwLmNyb3NzRG9tYWluPSEoIXJ8fHJbMV09PT1tblsxXSYmclsyXT09PW1uWzJdJiYoclszXXx8KCJodHRwOiI9PT1yWzFdPzgwOjQ0MykpPT0obW5bM118fCgiaHR0cDoiPT09bW5bMV0/ODA6NDQzKSkpKSxwLmRhdGEmJnAucHJvY2Vzc0RhdGEmJiJzdHJpbmciIT10eXBlb2YgcC5kYXRhJiYocC5kYXRhPWIucGFyYW0ocC5kYXRhLHAudHJhZGl0aW9uYWwpKSxxbihBbixwLG4sTiksMj09PXgpcmV0dXJuIE47dT1wLmdsb2JhbCx1JiYwPT09Yi5hY3RpdmUrKyYmYi5ldmVudC50cmlnZ2VyKCJhamF4U3RhcnQiKSxwLnR5cGU9cC50eXBlLnRvVXBwZXJDYXNlKCkscC5oYXNDb250ZW50PSFDbi50ZXN0KHAudHlwZSksbz1wLnVybCxwLmhhc0NvbnRlbnR8fChwLmRhdGEmJihvPXAudXJsKz0oYm4udGVzdChvKT8iJiI6Ij8iKStwLmRhdGEsZGVsZXRlIHAuZGF0YSkscC5jYWNoZT09PSExJiYocC51cmw9d24udGVzdChvKT9vLnJlcGxhY2Uod24sIiQxXz0iK3ZuKyspOm8rKGJuLnRlc3Qobyk/IiYiOiI/IikrIl89Iit2bisrKSkscC5pZk1vZGlmaWVkJiYoYi5sYXN0TW9kaWZpZWRbb10mJk4uc2V0UmVxdWVzdEhlYWRlcigiSWYtTW9kaWZpZWQtU2luY2UiLGIubGFzdE1vZGlmaWVkW29dKSxiLmV0YWdbb10mJk4uc2V0UmVxdWVzdEhlYWRlcigiSWYtTm9uZS1NYXRjaCIsYi5ldGFnW29dKSksKHAuZGF0YSYmcC5oYXNDb250ZW50JiZwLmNvbnRlbnRUeXBlIT09ITF8fG4uY29udGVudFR5cGUpJiZOLnNldFJlcXVlc3RIZWFkZXIoIkNvbnRlbnQtVHlwZSIscC5jb250ZW50VHlwZSksTi5zZXRSZXF1ZXN0SGVhZGVyKCJBY2NlcHQiLHAuZGF0YVR5cGVzWzBdJiZwLmFjY2VwdHNbcC5kYXRhVHlwZXNbMF1dP3AuYWNjZXB0c1twLmRhdGFUeXBlc1swXV0rKCIqIiE9PXAuZGF0YVR5cGVzWzBdPyIsICIrRG4rIjsgcT0wLjAxIjoiIik6cC5hY2NlcHRzWyIqIl0pO2ZvcihpIGluIHAuaGVhZGVycylOLnNldFJlcXVlc3RIZWFkZXIoaSxwLmhlYWRlcnNbaV0pO2lmKHAuYmVmb3JlU2VuZCYmKHAuYmVmb3JlU2VuZC5jYWxsKGYsTixwKT09PSExfHwyPT09eCkpcmV0dXJuIE4uYWJvcnQoKTtUPSJhYm9ydCI7Zm9yKGkgaW57c3VjY2VzczoxLGVycm9yOjEsY29tcGxldGU6MX0pTltpXShwW2ldKTtpZihsPXFuKGpuLHAsbixOKSl7Ti5yZWFkeVN0YXRlPTEsdSYmZC50cmlnZ2VyKCJhamF4U2VuZCIsW04scF0pLHAuYXN5bmMmJnAudGltZW91dD4wJiYocz1zZXRUaW1lb3V0KGZ1bmN0aW9uKCl7Ti5hYm9ydCgidGltZW91dCIpfSxwLnRpbWVvdXQpKTt0cnl7eD0xLGwuc2VuZCh5LGspfWNhdGNoKEMpe2lmKCEoMj54KSl0aHJvdyBDO2soLTEsQyl9fWVsc2UgaygtMSwiTm8gVHJhbnNwb3J0Iik7ZnVuY3Rpb24gayhlLG4scixpKXt2YXIgYyx5LHYsdyxULEM9bjsyIT09eCYmKHg9MixzJiZjbGVhclRpbWVvdXQocyksbD10LGE9aXx8IiIsTi5yZWFkeVN0YXRlPWU+MD80OjAsciYmKHc9X24ocCxOLHIpKSxlPj0yMDAmJjMwMD5lfHwzMDQ9PT1lPyhwLmlmTW9kaWZpZWQmJihUPU4uZ2V0UmVzcG9uc2VIZWFkZXIoIkxhc3QtTW9kaWZpZWQiKSxUJiYoYi5sYXN0TW9kaWZpZWRbb109VCksVD1OLmdldFJlc3BvbnNlSGVhZGVyKCJldGFnIiksVCYmKGIuZXRhZ1tvXT1UKSksMjA0PT09ZT8oYz0hMCxDPSJub2NvbnRlbnQiKTozMDQ9PT1lPyhjPSEwLEM9Im5vdG1vZGlmaWVkIik6KGM9Rm4ocCx3KSxDPWMuc3RhdGUseT1jLmRhdGEsdj1jLmVycm9yLGM9IXYpKToodj1DLChlfHwhQykmJihDPSJlcnJvciIsMD5lJiYoZT0wKSkpLE4uc3RhdHVzPWUsTi5zdGF0dXNUZXh0PShufHxDKSsiIixjP2gucmVzb2x2ZVdpdGgoZixbeSxDLE5dKTpoLnJlamVjdFdpdGgoZixbTixDLHZdKSxOLnN0YXR1c0NvZGUobSksbT10LHUmJmQudHJpZ2dlcihjPyJhamF4U3VjY2VzcyI6ImFqYXhFcnJvciIsW04scCxjP3k6dl0pLGcuZmlyZVdpdGgoZixbTixDXSksdSYmKGQudHJpZ2dlcigiYWpheENvbXBsZXRlIixbTixwXSksLS1iLmFjdGl2ZXx8Yi5ldmVudC50cmlnZ2VyKCJhamF4U3RvcCIpKSl9cmV0dXJuIE59LGdldFNjcmlwdDpmdW5jdGlvbihlLG4pe3JldHVybiBiLmdldChlLHQsbiwic2NyaXB0Iil9LGdldEpTT046ZnVuY3Rpb24oZSx0LG4pe3JldHVybiBiLmdldChlLHQsbiwianNvbiIpfX0pO2Z1bmN0aW9uIF9uKGUsbixyKXt2YXIgaSxvLGEscyx1PWUuY29udGVudHMsbD1lLmRhdGFUeXBlcyxjPWUucmVzcG9uc2VGaWVsZHM7Zm9yKHMgaW4gYylzIGluIHImJihuW2Nbc11dPXJbc10pO3doaWxlKCIqIj09PWxbMF0pbC5zaGlmdCgpLG89PT10JiYobz1lLm1pbWVUeXBlfHxuLmdldFJlc3BvbnNlSGVhZGVyKCJDb250ZW50LVR5cGUiKSk7aWYobylmb3IocyBpbiB1KWlmKHVbc10mJnVbc10udGVzdChvKSl7bC51bnNoaWZ0KHMpO2JyZWFrfWlmKGxbMF1pbiByKWE9bFswXTtlbHNle2ZvcihzIGluIHIpe2lmKCFsWzBdfHxlLmNvbnZlcnRlcnNbcysiICIrbFswXV0pe2E9czticmVha31pfHwoaT1zKX1hPWF8fGl9cmV0dXJuIGE/KGEhPT1sWzBdJiZsLnVuc2hpZnQoYSksclthXSk6dH1mdW5jdGlvbiBGbihlLHQpe3ZhciBuLHIsaSxvLGE9e30scz0wLHU9ZS5kYXRhVHlwZXMuc2xpY2UoKSxsPXVbMF07aWYoZS5kYXRhRmlsdGVyJiYodD1lLmRhdGFGaWx0ZXIodCxlLmRhdGFUeXBlKSksdVsxXSlmb3IoaSBpbiBlLmNvbnZlcnRlcnMpYVtpLnRvTG93ZXJDYXNlKCldPWUuY29udmVydGVyc1tpXTtmb3IoO3I9dVsrK3NdOylpZigiKiIhPT1yKXtpZigiKiIhPT1sJiZsIT09cil7aWYoaT1hW2wrIiAiK3JdfHxhWyIqICIrcl0sIWkpZm9yKG4gaW4gYSlpZihvPW4uc3BsaXQoIiAiKSxvWzFdPT09ciYmKGk9YVtsKyIgIitvWzBdXXx8YVsiKiAiK29bMF1dKSl7aT09PSEwP2k9YVtuXTphW25dIT09ITAmJihyPW9bMF0sdS5zcGxpY2Uocy0tLDAscikpO2JyZWFrfWlmKGkhPT0hMClpZihpJiZlWyJ0aHJvd3MiXSl0PWkodCk7ZWxzZSB0cnl7dD1pKHQpfWNhdGNoKGMpe3JldHVybntzdGF0ZToicGFyc2VyZXJyb3IiLGVycm9yOmk/YzoiTm8gY29udmVyc2lvbiBmcm9tICIrbCsiIHRvICIrcn19fWw9cn1yZXR1cm57c3RhdGU6InN1Y2Nlc3MiLGRhdGE6dH19Yi5hamF4U2V0dXAoe2FjY2VwdHM6e3NjcmlwdDoidGV4dC9qYXZhc2NyaXB0LCBhcHBsaWNhdGlvbi9qYXZhc2NyaXB0LCBhcHBsaWNhdGlvbi9lY21hc2NyaXB0LCBhcHBsaWNhdGlvbi94LWVjbWFzY3JpcHQifSxjb250ZW50czp7c2NyaXB0Oi8oPzpqYXZhfGVjbWEpc2NyaXB0L30sY29udmVydGVyczp7InRleHQgc2NyaXB0IjpmdW5jdGlvbihlKXtyZXR1cm4gYi5nbG9iYWxFdmFsKGUpLGV9fX0pLGIuYWpheFByZWZpbHRlcigic2NyaXB0IixmdW5jdGlvbihlKXtlLmNhY2hlPT09dCYmKGUuY2FjaGU9ITEpLGUuY3Jvc3NEb21haW4mJihlLnR5cGU9IkdFVCIsZS5nbG9iYWw9ITEpfSksYi5hamF4VHJhbnNwb3J0KCJzY3JpcHQiLGZ1bmN0aW9uKGUpe2lmKGUuY3Jvc3NEb21haW4pe3ZhciBuLHI9by5oZWFkfHxiKCJoZWFkIilbMF18fG8uZG9jdW1lbnRFbGVtZW50O3JldHVybntzZW5kOmZ1bmN0aW9uKHQsaSl7bj1vLmNyZWF0ZUVsZW1lbnQoInNjcmlwdCIpLG4uYXN5bmM9ITAsZS5zY3JpcHRDaGFyc2V0JiYobi5jaGFyc2V0PWUuc2NyaXB0Q2hhcnNldCksbi5zcmM9ZS51cmwsbi5vbmxvYWQ9bi5vbnJlYWR5c3RhdGVjaGFuZ2U9ZnVuY3Rpb24oZSx0KXsodHx8IW4ucmVhZHlTdGF0ZXx8L2xvYWRlZHxjb21wbGV0ZS8udGVzdChuLnJlYWR5U3RhdGUpKSYmKG4ub25sb2FkPW4ub25yZWFkeXN0YXRlY2hhbmdlPW51bGwsbi5wYXJlbnROb2RlJiZuLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQobiksbj1udWxsLHR8fGkoMjAwLCJzdWNjZXNzIikpfSxyLmluc2VydEJlZm9yZShuLHIuZmlyc3RDaGlsZCl9LGFib3J0OmZ1bmN0aW9uKCl7biYmbi5vbmxvYWQodCwhMCl9fX19KTt2YXIgT249W10sQm49Lyg9KVw/KD89JnwkKXxcP1w/LztiLmFqYXhTZXR1cCh7anNvbnA6ImNhbGxiYWNrIixqc29ucENhbGxiYWNrOmZ1bmN0aW9uKCl7dmFyIGU9T24ucG9wKCl8fGIuZXhwYW5kbysiXyIrdm4rKztyZXR1cm4gdGhpc1tlXT0hMCxlfX0pLGIuYWpheFByZWZpbHRlcigianNvbiBqc29ucCIsZnVuY3Rpb24obixyLGkpe3ZhciBvLGEscyx1PW4uanNvbnAhPT0hMSYmKEJuLnRlc3Qobi51cmwpPyJ1cmwiOiJzdHJpbmciPT10eXBlb2Ygbi5kYXRhJiYhKG4uY29udGVudFR5cGV8fCIiKS5pbmRleE9mKCJhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQiKSYmQm4udGVzdChuLmRhdGEpJiYiZGF0YSIpO3JldHVybiB1fHwianNvbnAiPT09bi5kYXRhVHlwZXNbMF0/KG89bi5qc29ucENhbGxiYWNrPWIuaXNGdW5jdGlvbihuLmpzb25wQ2FsbGJhY2spP24uanNvbnBDYWxsYmFjaygpOm4uanNvbnBDYWxsYmFjayx1P25bdV09blt1XS5yZXBsYWNlKEJuLCIkMSIrbyk6bi5qc29ucCE9PSExJiYobi51cmwrPShibi50ZXN0KG4udXJsKT8iJiI6Ij8iKStuLmpzb25wKyI9IitvKSxuLmNvbnZlcnRlcnNbInNjcmlwdCBqc29uIl09ZnVuY3Rpb24oKXtyZXR1cm4gc3x8Yi5lcnJvcihvKyIgd2FzIG5vdCBjYWxsZWQiKSxzWzBdfSxuLmRhdGFUeXBlc1swXT0ianNvbiIsYT1lW29dLGVbb109ZnVuY3Rpb24oKXtzPWFyZ3VtZW50c30saS5hbHdheXMoZnVuY3Rpb24oKXtlW29dPWEsbltvXSYmKG4uanNvbnBDYWxsYmFjaz1yLmpzb25wQ2FsbGJhY2ssT24ucHVzaChvKSkscyYmYi5pc0Z1bmN0aW9uKGEpJiZhKHNbMF0pLHM9YT10fSksInNjcmlwdCIpOnR9KTt2YXIgUG4sUm4sV249MCwkbj1lLkFjdGl2ZVhPYmplY3QmJmZ1bmN0aW9uKCl7dmFyIGU7Zm9yKGUgaW4gUG4pUG5bZV0odCwhMCl9O2Z1bmN0aW9uIEluKCl7dHJ5e3JldHVybiBuZXcgZS5YTUxIdHRwUmVxdWVzdH1jYXRjaCh0KXt9fWZ1bmN0aW9uIHpuKCl7dHJ5e3JldHVybiBuZXcgZS5BY3RpdmVYT2JqZWN0KCJNaWNyb3NvZnQuWE1MSFRUUCIpfWNhdGNoKHQpe319Yi5hamF4U2V0dGluZ3MueGhyPWUuQWN0aXZlWE9iamVjdD9mdW5jdGlvbigpe3JldHVybiF0aGlzLmlzTG9jYWwmJkluKCl8fHpuKCl9OkluLFJuPWIuYWpheFNldHRpbmdzLnhocigpLGIuc3VwcG9ydC5jb3JzPSEhUm4mJiJ3aXRoQ3JlZGVudGlhbHMiaW4gUm4sUm49Yi5zdXBwb3J0LmFqYXg9ISFSbixSbiYmYi5hamF4VHJhbnNwb3J0KGZ1bmN0aW9uKG4pe2lmKCFuLmNyb3NzRG9tYWlufHxiLnN1cHBvcnQuY29ycyl7dmFyIHI7cmV0dXJue3NlbmQ6ZnVuY3Rpb24oaSxvKXt2YXIgYSxzLHU9bi54aHIoKTtpZihuLnVzZXJuYW1lP3Uub3BlbihuLnR5cGUsbi51cmwsbi5hc3luYyxuLnVzZXJuYW1lLG4ucGFzc3dvcmQpOnUub3BlbihuLnR5cGUsbi51cmwsbi5hc3luYyksbi54aHJGaWVsZHMpZm9yKHMgaW4gbi54aHJGaWVsZHMpdVtzXT1uLnhockZpZWxkc1tzXTtuLm1pbWVUeXBlJiZ1Lm92ZXJyaWRlTWltZVR5cGUmJnUub3ZlcnJpZGVNaW1lVHlwZShuLm1pbWVUeXBlKSxuLmNyb3NzRG9tYWlufHxpWyJYLVJlcXVlc3RlZC1XaXRoIl18fChpWyJYLVJlcXVlc3RlZC1XaXRoIl09IlhNTEh0dHBSZXF1ZXN0Iik7dHJ5e2ZvcihzIGluIGkpdS5zZXRSZXF1ZXN0SGVhZGVyKHMsaVtzXSl9Y2F0Y2gobCl7fXUuc2VuZChuLmhhc0NvbnRlbnQmJm4uZGF0YXx8bnVsbCkscj1mdW5jdGlvbihlLGkpe3ZhciBzLGwsYyxwO3RyeXtpZihyJiYoaXx8ND09PXUucmVhZHlTdGF0ZSkpaWYocj10LGEmJih1Lm9ucmVhZHlzdGF0ZWNoYW5nZT1iLm5vb3AsJG4mJmRlbGV0ZSBQblthXSksaSk0IT09dS5yZWFkeVN0YXRlJiZ1LmFib3J0KCk7ZWxzZXtwPXt9LHM9dS5zdGF0dXMsbD11LmdldEFsbFJlc3BvbnNlSGVhZGVycygpLCJzdHJpbmciPT10eXBlb2YgdS5yZXNwb25zZVRleHQmJihwLnRleHQ9dS5yZXNwb25zZVRleHQpO3RyeXtjPXUuc3RhdHVzVGV4dH1jYXRjaChmKXtjPSIifXN8fCFuLmlzTG9jYWx8fG4uY3Jvc3NEb21haW4/MTIyMz09PXMmJihzPTIwNCk6cz1wLnRleHQ/MjAwOjQwNH19Y2F0Y2goZCl7aXx8bygtMSxkKX1wJiZvKHMsYyxwLGwpfSxuLmFzeW5jPzQ9PT11LnJlYWR5U3RhdGU/c2V0VGltZW91dChyKTooYT0rK1duLCRuJiYoUG58fChQbj17fSxiKGUpLnVubG9hZCgkbikpLFBuW2FdPXIpLHUub25yZWFkeXN0YXRlY2hhbmdlPXIpOnIoKX0sYWJvcnQ6ZnVuY3Rpb24oKXtyJiZyKHQsITApfX19fSk7dmFyIFhuLFVuLFZuPS9eKD86dG9nZ2xlfHNob3d8aGlkZSkkLyxZbj1SZWdFeHAoIl4oPzooWystXSk9fCkoIit4KyIpKFthLXolXSopJCIsImkiKSxKbj0vcXVldWVIb29rcyQvLEduPVtucl0sUW49eyIqIjpbZnVuY3Rpb24oZSx0KXt2YXIgbixyLGk9dGhpcy5jcmVhdGVUd2VlbihlLHQpLG89WW4uZXhlYyh0KSxhPWkuY3VyKCkscz0rYXx8MCx1PTEsbD0yMDtpZihvKXtpZihuPStvWzJdLHI9b1szXXx8KGIuY3NzTnVtYmVyW2VdPyIiOiJweCIpLCJweCIhPT1yJiZzKXtzPWIuY3NzKGkuZWxlbSxlLCEwKXx8bnx8MTtkbyB1PXV8fCIuNSIscy89dSxiLnN0eWxlKGkuZWxlbSxlLHMrcik7d2hpbGUodSE9PSh1PWkuY3VyKCkvYSkmJjEhPT11JiYtLWwpfWkudW5pdD1yLGkuc3RhcnQ9cyxpLmVuZD1vWzFdP3MrKG9bMV0rMSkqbjpufXJldHVybiBpfV19O2Z1bmN0aW9uIEtuKCl7cmV0dXJuIHNldFRpbWVvdXQoZnVuY3Rpb24oKXtYbj10fSksWG49Yi5ub3coKX1mdW5jdGlvbiBabihlLHQpe2IuZWFjaCh0LGZ1bmN0aW9uKHQsbil7dmFyIHI9KFFuW3RdfHxbXSkuY29uY2F0KFFuWyIqIl0pLGk9MCxvPXIubGVuZ3RoO2Zvcig7bz5pO2krKylpZihyW2ldLmNhbGwoZSx0LG4pKXJldHVybn0pfWZ1bmN0aW9uIGVyKGUsdCxuKXt2YXIgcixpLG89MCxhPUduLmxlbmd0aCxzPWIuRGVmZXJyZWQoKS5hbHdheXMoZnVuY3Rpb24oKXtkZWxldGUgdS5lbGVtfSksdT1mdW5jdGlvbigpe2lmKGkpcmV0dXJuITE7dmFyIHQ9WG58fEtuKCksbj1NYXRoLm1heCgwLGwuc3RhcnRUaW1lK2wuZHVyYXRpb24tdCkscj1uL2wuZHVyYXRpb258fDAsbz0xLXIsYT0wLHU9bC50d2VlbnMubGVuZ3RoO2Zvcig7dT5hO2ErKylsLnR3ZWVuc1thXS5ydW4obyk7cmV0dXJuIHMubm90aWZ5V2l0aChlLFtsLG8sbl0pLDE+byYmdT9uOihzLnJlc29sdmVXaXRoKGUsW2xdKSwhMSl9LGw9cy5wcm9taXNlKHtlbGVtOmUscHJvcHM6Yi5leHRlbmQoe30sdCksb3B0czpiLmV4dGVuZCghMCx7c3BlY2lhbEVhc2luZzp7fX0sbiksb3JpZ2luYWxQcm9wZXJ0aWVzOnQsb3JpZ2luYWxPcHRpb25zOm4sc3RhcnRUaW1lOlhufHxLbigpLGR1cmF0aW9uOm4uZHVyYXRpb24sdHdlZW5zOltdLGNyZWF0ZVR3ZWVuOmZ1bmN0aW9uKHQsbil7dmFyIHI9Yi5Ud2VlbihlLGwub3B0cyx0LG4sbC5vcHRzLnNwZWNpYWxFYXNpbmdbdF18fGwub3B0cy5lYXNpbmcpO3JldHVybiBsLnR3ZWVucy5wdXNoKHIpLHJ9LHN0b3A6ZnVuY3Rpb24odCl7dmFyIG49MCxyPXQ/bC50d2VlbnMubGVuZ3RoOjA7aWYoaSlyZXR1cm4gdGhpcztmb3IoaT0hMDtyPm47bisrKWwudHdlZW5zW25dLnJ1bigxKTtyZXR1cm4gdD9zLnJlc29sdmVXaXRoKGUsW2wsdF0pOnMucmVqZWN0V2l0aChlLFtsLHRdKSx0aGlzfX0pLGM9bC5wcm9wcztmb3IodHIoYyxsLm9wdHMuc3BlY2lhbEVhc2luZyk7YT5vO28rKylpZihyPUduW29dLmNhbGwobCxlLGMsbC5vcHRzKSlyZXR1cm4gcjtyZXR1cm4gWm4obCxjKSxiLmlzRnVuY3Rpb24obC5vcHRzLnN0YXJ0KSYmbC5vcHRzLnN0YXJ0LmNhbGwoZSxsKSxiLmZ4LnRpbWVyKGIuZXh0ZW5kKHUse2VsZW06ZSxhbmltOmwscXVldWU6bC5vcHRzLnF1ZXVlfSkpLGwucHJvZ3Jlc3MobC5vcHRzLnByb2dyZXNzKS5kb25lKGwub3B0cy5kb25lLGwub3B0cy5jb21wbGV0ZSkuZmFpbChsLm9wdHMuZmFpbCkuYWx3YXlzKGwub3B0cy5hbHdheXMpfWZ1bmN0aW9uIHRyKGUsdCl7dmFyIG4scixpLG8sYTtmb3IoaSBpbiBlKWlmKHI9Yi5jYW1lbENhc2UoaSksbz10W3JdLG49ZVtpXSxiLmlzQXJyYXkobikmJihvPW5bMV0sbj1lW2ldPW5bMF0pLGkhPT1yJiYoZVtyXT1uLGRlbGV0ZSBlW2ldKSxhPWIuY3NzSG9va3Nbcl0sYSYmImV4cGFuZCJpbiBhKXtuPWEuZXhwYW5kKG4pLGRlbGV0ZSBlW3JdO2ZvcihpIGluIG4paSBpbiBlfHwoZVtpXT1uW2ldLHRbaV09byl9ZWxzZSB0W3JdPW99Yi5BbmltYXRpb249Yi5leHRlbmQoZXIse3R3ZWVuZXI6ZnVuY3Rpb24oZSx0KXtiLmlzRnVuY3Rpb24oZSk/KHQ9ZSxlPVsiKiJdKTplPWUuc3BsaXQoIiAiKTt2YXIgbixyPTAsaT1lLmxlbmd0aDtmb3IoO2k+cjtyKyspbj1lW3JdLFFuW25dPVFuW25dfHxbXSxRbltuXS51bnNoaWZ0KHQpfSxwcmVmaWx0ZXI6ZnVuY3Rpb24oZSx0KXt0P0duLnVuc2hpZnQoZSk6R24ucHVzaChlKX19KTtmdW5jdGlvbiBucihlLHQsbil7dmFyIHIsaSxvLGEscyx1LGwsYyxwLGY9dGhpcyxkPWUuc3R5bGUsaD17fSxnPVtdLG09ZS5ub2RlVHlwZSYmbm4oZSk7bi5xdWV1ZXx8KGM9Yi5fcXVldWVIb29rcyhlLCJmeCIpLG51bGw9PWMudW5xdWV1ZWQmJihjLnVucXVldWVkPTAscD1jLmVtcHR5LmZpcmUsYy5lbXB0eS5maXJlPWZ1bmN0aW9uKCl7Yy51bnF1ZXVlZHx8cCgpfSksYy51bnF1ZXVlZCsrLGYuYWx3YXlzKGZ1bmN0aW9uKCl7Zi5hbHdheXMoZnVuY3Rpb24oKXtjLnVucXVldWVkLS0sYi5xdWV1ZShlLCJmeCIpLmxlbmd0aHx8Yy5lbXB0eS5maXJlKCl9KX0pKSwxPT09ZS5ub2RlVHlwZSYmKCJoZWlnaHQiaW4gdHx8IndpZHRoImluIHQpJiYobi5vdmVyZmxvdz1bZC5vdmVyZmxvdyxkLm92ZXJmbG93WCxkLm92ZXJmbG93WV0sImlubGluZSI9PT1iLmNzcyhlLCJkaXNwbGF5IikmJiJub25lIj09PWIuY3NzKGUsImZsb2F0IikmJihiLnN1cHBvcnQuaW5saW5lQmxvY2tOZWVkc0xheW91dCYmImlubGluZSIhPT11bihlLm5vZGVOYW1lKT9kLnpvb209MTpkLmRpc3BsYXk9ImlubGluZS1ibG9jayIpKSxuLm92ZXJmbG93JiYoZC5vdmVyZmxvdz0iaGlkZGVuIixiLnN1cHBvcnQuc2hyaW5rV3JhcEJsb2Nrc3x8Zi5hbHdheXMoZnVuY3Rpb24oKXtkLm92ZXJmbG93PW4ub3ZlcmZsb3dbMF0sZC5vdmVyZmxvd1g9bi5vdmVyZmxvd1sxXSxkLm92ZXJmbG93WT1uLm92ZXJmbG93WzJdfSkpO2ZvcihpIGluIHQpaWYoYT10W2ldLFZuLmV4ZWMoYSkpe2lmKGRlbGV0ZSB0W2ldLHU9dXx8InRvZ2dsZSI9PT1hLGE9PT0obT8iaGlkZSI6InNob3ciKSljb250aW51ZTtnLnB1c2goaSl9aWYobz1nLmxlbmd0aCl7cz1iLl9kYXRhKGUsImZ4c2hvdyIpfHxiLl9kYXRhKGUsImZ4c2hvdyIse30pLCJoaWRkZW4iaW4gcyYmKG09cy5oaWRkZW4pLHUmJihzLmhpZGRlbj0hbSksbT9iKGUpLnNob3coKTpmLmRvbmUoZnVuY3Rpb24oKXtiKGUpLmhpZGUoKX0pLGYuZG9uZShmdW5jdGlvbigpe3ZhciB0O2IuX3JlbW92ZURhdGEoZSwiZnhzaG93Iik7Zm9yKHQgaW4gaCliLnN0eWxlKGUsdCxoW3RdKX0pO2ZvcihpPTA7bz5pO2krKylyPWdbaV0sbD1mLmNyZWF0ZVR3ZWVuKHIsbT9zW3JdOjApLGhbcl09c1tyXXx8Yi5zdHlsZShlLHIpLHIgaW4gc3x8KHNbcl09bC5zdGFydCxtJiYobC5lbmQ9bC5zdGFydCxsLnN0YXJ0PSJ3aWR0aCI9PT1yfHwiaGVpZ2h0Ij09PXI/MTowKSl9fWZ1bmN0aW9uIHJyKGUsdCxuLHIsaSl7cmV0dXJuIG5ldyByci5wcm90b3R5cGUuaW5pdChlLHQsbixyLGkpfWIuVHdlZW49cnIscnIucHJvdG90eXBlPXtjb25zdHJ1Y3Rvcjpycixpbml0OmZ1bmN0aW9uKGUsdCxuLHIsaSxvKXt0aGlzLmVsZW09ZSx0aGlzLnByb3A9bix0aGlzLmVhc2luZz1pfHwic3dpbmciLHRoaXMub3B0aW9ucz10LHRoaXMuc3RhcnQ9dGhpcy5ub3c9dGhpcy5jdXIoKSx0aGlzLmVuZD1yLHRoaXMudW5pdD1vfHwoYi5jc3NOdW1iZXJbbl0/IiI6InB4Iil9LGN1cjpmdW5jdGlvbigpe3ZhciBlPXJyLnByb3BIb29rc1t0aGlzLnByb3BdO3JldHVybiBlJiZlLmdldD9lLmdldCh0aGlzKTpyci5wcm9wSG9va3MuX2RlZmF1bHQuZ2V0KHRoaXMpfSxydW46ZnVuY3Rpb24oZSl7dmFyIHQsbj1yci5wcm9wSG9va3NbdGhpcy5wcm9wXTtyZXR1cm4gdGhpcy5wb3M9dD10aGlzLm9wdGlvbnMuZHVyYXRpb24/Yi5lYXNpbmdbdGhpcy5lYXNpbmddKGUsdGhpcy5vcHRpb25zLmR1cmF0aW9uKmUsMCwxLHRoaXMub3B0aW9ucy5kdXJhdGlvbik6ZSx0aGlzLm5vdz0odGhpcy5lbmQtdGhpcy5zdGFydCkqdCt0aGlzLnN0YXJ0LHRoaXMub3B0aW9ucy5zdGVwJiZ0aGlzLm9wdGlvbnMuc3RlcC5jYWxsKHRoaXMuZWxlbSx0aGlzLm5vdyx0aGlzKSxuJiZuLnNldD9uLnNldCh0aGlzKTpyci5wcm9wSG9va3MuX2RlZmF1bHQuc2V0KHRoaXMpLHRoaXN9fSxyci5wcm90b3R5cGUuaW5pdC5wcm90b3R5cGU9cnIucHJvdG90eXBlLHJyLnByb3BIb29rcz17X2RlZmF1bHQ6e2dldDpmdW5jdGlvbihlKXt2YXIgdDtyZXR1cm4gbnVsbD09ZS5lbGVtW2UucHJvcF18fGUuZWxlbS5zdHlsZSYmbnVsbCE9ZS5lbGVtLnN0eWxlW2UucHJvcF0/KHQ9Yi5jc3MoZS5lbGVtLGUucHJvcCwiIiksdCYmImF1dG8iIT09dD90OjApOmUuZWxlbVtlLnByb3BdfSxzZXQ6ZnVuY3Rpb24oZSl7Yi5meC5zdGVwW2UucHJvcF0/Yi5meC5zdGVwW2UucHJvcF0oZSk6ZS5lbGVtLnN0eWxlJiYobnVsbCE9ZS5lbGVtLnN0eWxlW2IuY3NzUHJvcHNbZS5wcm9wXV18fGIuY3NzSG9va3NbZS5wcm9wXSk/Yi5zdHlsZShlLmVsZW0sZS5wcm9wLGUubm93K2UudW5pdCk6ZS5lbGVtW2UucHJvcF09ZS5ub3d9fX0scnIucHJvcEhvb2tzLnNjcm9sbFRvcD1yci5wcm9wSG9va3Muc2Nyb2xsTGVmdD17c2V0OmZ1bmN0aW9uKGUpe2UuZWxlbS5ub2RlVHlwZSYmZS5lbGVtLnBhcmVudE5vZGUmJihlLmVsZW1bZS5wcm9wXT1lLm5vdyl9fSxiLmVhY2goWyJ0b2dnbGUiLCJzaG93IiwiaGlkZSJdLGZ1bmN0aW9uKGUsdCl7dmFyIG49Yi5mblt0XTtiLmZuW3RdPWZ1bmN0aW9uKGUscixpKXtyZXR1cm4gbnVsbD09ZXx8ImJvb2xlYW4iPT10eXBlb2YgZT9uLmFwcGx5KHRoaXMsYXJndW1lbnRzKTp0aGlzLmFuaW1hdGUoaXIodCwhMCksZSxyLGkpfX0pLGIuZm4uZXh0ZW5kKHtmYWRlVG86ZnVuY3Rpb24oZSx0LG4scil7cmV0dXJuIHRoaXMuZmlsdGVyKG5uKS5jc3MoIm9wYWNpdHkiLDApLnNob3coKS5lbmQoKS5hbmltYXRlKHtvcGFjaXR5OnR9LGUsbixyKX0sYW5pbWF0ZTpmdW5jdGlvbihlLHQsbixyKXt2YXIgaT1iLmlzRW1wdHlPYmplY3QoZSksbz1iLnNwZWVkKHQsbixyKSxhPWZ1bmN0aW9uKCl7dmFyIHQ9ZXIodGhpcyxiLmV4dGVuZCh7fSxlKSxvKTthLmZpbmlzaD1mdW5jdGlvbigpe3Quc3RvcCghMCl9LChpfHxiLl9kYXRhKHRoaXMsImZpbmlzaCIpKSYmdC5zdG9wKCEwKX07cmV0dXJuIGEuZmluaXNoPWEsaXx8by5xdWV1ZT09PSExP3RoaXMuZWFjaChhKTp0aGlzLnF1ZXVlKG8ucXVldWUsYSl9LHN0b3A6ZnVuY3Rpb24oZSxuLHIpe3ZhciBpPWZ1bmN0aW9uKGUpe3ZhciB0PWUuc3RvcDtkZWxldGUgZS5zdG9wLHQocil9O3JldHVybiJzdHJpbmciIT10eXBlb2YgZSYmKHI9bixuPWUsZT10KSxuJiZlIT09ITEmJnRoaXMucXVldWUoZXx8ImZ4IixbXSksdGhpcy5lYWNoKGZ1bmN0aW9uKCl7dmFyIHQ9ITAsbj1udWxsIT1lJiZlKyJxdWV1ZUhvb2tzIixvPWIudGltZXJzLGE9Yi5fZGF0YSh0aGlzKTtpZihuKWFbbl0mJmFbbl0uc3RvcCYmaShhW25dKTtlbHNlIGZvcihuIGluIGEpYVtuXSYmYVtuXS5zdG9wJiZKbi50ZXN0KG4pJiZpKGFbbl0pO2ZvcihuPW8ubGVuZ3RoO24tLTspb1tuXS5lbGVtIT09dGhpc3x8bnVsbCE9ZSYmb1tuXS5xdWV1ZSE9PWV8fChvW25dLmFuaW0uc3RvcChyKSx0PSExLG8uc3BsaWNlKG4sMSkpOyh0fHwhcikmJmIuZGVxdWV1ZSh0aGlzLGUpfSl9LGZpbmlzaDpmdW5jdGlvbihlKXtyZXR1cm4gZSE9PSExJiYoZT1lfHwiZngiKSx0aGlzLmVhY2goZnVuY3Rpb24oKXt2YXIgdCxuPWIuX2RhdGEodGhpcykscj1uW2UrInF1ZXVlIl0saT1uW2UrInF1ZXVlSG9va3MiXSxvPWIudGltZXJzLGE9cj9yLmxlbmd0aDowO2ZvcihuLmZpbmlzaD0hMCxiLnF1ZXVlKHRoaXMsZSxbXSksaSYmaS5jdXImJmkuY3VyLmZpbmlzaCYmaS5jdXIuZmluaXNoLmNhbGwodGhpcyksdD1vLmxlbmd0aDt0LS07KW9bdF0uZWxlbT09PXRoaXMmJm9bdF0ucXVldWU9PT1lJiYob1t0XS5hbmltLnN0b3AoITApLG8uc3BsaWNlKHQsMSkpO2Zvcih0PTA7YT50O3QrKylyW3RdJiZyW3RdLmZpbmlzaCYmclt0XS5maW5pc2guY2FsbCh0aGlzKTtkZWxldGUgbi5maW5pc2h9KX19KTtmdW5jdGlvbiBpcihlLHQpe3ZhciBuLHI9e2hlaWdodDplfSxpPTA7Zm9yKHQ9dD8xOjA7ND5pO2krPTItdCluPVp0W2ldLHJbIm1hcmdpbiIrbl09clsicGFkZGluZyIrbl09ZTtyZXR1cm4gdCYmKHIub3BhY2l0eT1yLndpZHRoPWUpLHJ9Yi5lYWNoKHtzbGlkZURvd246aXIoInNob3ciKSxzbGlkZVVwOmlyKCJoaWRlIiksc2xpZGVUb2dnbGU6aXIoInRvZ2dsZSIpLGZhZGVJbjp7b3BhY2l0eToic2hvdyJ9LGZhZGVPdXQ6e29wYWNpdHk6ImhpZGUifSxmYWRlVG9nZ2xlOntvcGFjaXR5OiJ0b2dnbGUifX0sZnVuY3Rpb24oZSx0KXtiLmZuW2VdPWZ1bmN0aW9uKGUsbixyKXtyZXR1cm4gdGhpcy5hbmltYXRlKHQsZSxuLHIpfX0pLGIuc3BlZWQ9ZnVuY3Rpb24oZSx0LG4pe3ZhciByPWUmJiJvYmplY3QiPT10eXBlb2YgZT9iLmV4dGVuZCh7fSxlKTp7Y29tcGxldGU6bnx8IW4mJnR8fGIuaXNGdW5jdGlvbihlKSYmZSxkdXJhdGlvbjplLGVhc2luZzpuJiZ0fHx0JiYhYi5pc0Z1bmN0aW9uKHQpJiZ0fTtyZXR1cm4gci5kdXJhdGlvbj1iLmZ4Lm9mZj8wOiJudW1iZXIiPT10eXBlb2Ygci5kdXJhdGlvbj9yLmR1cmF0aW9uOnIuZHVyYXRpb24gaW4gYi5meC5zcGVlZHM/Yi5meC5zcGVlZHNbci5kdXJhdGlvbl06Yi5meC5zcGVlZHMuX2RlZmF1bHQsKG51bGw9PXIucXVldWV8fHIucXVldWU9PT0hMCkmJihyLnF1ZXVlPSJmeCIpLHIub2xkPXIuY29tcGxldGUsci5jb21wbGV0ZT1mdW5jdGlvbigpe2IuaXNGdW5jdGlvbihyLm9sZCkmJnIub2xkLmNhbGwodGhpcyksci5xdWV1ZSYmYi5kZXF1ZXVlKHRoaXMsci5xdWV1ZSl9LHJ9LGIuZWFzaW5nPXtsaW5lYXI6ZnVuY3Rpb24oZSl7cmV0dXJuIGV9LHN3aW5nOmZ1bmN0aW9uKGUpe3JldHVybi41LU1hdGguY29zKGUqTWF0aC5QSSkvMn19LGIudGltZXJzPVtdLGIuZng9cnIucHJvdG90eXBlLmluaXQsYi5meC50aWNrPWZ1bmN0aW9uKCl7dmFyIGUsbj1iLnRpbWVycyxyPTA7Zm9yKFhuPWIubm93KCk7bi5sZW5ndGg+cjtyKyspZT1uW3JdLGUoKXx8bltyXSE9PWV8fG4uc3BsaWNlKHItLSwxKTtuLmxlbmd0aHx8Yi5meC5zdG9wKCksWG49dH0sYi5meC50aW1lcj1mdW5jdGlvbihlKXtlKCkmJmIudGltZXJzLnB1c2goZSkmJmIuZnguc3RhcnQoKX0sYi5meC5pbnRlcnZhbD0xMyxiLmZ4LnN0YXJ0PWZ1bmN0aW9uKCl7VW58fChVbj1zZXRJbnRlcnZhbChiLmZ4LnRpY2ssYi5meC5pbnRlcnZhbCkpfSxiLmZ4LnN0b3A9ZnVuY3Rpb24oKXtjbGVhckludGVydmFsKFVuKSxVbj1udWxsfSxiLmZ4LnNwZWVkcz17c2xvdzo2MDAsZmFzdDoyMDAsX2RlZmF1bHQ6NDAwfSxiLmZ4LnN0ZXA9e30sYi5leHByJiZiLmV4cHIuZmlsdGVycyYmKGIuZXhwci5maWx0ZXJzLmFuaW1hdGVkPWZ1bmN0aW9uKGUpe3JldHVybiBiLmdyZXAoYi50aW1lcnMsZnVuY3Rpb24odCl7cmV0dXJuIGU9PT10LmVsZW19KS5sZW5ndGh9KSxiLmZuLm9mZnNldD1mdW5jdGlvbihlKXtpZihhcmd1bWVudHMubGVuZ3RoKXJldHVybiBlPT09dD90aGlzOnRoaXMuZWFjaChmdW5jdGlvbih0KXtiLm9mZnNldC5zZXRPZmZzZXQodGhpcyxlLHQpfSk7dmFyIG4scixvPXt0b3A6MCxsZWZ0OjB9LGE9dGhpc1swXSxzPWEmJmEub3duZXJEb2N1bWVudDtpZihzKXJldHVybiBuPXMuZG9jdW1lbnRFbGVtZW50LGIuY29udGFpbnMobixhKT8odHlwZW9mIGEuZ2V0Qm91bmRpbmdDbGllbnRSZWN0IT09aSYmKG89YS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKSkscj1vcihzKSx7dG9wOm8udG9wKyhyLnBhZ2VZT2Zmc2V0fHxuLnNjcm9sbFRvcCktKG4uY2xpZW50VG9wfHwwKSxsZWZ0Om8ubGVmdCsoci5wYWdlWE9mZnNldHx8bi5zY3JvbGxMZWZ0KS0obi5jbGllbnRMZWZ0fHwwKX0pOm99LGIub2Zmc2V0PXtzZXRPZmZzZXQ6ZnVuY3Rpb24oZSx0LG4pe3ZhciByPWIuY3NzKGUsInBvc2l0aW9uIik7InN0YXRpYyI9PT1yJiYoZS5zdHlsZS5wb3NpdGlvbj0icmVsYXRpdmUiKTt2YXIgaT1iKGUpLG89aS5vZmZzZXQoKSxhPWIuY3NzKGUsInRvcCIpLHM9Yi5jc3MoZSwibGVmdCIpLHU9KCJhYnNvbHV0ZSI9PT1yfHwiZml4ZWQiPT09cikmJmIuaW5BcnJheSgiYXV0byIsW2Esc10pPi0xLGw9e30sYz17fSxwLGY7dT8oYz1pLnBvc2l0aW9uKCkscD1jLnRvcCxmPWMubGVmdCk6KHA9cGFyc2VGbG9hdChhKXx8MCxmPXBhcnNlRmxvYXQocyl8fDApLGIuaXNGdW5jdGlvbih0KSYmKHQ9dC5jYWxsKGUsbixvKSksbnVsbCE9dC50b3AmJihsLnRvcD10LnRvcC1vLnRvcCtwKSxudWxsIT10LmxlZnQmJihsLmxlZnQ9dC5sZWZ0LW8ubGVmdCtmKSwidXNpbmciaW4gdD90LnVzaW5nLmNhbGwoZSxsKTppLmNzcyhsKX19LGIuZm4uZXh0ZW5kKHtwb3NpdGlvbjpmdW5jdGlvbigpe2lmKHRoaXNbMF0pe3ZhciBlLHQsbj17dG9wOjAsbGVmdDowfSxyPXRoaXNbMF07cmV0dXJuImZpeGVkIj09PWIuY3NzKHIsInBvc2l0aW9uIik/dD1yLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpOihlPXRoaXMub2Zmc2V0UGFyZW50KCksdD10aGlzLm9mZnNldCgpLGIubm9kZU5hbWUoZVswXSwiaHRtbCIpfHwobj1lLm9mZnNldCgpKSxuLnRvcCs9Yi5jc3MoZVswXSwiYm9yZGVyVG9wV2lkdGgiLCEwKSxuLmxlZnQrPWIuY3NzKGVbMF0sImJvcmRlckxlZnRXaWR0aCIsITApKSx7dG9wOnQudG9wLW4udG9wLWIuY3NzKHIsIm1hcmdpblRvcCIsITApLGxlZnQ6dC5sZWZ0LW4ubGVmdC1iLmNzcyhyLCJtYXJnaW5MZWZ0IiwhMCl9fX0sb2Zmc2V0UGFyZW50OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMubWFwKGZ1bmN0aW9uKCl7dmFyIGU9dGhpcy5vZmZzZXRQYXJlbnR8fG8uZG9jdW1lbnRFbGVtZW50O3doaWxlKGUmJiFiLm5vZGVOYW1lKGUsImh0bWwiKSYmInN0YXRpYyI9PT1iLmNzcyhlLCJwb3NpdGlvbiIpKWU9ZS5vZmZzZXRQYXJlbnQ7cmV0dXJuIGV8fG8uZG9jdW1lbnRFbGVtZW50fSl9fSksYi5lYWNoKHtzY3JvbGxMZWZ0OiJwYWdlWE9mZnNldCIsc2Nyb2xsVG9wOiJwYWdlWU9mZnNldCJ9LGZ1bmN0aW9uKGUsbil7dmFyIHI9L1kvLnRlc3Qobik7Yi5mbltlXT1mdW5jdGlvbihpKXtyZXR1cm4gYi5hY2Nlc3ModGhpcyxmdW5jdGlvbihlLGksbyl7dmFyIGE9b3IoZSk7cmV0dXJuIG89PT10P2E/biBpbiBhP2Fbbl06YS5kb2N1bWVudC5kb2N1bWVudEVsZW1lbnRbaV06ZVtpXTooYT9hLnNjcm9sbFRvKHI/YihhKS5zY3JvbGxMZWZ0KCk6byxyP286YihhKS5zY3JvbGxUb3AoKSk6ZVtpXT1vLHQpfSxlLGksYXJndW1lbnRzLmxlbmd0aCxudWxsKX19KTtmdW5jdGlvbiBvcihlKXtyZXR1cm4gYi5pc1dpbmRvdyhlKT9lOjk9PT1lLm5vZGVUeXBlP2UuZGVmYXVsdFZpZXd8fGUucGFyZW50V2luZG93OiExfWIuZWFjaCh7SGVpZ2h0OiJoZWlnaHQiLFdpZHRoOiJ3aWR0aCJ9LGZ1bmN0aW9uKGUsbil7Yi5lYWNoKHtwYWRkaW5nOiJpbm5lciIrZSxjb250ZW50Om4sIiI6Im91dGVyIitlfSxmdW5jdGlvbihyLGkpe2IuZm5baV09ZnVuY3Rpb24oaSxvKXt2YXIgYT1hcmd1bWVudHMubGVuZ3RoJiYocnx8ImJvb2xlYW4iIT10eXBlb2YgaSkscz1yfHwoaT09PSEwfHxvPT09ITA/Im1hcmdpbiI6ImJvcmRlciIpO3JldHVybiBiLmFjY2Vzcyh0aGlzLGZ1bmN0aW9uKG4scixpKXt2YXIgbztyZXR1cm4gYi5pc1dpbmRvdyhuKT9uLmRvY3VtZW50LmRvY3VtZW50RWxlbWVudFsiY2xpZW50IitlXTo5PT09bi5ub2RlVHlwZT8obz1uLmRvY3VtZW50RWxlbWVudCxNYXRoLm1heChuLmJvZHlbInNjcm9sbCIrZV0sb1sic2Nyb2xsIitlXSxuLmJvZHlbIm9mZnNldCIrZV0sb1sib2Zmc2V0IitlXSxvWyJjbGllbnQiK2VdKSk6aT09PXQ/Yi5jc3MobixyLHMpOmIuc3R5bGUobixyLGkscyl9LG4sYT9pOnQsYSxudWxsKX19KX0pLGUualF1ZXJ5PWUuJD1iLCJmdW5jdGlvbiI9PXR5cGVvZiBkZWZpbmUmJmRlZmluZS5hbWQmJmRlZmluZS5hbWQualF1ZXJ5JiZkZWZpbmUoImpxdWVyeSIsW10sZnVuY3Rpb24oKXtyZXR1cm4gYn0pfSkod2luZG93KTsKCTwvc2NyaXB0PgoJPHNjcmlwdD4KCQlmdW5jdGlvbiBBY2NvcmRpb25NZW51KG9wdGlvbnMpe3RoaXMuY29uZmlnPXtjb250YWluZXJDbHM6Ii53cmFwLW1lbnUiLG1lbnVBcnJzOiIiLHR5cGU6ImNsaWNrIixyZW5kZXJDYWxsQmFjazpudWxsLGNsaWNrSXRlbUNhbGxCYWNrOm51bGx9O3RoaXMuY2FjaGU9e307dGhpcy5pbml0KG9wdGlvbnMpfUFjY29yZGlvbk1lbnUucHJvdG90eXBlPXtjb25zdHJ1Y3RvcjpBY2NvcmRpb25NZW51LGluaXQ6ZnVuY3Rpb24ob3B0aW9ucyl7dGhpcy5jb25maWc9JC5leHRlbmQodGhpcy5jb25maWcsb3B0aW9uc3x8e30pO3ZhciBzZWxmPXRoaXMsX2NvbmZpZz1zZWxmLmNvbmZpZyxfY2FjaGU9c2VsZi5jYWNoZTskKF9jb25maWcuY29udGFpbmVyQ2xzKS5lYWNoKGZ1bmN0aW9uKGluZGV4LGl0ZW0pe3NlbGYuX3JlbmRlckhUTUwoaXRlbSk7c2VsZi5fYmluZEVudihpdGVtKX0pfSxfcmVuZGVySFRNTDpmdW5jdGlvbihjb250YWluZXIpe3ZhciBzZWxmPXRoaXMsX2NvbmZpZz1zZWxmLmNvbmZpZyxfY2FjaGU9c2VsZi5jYWNoZTt2YXIgdWxodG1sPSQoIjx1bD48L3VsPiIpOyQoX2NvbmZpZy5tZW51QXJycykuZWFjaChmdW5jdGlvbihpbmRleCxpdGVtKXt2YXIgbGlodG1sPSQoIjxsaT48aDI+IitpdGVtLm5hbWUrIjwvaDI+PC9saT4iKTtpZihpdGVtLnN1Ym1lbnUmJml0ZW0uc3VibWVudS5sZW5ndGg+MCl7c2VsZi5fY3JlYXRlU3ViTWVudShpdGVtLnN1Ym1lbnUsbGlodG1sKX0kKHVsaHRtbCkuYXBwZW5kKGxpaHRtbCl9KTskKGNvbnRhaW5lcikuYXBwZW5kKHVsaHRtbCk7X2NvbmZpZy5yZW5kZXJDYWxsQmFjayYmJC5pc0Z1bmN0aW9uKF9jb25maWcucmVuZGVyQ2FsbEJhY2spJiZfY29uZmlnLnJlbmRlckNhbGxCYWNrKCk7c2VsZi5fbGV2ZWxJbmRlbnQodWxodG1sKX0sX2NyZWF0ZVN1Yk1lbnU6ZnVuY3Rpb24oc3VibWVudSxsaWh0bWwpe3ZhciBzZWxmPXRoaXMsX2NvbmZpZz1zZWxmLmNvbmZpZyxfY2FjaGU9c2VsZi5jYWNoZTt2YXIgc3ViVWw9JCgiPHVsPjwvdWw+IiksY2FsbGVlPWFyZ3VtZW50cy5jYWxsZWUsc3ViTGk7JChzdWJtZW51KS5lYWNoKGZ1bmN0aW9uKGluZGV4LGl0ZW0pe3ZhciB1cmw9aXRlbS51cmx8fCJqYXZhc2NyaXB0OnZvaWQoMCkiO3N1YkxpPSQoJzxsaT48YSBocmVmPSInK3VybCsnIj4nK2l0ZW0ubmFtZSsiPC9hPjwvbGk+Iik7aWYoaXRlbS5zdWJtZW51JiZpdGVtLnN1Ym1lbnUubGVuZ3RoPjApeyQoc3ViTGkpLmNoaWxkcmVuKCJhIikucHJlcGVuZCgnPGltZyBzcmM9ImRhdGE6aW1hZ2UvZ2lmO2Jhc2U2NCxSMGxHT0RsaEFRQUJBSUFBQVAvLy93QUFBQ0gvQzFoTlVDQkVZWFJoV0UxUVBEOTRjR0ZqYTJWMElHSmxaMmx1UFNMdnU3OGlJR2xrUFNKWE5VMHdUWEJEWldocFNIcHlaVk42VGxSamVtdGpPV1FpUHo0Z1BIZzZlRzF3YldWMFlTQjRiV3h1Y3pwNFBTSmhaRzlpWlRwdWN6cHRaWFJoTHlJZ2VEcDRiWEIwYXowaVFXUnZZbVVnV0UxUUlFTnZjbVVnTlM0d0xXTXdOakFnTmpFdU1UTTBOemMzTENBeU1ERXdMekF5THpFeUxURTNPak15T2pBd0lDQWdJQ0FnSUNBaVBpQThjbVJtT2xKRVJpQjRiV3h1Y3pweVpHWTlJbWgwZEhBNkx5OTNkM2N1ZHpNdWIzSm5MekU1T1Rrdk1ESXZNakl0Y21SbUxYTjViblJoZUMxdWN5TWlQaUE4Y21SbU9rUmxjMk55YVhCMGFXOXVJSEprWmpwaFltOTFkRDBpSWlCNGJXeHVjenA0YlhBOUltaDBkSEE2THk5dWN5NWhaRzlpWlM1amIyMHZlR0Z3THpFdU1DOGlJSGh0Ykc1ek9uaHRjRTFOUFNKb2RIUndPaTh2Ym5NdVlXUnZZbVV1WTI5dEwzaGhjQzh4TGpBdmJXMHZJaUI0Yld4dWN6cHpkRkpsWmowaWFIUjBjRG92TDI1ekxtRmtiMkpsTG1OdmJTOTRZWEF2TVM0d0wzTlVlWEJsTDFKbGMyOTFjbU5sVW1WbUl5SWdlRzF3T2tOeVpXRjBiM0pVYjI5c1BTSkJaRzlpWlNCUWFHOTBiM05vYjNBZ1ExTTFJRmRwYm1SdmQzTWlJSGh0Y0UxTk9rbHVjM1JoYm1ObFNVUTlJbmh0Y0M1cGFXUTZOVFJET1VVNVFUYzVSakF6TVRGRk1UazVOVVpCTURWR1FrVkZOVVUzTlRJaUlIaHRjRTFOT2tSdlkzVnRaVzUwU1VROUluaHRjQzVrYVdRNk5UUkRPVVU1UVRnNVJqQXpNVEZGTVRrNU5VWkJNRFZHUWtWRk5VVTNOVElpUGlBOGVHMXdUVTA2UkdWeWFYWmxaRVp5YjIwZ2MzUlNaV1k2YVc1emRHRnVZMlZKUkQwaWVHMXdMbWxwWkRvMU5FTTVSVGxCTlRsR01ETXhNVVV4T1RrMVJrRXdOVVpDUlVVMVJUYzFNaUlnYzNSU1pXWTZaRzlqZFcxbGJuUkpSRDBpZUcxd0xtUnBaRG8xTkVNNVJUbEJOamxHTURNeE1VVXhPVGsxUmtFd05VWkNSVVUxUlRjMU1pSXZQaUE4TDNKa1pqcEVaWE5qY21sd2RHbHZiajRnUEM5eVpHWTZVa1JHUGlBOEwzZzZlRzF3YldWMFlUNGdQRDk0Y0dGamEyVjBJR1Z1WkQwaWNpSS9QZ0gvL3YzOCsvcjUrUGYyOWZUejh2SHc3Kzd0N092cTZlam41dVhrNCtMaDROL2UzZHpiMnRuWTE5YlYxTlBTMGREUHpzM015OHJKeU1mR3hjVER3c0hBdjc2OXZMdTZ1YmkzdHJXMHM3S3hzSyt1cmF5cnFxbW9wNmFscEtPaW9hQ2ZucDJjbTVxWm1KZVdsWlNUa3BHUWo0Nk5qSXVLaVlpSGhvV0VnNEtCZ0g5K2ZYeDdlbmw0ZDNaMWRITnljWEJ2Ym0xc2EycHBhR2RtWldSalltRmdYMTVkWEZ0YVdWaFhWbFZVVTFKUlVFOU9UVXhMU2tsSVIwWkZSRU5DUVVBL1BqMDhPem81T0RjMk5UUXpNakV3THk0dExDc3FLU2duSmlVa0l5SWhJQjhlSFJ3Ykdoa1lGeFlWRkJNU0VSQVBEZzBNQ3dvSkNBY0dCUVFEQWdFQUFDSDVCQUVBQUFBQUxBQUFBQUFCQUFFQUFBSUNSQUVBT3c9PSIgYWx0PSIiLz4nKTtjYWxsZWUoaXRlbS5zdWJtZW51LHN1YkxpKX0kKHN1YlVsKS5hcHBlbmQoc3ViTGkpfSk7JChsaWh0bWwpLmFwcGVuZChzdWJVbCl9LF9sZXZlbEluZGVudDpmdW5jdGlvbih1bExpc3Qpe3ZhciBzZWxmPXRoaXMsX2NvbmZpZz1zZWxmLmNvbmZpZyxfY2FjaGU9c2VsZi5jYWNoZSxjYWxsZWU9YXJndW1lbnRzLmNhbGxlZTt2YXIgaW5pdFRleHRJbmRlbnQ9MixsZXY9MSwkb1VsPSQodWxMaXN0KTt3aGlsZSgkb1VsLmZpbmQoInVsIikubGVuZ3RoPjApe2luaXRUZXh0SW5kZW50PXBhcnNlSW50KGluaXRUZXh0SW5kZW50LDEwKSsyKyJlbSI7JG9VbC5jaGlsZHJlbigpLmNoaWxkcmVuKCJ1bCIpLmFkZENsYXNzKCJsZXYtIitsZXYpLmNoaWxkcmVuKCJsaSIpLmNzcygidGV4dC1pbmRlbnQiLGluaXRUZXh0SW5kZW50KTskb1VsPSRvVWwuY2hpbGRyZW4oKS5jaGlsZHJlbigidWwiKTtsZXYrK30kKHVsTGlzdCkuZmluZCgidWwiKS5oaWRlKCk7JCh1bExpc3QpLmZpbmQoInVsOmZpcnN0Iikuc2hvdygpfSxfYmluZEVudjpmdW5jdGlvbihjb250YWluZXIpe3ZhciBzZWxmPXRoaXMsX2NvbmZpZz1zZWxmLmNvbmZpZzskKCJoMixhIixjb250YWluZXIpLnVuYmluZChfY29uZmlnLnR5cGUpOyQoImgyLGEiLGNvbnRhaW5lcikuYmluZChfY29uZmlnLnR5cGUsZnVuY3Rpb24oZSl7aWYoJCh0aGlzKS5zaWJsaW5ncygidWwiKS5sZW5ndGg+MCl7JCh0aGlzKS5zaWJsaW5ncygidWwiKS5zbGlkZVRvZ2dsZSgic2xvdyIpLmVuZCgpLmNoaWxkcmVuKCJpbWciKS50b2dnbGVDbGFzcygidW5mb2xkIil9JCh0aGlzKS5wYXJlbnQoImxpIikuc2libGluZ3MoKS5maW5kKCJ1bCIpLmhpZGUoKS5lbmQoKS5maW5kKCJpbWcudW5mb2xkIikucmVtb3ZlQ2xhc3MoInVuZm9sZCIpO19jb25maWcuY2xpY2tJdGVtQ2FsbEJhY2smJiQuaXNGdW5jdGlvbihfY29uZmlnLmNsaWNrSXRlbUNhbGxCYWNrKSYmX2NvbmZpZy5jbGlja0l0ZW1DYWxsQmFjaygkKHRoaXMpKX0pfX07Cgk8L3NjcmlwdD4KCTwvaGVhZD4KCTxib2R5PgoJCTxkaXYgY2xhc3M9IndyYXAtbWVudSI+CgkJPC9kaXY+CgkJPGRpdiBjbGFzcz0id3JhcC1kYXRhIj4KCQkJPGRpdiBpZD0ncmVzdWx0Jz4KCQkJJHN0YXRpc3RpY3MkCgkJCTwvZGl2PgoJCTwvZGl2PgoJPC9ib2R5PgoJPHNjcmlwdD4KCXZhciBhZGluZm89JGFkaW5mbyQ7CgkkKGZ1bmN0aW9uKCl7CgkJbmV3IEFjY29yZGlvbk1lbnUoe21lbnVBcnJzOmFkaW5mb30pOwoJfSk7CgkJZnVuY3Rpb24gdmlldyhpcCl7CgkJdmFyIGRhdGEgPSAkZGF0YSQ7CgkJdHJ5ewoJCQkkKCIjcmVzdWx0IikuaHRtbCgiPHByZT4iICsgZGVjb2RlVVJJQ29tcG9uZW50KGRhdGFbaXBdKSArICI8L3ByZT4iKTsKCQl9Y2F0Y2goZXJyKXsKCQkJJCgiI3Jlc3VsdCIpLmh0bWwoIjxwcmU+IiArIHVuZXNjYXBlKGRhdGFbaXBdKSArICI8L3ByZT4iKTsKCQl9CgkJfQoJPC9zY3JpcHQ+CjwvaHRtbD4=")
mo_html = mo_html.replace('$adinfo$',str(json.dumps(re_json)))
mo_html = mo_html.replace('$data$',json.dumps(port_data))
mo_html = mo_html.replace('$statistics$',td_html)
result = open(ip + "-" + str(int(time.time())) + ".html","w")
result.write(mo_html)
result.close()
except Exception,e:
print 'Results output failure'
def t_join(m_count):
tmp_count = 0
i = 0
while True:
time.sleep(2)
ac_count = threading.activeCount()
if ac_count < m_count and ac_count == tmp_count:
i+=1
else:
i = 0
tmp_count = ac_count
#print ac_count,queue.qsize()
if (queue.empty() and threading.activeCount() <= 1) or i > 5:
break
if __name__=="__main__":
mark_list = read_config('server_info')
msg = '''
Scanning a network asset information script,author:wolf@future-sec.
Usage: python F-NAScan.py -h 192.168.1 [-p 21,80,3306] [-m 50] [-t 10] [-n]
'''
if len(sys.argv) < 2:
print msg
try:
options,args = getopt.getopt(sys.argv[1:],"h:p:m:t:n")
ip = ''
noping = False
port = '21,22,23,25,53,80,110,139,143,389,443,445,465,873,993,995,1080,1723,1433,1521,3306,3389,3690,5432,5800,5900,6379,7001,8000,8001,8080,8081,8888,9200,9300,9080,9999,11211,27017'
m_count = 100
for opt,arg in options:
if opt == '-h':
ip = arg
elif opt == '-p':
port = arg
elif opt == '-m':
m_count = int(arg)
elif opt == '-t':
timeout = int(arg)
elif opt == '-n':
noping = True
if ip:
ip_list = get_ip_list(ip)
port_list = get_port_list(port)
if not noping:ip_list=get_ac_ip(ip_list)
for ip_str in ip_list:
for port_int in port_list:
queue.put(':'.join([ip_str,port_int]))
for i in range(m_count):
t = ThreadNum(queue)
t.setDaemon(True)
t.start()
t_join(m_count)
write_result()
except Exception,e:
print e
print msg