KEXEL commited on
Commit
aa802f5
·
verified ·
1 Parent(s): 1f520cf
d-framework/icon/144/favicon.png ADDED
d-framework/icon/192/favicon.png ADDED
d-framework/icon/36/favicon.png ADDED
d-framework/icon/48/favicon.png ADDED
d-framework/icon/512/favicon.png ADDED
d-framework/icon/72/favicon.png ADDED
d-framework/icon/96/favicon.png ADDED
index.html CHANGED
@@ -1,428 +1,234 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Network Speed Test</title>
7
- <script src="https://cdn.tailwindcss.com"></script>
8
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
- <style>
10
- .gauge {
11
- position: relative;
12
- width: 300px;
13
- height: 150px;
14
- margin: 0 auto;
15
- }
16
-
17
- .gauge-body {
18
- width: 100%;
19
- height: 0;
20
- padding-bottom: 50%;
21
- position: relative;
22
- border-top-left-radius: 100% 200%;
23
- border-top-right-radius: 100% 200%;
24
- overflow: hidden;
25
- background: #e0e0e0;
26
- }
27
-
28
- .gauge-fill {
29
- position: absolute;
30
- top: 100%;
31
- left: 0;
32
- width: 100%;
33
- height: 100%;
34
- background: linear-gradient(90deg, #4ade80, #3b82f6, #ef4444);
35
- transform-origin: center top;
36
- transform: rotate(0.5turn);
37
- transition: transform 0.5s ease-out;
38
- }
39
-
40
- .gauge-cover {
41
- width: 75%;
42
- height: 150%;
43
- background: white;
44
- border-radius: 50%;
45
- position: absolute;
46
- top: 25%;
47
- left: 50%;
48
- transform: translateX(-50%);
49
- display: flex;
50
- align-items: center;
51
- justify-content: center;
52
- font-size: 1.5rem;
53
- font-weight: bold;
54
- color: #333;
55
- }
56
-
57
- .progress-bar {
58
- height: 10px;
59
- background-color: #e0e0e0;
60
- border-radius: 5px;
61
- overflow: hidden;
62
- }
63
-
64
- .progress-fill {
65
- height: 100%;
66
- background: linear-gradient(90deg, #4ade80, #3b82f6);
67
- width: 0%;
68
- transition: width 0.3s ease;
69
- }
70
-
71
- @keyframes pulse {
72
- 0% { opacity: 1; }
73
- 50% { opacity: 0.5; }
74
- 100% { opacity: 1; }
75
- }
76
-
77
- .pulse {
78
- animation: pulse 1.5s infinite;
79
- }
80
-
81
- .test-btn {
82
- transition: all 0.3s ease;
83
- }
84
-
85
- .test-btn:hover {
86
- transform: translateY(-2px);
87
- box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
88
- }
89
- </style>
90
- </head>
91
- <body class="bg-gray-50 min-h-screen flex flex-col">
92
- <header class="bg-white shadow-sm py-4">
93
- <div class="container mx-auto px-4">
94
- <h1 class="text-3xl font-bold text-center text-indigo-600">
95
- <i class="fas fa-tachometer-alt mr-2"></i>Network Speed Test
96
- </h1>
97
- </div>
98
- </header>
99
-
100
- <main class="flex-grow container mx-auto px-4 py-8">
101
- <div class="max-w-3xl mx-auto bg-white rounded-xl shadow-md overflow-hidden p-6">
102
- <div class="text-center mb-8">
103
- <h2 class="text-2xl font-semibold text-gray-800">Test Your Internet Speed</h2>
104
- <p class="text-gray-600 mt-2">Measure your download, upload speed and ping</p>
105
- </div>
106
-
107
- <div class="flex flex-col md:flex-row justify-around items-center mb-8">
108
- <div class="gauge mb-8 md:mb-0">
109
- <div class="gauge-body">
110
- <div class="gauge-fill" id="downloadGauge"></div>
111
- </div>
112
- <div class="gauge-cover" id="downloadSpeed">0 Mbps</div>
113
- </div>
114
-
115
- <div class="gauge">
116
- <div class="gauge-body">
117
- <div class="gauge-fill" id="uploadGauge"></div>
118
- </div>
119
- <div class="gauge-cover" id="uploadSpeed">0 Mbps</div>
120
- </div>
121
- </div>
122
-
123
- <div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-8">
124
- <div class="bg-gray-50 p-4 rounded-lg text-center">
125
- <div class="text-gray-500 mb-1"><i class="fas fa-download mr-2"></i>Download</div>
126
- <div class="text-2xl font-bold text-indigo-600" id="finalDownload">0 Mbps</div>
127
- </div>
128
-
129
- <div class="bg-gray-50 p-4 rounded-lg text-center">
130
- <div class="text-gray-500 mb-1"><i class="fas fa-upload mr-2"></i>Upload</div>
131
- <div class="text-2xl font-bold text-indigo-600" id="finalUpload">0 Mbps</div>
132
- </div>
133
-
134
- <div class="bg-gray-50 p-4 rounded-lg text-center">
135
- <div class="text-gray-500 mb-1"><i class="fas fa-stopwatch mr-2"></i>Ping</div>
136
- <div class="text-2xl font-bold text-indigo-600" id="pingResult">0 ms</div>
137
- </div>
138
- </div>
139
-
140
- <div class="mb-6">
141
- <div class="flex justify-between mb-1">
142
- <span class="text-gray-700">Test Progress</span>
143
- <span class="text-gray-700" id="testStatus">Ready</span>
144
- </div>
145
- <div class="progress-bar">
146
- <div class="progress-fill" id="testProgress"></div>
147
- </div>
148
- </div>
149
-
150
- <div class="text-center">
151
- <button id="startTest" class="test-btn bg-indigo-600 hover:bg-indigo-700 text-white font-bold py-3 px-8 rounded-full text-lg transition-all duration-300">
152
- <i class="fas fa-play mr-2"></i>Start Test
153
- </button>
154
- </div>
155
-
156
- <div class="mt-8 bg-blue-50 border-l-4 border-blue-500 p-4 rounded hidden" id="tips">
157
- <div class="flex">
158
- <div class="flex-shrink-0 text-blue-500">
159
- <i class="fas fa-info-circle text-xl"></i>
160
- </div>
161
- <div class="ml-3">
162
- <h3 class="text-sm font-medium text-blue-800">Tips for accurate results</h3>
163
- <div class="mt-2 text-sm text-blue-700">
164
- <p>• Close other tabs and applications</p>
165
- <p>• Connect directly to your router with Ethernet if possible</p>
166
- <p>• Stop any ongoing downloads or uploads</p>
167
- </div>
168
- </div>
169
- </div>
170
- </div>
171
- </div>
172
-
173
- <div class="max-w-3xl mx-auto bg-white rounded-xl shadow-md overflow-hidden p-6 mt-8">
174
- <h3 class="text-xl font-semibold text-gray-800 mb-4"><i class="fas fa-history mr-2"></i>Test History</h3>
175
- <div class="overflow-x-auto">
176
- <table class="min-w-full divide-y divide-gray-200">
177
- <thead class="bg-gray-50">
178
- <tr>
179
- <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Date</th>
180
- <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Download</th>
181
- <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Upload</th>
182
- <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Ping</th>
183
- </tr>
184
- </thead>
185
- <tbody class="bg-white divide-y divide-gray-200" id="historyTable">
186
- <!-- History will be populated here -->
187
- </tbody>
188
- </table>
189
- </div>
190
- </div>
191
- </main>
192
-
193
- <footer class="bg-white shadow-sm py-4 mt-8">
194
- <div class="container mx-auto px-4 text-center text-gray-500 text-sm">
195
- <p>© 2023 Network Speed Test | All rights reserved</p>
196
- </div>
197
- </footer>
198
-
199
- <script>
200
- document.addEventListener('DOMContentLoaded', function() {
201
- const startTestBtn = document.getElementById('startTest');
202
- const downloadSpeed = document.getElementById('downloadSpeed');
203
- const uploadSpeed = document.getElementById('uploadSpeed');
204
- const finalDownload = document.getElementById('finalDownload');
205
- const finalUpload = document.getElementById('finalUpload');
206
- const pingResult = document.getElementById('pingResult');
207
- const testStatus = document.getElementById('testStatus');
208
- const testProgress = document.getElementById('testProgress');
209
- const downloadGauge = document.getElementById('downloadGauge');
210
- const uploadGauge = document.getElementById('uploadGauge');
211
- const historyTable = document.getElementById('historyTable');
212
- const tipsSection = document.getElementById('tips');
213
-
214
- let testInProgress = false;
215
- let testHistory = JSON.parse(localStorage.getItem('speedTestHistory')) || [];
216
-
217
- // Display test history
218
- renderHistory();
219
-
220
- startTestBtn.addEventListener('click', function() {
221
- if (testInProgress) return;
222
-
223
- startTest();
224
- });
225
-
226
- function startTest() {
227
- testInProgress = true;
228
- startTestBtn.disabled = true;
229
- startTestBtn.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i>Testing...';
230
- startTestBtn.classList.remove('bg-indigo-600', 'hover:bg-indigo-700');
231
- startTestBtn.classList.add('bg-gray-400', 'cursor-not-allowed');
232
-
233
- // Reset values
234
- downloadSpeed.textContent = '0 Mbps';
235
- uploadSpeed.textContent = '0 Mbps';
236
- finalDownload.textContent = '0 Mbps';
237
- finalUpload.textContent = '0 Mbps';
238
- pingResult.textContent = '0 ms';
239
- testStatus.textContent = 'Starting...';
240
- testProgress.style.width = '0%';
241
- downloadGauge.style.transform = 'rotate(0.5turn)';
242
- uploadGauge.style.transform = 'rotate(0.5turn)';
243
-
244
- tipsSection.classList.add('hidden');
245
-
246
- // Show pulse animation on gauges
247
- downloadGauge.classList.add('pulse');
248
- uploadGauge.classList.add('pulse');
249
-
250
- // Start tests in sequence
251
- setTimeout(() => {
252
- testPing().then(ping => {
253
- pingResult.textContent = ping + ' ms';
254
- testStatus.textContent = 'Testing download speed...';
255
- testProgress.style.width = '30%';
256
-
257
- return testDownloadSpeed();
258
- }).then(downloadSpeedValue => {
259
- const roundedDownload = Math.round(downloadSpeedValue * 10) / 10;
260
- finalDownload.textContent = roundedDownload + ' Mbps';
261
- testStatus.textContent = 'Testing upload speed...';
262
- testProgress.style.width = '70%';
263
-
264
- // Update gauge
265
- const downloadAngle = Math.min(0.5 + (downloadSpeedValue / 200), 1);
266
- downloadGauge.style.transform = `rotate(${downloadAngle}turn)`;
267
- downloadGauge.classList.remove('pulse');
268
-
269
- return testUploadSpeed();
270
- }).then(uploadSpeedValue => {
271
- const roundedUpload = Math.round(uploadSpeedValue * 10) / 10;
272
- finalUpload.textContent = roundedUpload + ' Mbps';
273
- testStatus.textContent = 'Test complete!';
274
- testProgress.style.width = '100%';
275
-
276
- // Update gauge
277
- const uploadAngle = Math.min(0.5 + (uploadSpeedValue / 50), 1);
278
- uploadGauge.style.transform = `rotate(${uploadAngle}turn)`;
279
- uploadGauge.classList.remove('pulse');
280
-
281
- // Save to history
282
- saveTestResult(roundedDownload, roundedUpload, pingResult.textContent);
283
-
284
- // Reset button
285
- resetTestButton();
286
- }).catch(error => {
287
- console.error('Test failed:', error);
288
- testStatus.textContent = 'Test failed. Try again.';
289
- testStatus.classList.add('text-red-500');
290
- resetTestButton();
291
- });
292
- }, 1000);
293
- }
294
-
295
- function resetTestButton() {
296
- testInProgress = false;
297
- startTestBtn.disabled = false;
298
- startTestBtn.innerHTML = '<i class="fas fa-sync-alt mr-2"></i>Test Again';
299
- startTestBtn.classList.remove('bg-gray-400', 'cursor-not-allowed');
300
- startTestBtn.classList.add('bg-indigo-600', 'hover:bg-indigo-700');
301
-
302
- // Show tips
303
- tipsSection.classList.remove('hidden');
304
- }
305
-
306
- function testPing() {
307
- return new Promise((resolve) => {
308
- // Simulate ping test with random value (real implementation would use actual ping)
309
- const start = new Date().getTime();
310
- setTimeout(() => {
311
- const latency = Math.floor(Math.random() * 30) + 5;
312
- resolve(latency);
313
- }, 300);
314
- });
315
- }
316
-
317
- function testDownloadSpeed() {
318
- return new Promise((resolve) => {
319
- let startTime, endTime;
320
- const fileSize = 5 * 1024 * 1024; // 5MB test file
321
- const testUrl = `https://httpbin.org/bytes/${fileSize}?r=${Math.random()}`;
322
-
323
- startTime = new Date().getTime();
324
-
325
- fetch(testUrl)
326
- .then(response => {
327
- endTime = new Date().getTime();
328
- return response.blob();
329
- })
330
- .then(() => {
331
- const duration = (endTime - startTime) / 1000;
332
- const bitsLoaded = fileSize * 8;
333
- const speedMbps = (bitsLoaded / duration / 1024 / 1024).toFixed(2);
334
-
335
- // Update speed in real-time during test
336
- let progress = 0;
337
- const interval = setInterval(() => {
338
- if (progress >= speedMbps) {
339
- clearInterval(interval);
340
- resolve(parseFloat(speedMbps));
341
- } else {
342
- progress += Math.random() * 5;
343
- downloadSpeed.textContent = Math.min(progress, speedMbps).toFixed(1) + ' Mbps';
344
- }
345
- }, 100);
346
- });
347
- });
348
- }
349
-
350
- function testUploadSpeed() {
351
- return new Promise((resolve) => {
352
- let startTime, endTime;
353
- const fileSize = 1 * 1024 * 1024; // 1MB test file
354
- const testData = new Blob([new Uint8Array(fileSize)], {type: 'application/octet-stream'});
355
-
356
- startTime = new Date().getTime();
357
-
358
- fetch('https://httpbin.org/post', {
359
- method: 'POST',
360
- body: testData
361
- })
362
- .then(response => response.json())
363
- .then(() => {
364
- endTime = new Date().getTime();
365
- const duration = (endTime - startTime) / 1000;
366
- const bitsLoaded = fileSize * 8;
367
- const speedMbps = (bitsLoaded / duration / 1024 / 1024).toFixed(2);
368
-
369
- // Update speed in real-time during test
370
- let progress = 0;
371
- const interval = setInterval(() => {
372
- if (progress >= speedMbps) {
373
- clearInterval(interval);
374
- resolve(parseFloat(speedMbps));
375
- } else {
376
- progress += Math.random() * 2;
377
- uploadSpeed.textContent = Math.min(progress, speedMbps).toFixed(1) + ' Mbps';
378
- }
379
- }, 100);
380
- });
381
- });
382
- }
383
-
384
- function saveTestResult(download, upload, ping) {
385
- const now = new Date();
386
- const testResult = {
387
- date: now.toLocaleString(),
388
- download: download,
389
- upload: upload,
390
- ping: ping
391
- };
392
-
393
- testHistory.unshift(testResult);
394
- if (testHistory.length > 5) {
395
- testHistory = testHistory.slice(0, 5);
396
- }
397
-
398
- localStorage.setItem('speedTestHistory', JSON.stringify(testHistory));
399
- renderHistory();
400
- }
401
-
402
- function renderHistory() {
403
- historyTable.innerHTML = '';
404
-
405
- if (testHistory.length === 0) {
406
- const row = document.createElement('tr');
407
- row.innerHTML = `
408
- <td colspan="4" class="px-6 py-4 text-center text-gray-500">No test history yet</td>
409
- `;
410
- historyTable.appendChild(row);
411
- return;
412
- }
413
-
414
- testHistory.forEach(result => {
415
- const row = document.createElement('tr');
416
- row.innerHTML = `
417
- <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${result.date}</td>
418
- <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-green-600">${result.download} Mbps</td>
419
- <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-blue-600">${result.upload} Mbps</td>
420
- <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-purple-600">${result.ping}</td>
421
- `;
422
- historyTable.appendChild(row);
423
- });
424
- }
425
- });
426
- </script>
427
- <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=KEXEL/speedtest" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
428
  </html>
 
1
+ <!DOCTYPE html>
2
+ <html lang="pt-br">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <title>STUDIO.POLODESIG</title>
7
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
8
+ <meta name="description" content="STUDIO.POLODESIG..." />
9
+ <meta name="mobile-web-app-capable" content="yes" />
10
+ <meta name="apple-mobile-web-app-capable" content="yes" />
11
+ <meta name="application-name" content="STUDIO.POLODESIG" />
12
+ <meta name="apple-mobile-web-app-title" content="STUDIO.POLODESIG" />
13
+ <meta name="msapplication-starturl" content="/?Installed=design" />
14
+ <meta name="theme-color" content="#602ab6" />
15
+ <meta name="msapplication-navbutton-color" content="#602ab6" />
16
+ <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
17
+ <meta name="apple-touch-fullscreen" content="yes" />
18
+ <meta name="robots" content="index, follow" />
19
+ <meta name="googlebot" content="index, follow" />
20
+ <meta property="og:image" content="./d-framework/icon/icon/512/favicon.png" />
21
+ <link rel="icon" type="image/png" sizes="512x512" href="./d-framework/icon/512/favicon.png" />
22
+ <link rel="apple-touch-icon" type="image/png" sizes="512x512" href="./d-framework/icon/512/favicon.png" />
23
+ <link rel="icon" type="image/png" sizes="192x192" href="./d-framework/icon/192/favicon.png" />
24
+ <link rel="apple-touch-icon" type="image/png" sizes="192x192" href="./d-framework/icon/192/favicon.png" />
25
+ <link rel="icon" type="image/png" sizes="144x144" href="./d-framework/icon/144/favicon.png" />
26
+ <link rel="apple-touch-icon" type="image/png" sizes="144x144" href="./d-framework/icon/144/favicon.png" />
27
+ <link rel="icon" type="image/png" sizes="96x96" href="./d-framework/icon/96/favicon.png" />
28
+ <link rel="apple-touch-icon" type="image/png" sizes="96x96" href="./d-framework/icon/96/favicon.png" />
29
+ <link rel="icon" type="image/png" sizes="72x72" href="./d-framework/icon/72/favicon.png" />
30
+ <link rel="apple-touch-icon" type="image/png" sizes="72x72" href="./d-framework/icon/72/favicon.png" />
31
+ <link rel="icon" type="image/png" sizes="48x48" href="./d-framework/icon/48/favicon.png" />
32
+ <link rel="apple-touch-icon" type="image/png" sizes="48x48" href="./d-framework/icon/48/favicon.png" />
33
+ <link rel="icon" type="image/png" sizes="36x36" href="./d-framework/icon/36/favicon.png" />
34
+ <link rel="apple-touch-icon" type="image/png" sizes="36x36" href="./d-framework/icon/36/favicon.png" />
35
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5/dist/css/bootstrap.min.css" />
36
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1/font/bootstrap-icons.css" />
37
+ <script src="https://cdn.jsdelivr.net/npm/bootstrap@5/dist/js/bootstrap.bundle.min.js"></script>
38
+ <script
39
+ src="data:text/plain;charset=utf-8;base64,dmFyIGNvbG9iZCA9ICIjMmIzMDM1YzciOyB2YXIgY29sb2xpcyA9ICIjNzI2ZDNiIjsgdmFyIGNvbG90eHQgPSAiI2ZmZjkiOwpkb2N1bWVudC53cml0ZSgnPHN0eWxlPi5wYWNley13ZWJraXQtcG9pbnRlci1ldmVudHM6bm9uZTtwb2ludGVyLWV2ZW50czpub25lOy13ZWJraXQtdXNlci1zZWxlY3Q6bm9uZTstbW96LXVzZXItc2VsZWN0Om5vbmU7dXNlci1zZWxlY3Q6bm9uZTt6LWluZGV4Ojk5OTk5OTk7cG9zaXRpb246Zml4ZWQ7bWFyZ2luOmF1dG87dG9wOjA7bGVmdDowO3JpZ2h0OjA7Ym90dG9tOjA7aGVpZ2h0OjEwMCU7d2lkdGg6MTAwJTtiYWNrZ3JvdW5kOicrY29sb2JkKyc7b3ZlcmZsb3c6aGlkZGVuO30ucGFjZTo6YmVmb3Jle2NvbnRlbnQ6IkNBUlJFR0FORE8uLi4iO2NvbG9yOicrY29sb3R4dCsnO3Bvc2l0aW9uOmFic29sdXRlO3RvcDo0NyU7bGVmdDo1MCU7LW1zLXRyYW5zZm9ybTp0cmFuc2xhdGUoLTUwJSwtNTAlKTt0cmFuc2Zvcm06dHJhbnNsYXRlKC01MCUsLTUwJSk7fS5wYWNlIC5wYWNlLXByb2dyZXNzey13ZWJraXQtYm94LXNpemluZzpib3JkZXItYm94Oy1tb3otYm94LXNpemluZzpib3JkZXItYm94Oy1tcy1ib3gtc2l6aW5nOmJvcmRlci1ib3g7LW8tYm94LXNpemluZzpib3JkZXItYm94O2JveC1zaXppbmc6Ym9yZGVyLWJveDstd2Via2l0LXRyYW5zZm9ybTp0cmFuc2xhdGUzZCgwLDAsMCk7LW1vei10cmFuc2Zvcm06dHJhbnNsYXRlM2QoMCwwLDApOy1tcy10cmFuc2Zvcm06dHJhbnNsYXRlM2QoMCwwLDApOy1vLXRyYW5zZm9ybTp0cmFuc2xhdGUzZCgwLDAsMCk7dHJhbnNmb3JtOnRyYW5zbGF0ZTNkKDAsMCwwKTttYXgtd2lkdGg6MTAwJTtwb3NpdGlvbjpmaXhlZDt6LWluZGV4OjIwMDA7ZGlzcGxheTpibG9jaztwb3NpdGlvbjphYnNvbHV0ZTtib3R0b206NTAlO3JpZ2h0OjEwMCU7aGVpZ2h0OjVweDt3aWR0aDoxMDAlO2JhY2tncm91bmQ6Jytjb2xvbGlzKyc7fS5wYWNlLnBhY2UtaW5hY3RpdmV7ZGlzcGxheTpub25lO308L3N0eWxlPicpOwooZnVuY3Rpb24oKXtmdW5jdGlvbiBvKHQsZSl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIHQuYXBwbHkoZSxhcmd1bWVudHMpfX12YXIgdSxjLGksbix5LHQsbCx2LHIscyxhLGUscCx3LGIsaCxmLGQsZyxtLGssUyxxLHgsTCxQLFQsUixqLE8sRSxNLEEsQyxOLF8sRixVLFcsWCxELEgsSSx6LEcsQj1bXS5zbGljZSxKPXt9Lmhhc093blByb3BlcnR5LEs9ZnVuY3Rpb24odCxlKXtmb3IodmFyIG4gaW4gZSlKLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1yZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sUT1bXS5pbmRleE9mfHxmdW5jdGlvbih0KXtmb3IodmFyIGU9MCxuPXRoaXMubGVuZ3RoO2U8bjtlKyspaWYoZSBpbiB0aGlzJiZ0aGlzW2VdPT09dClyZXR1cm4gZTtyZXR1cm4tMX07ZnVuY3Rpb24gVigpe31mb3IoZj17Y2xhc3NOYW1lOiIiLGNhdGNodXBUaW1lOjEwMCxpbml0aWFsUmF0ZTouMDMsbWluVGltZToyNTAsZ2hvc3RUaW1lOjEwMCxtYXhQcm9ncmVzc1BlckZyYW1lOjIwLGVhc2VGYWN0b3I6MS4yNSxzdGFydE9uUGFnZUxvYWQ6ITAscmVzdGFydE9uUHVzaFN0YXRlOiEwLHJlc3RhcnRPblJlcXVlc3RBZnRlcjo1MDAsdGFyZ2V0OiJib2R5IixlbGVtZW50czp7Y2hlY2tJbnRlcnZhbDoxMDAsc2VsZWN0b3JzOlsiYm9keSJdfSxldmVudExhZzp7bWluU2FtcGxlczoxMCxzYW1wbGVDb3VudDozLGxhZ1RocmVzaG9sZDozfSxhamF4Ont0cmFja01ldGhvZHM6WyJHRVQiXSx0cmFja1dlYlNvY2tldHM6ITAsaWdub3JlVVJMczpbXX19LEw9ZnVuY3Rpb24oKXt2YXIgdDtyZXR1cm4gbnVsbCE9KHQ9InVuZGVmaW5lZCIhPXR5cGVvZiBwZXJmb3JtYW5jZSYmbnVsbCE9PXBlcmZvcm1hbmNlJiYiZnVuY3Rpb24iPT10eXBlb2YgcGVyZm9ybWFuY2Uubm93P3BlcmZvcm1hbmNlLm5vdygpOnZvaWQgMCk/dDorbmV3IERhdGV9LFQ9d2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZXx8d2luZG93Lm1velJlcXVlc3RBbmltYXRpb25GcmFtZXx8d2luZG93LndlYmtpdFJlcXVlc3RBbmltYXRpb25GcmFtZXx8d2luZG93Lm1zUmVxdWVzdEFuaW1hdGlvbkZyYW1lLGg9d2luZG93LmNhbmNlbEFuaW1hdGlvbkZyYW1lfHx3aW5kb3cubW96Q2FuY2VsQW5pbWF0aW9uRnJhbWUsYT1mdW5jdGlvbih0LGUsbil7cmV0dXJuKCJmdW5jdGlvbiI9PXR5cGVvZiB0LmFkZEV2ZW50TGlzdGVuZXI/dC5hZGRFdmVudExpc3RlbmVyKGUsbiwhMSk6dm9pZCAwKXx8KHRbIm9uIitlXT1uKX0sbnVsbD09VCYmKFQ9ZnVuY3Rpb24odCl7cmV0dXJuIHNldFRpbWVvdXQodCw1MCl9LGg9ZnVuY3Rpb24odCl7cmV0dXJuIGNsZWFyVGltZW91dCh0KX0pLGo9ZnVuY3Rpb24oZSl7dmFyIG49TCgpLHI9ZnVuY3Rpb24oKXt2YXIgdD1MKCktbjtyZXR1cm4gMzM8PXQ/KG49TCgpLGUodCxmdW5jdGlvbigpe3JldHVybiBUKHIpfSkpOnNldFRpbWVvdXQociwzMy10KX07cmV0dXJuIHIoKX0sUj1mdW5jdGlvbigpe3ZhciB0PWFyZ3VtZW50c1swXSxlPWFyZ3VtZW50c1sxXSxuPTM8PWFyZ3VtZW50cy5sZW5ndGg/Qi5jYWxsKGFyZ3VtZW50cywyKTpbXTtyZXR1cm4iZnVuY3Rpb24iPT10eXBlb2YgdFtlXT90W2VdLmFwcGx5KHQsbik6dFtlXX0sZD1mdW5jdGlvbigpe2Zvcih2YXIgdCxlLG4scj1hcmd1bWVudHNbMF0scz0yPD1hcmd1bWVudHMubGVuZ3RoP0IuY2FsbChhcmd1bWVudHMsMSk6W10sbz0wLGk9cy5sZW5ndGg7bzxpO28rKylpZihlPXNbb10pZm9yKHQgaW4gZSlKLmNhbGwoZSx0KSYmKG49ZVt0XSxudWxsIT1yW3RdJiYib2JqZWN0Ij09dHlwZW9mIHJbdF0mJm51bGwhPW4mJiJvYmplY3QiPT10eXBlb2Ygbj9kKHJbdF0sbik6clt0XT1uKTtyZXR1cm4gcn0scD1mdW5jdGlvbih0KXtmb3IodmFyIGUsbixyPWU9MCxzPTAsbz10Lmxlbmd0aDtzPG87cysrKW49dFtzXSxyKz1NYXRoLmFicyhuKSxlKys7cmV0dXJuIHIvZX0sbT1mdW5jdGlvbih0LGUpe3ZhciBuLHI7aWYobnVsbD09dCYmKHQ9Im9wdGlvbnMiKSxudWxsPT1lJiYoZT0hMCkscj1kb2N1bWVudC5xdWVyeVNlbGVjdG9yKCJbZGF0YS1wYWNlLSIrdCsiXSIpKXtpZihuPXIuZ2V0QXR0cmlidXRlKCJkYXRhLXBhY2UtIit0KSwhZSlyZXR1cm4gbjt0cnl7cmV0dXJuIEpTT04ucGFyc2Uobil9Y2F0Y2godCl7cmV0dXJuInVuZGVmaW5lZCIhPXR5cGVvZiBjb25zb2xlJiZudWxsIT09Y29uc29sZT9jb25zb2xlLmVycm9yKCJFcnJvciBwYXJzaW5nIGlubGluZSBwYWNlIG9wdGlvbnMiLHQpOnZvaWQgMH19fSxWLnByb3RvdHlwZS5vbj1mdW5jdGlvbih0LGUsbixyKXt2YXIgcztyZXR1cm4gbnVsbD09ciYmKHI9ITEpLG51bGw9PXRoaXMuYmluZGluZ3MmJih0aGlzLmJpbmRpbmdzPXt9KSxudWxsPT0ocz10aGlzLmJpbmRpbmdzKVt0XSYmKHNbdF09W10pLHRoaXMuYmluZGluZ3NbdF0ucHVzaCh7aGFuZGxlcjplLGN0eDpuLG9uY2U6cn0pfSxWLnByb3RvdHlwZS5vbmNlPWZ1bmN0aW9uKHQsZSxuKXtyZXR1cm4gdGhpcy5vbih0LGUsbiwhMCl9LFYucHJvdG90eXBlLm9mZj1mdW5jdGlvbih0LGUpe3ZhciBuLHIscztpZihudWxsIT0obnVsbCE9KHI9dGhpcy5iaW5kaW5ncyk/clt0XTp2b2lkIDApKXtpZihudWxsPT1lKXJldHVybiBkZWxldGUgdGhpcy5iaW5kaW5nc1t0XTtmb3Iobj0wLHM9W107bjx0aGlzLmJpbmRpbmdzW3RdLmxlbmd0aDspdGhpcy5iaW5kaW5nc1t0XVtuXS5oYW5kbGVyPT09ZT9zLnB1c2godGhpcy5iaW5kaW5nc1t0XS5zcGxpY2UobiwxKSk6cy5wdXNoKG4rKyk7cmV0dXJuIHN9fSxWLnByb3RvdHlwZS50cmlnZ2VyPWZ1bmN0aW9uKCl7dmFyIHQsZSxuLHIscyxvLGk9YXJndW1lbnRzWzBdLGE9Mjw9YXJndW1lbnRzLmxlbmd0aD9CLmNhbGwoYXJndW1lbnRzLDEpOltdO2lmKG51bGwhPShyPXRoaXMuYmluZGluZ3MpJiZyW2ldKXtmb3Iobj0wLG89W107bjx0aGlzLmJpbmRpbmdzW2ldLmxlbmd0aDspZT0ocz10aGlzLmJpbmRpbmdzW2ldW25dKS5oYW5kbGVyLHQ9cy5jdHgscz1zLm9uY2UsZS5hcHBseShudWxsIT10P3Q6dGhpcyxhKSxzP28ucHVzaCh0aGlzLmJpbmRpbmdzW2ldLnNwbGljZShuLDEpKTpvLnB1c2gobisrKTtyZXR1cm4gb319LEc9Vix5PXdpbmRvdy5QYWNlfHx7fSx3aW5kb3cuUGFjZT15LGQoeSxHLnByb3RvdHlwZSksUD15Lm9wdGlvbnM9ZCh7fSxmLHdpbmRvdy5wYWNlT3B0aW9ucyxtKCkpLFc9MCxEPShJPVsiYWpheCIsImRvY3VtZW50IiwiZXZlbnRMYWciLCJlbGVtZW50cyJdKS5sZW5ndGg7VzxEO1crKykhMD09PVBbQT1JW1ddXSYmKFBbQV09ZltBXSk7ZnVuY3Rpb24gWSgpe3JldHVybiBZLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9ZnVuY3Rpb24gWigpe3RoaXMucHJvZ3Jlc3M9MH1mdW5jdGlvbiAkKCl7dGhpcy5iaW5kaW5ncz17fX1mdW5jdGlvbiB0dCgpe3ZhciBlLG89dGhpczt0dC5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpLGU9ZnVuY3Rpb24ocil7dmFyIHM9ci5vcGVuO3JldHVybiByLm9wZW49ZnVuY3Rpb24odCxlLG4pe3JldHVybiBNKHQpJiZvLnRyaWdnZXIoInJlcXVlc3QiLHt0eXBlOnQsdXJsOmUscmVxdWVzdDpyfSkscy5hcHBseShyLGFyZ3VtZW50cyl9fSx3aW5kb3cuWE1MSHR0cFJlcXVlc3Q9ZnVuY3Rpb24odCl7dD1uZXcgVSh0KTtyZXR1cm4gZSh0KSx0fTt0cnl7Zyh3aW5kb3cuWE1MSHR0cFJlcXVlc3QsVSl9Y2F0Y2godCl7fWlmKG51bGwhPUYpe3dpbmRvdy5YRG9tYWluUmVxdWVzdD1mdW5jdGlvbigpe3ZhciB0PW5ldyBGO3JldHVybiBlKHQpLHR9O3RyeXtnKHdpbmRvdy5YRG9tYWluUmVxdWVzdCxGKX1jYXRjaCh0KXt9fWlmKG51bGwhPV8mJlAuYWpheC50cmFja1dlYlNvY2tldHMpe3dpbmRvdy5XZWJTb2NrZXQ9ZnVuY3Rpb24odCxlKXt2YXIgbj1udWxsIT1lP25ldyBfKHQsZSk6bmV3IF8odCk7cmV0dXJuIE0oInNvY2tldCIpJiZvLnRyaWdnZXIoInJlcXVlc3QiLHt0eXBlOiJzb2NrZXQiLHVybDp0LHByb3RvY29sczplLHJlcXVlc3Q6bn0pLG59O3RyeXtnKHdpbmRvdy5XZWJTb2NrZXQsXyl9Y2F0Y2godCl7fX19ZnVuY3Rpb24gZXQoKXt0aGlzLmNvbXBsZXRlPW8odGhpcy5jb21wbGV0ZSx0aGlzKTt2YXIgdD10aGlzO3RoaXMuZWxlbWVudHM9W10saygpLm9uKCJyZXF1ZXN0IixmdW5jdGlvbigpe3JldHVybiB0LndhdGNoLmFwcGx5KHQsYXJndW1lbnRzKX0pfWZ1bmN0aW9uIG50KHQpe3ZhciBlLG4scixzO2ZvcihudWxsPT10JiYodD17fSksdGhpcy5jb21wbGV0ZT1vKHRoaXMuY29tcGxldGUsdGhpcyksdGhpcy5lbGVtZW50cz1bXSxudWxsPT10LnNlbGVjdG9ycyYmKHQuc2VsZWN0b3JzPVtdKSxuPTAscj0ocz10LnNlbGVjdG9ycykubGVuZ3RoO248cjtuKyspZT1zW25dLHRoaXMuZWxlbWVudHMucHVzaChuZXcgaShlLHRoaXMuY29tcGxldGUpKX1mdW5jdGlvbiBydCh0LGUpe3RoaXMuc2VsZWN0b3I9dCx0aGlzLmNvbXBsZXRlQ2FsbGJhY2s9ZSx0aGlzLnByb2dyZXNzPTAsdGhpcy5jaGVjaygpfWZ1bmN0aW9uIHN0KCl7dmFyIHQsZSxuPXRoaXM7dGhpcy5wcm9ncmVzcz1udWxsIT0oZT10aGlzLnN0YXRlc1tkb2N1bWVudC5yZWFkeVN0YXRlXSk/ZToxMDAsdD1kb2N1bWVudC5vbnJlYWR5c3RhdGVjaGFuZ2UsZG9jdW1lbnQub25yZWFkeXN0YXRlY2hhbmdlPWZ1bmN0aW9uKCl7cmV0dXJuIG51bGwhPW4uc3RhdGVzW2RvY3VtZW50LnJlYWR5U3RhdGVdJiYobi5wcm9ncmVzcz1uLnN0YXRlc1tkb2N1bWVudC5yZWFkeVN0YXRlXSksImZ1bmN0aW9uIj09dHlwZW9mIHQ/dC5hcHBseShudWxsLGFyZ3VtZW50cyk6dm9pZCAwfX1mdW5jdGlvbiBvdCh0KXt0aGlzLnNvdXJjZT10LHRoaXMubGFzdD10aGlzLnNpbmNlTGFzdFVwZGF0ZT0wLHRoaXMucmF0ZT1QLmluaXRpYWxSYXRlLHRoaXMuY2F0Y2h1cD0wLHRoaXMucHJvZ3Jlc3M9dGhpcy5sYXN0UHJvZ3Jlc3M9MCxudWxsIT10aGlzLnNvdXJjZSYmKHRoaXMucHJvZ3Jlc3M9Uih0aGlzLnNvdXJjZSwicHJvZ3Jlc3MiKSl9Rz1FcnJvcixLKFksRyksbj1ZLFoucHJvdG90eXBlLmdldEVsZW1lbnQ9ZnVuY3Rpb24oKXt2YXIgdDtpZihudWxsPT10aGlzLmVsKXtpZighKHQ9ZG9jdW1lbnQucXVlcnlTZWxlY3RvcihQLnRhcmdldCkpKXRocm93IG5ldyBuO3RoaXMuZWw9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiZGl2IiksdGhpcy5lbC5jbGFzc05hbWU9InBhY2UgcGFjZS1hY3RpdmUiLGRvY3VtZW50LmJvZHkuY2xhc3NOYW1lPWRvY3VtZW50LmJvZHkuY2xhc3NOYW1lLnJlcGxhY2UoLyhwYWNlLWRvbmUgKXwvLCJwYWNlLXJ1bm5pbmcgIik7dmFyIGU9IiIhPT1QLmNsYXNzTmFtZT8iICIrUC5jbGFzc05hbWU6IiI7dGhpcy5lbC5pbm5lckhUTUw9JzxkaXYgY2xhc3M9InBhY2UtcHJvZ3Jlc3MnK2UrJyI+XG4gIDxkaXYgY2xhc3M9InBhY2UtcHJvZ3Jlc3MtaW5uZXIiPjwvZGl2PlxuPC9kaXY+XG48ZGl2IGNsYXNzPSJwYWNlLWFjdGl2aXR5Ij48L2Rpdj4nLG51bGwhPXQuZmlyc3RDaGlsZD90Lmluc2VydEJlZm9yZSh0aGlzLmVsLHQuZmlyc3RDaGlsZCk6dC5hcHBlbmRDaGlsZCh0aGlzLmVsKX1yZXR1cm4gdGhpcy5lbH0sWi5wcm90b3R5cGUuZmluaXNoPWZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5nZXRFbGVtZW50KCk7cmV0dXJuIHQuY2xhc3NOYW1lPXQuY2xhc3NOYW1lLnJlcGxhY2UoInBhY2UtYWN0aXZlIiwicGFjZS1pbmFjdGl2ZSIpLGRvY3VtZW50LmJvZHkuY2xhc3NOYW1lPWRvY3VtZW50LmJvZHkuY2xhc3NOYW1lLnJlcGxhY2UoInBhY2UtcnVubmluZyAiLCJwYWNlLWRvbmUgIil9LFoucHJvdG90eXBlLnVwZGF0ZT1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5wcm9ncmVzcz10LHkudHJpZ2dlcigicHJvZ3Jlc3MiLHQpLHRoaXMucmVuZGVyKCl9LFoucHJvdG90eXBlLmRlc3Ryb3k9ZnVuY3Rpb24oKXt0cnl7dGhpcy5nZXRFbGVtZW50KCkucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCh0aGlzLmdldEVsZW1lbnQoKSl9Y2F0Y2godCl7bj10fXJldHVybiB0aGlzLmVsPXZvaWQgMH0sWi5wcm90b3R5cGUucmVuZGVyPWZ1bmN0aW9uKCl7dmFyIHQsZSxuLHIscyxvLGk7aWYobnVsbD09ZG9jdW1lbnQucXVlcnlTZWxlY3RvcihQLnRhcmdldCkpcmV0dXJuITE7Zm9yKHQ9dGhpcy5nZXRFbGVtZW50KCkscj0idHJhbnNsYXRlM2QoIit0aGlzLnByb2dyZXNzKyIlLCAwLCAwKSIscz0wLG89KGk9WyJ3ZWJraXRUcmFuc2Zvcm0iLCJtc1RyYW5zZm9ybSIsInRyYW5zZm9ybSJdKS5sZW5ndGg7czxvO3MrKyllPWlbc10sdC5jaGlsZHJlblswXS5zdHlsZVtlXT1yO3JldHVybighdGhpcy5sYXN0UmVuZGVyZWRQcm9ncmVzc3x8dGhpcy5sYXN0UmVuZGVyZWRQcm9ncmVzc3wwIT09dGhpcy5wcm9ncmVzc3wwKSYmKHQuY2hpbGRyZW5bMF0uc2V0QXR0cmlidXRlKCJkYXRhLXByb2dyZXNzLXRleHQiLCgwfHRoaXMucHJvZ3Jlc3MpKyIlIiksMTAwPD10aGlzLnByb2dyZXNzP249Ijk5Ijoobj10aGlzLnByb2dyZXNzPDEwPyIwIjoiIixuKz0wfHRoaXMucHJvZ3Jlc3MpLHQuY2hpbGRyZW5bMF0uc2V0QXR0cmlidXRlKCJkYXRhLXByb2dyZXNzIiwiIituKSkseS50cmlnZ2VyKCJjaGFuZ2UiLHRoaXMucHJvZ3Jlc3MpLHRoaXMubGFzdFJlbmRlcmVkUHJvZ3Jlc3M9dGhpcy5wcm9ncmVzc30sWi5wcm90b3R5cGUuZG9uZT1mdW5jdGlvbigpe3JldHVybiAxMDA8PXRoaXMucHJvZ3Jlc3N9LGM9WiwkLnByb3RvdHlwZS50cmlnZ2VyPWZ1bmN0aW9uKHQsZSl7dmFyIG4scixzLG8saTtpZihudWxsIT10aGlzLmJpbmRpbmdzW3RdKXtmb3IoaT1bXSxyPTAscz0obz10aGlzLmJpbmRpbmdzW3RdKS5sZW5ndGg7cjxzO3IrKyluPW9bcl0saS5wdXNoKG4uY2FsbCh0aGlzLGUpKTtyZXR1cm4gaX19LCQucHJvdG90eXBlLm9uPWZ1bmN0aW9uKHQsZSl7dmFyIG47cmV0dXJuIG51bGw9PShuPXRoaXMuYmluZGluZ3MpW3RdJiYoblt0XT1bXSksdGhpcy5iaW5kaW5nc1t0XS5wdXNoKGUpfSxtPSQsVT13aW5kb3cuWE1MSHR0cFJlcXVlc3QsRj13aW5kb3cuWERvbWFpblJlcXVlc3QsXz13aW5kb3cuV2ViU29ja2V0LGc9ZnVuY3Rpb24odCxlKXt2YXIgbixyPVtdO2ZvcihuIGluIGUucHJvdG90eXBlKXRyeXtudWxsPT10W25dJiYiZnVuY3Rpb24iIT10eXBlb2YgZVtuXT8iZnVuY3Rpb24iPT10eXBlb2YgT2JqZWN0LmRlZmluZVByb3BlcnR5P3IucHVzaChPYmplY3QuZGVmaW5lUHJvcGVydHkodCxuLHtnZXQ6ZnVuY3Rpb24odCl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIGUucHJvdG90eXBlW3RdfX0obiksY29uZmlndXJhYmxlOiEwLGVudW1lcmFibGU6ITB9KSk6ci5wdXNoKHRbbl09ZS5wcm90b3R5cGVbbl0pOnIucHVzaCh2b2lkIDApfWNhdGNoKHQpezB9cmV0dXJuIHJ9LHE9W10seS5pZ25vcmU9ZnVuY3Rpb24oKXt2YXIgdD1hcmd1bWVudHNbMF0sZT0yPD1hcmd1bWVudHMubGVuZ3RoP0IuY2FsbChhcmd1bWVudHMsMSk6W107cmV0dXJuIHEudW5zaGlmdCgiaWdub3JlIiksZT10LmFwcGx5KG51bGwsZSkscS5zaGlmdCgpLGV9LHkudHJhY2s9ZnVuY3Rpb24oKXt2YXIgdD1hcmd1bWVudHNbMF0sZT0yPD1hcmd1bWVudHMubGVuZ3RoP0IuY2FsbChhcmd1bWVudHMsMSk6W107cmV0dXJuIHEudW5zaGlmdCgidHJhY2siKSxlPXQuYXBwbHkobnVsbCxlKSxxLnNoaWZ0KCksZX0sTT1mdW5jdGlvbih0KXtpZihudWxsPT10JiYodD0iR0VUIiksInRyYWNrIj09PXFbMF0pcmV0dXJuImZvcmNlIjtpZighcS5sZW5ndGgmJlAuYWpheCl7aWYoInNvY2tldCI9PT10JiZQLmFqYXgudHJhY2tXZWJTb2NrZXRzKXJldHVybiEwO2lmKHQ9dC50b1VwcGVyQ2FzZSgpLDA8PVEuY2FsbChQLmFqYXgudHJhY2tNZXRob2RzLHQpKXJldHVybiEwfXJldHVybiExfSxLKHR0LG0pLHQ9dHQsWD1udWxsLEU9ZnVuY3Rpb24odCl7Zm9yKHZhciBlLG49UC5hamF4Lmlnbm9yZVVSTHMscj0wLHM9bi5sZW5ndGg7cjxzO3IrKylpZigic3RyaW5nIj09dHlwZW9mKGU9bltyXSkpe2lmKC0xIT09dC5pbmRleE9mKGUpKXJldHVybiEwfWVsc2UgaWYoZS50ZXN0KHQpKXJldHVybiEwO3JldHVybiExfSwoaz1mdW5jdGlvbigpe3JldHVybiBudWxsPT1YJiYoWD1uZXcgdCksWH0pKCkub24oInJlcXVlc3QiLGZ1bmN0aW9uKHQpe3ZhciBvLGk9dC50eXBlLGE9dC5yZXF1ZXN0LGU9dC51cmw7aWYoIUUoZSkpcmV0dXJuIHkucnVubmluZ3x8ITE9PT1QLnJlc3RhcnRPblJlcXVlc3RBZnRlciYmImZvcmNlIiE9PU0oaSk/dm9pZCAwOihvPWFyZ3VtZW50cywiYm9vbGVhbiI9PXR5cGVvZihlPVAucmVzdGFydE9uUmVxdWVzdEFmdGVyfHwwKSYmKGU9MCksc2V0VGltZW91dChmdW5jdGlvbigpe3ZhciB0LGUsbixyLHM9InNvY2tldCI9PT1pP2EucmVhZHlTdGF0ZTwxOjA8KHM9YS5yZWFkeVN0YXRlKSYmczw0O2lmKHMpe2Zvcih5LnJlc3RhcnQoKSxyPVtdLHQ9MCxlPShuPXkuc291cmNlcykubGVuZ3RoO3Q8ZTt0Kyspe2lmKChBPW5bdF0paW5zdGFuY2VvZiB1KXtBLndhdGNoLmFwcGx5KEEsbyk7YnJlYWt9ci5wdXNoKHZvaWQgMCl9cmV0dXJuIHJ9fSxlKSl9KSxldC5wcm90b3R5cGUud2F0Y2g9ZnVuY3Rpb24odCl7dmFyIGU9dC50eXBlLG49dC5yZXF1ZXN0LHQ9dC51cmw7aWYoIUUodCkpcmV0dXJuIG49bmV3KCJzb2NrZXQiPT09ZT9yOnMpKG4sdGhpcy5jb21wbGV0ZSksdGhpcy5lbGVtZW50cy5wdXNoKG4pfSxldC5wcm90b3R5cGUuY29tcGxldGU9ZnVuY3Rpb24oZSl7cmV0dXJuIHRoaXMuZWxlbWVudHM9dGhpcy5lbGVtZW50cy5maWx0ZXIoZnVuY3Rpb24odCl7cmV0dXJuIHQhPT1lfSl9LHU9ZXQscz1mdW5jdGlvbihlLG4pe3ZhciB0LHIscyxvLGk9dGhpcztpZih0aGlzLnByb2dyZXNzPTAsbnVsbCE9d2luZG93LlByb2dyZXNzRXZlbnQpZm9yKGEoZSwicHJvZ3Jlc3MiLGZ1bmN0aW9uKHQpe3JldHVybiB0Lmxlbmd0aENvbXB1dGFibGU/aS5wcm9ncmVzcz0xMDAqdC5sb2FkZWQvdC50b3RhbDppLnByb2dyZXNzPWkucHJvZ3Jlc3MrKDEwMC1pLnByb2dyZXNzKS8yfSksdD0wLHI9KG89WyJsb2FkIiwiYWJvcnQiLCJ0aW1lb3V0IiwiZXJyb3IiXSkubGVuZ3RoO3Q8cjt0KyspYShlLG9bdF0sZnVuY3Rpb24oKXtyZXR1cm4gbihpKSxpLnByb2dyZXNzPTEwMH0pO2Vsc2Ugcz1lLm9ucmVhZHlzdGF0ZWNoYW5nZSxlLm9ucmVhZHlzdGF0ZWNoYW5nZT1mdW5jdGlvbigpe3ZhciB0O3JldHVybiAwPT09KHQ9ZS5yZWFkeVN0YXRlKXx8ND09PXQ/KG4oaSksaS5wcm9ncmVzcz0xMDApOjM9PT1lLnJlYWR5U3RhdGUmJihpLnByb2dyZXNzPTUwKSwiZnVuY3Rpb24iPT10eXBlb2Ygcz9zLmFwcGx5KG51bGwsYXJndW1lbnRzKTp2b2lkIDB9fSxyPWZ1bmN0aW9uKHQsZSl7Zm9yKHZhciBuLHI9dGhpcyxzPXRoaXMucHJvZ3Jlc3M9MCxvPShuPVsiZXJyb3IiLCJvcGVuIl0pLmxlbmd0aDtzPG87cysrKWEodCxuW3NdLGZ1bmN0aW9uKCl7cmV0dXJuIGUociksci5wcm9ncmVzcz0xMDB9KX0sbnQucHJvdG90eXBlLmNvbXBsZXRlPWZ1bmN0aW9uKGUpe3JldHVybiB0aGlzLmVsZW1lbnRzPXRoaXMuZWxlbWVudHMuZmlsdGVyKGZ1bmN0aW9uKHQpe3JldHVybiB0IT09ZX0pfSxHPW50LHJ0LnByb3RvdHlwZS5jaGVjaz1mdW5jdGlvbigpe3ZhciB0PXRoaXM7cmV0dXJuIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IodGhpcy5zZWxlY3Rvcik/dGhpcy5kb25lKCk6c2V0VGltZW91dChmdW5jdGlvbigpe3JldHVybiB0LmNoZWNrKCl9LFAuZWxlbWVudHMuY2hlY2tJbnRlcnZhbCl9LHJ0LnByb3RvdHlwZS5kb25lPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuY29tcGxldGVDYWxsYmFjayh0aGlzKSx0aGlzLmNvbXBsZXRlQ2FsbGJhY2s9bnVsbCx0aGlzLnByb2dyZXNzPTEwMH0saT1ydCxzdC5wcm90b3R5cGUuc3RhdGVzPXtsb2FkaW5nOjAsaW50ZXJhY3RpdmU6NTAsY29tcGxldGU6MTAwfSxLPXN0LG09ZnVuY3Rpb24oKXt2YXIgZSxuLHIscyxvLGk9dGhpczt0aGlzLnByb2dyZXNzPTAsbz1bXSxzPTAscj1MKCksbj1zZXRJbnRlcnZhbChmdW5jdGlvbigpe3ZhciB0PUwoKS1yLTUwO3JldHVybiByPUwoKSxvLnB1c2godCksby5sZW5ndGg+UC5ldmVudExhZy5zYW1wbGVDb3VudCYmby5zaGlmdCgpLGU9cChvKSwrK3M+PVAuZXZlbnRMYWcubWluU2FtcGxlcyYmZTxQLmV2ZW50TGFnLmxhZ1RocmVzaG9sZD8oaS5wcm9ncmVzcz0xMDAsY2xlYXJJbnRlcnZhbChuKSk6aS5wcm9ncmVzcz0zLyhlKzMpKjEwMH0sNTApfSxvdC5wcm90b3R5cGUudGljaz1mdW5jdGlvbih0LGUpe3JldHVybiBudWxsPT1lJiYoZT1SKHRoaXMuc291cmNlLCJwcm9ncmVzcyIpKSwxMDA8PWUmJih0aGlzLmRvbmU9ITApLGU9PT10aGlzLmxhc3Q/dGhpcy5zaW5jZUxhc3RVcGRhdGUrPXQ6KHRoaXMuc2luY2VMYXN0VXBkYXRlJiYodGhpcy5yYXRlPShlLXRoaXMubGFzdCkvdGhpcy5zaW5jZUxhc3RVcGRhdGUpLHRoaXMuY2F0Y2h1cD0oZS10aGlzLnByb2dyZXNzKS9QLmNhdGNodXBUaW1lLHRoaXMuc2luY2VMYXN0VXBkYXRlPTAsdGhpcy5sYXN0PWUpLGU+dGhpcy5wcm9ncmVzcyYmKHRoaXMucHJvZ3Jlc3MrPXRoaXMuY2F0Y2h1cCp0KSxlPTEtTWF0aC5wb3codGhpcy5wcm9ncmVzcy8xMDAsUC5lYXNlRmFjdG9yKSx0aGlzLnByb2dyZXNzKz1lKnRoaXMucmF0ZSp0LHRoaXMucHJvZ3Jlc3M9TWF0aC5taW4odGhpcy5sYXN0UHJvZ3Jlc3MrUC5tYXhQcm9ncmVzc1BlckZyYW1lLHRoaXMucHJvZ3Jlc3MpLHRoaXMucHJvZ3Jlc3M9TWF0aC5tYXgoMCx0aGlzLnByb2dyZXNzKSx0aGlzLnByb2dyZXNzPU1hdGgubWluKDEwMCx0aGlzLnByb2dyZXNzKSx0aGlzLmxhc3RQcm9ncmVzcz10aGlzLnByb2dyZXNzLHRoaXMucHJvZ3Jlc3N9LHY9b3QsYj1lPU49dz1PPUM9bnVsbCx5LnJ1bm5pbmc9ITEsUz1mdW5jdGlvbigpe2lmKFAucmVzdGFydE9uUHVzaFN0YXRlKXJldHVybiB5LnJlc3RhcnQoKX0sbnVsbCE9d2luZG93Lmhpc3RvcnkucHVzaFN0YXRlJiYoSD13aW5kb3cuaGlzdG9yeS5wdXNoU3RhdGUsd2luZG93Lmhpc3RvcnkucHVzaFN0YXRlPWZ1bmN0aW9uKCl7cmV0dXJuIFMoKSxILmFwcGx5KHdpbmRvdy5oaXN0b3J5LGFyZ3VtZW50cyl9KSxudWxsIT13aW5kb3cuaGlzdG9yeS5yZXBsYWNlU3RhdGUmJih6PXdpbmRvdy5oaXN0b3J5LnJlcGxhY2VTdGF0ZSx3aW5kb3cuaGlzdG9yeS5yZXBsYWNlU3RhdGU9ZnVuY3Rpb24oKXtyZXR1cm4gUygpLHouYXBwbHkod2luZG93Lmhpc3RvcnksYXJndW1lbnRzKX0pLGw9e2FqYXg6dSxlbGVtZW50czpHLGRvY3VtZW50OkssZXZlbnRMYWc6bX0sKHg9ZnVuY3Rpb24oKXt2YXIgdCxlLG4scixzLG8saSxhO2Zvcih5LnNvdXJjZXM9Qz1bXSxlPTAscj0obz1bImFqYXgiLCJlbGVtZW50cyIsImRvY3VtZW50IiwiZXZlbnRMYWciXSkubGVuZ3RoO2U8cjtlKyspITEhPT1QW3Q9b1tlXV0mJkMucHVzaChuZXcgbFt0XShQW3RdKSk7Zm9yKG49MCxzPShhPW51bGwhPShpPVAuZXh0cmFTb3VyY2VzKT9pOltdKS5sZW5ndGg7bjxzO24rKylBPWFbbl0sQy5wdXNoKG5ldyBBKFApKTtyZXR1cm4geS5iYXI9dz1uZXcgYyxPPVtdLE49bmV3IHZ9KSgpLHkuc3RvcD1mdW5jdGlvbigpe3JldHVybiB5LnRyaWdnZXIoInN0b3AiKSx5LnJ1bm5pbmc9ITEsdy5kZXN0cm95KCksYj0hMCxudWxsIT1lJiYoImZ1bmN0aW9uIj09dHlwZW9mIGgmJmgoZSksZT1udWxsKSx4KCl9LHkucmVzdGFydD1mdW5jdGlvbigpe3JldHVybiB5LnRyaWdnZXIoInJlc3RhcnQiKSx5LnN0b3AoKSx5LnN0YXJ0KCl9LHkuZ289ZnVuY3Rpb24oKXt2YXIgbTtyZXR1cm4geS5ydW5uaW5nPSEwLHcucmVuZGVyKCksbT1MKCksYj0hMSxlPWooZnVuY3Rpb24odCxlKXt3LnByb2dyZXNzO2Zvcih2YXIgbixyLHMsbyxpLGEsdSxjLGwscCxoPWE9MCxmPSEwLGQ9dT0wLGc9Qy5sZW5ndGg7dTxnO2Q9Kyt1KWZvcihBPUNbZF0saT1udWxsIT1PW2RdP09bZF06T1tkXT1bXSxzPWM9MCxsPShyPW51bGwhPShwPUEuZWxlbWVudHMpP3A6W0FdKS5sZW5ndGg7YzxsO3M9KytjKW89cltzXSxmJj0obz1udWxsIT1pW3NdP2lbc106aVtzXT1uZXcgdihvKSkuZG9uZSxvLmRvbmV8fChoKyssYSs9by50aWNrKHQpKTtyZXR1cm4gbj1hL2gsdy51cGRhdGUoTi50aWNrKHQsbikpLHcuZG9uZSgpfHxmfHxiPyh3LnVwZGF0ZSgxMDApLHkudHJpZ2dlcigiZG9uZSIpLHNldFRpbWVvdXQoZnVuY3Rpb24oKXtyZXR1cm4gdy5maW5pc2goKSx5LnJ1bm5pbmc9ITEseS50cmlnZ2VyKCJoaWRlIil9LE1hdGgubWF4KFAuZ2hvc3RUaW1lLE1hdGgubWF4KFAubWluVGltZS0oTCgpLW0pLDApKSkpOmUoKX0pfSx5LnN0YXJ0PWZ1bmN0aW9uKHQpe2QoUCx0KSx5LnJ1bm5pbmc9ITA7dHJ5e3cucmVuZGVyKCl9Y2F0Y2godCl7bj10fXJldHVybiBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCIucGFjZSIpPyh5LnRyaWdnZXIoInN0YXJ0IikseS5nbygpKTpzZXRUaW1lb3V0KHkuc3RhcnQsNTApfSwiZnVuY3Rpb24iPT10eXBlb2YgZGVmaW5lJiZkZWZpbmUuYW1kP2RlZmluZShmdW5jdGlvbigpe3JldHVybiB5fSk6Im9iamVjdCI9PXR5cGVvZiBleHBvcnRzP21vZHVsZS5leHBvcnRzPXk6UC5zdGFydE9uUGFnZUxvYWQmJnkuc3RhcnQoKX0pLmNhbGwodGhpcyk7"></script>
40
+ <link rel="manifest" href="./manifest.json" />
41
+ <script
42
+ src="data:application/javascript;charset=utf-8;base64,KGZ1bmN0aW9uKCl7ZnVuY3Rpb24gcCgpe3ZhciBiPWRvY3VtZW50LmhlYWQucXVlcnlTZWxlY3RvcignbGlua1tyZWw9Im1hbmlmZXN0Il0nKSxhPWI/Yi5ocmVmOiIiO2lmKCFhKXRocm93J2NhblwndCBmaW5kIDxsaW5rIHJlbD0ibWFuaWZlc3QiIGhyZWY9Ii4uIiAvPlwnJzt2YXIgZD1BKFthLHdpbmRvdy5sb2NhdGlvbl0pLGU9bmV3IFhNTEh0dHBSZXF1ZXN0O2Uub3BlbigiR0VUIixhKTtlLndpdGhDcmVkZW50aWFscz0idXNlLWNyZWRlbnRpYWxzIj09PWIuZ2V0QXR0cmlidXRlKCJjcm9zc29yaWdpbiIpO2Uub25sb2FkPWZ1bmN0aW9uKCl7dHJ5e3ZhciBiPUpTT04ucGFyc2UoZS5yZXNwb25zZVRleHQpO0IoYixkKX1jYXRjaChrKXtjb25zb2xlLndhcm4oImVycm9yIixrKX19O2Uuc2VuZChudWxsKX1mdW5jdGlvbiBBKGIpe2Zvcih2YXIgYT17fSxkPTA7ZDxiLmxlbmd0aDthPXtjOmEuY30sKytkKXthLmM9YltkXTt0cnl7cmV0dXJuIG5ldyBVUkwoIiIsCmEuYyksZnVuY3Rpb24oYil7cmV0dXJuIGZ1bmN0aW9uKGEpe3JldHVybihuZXcgVVJMKGF8fCIiLGIuYykpLnRvU3RyaW5nKCl9fShhKX1jYXRjaChlKXt9fXJldHVybiBmdW5jdGlvbihiKXtyZXR1cm4gYnx8IiJ9fWZ1bmN0aW9uIHUoYixhKXtiPWRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoYik7Zm9yKHZhciBkIGluIGEpYi5zZXRBdHRyaWJ1dGUoZCxhW2RdKTtkb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKGIpO3JldHVybiBifWZ1bmN0aW9uIGMoYixhKXthJiYoITA9PT1hJiYoYT0ieWVzIiksdSgibWV0YSIse25hbWU6Yixjb250ZW50OmF9KSl9ZnVuY3Rpb24gQihiLGEpe2Z1bmN0aW9uIGQoYSxkLGcpe3ZhciBlPWEud2lkdGgsYz1hLmhlaWdodDthPXdpbmRvdy5kZXZpY2VQaXhlbFJhdGlvO3ZhciBmPXYoe3dpZHRoOmUqYSxoZWlnaHQ6YyphfSk7Zi5zY2FsZShhLGEpO2YuZmlsbFN0eWxlPWIuYmFja2dyb3VuZF9jb2xvcnx8IiNmOGY5ZmEiO2YuZmlsbFJlY3QoMCwwLGUsYyk7CmYudHJhbnNsYXRlKGUvMiwoYy0zMikvMik7ZyYmKGM9Zy53aWR0aC9hLGE9Zy5oZWlnaHQvYSwxMjg8YSYmKGMvPWEvMTI4LGE9MTI4KSw0ODw9YyYmNDg8PWEmJihmLmRyYXdJbWFnZShnLGMvLTIsYS8tMixjLGEpLGYudHJhbnNsYXRlKDAsYS8yKzMyKSkpO2YuZmlsbFN0eWxlPXQ/IndoaXRlIjoiYmxhY2siO2YuZm9udD0iMjRweCBIZWx2ZXRpY2FOZXVlLUNvbmRlbnNlZEJvbGQiO2c9Yi5uYW1lfHxiLnNob3J0X25hbWV8fGRvY3VtZW50LnRpdGxlO2E9Zi5tZWFzdXJlVGV4dChnKS53aWR0aDtpZihhPC44KmUpZi5maWxsVGV4dChnLGEvLTIsMCk7ZWxzZSBmb3IoZz1nLnNwbGl0KC9ccysvZyksYT0xO2E8PWcubGVuZ3RoOysrYSl7Yz1nLnNsaWNlKDAsYSkuam9pbigiICIpO3ZhciB3PWYubWVhc3VyZVRleHQoYykud2lkdGg7aWYoYT09PWcubGVuZ3RofHx3Pi42KmUpZi5maWxsVGV4dChjLHcvLTIsMCksZi50cmFuc2xhdGUoMCwyNCoxLjIpLGcuc3BsaWNlKDAsYSksYT0wfXJldHVybiBmdW5jdGlvbigpe3ZhciBhPQpkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJsaW5rIik7YS5zZXRBdHRyaWJ1dGUoInJlbCIsImFwcGxlLXRvdWNoLXN0YXJ0dXAtaW1hZ2UiKTthLnNldEF0dHJpYnV0ZSgibWVkaWEiLCIob3JpZW50YXRpb246ICIrZCsiKSIpO2Euc2V0QXR0cmlidXRlKCJocmVmIixmLmNhbnZhcy50b0RhdGFVUkwoKSk7cmV0dXJuIGF9fWZ1bmN0aW9uIGUoYSl7dmFyIGI9ZCh3aW5kb3cuc2NyZWVuLCJwb3J0cmFpdCIsYSksYz1kKHt3aWR0aDp3aW5kb3cuc2NyZWVuLmhlaWdodCxoZWlnaHQ6d2luZG93LnNjcmVlbi53aWR0aH0sImxhbmRzY2FwZSIsYSk7d2luZG93LnNldFRpbWVvdXQoZnVuY3Rpb24oKXtkb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKGIoKSk7d2luZG93LnNldFRpbWVvdXQoZnVuY3Rpb24oKXtkb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKGMoKSl9LDEwKX0sMTApfXZhciBoPWIuaWNvbnN8fFtdO2guc29ydChmdW5jdGlvbihhLGIpe3JldHVybiBwYXJzZUludChiLnNpemVzLDEwKS0KcGFyc2VJbnQoYS5zaXplcywxMCl9KTt2YXIgaz1oLm1hcChmdW5jdGlvbihiKXt2YXIgZD17cmVsOiJpY29uIixocmVmOmEoYi5zcmMpLHNpemVzOmIuc2l6ZXN9O3UoImxpbmsiLGQpO2lmKHEmJiEoMTIwPnBhcnNlSW50KGIuc2l6ZXMsMTApKSlyZXR1cm4gZC5yZWw9ImFwcGxlLXRvdWNoLWljb24iLHUoImxpbmsiLGQpfSkuZmlsdGVyKEJvb2xlYW4pO2subGVuZ3RoJiZrW2subGVuZ3RoLTFdLnJlbW92ZUF0dHJpYnV0ZSgic2l6ZXMiKTt2YXIgbT1kb2N1bWVudC5oZWFkLnF1ZXJ5U2VsZWN0b3IoJ21ldGFbbmFtZT0idmlld3BvcnQiXScpLHA9ISEobSYmbS5jb250ZW50fHwiIikubWF0Y2goL1xidmlld3BvcnQtZml0XHMqPVxzKmNvdmVyXGIvKSxyPWIuZGlzcGxheTttPS0xIT09Qy5pbmRleE9mKHIpO2MoIm1vYmlsZS13ZWItYXBwLWNhcGFibGUiLG0pO0QoYi50aGVtZV9jb2xvcnx8ImJsYWNrIixwKTtFJiYoYygiYXBwbGljYXRpb24tbmFtZSIsYi5zaG9ydF9uYW1lKSxjKCJtc2FwcGxpY2F0aW9uLXRvb2x0aXAiLApiLmRlc2NyaXB0aW9uKSxjKCJtc2FwcGxpY2F0aW9uLXN0YXJ0dXJsIixhKGIuc3RhcnRfdXJsfHwiLiIpKSxjKCJtc2FwcGxpY2F0aW9uLW5hdmJ1dHRvbi1jb2xvciIsYi50aGVtZV9jb2xvciksKGg9aFswXSkmJmMoIm1zYXBwbGljYXRpb24tVGlsZUltYWdlIixhKGguc3JjKSksYygibXNhcHBsaWNhdGlvbi1UaWxlQ29sb3IiLGIuYmFja2dyb3VuZF9jb2xvcikpO2RvY3VtZW50LmhlYWQucXVlcnlTZWxlY3RvcignW25hbWU9InRoZW1lLWNvbG9yIl0nKXx8YygidGhlbWUtY29sb3IiLGIudGhlbWVfY29sb3IpO2lmKHEpe3ZhciB0PXgoYi5iYWNrZ3JvdW5kX2NvbG9yfHwiI2Y4ZjlmYSIpOyhyPUYoYi5yZWxhdGVkX2FwcGxpY2F0aW9ucykpJiZjKCJhcHBsZS1pdHVuZXMtYXBwIiwiYXBwLWlkPSIrcik7YygiYXBwbGUtbW9iaWxlLXdlYi1hcHAtY2FwYWJsZSIsbSk7YygiYXBwbGUtbW9iaWxlLXdlYi1hcHAtdGl0bGUiLGIuc2hvcnRfbmFtZXx8Yi5uYW1lKTt2YXIgbj1rWzBdLApsPW5ldyBJbWFnZTtsLmNyb3NzT3JpZ2luPSJhbm9ueW1vdXMiO2wub25lcnJvcj1mdW5jdGlvbigpe2UoKX07aWYoay5sZW5ndGgpbC5vbmxvYWQ9ZnVuY3Rpb24oKXtlKGwpO2lmKGIuYmFja2dyb3VuZF9jb2xvcil7dmFyIGE9eShsLGIuYmFja2dyb3VuZF9jb2xvcik7YSYmKG4uaHJlZj1hLGsuc2xpY2UoMSkuZm9yRWFjaChmdW5jdGlvbihhKXt2YXIgZD1uZXcgSW1hZ2U7ZC5jcm9zc09yaWdpbj0iYW5vbnltb3VzIjtkLm9ubG9hZD1mdW5jdGlvbigpe3ZhciBjPXkoZCxiLmJhY2tncm91bmRfY29sb3IsITApO2EuaHJlZj1jfTtkLnNyYz1hLmhyZWZ9KSl9fSxsLnNyYz1uLmhyZWY7ZWxzZSBsLm9uZXJyb3IoKX1lbHNlIGg9e3BvcjoicG9ydHJhaXQiLGxhbjoibGFuZHNjYXBlIn1bU3RyaW5nKGIub3JpZW50YXRpb258fCIiKS5zdWJzdHIoMCwzKV18fCIiLGMoIng1LW9yaWVudGF0aW9uIixoKSxjKCJzY3JlZW4tb3JpZW50YXRpb24iLGgpLCJmdWxsc2NyZWVuIj09PXI/KGMoIng1LWZ1bGxzY3JlZW4iLAoidHJ1ZSIpLGMoImZ1bGwtc2NyZWVuIiwieWVzIikpOm0mJihjKCJ4NS1wYWdlLW1vZGUiLCJhcHAiKSxjKCJicm93c2VybW9kZSIsImFwcGxpY2F0aW9uIikpfWZ1bmN0aW9uIEYoYil7dmFyIGE7KGJ8fFtdKS5maWx0ZXIoZnVuY3Rpb24oYSl7cmV0dXJuIml0dW5lcyI9PT1hLnBsYXRmb3JtfSkuZm9yRWFjaChmdW5jdGlvbihiKXtiLmlkP2E9Yi5pZDooYj1iLnVybC5tYXRjaCgvaWQoXGQrKS8pKSYmKGE9YlsxXSl9KTtyZXR1cm4gYX1mdW5jdGlvbiBEKGIsYSl7aWYocXx8Ryl7dmFyIGQ9eChiKTtpZihxKWMoImFwcGxlLW1vYmlsZS13ZWItYXBwLXN0YXR1cy1iYXItc3R5bGUiLGE/ImJsYWNrLXRyYW5zbHVjZW50IjpkPyJibGFjayI6ImRlZmF1bHQiKTtlbHNle2E6e3RyeXt2YXIgZT1XaW5kb3dzLlVJLlZpZXdNYW5hZ2VtZW50LkFwcGxpY2F0aW9uVmlldy5nZXRGb3JDdXJyZW50VmlldygpLnRpdGxlQmFyO2JyZWFrIGF9Y2F0Y2goaCl7fWU9dm9pZCAwfWlmKGE9ZSlhLmZvcmVncm91bmRDb2xvcj0KdChkPyJibGFjayI6IndoaXRlIiksYS5iYWNrZ3JvdW5kQ29sb3I9dChiKX19fWZ1bmN0aW9uIHQoYil7Yj1uKGIpO3JldHVybntyOmJbMF0sZzpiWzFdLGI6YlsyXSxhOmJbM119fWZ1bmN0aW9uIG4oYil7dmFyIGE9digpO2EuZmlsbFN0eWxlPWI7YS5maWxsUmVjdCgwLDAsMSwxKTtyZXR1cm4gYS5nZXRJbWFnZURhdGEoMCwwLDEsMSkuZGF0YX1mdW5jdGlvbiB4KGIpe2I9bihiKS5tYXAoZnVuY3Rpb24oYSl7YS89MjU1O3JldHVybi4wMzkyOD5hP2EvMTIuOTI6TWF0aC5wb3coKGErLjA1NSkvMS4wNTUsMi40KX0pO3JldHVybiAzPE1hdGguYWJzKDEuMDUvKC4yMTI2KmJbMF0rLjcxNTIqYlsxXSsuMDcyMipiWzJdKy4wNSkpfWZ1bmN0aW9uIHkoYixhLGMpe2M9dm9pZCAwPT09Yz8hMTpjO3ZhciBkPXYoYik7ZC5kcmF3SW1hZ2UoYiwwLDApO2lmKGN8fDI1NSE9ZC5nZXRJbWFnZURhdGEoMCwwLDEsMSkuZGF0YVszXSlyZXR1cm4gZC5nbG9iYWxDb21wb3NpdGVPcGVyYXRpb249CiJkZXN0aW5hdGlvbi1vdmVyIixkLmZpbGxTdHlsZT1hLGQuZmlsbFJlY3QoMCwwLGIud2lkdGgsYi5oZWlnaHQpLGQuY2FudmFzLnRvRGF0YVVSTCgpfWZ1bmN0aW9uIHYoYil7Yj12b2lkIDA9PT1iP3t3aWR0aDoxLGhlaWdodDoxfTpiO3ZhciBhPWIuaGVpZ2h0LGM9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiY2FudmFzIik7Yy53aWR0aD1iLndpZHRoO2MuaGVpZ2h0PWE7cmV0dXJuIGMuZ2V0Q29udGV4dCgiMmQiKX1pZigib25sb2FkImluIFhNTEh0dHBSZXF1ZXN0LnByb3RvdHlwZSYmIW5hdmlnYXRvci5mKXt2YXIgQz1bInN0YW5kYWxvbmUiLCJmdWxsc2NyZWVuIiwibWluaW1hbC11aSJdLHo9bmF2aWdhdG9yLnVzZXJBZ2VudHx8IiIscT1uYXZpZ2F0b3IudmVuZG9yJiYtMSE9PW5hdmlnYXRvci52ZW5kb3IuaW5kZXhPZigiQXBwbGUiKSYmLTEhPT16LmluZGV4T2YoIk1vYmlsZS8iKSxFPSEhei5tYXRjaCgvKE1TSUUgfEVkZ2VcL3xUcmlkZW50XC8pLyksRz0idW5kZWZpbmVkIiE9PQp0eXBlb2YgV2luZG93czsiY29tcGxldGUiPT09ZG9jdW1lbnQucmVhZHlTdGF0ZT9wKCk6d2luZG93LmFkZEV2ZW50TGlzdGVuZXIoImxvYWQiLHApfX0pKCk7"></script>
43
+ <script> if (navigator.serviceWorker) { navigator.serviceWorker.register } </script>
44
+
45
+ <style>
46
+ .bg-hover:hover,
47
+ .bg-hover:focus,
48
+ .bg-hover:active,
49
+ .bg-hover:target {
50
+ opacity: 0.45 !important;
51
+ }
52
+
53
+ .interobject {
54
+ position: fixed;
55
+ bottom: 0px;
56
+ left: 0;
57
+ width: 100%;
58
+ height: 100%;
59
+ border-block-start: 58px solid #00000000;
60
+ }
61
+
62
+ body {
63
+ margin: 0;
64
+ /*background-color: #111;*/
65
+ background-image: url(./d-framework/icon/144/favicon.png);
66
+ background-repeat: no-repeat;
67
+ background-attachment: fixed;
68
+ background-position: center;
69
+ }
70
+ </style>
71
+
72
+ </head>
73
+
74
+ <body>
75
+
76
+ <!-- MENU -->
77
+ <div class="offcanvas offcanvas-start z-12" tabindex="-1" id="offcanvasmenu" aria-labelledby="offcanvasmenuLabel"
78
+ style="width: 280px;">
79
+ <div class="offcanvas-header shadow bg-body-tertiary">
80
+ <h5 class="offcanvas-title" id="offcanvasmenuLabel"><i class="bi bi-columns-gap pe-3"></i> MENU</h5>
81
+ <button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
82
+ </div>
83
+ <div class="offcanvas-body">
84
+
85
+ <div class="fw-light fs-6 text-uppercase">
86
+ Aplicativos para várias plataformas by Developer Davidsonbpe.❞
87
+ </div>
88
+ <hr>
89
+ <div class="d-grid gap-2">
90
+
91
+ <button type="button"
92
+ onclick="javascript:window.open('https://embed.polotno.com/?publishLabel=Download&allowDownload=true&KEY=nFA5H9elEytDyPyvKL7T&jsonUrl=https://api.polotno.com/polotno.com-image-demo.json', 'janela-one')"
93
+ class="mt-1 btn btn-secondary rounded-0 text-start fs-6 text-uppercase opacity-75"><i
94
+ class="bi bi-justify-left float-start pe-3"></i> studio.polo.image
95
+ </button>
96
+
97
+ <button type="button"
98
+ onclick="javascript:window.open('https://embed.polotno.com/?publishLabel=Download&allowDownload=true&animationsEnabled=true&KEY=nFA5H9elEytDyPyvKL7T&jsonUrl=https://api.polotno.com/polotno.com-video-demo.json', 'janela-one')"
99
+ class="mt-1 btn btn-secondary rounded-0 text-start fs-6 text-uppercase opacity-75"><i
100
+ class="bi bi-justify-left float-start pe-3"></i> studio.polo.video
101
+ </button>
102
+
103
+ <button type="button" onclick="javascript:window.open('https://studio.polotno.com/', 'janela-one')"
104
+ class="mt-1 btn btn-secondary rounded-0 text-start fs-6 text-uppercase opacity-75"><i
105
+ class="bi bi-justify-left float-start pe-3"></i> studio.polo.versat
106
+ </button>
107
+
108
+ <button type="button" onclick="javascript:window.open('https://github.com/davidsonbpe')"
109
+ class="mt-1 btn btn-secondary rounded-0 text-start fs-6 text-uppercase opacity-75">
110
+ <i class="bi bi-justify-left float-start pe-3"></i> GitHub
111
+ </button>
112
+
113
+ <button type="button" onclick="javascript:window.open('https://codepen.io/davidsonbpe')"
114
+ class="mt-1 btn btn-secondary rounded-0 text-start fs-6 text-uppercase opacity-75">
115
+ <i class="bi bi-justify-left float-start pe-3"></i> CodePen
116
+ </button>
117
+
118
+ <button class="mt-1 btn btn-secondary rounded-0 text-start fs-6 text-uppercase opacity-75"
119
+ data-bs-toggle="collapse" data-bs-target="#dashboard-collapse" aria-expanded="false">
120
+ <i class="bi bi-justify-left float-start pe-3"></i> Infor Termos <i
121
+ class="bi bi-caret-down float-end"></i>
122
+ </button>
123
+
124
+ <div class="collapse" id="dashboard-collapse">
125
+ <ul class="btn-toggle-nav list-unstyled fw-normal pb-1 small">
126
+ <li>
127
+ <button type="button" title="INFORMAR"
128
+ onclick="javascript:alert(document.title+' | '+document.querySelector('meta[name=description]').getAttribute('content'));"
129
+ class="w-100 mt-1 btn btn-secondary rounded-0 text-start fs-6 text-uppercase opacity-75"><i
130
+ class="bi bi-justify-left float-start pe-3"></i> Informar
131
+ </button>
132
+ </li>
133
+ <li>
134
+ <button onclick="javascript:window.open('https://davidsonbpe.blogspot.com/')"
135
+ class="w-100 mt-1 btn btn-secondary rounded-0 text-start fs-6 text-uppercase opacity-75"
136
+ type="button"><i class="bi bi-justify-left float-start pe-3"></i> Developer
137
+ </button>
138
+ </li>
139
+
140
+ <li>
141
+ <button type="button" onclick="javascript:window.open('https://pag.ae/7Y3uUnhg8')"
142
+ class="w-100 mt-1 btn btn-secondary rounded-0 text-start fs-6 text-uppercase opacity-75">
143
+ <i class="bi bi-justify-left float-start pe-3"></i> Doar com
144
+ </button>
145
+ </li>
146
+
147
+ </ul>
148
+ </div>
149
+
150
+ <button type="button" onclick="sharesbutton();"
151
+ class="mt-1 btn btn-secondary rounded-0 text-start fs-6 text-uppercase opacity-75">
152
+ <i class="bi bi-justify-left float-start pe-3"></i> Compartilhar
153
+ </button>
154
+ </div>
155
+ </div>
156
+
157
+ <div class="p-2 border-top">
158
+
159
+ <button type="button" class="btn btn-secondary rounded-0 fs-6 ps-4 pe-4 text-uppercase float-end opacity-75"
160
+ data-bs-dismiss="offcanvas">Sair</button>
161
+ </div>
162
+ </div>
163
+ <!-- MENU -->
164
+
165
+ <div class="d-flex position-fixed z-3 w-100 border-bottom">
166
+
167
+ <img type="button" title="MENU" data-bs-toggle="offcanvas" data-bs-target="#offcanvasmenu"
168
+ aria-controls="offcanvasmenu" src="./d-framework/icon/144/favicon.png"
169
+ class="img-thumbnail rounded-0 border-0 p-0 bg-hover bg-light" width="56" height="50" />
170
+
171
+ <div class="form-floating flex-grow-1 rounded-0 border-0 text-uppercase">
172
+ <select type="button" title="MENU SELECT" class="form-select rounded-0 border-0 border-end text-uppercase"
173
+ id="mySelects" aria-label="Floating label select example">
174
+ <option selected value="javascript:location.reload();">studio.polodesig HOME</option>
175
+ <option value="javascript:sharesbutton();">COMPARTILHAR</option>
176
+ <option value="javascript:window.open('https://dpripol.pages.dev/?='+document.title+'');">PRIVACY POLICY
177
+ </option>
178
+ <option value="javascript:window.open('https://pag.ae/7Y3uUnhg8');">DOAR COM</option>
179
+ </select>
180
+ <label class="d-inline-block text-truncate w-100" for="floatingSelect">studio.polodesig</label>
181
+ </div>
182
+
183
+ <button type="button" onclick="sharesbutton();" title="COMPARTILHAR SITE"
184
+ class="btn bg-body bg-hover rounded-0 text-dark fs-4 px-3 border-end"><i
185
+ class="bi bi-share-fill opacity-75"></i></button>
186
+
187
+ </div>
188
+
189
+ <div class="container" style="height: 60px;top: 0px; position: sticky;"></div>
190
+
191
+ <object name="janela-one" class="interobject"
192
+ data="https://embed.polotno.com/?publishLabel=Download&allowDownload=true&KEY=nFA5H9elEytDyPyvKL7T&jsonUrl=https://api.polotno.com/polotno.com-image-demo.json"></object>
193
+
194
+
195
+ <script>
196
+ fetch("https://dav7.pages.dev/api/serve.json")
197
+ .then((response) => response.json())
198
+ .then((data) => {
199
+ const sites = data.sites;
200
+ const mySelects = document.getElementById("mySelects");
201
+
202
+ sites.forEach((sites) => {
203
+ const preElement = document.createElement("option");
204
+ preElement.value = `${sites.properties.links}`;
205
+ preElement.textContent = `${sites.properties.title}`;
206
+ mySelects.appendChild(preElement);
207
+ });
208
+ })
209
+ .catch((error) => {
210
+ console.log("ERROR", error);
211
+ });
212
+
213
+ const select = document.getElementById("mySelects");
214
+ select.addEventListener("change", function () {
215
+ const url = this.value;
216
+ if (url) {
217
+ window.location = url;
218
+ }
219
+ });
220
+
221
+ /*shared*/
222
+ function sharesbutton() {
223
+ navigator.share({
224
+ title: document.title,
225
+ text: "Compartilhar" + document.title,
226
+ url: window.location.href
227
+ });
228
+ }
229
+ </script>
230
+
231
+ <script src="https://redek-dp.github.io/servdevanalytics/v1/app.id.js"></script>
232
+ </body>
233
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
234
  </html>
manifest.json ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "STUDIO.POLODESIG",
3
+ "short_name": "STUDIO.POLODESIG",
4
+ "lang": "pt-BR",
5
+ "description": "STUDIO.POLODESIG. APLICATIVO BY DEVELOPER DAVIDSONBPE.",
6
+ "theme_color": "#602ab6",
7
+ "background_color": "#602ab6",
8
+ "display": "standalone",
9
+ "orientation": "any",
10
+ "start_url": "/?Installe=design",
11
+ "id": "design",
12
+ "iarc_rating_id": "II47-UB88-BR22-FL96-RY47-JD01-DK93-RM22-2025",
13
+ "dir": "auto",
14
+ "display_override": [
15
+ "standalone"
16
+ ],
17
+ "categories": [
18
+ "books"
19
+ ],
20
+ "icons": [
21
+ {
22
+ "src": "./d-framework/icon/144/favicon.png",
23
+ "sizes": "144x144",
24
+ "type": "image/png"
25
+ },
26
+ {
27
+ "src": "./d-framework/icon/36/favicon.png",
28
+ "sizes": "36x36",
29
+ "type": "image/png"
30
+ },
31
+ {
32
+ "src": "./d-framework/icon/48/favicon.png",
33
+ "sizes": "48x48",
34
+ "type": "image/png"
35
+ },
36
+ {
37
+ "src": "./d-framework/icon/72/favicon.png",
38
+ "sizes": "72x72",
39
+ "type": "image/png"
40
+ },
41
+ {
42
+ "src": "./d-framework/icon/96/favicon.png",
43
+ "sizes": "96x96",
44
+ "type": "image/png"
45
+ },
46
+ {
47
+ "src": "./d-framework/icon/192/favicon.png",
48
+ "sizes": "192x192",
49
+ "type": "image/png",
50
+ "purpose": "any maskable monochrome"
51
+ },
52
+ {
53
+ "src": "./d-framework/icon/512/favicon.png",
54
+ "sizes": "512x512",
55
+ "type": "image/png"
56
+ }
57
+ ],
58
+ "screenshots": [
59
+ {
60
+ "src": "./d-framework/icon/512/favicon.png",
61
+ "sizes": "512x512",
62
+ "type": "image/png",
63
+ "platform": "wide"
64
+ }
65
+ ]
66
+ }