1import { createHotContext as __vite__createHotContext } from "/@vite/client";import.meta.hot = __vite__createHotContext("/src/pages/query-builder/QueryAnalyticsPage.tsx");const useState = __vite__cjsImport0_react["useState"];const _jsxDEV = __vite__cjsImport13_react_jsxDevRuntime["jsxDEV"]; const _Fragment = __vite__cjsImport13_react_jsxDevRuntime["Fragment"];import __vite__cjsImport0_react from "/node_modules/.vite/deps/react.js?v=0fe5e139"; 2import { useNavigate, useParams } from "/node_modules/.vite/deps/react-router-dom.js?v=0fe5e139"; 3import { Doughnut, Line } from "/node_modules/.vite/deps/react-chartjs-2.js?v=0fe5e139"; 4import { Chart as ChartJS, ArcElement, CategoryScale, LinearScale, PointElement, LineElement, Tooltip, Legend, Filler } from "/node_modules/.vite/deps/chart__js.js?v=0fe5e139"; 5import ChartDataLabels from "/node_modules/.vite/deps/chartjs-plugin-datalabels.js?v=0fe5e139"; 6import { ArrowLeft, MessageCircle, Activity, Zap, Heart, Globe } from "/node_modules/.vite/deps/lucide-react.js?v=0fe5e139"; 7import { Heading } from "/src/components/ui/Heading.tsx"; 8import { Text } from "/src/components/ui/Text.tsx"; 9import { Button } from "/src/components/ui/Button.tsx"; 10import { PageSpinner } from "/src/components/ui/Spinner.tsx"; 11import { cn } from "/src/lib/utils.ts"; 12import { useGetQueryQuery, useGetAnalyticsQuery } from "/src/store/api/queryBuilderApi.ts"; 13import { lineEndpointLabels, sliceValueLabels } from "/src/utils/chartDataLabels.ts"; 14var _jsxFileName = "/app/src/pages/query-builder/QueryAnalyticsPage.tsx"; 15import __vite__cjsImport13_react_jsxDevRuntime from "/node_modules/.vite/deps/react_jsx-dev-runtime.js?v=0fe5e139"; 16var _s = $RefreshSig$(); 17ChartJS.register(ArcElement, CategoryScale, LinearScale, PointElement, LineElement, Tooltip, Legend, Filler, ChartDataLabels); 18// The plugin registry is process-wide (every Chart.js instance in the app shares it) â off by 19// default here, opted in per dataset below, so it can't leak onto some other chart unexpectedly. 20ChartJS.defaults.plugins.datalabels = { display: false }; 21// Backend's real emotion label set: anger/fear/joy/sadness/disgust/surprise/none. 22const EMOTION_COLORS = { 23 joy: "bg-orange-400", 24 surprise: "bg-violet-500", 25 anger: "bg-red-500", 26 fear: "bg-blue-500", 27 sadness: "bg-gray-400", 28 disgust: "bg-emerald-500", 29 none: "bg-slate-300" 30}; 31const DEFAULT_EMOTION_COLOR = "bg-indigo-400"; 32const languageDisplayNames = new Intl.DisplayNames(["en"], { type: "language" }); 33function languageName(code) { 34 try { 35 return languageDisplayNames.of(code) ?? code; 36 } catch { 37 return code; 38 } 39} 40function BreakdownCard({ title, icon: Icon, iconColor, rows, emptyNote }) { 41 return /* @__PURE__ */ _jsxDEV("div", { 42 className: "rounded-xl border border-gray-200 bg-white p-5 dark:border-gray-700 dark:bg-gray-800", 43 children: [/* @__PURE__ */ _jsxDEV("div", { 44 className: "mb-4 flex items-center gap-2", 45 children: [/* @__PURE__ */ _jsxDEV(Icon, { className: `h-4 w-4 ${iconColor}` }, void 0, false, { 46 fileName: _jsxFileName, 47 lineNumber: 70, 48 columnNumber: 9 49 }, this), /* @__PURE__ */ _jsxDEV(Text, { 50 weight: "semibold", 51 children: title 52 }, void 0, false, { 53 fileName: _jsxFileName, 54 lineNumber: 71, 55 columnNumber: 9 56 }, this)] 57 }, void 0, true, { 58 fileName: _jsxFileName, 59 lineNumber: 69, 60 columnNumber: 7 61 }, this), rows.length === 0 ? /* @__PURE__ */ _jsxDEV(Text, { 62 tone: "secondary", 63 children: emptyNote 64 }, void 0, false, { 65 fileName: _jsxFileName, 66 lineNumber: 74, 67 columnNumber: 9 68 }, this) : /* @__PURE__ */ _jsxDEV("div", { 69 className: "space-y-3", 70 children: rows.map((r) => { 71 const color = EMOTION_COLORS[r.label.toLowerCase()] ?? DEFAULT_EMOTION_COLOR; 72 return /* @__PURE__ */ _jsxDEV("div", { 73 className: "flex items-center gap-3", 74 children: [ 75 /* @__PURE__ */ _jsxDEV("span", { className: cn("h-2 w-2 shrink-0 rounded-full", color) }, void 0, false, { 76 fileName: _jsxFileName, 77 lineNumber: 81, 78 columnNumber: 17 79 }, this), 80 /* @__PURE__ */ _jsxDEV(Text, {
81 as: "span", 82 variant: "label", 83 className: "w-16 shrink-0", 84 children: r.label 85 }, void 0, false, { 86 fileName: _jsxFileName, 87 lineNumber: 82, 88 columnNumber: 17 89 }, this), 90 /* @__PURE__ */ _jsxDEV("div", { 91 className: "h-1.5 flex-1 overflow-hidden rounded-full bg-gray-100 dark:bg-gray-700", 92 children: /* @__PURE__ */ _jsxDEV("div", { 93 className: cn("h-full rounded-full", color), 94 style: { width: `${r.percent}%` } 95 }, void 0, false, { 96 fileName: _jsxFileName, 97 lineNumber: 84, 98 columnNumber: 19 99 }, this) 100 }, void 0, false, { 101 fileName: _jsxFileName, 102 lineNumber: 83, 103 columnNumber: 17 104 }, this), 105 /* @__PURE__ */ _jsxDEV(Text, { 106 as: "span", 107 variant: "label", 108 weight: "semibold", 109 className: "w-10 shrink-0 text-right", 110 children: [r.percent, "%"] 111 }, void 0, true, { 112 fileName: _jsxFileName, 113 lineNumber: 86, 114 columnNumber: 17 115 }, this) 116 ] 117 }, r.label, true, { 118 fileName: _jsxFileName, 119 lineNumber: 80, 120 columnNumber: 15 121 }, this); 122 }) 123 }, void 0, false, { 124 fileName: _jsxFileName, 125 lineNumber: 76, 126 columnNumber: 9 127 }, this)] 128 }, void 0, true, { 129 fileName: _jsxFileName, 130 lineNumber: 68, 131 columnNumber: 5 132 }, this); 133} 134_c = BreakdownCard; 135function coverageNote(s) { 136 if (s.totalMatched <= 0) return "No matched posts yet."; 137 if (s.sampleTooSmall) return `only ${s.classifiedCount} of ${s.totalMatched} posts classified`; 138 const coveragePercent = Math.round(s.classifiedCount / s.totalMatched * 100); 139 return `±${s.marginPoints} pts · based on ${coveragePercent}% of matched posts`; 140} 141/** The margin sentence that sits with the number, not on another screen: how 142* far this percentage could be from the truth, and what it was measured over. 143* Kept verbally distinct from per-item model confidence â the two are 144* different quantities and a reader must never merge them. */ 145function marginNote(s) { 146 if (s.totalMatched <= 0) return "No matched posts yet."; 147 if (s.sampleTooSmall) { 148 return `Not enough classified posts to quote a percentage â ${s.classifiedCount} of ${s.totalMatched} classified so far.`; 149 } 150 return `±${s.marginPoints} points at 95% confidence, from ${s.classifiedCount} of ` + `${s.totalMatched} matched posts classified. This is how sure we are of the ` + `percentage, not how sure the model is about any one post. Percentages ` + `describe post captions; audience reaction in the comments is not counted here.`; 151} 152function formatBucketLabel(iso, granularity) { 153 const date = new Date(iso); 154 if (granularity === "month") return date.toLocaleDateString(undefined, { 155 month: "short", 156 year: "numeric" 157 }); 158 return date.toLocaleDateString(undefined, { 159 month: "short", 160 day: "numeric" 161 }); 162} 163export default function QueryAnalyticsPage() { 164 _s(); 165 const navigate = useNavigate(); 166 const { id } = useParams(); 167 const { data: query, isLoading: queryLoading, isFetching: queryFetching } = useGetQueryQuery(id, { skip: !id }); 168 const [fromDate, setFromDate] = useState(""); 169 const [toDate, setToDate] = useState(""); 170 const [granularity, setGranularity] = useState("month"); 171 const [applyFilters, setApplyFilters] = useState(true); 172 const { data: analytics, isLoading: analyticsLoading, isFetching: analyticsFetching, isError: analyticsError } = useGetAnalyticsQuery({ 173 id, 174 from: fromDate || undefined, 175 to: toDate || undefined, 176 granularity, 177 applyFilters 178 }, { skip: !id }); 179 // isFetching (not just isLoading) so switching back to an 180 // already-cached date range/granularity still shows the shared page 181 // loader instead of silently sitting on the previous selection's data. 182 if (queryLoading || queryFetching) { 183 return /* @__PURE__ */ _jsxDEV(PageSpinner, {}, void 0, false, { 184 fileName: _jsxFileName, 185 lineNumber: 156, 186 columnNumber: 12 187 }, this); 188 } 189 if (!query) { 190 return /* @__PURE__ */ _jsxDEV("div", { 191 className: "p-6", 192 children: [/* @__PURE__ */ _jsxDEV(Text, { 193 tone: "secondary", 194 children: "Query not found." 195 }, void 0, false, { 196 fileName: _jsxFileName, 197 lineNumber: 162, 198 columnNumber: 9 199 }
199, this), /* @__PURE__ */ _jsxDEV(Button, { 200 variant: "outline", 201 className: "mt-3", 202 onClick: () => navigate("/listen/query-builder"), 203 children: "Back to Query Builder" 204 }, void 0, false, { 205 fileName: _jsxFileName, 206 lineNumber: 163, 207 columnNumber: 9 208 }, this)] 209 }, void 0, true, { 210 fileName: _jsxFileName, 211 lineNumber: 161, 212 columnNumber: 7 213 }, this); 214 } 215 // A percentage off a handful of classified posts is not an answer, it is a 216 // coincidence â below the backend's minimum sample it is withheld entirely 217 // rather than shown with a caveat nobody reads. 218 const tooFewClassified = analytics?.positiveSentiment.sampleTooSmall ?? false; 219 const positivePercent = tooFewClassified ? null : analytics?.positiveSentiment.percent ?? null; 220 const negativePercent = tooFewClassified ? null : analytics?.negativeSentiment.percent ?? null; 221 const neutralPercent = positivePercent !== null && negativePercent !== null ? Math.max(0, 100 - positivePercent - negativePercent) : null; 222 const sentimentSplit = [ 223 { 224 label: "Positive", 225 percent: positivePercent ?? 0, 226 color: "#22c55e" 227 }, 228 { 229 label: "Neutral", 230 percent: neutralPercent ?? 0, 231 color: "#9ca3af" 232 }, 233 { 234 label: "Negative", 235 percent: negativePercent ?? 0, 236 color: "#ef4444" 237 } 238 ]; 239 const statCards = [ 240 { 241 label: "Total Mentions", 242 value: analytics ? analytics.topicVolume.toLocaleString() : "0", 243 sub: analytics ? "Matched this date range" : "No data yet", 244 icon: MessageCircle, 245 color: "bg-pink-100 text-pink-600" 246 }, 247 { 248 label: "Positive Sentiment", 249 value: positivePercent !== null ? `${positivePercent}%` : "â", 250 sub: analytics ? coverageNote(analytics.positiveSentiment) : "No data yet", 251 icon: Activity, 252 color: "bg-green-100 text-green-600" 253 }, 254 { 255 label: "Engagements", 256 value: analytics ? analytics.engagements.toLocaleString() : "0", 257 sub: "Likes + comments + shares, this date range", 258 icon: Zap, 259 color: "bg-amber-100 text-amber-600" 260 } 261 ]; 262 const emotionRows = analytics?.emotionBreakdown ?? []; 263 const languageRows = (analytics?.languageBreakdown ?? []).map((r) => ({ 264 ...r, 265 label: languageName(r.label) 266 })); 267 return /* @__PURE__ */ _jsxDEV("div", { 268 className: "space-y-6 p-6", 269 children: [/* @__PURE__ */ _jsxDEV("div", { 270 className: "flex flex-wrap items-center justify-between gap-3", 271 children: [/* @__PURE__ */ _jsxDEV("div", { 272 className: "flex items-center gap-3", 273 children: [/* @__PURE__ */ _jsxDEV(Button, { 274 variant: "ghost", 275 size: "icon", 276 onClick: () => navigate("/listen/query-builder"), 277 "aria-label": "Back", 278 children: /* @__PURE__ */ _jsxDEV(ArrowLeft, { className: "h-5 w-5" }, void 0, false, { 279 fileName: _jsxFileName, 280 lineNumber: 217, 281 columnNumber: 13 282 }, this) 283 }, void 0, false, { 284 fileName: _jsxFileName, 285 lineNumber: 216, 286 columnNumber: 11 287 }, this), /* @__PURE__ */ _jsxDEV("div", { children: [/* @__PURE__ */ _jsxDEV(Heading, { 288 variant: "h2", 289 children: [query.name, " â Analytics"] 290 }, void 0, true, { 291 fileName: _jsxFileName, 292 lineNumber: 220, 293 columnNumber: 13 294 }, this), /* @__PURE__ */ _jsxDEV(Text, { 295 tone: "secondary", 296 children: "Follows this query's own date range" 297 }, void 0, false, { 298 fileName: _jsxFileName, 299 lineNumber: 221, 300 columnNumber: 13 301 }, this)] }, void 0, true, { 302 fileName: _jsxFileName, 303 lineNumber: 219, 304 columnNumber: 11 305 }, this)] 306 }, void 0, true, { 307 fileName: _jsxFileName, 308 lineNumber: 215, 309 columnNumber: 9 310 }, this), /* @__PURE__ */ _jsxDEV("div", { 311 className: "flex flex-wrap items-center gap-2", 312 children: [ 313 /* @__PURE__ */ _jsxDEV("div", { 314 className: "flex items-center gap-2", 315 children: [ 316 /* @__PURE__ */ _jsxDEV(Text, { 317 as: "span", 318 variant: "caption", 319 tone: "light", 320 children: "From" 321 }, void 0, false, { 322 fileName: _jsxFileName, 323 lineNumber: 227, 324 columnNumber: 13 325 }, this), 326 /* @__PURE__ */ _jsxDEV("input", { 327 type: "date", 328 value: fromDate, 329 onChange: (e) => setFromDate(e.target.value), 330 className: "h-9 rounded-lg border border-gray-300 px-2 text-sm dark:border-gray-600 dark:bg-gray-800" 331 }, void 0, false, { 332 fileName: _jsxFileName, 333 lineNumber: 228, 334 columnNumber: 13 335 }, this),
336 /* @__PURE__ */ _jsxDEV(Text, { 337 as: "span", 338 variant: "caption", 339 tone: "light", 340 children: "To" 341 }, void 0, false, { 342 fileName: _jsxFileName, 343 lineNumber: 234, 344 columnNumber: 13 345 }, this), 346 /* @__PURE__ */ _jsxDEV("input", { 347 type: "date", 348 value: toDate, 349 onChange: (e) => setToDate(e.target.value), 350 className: "h-9 rounded-lg border border-gray-300 px-2 text-sm dark:border-gray-600 dark:bg-gray-800" 351 }, void 0, false, { 352 fileName: _jsxFileName, 353 lineNumber: 235, 354 columnNumber: 13 355 }, this) 356 ] 357 }, void 0, true, { 358 fileName: _jsxFileName, 359 lineNumber: 226, 360 columnNumber: 11 361 }, this), 362 /* @__PURE__ */ _jsxDEV("div", { 363 className: "flex items-center gap-1 rounded-lg border border-gray-200 p-1 dark:border-gray-700", 364 children: [ 365 "day", 366 "week", 367 "month" 368 ].map((g) => /* @__PURE__ */ _jsxDEV("button", { 369 onClick: () => setGranularity(g), 370 className: cn("rounded-md px-3 py-1 text-sm font-medium capitalize transition-colors", granularity === g ? "bg-primary text-white" : "text-text-secondary hover:bg-secondary"), 371 children: g 372 }, g, false, { 373 fileName: _jsxFileName, 374 lineNumber: 244, 375 columnNumber: 15 376 }, this)) 377 }, void 0, false, { 378 fileName: _jsxFileName, 379 lineNumber: 242, 380 columnNumber: 11 381 }, this), 382 /* @__PURE__ */ _jsxDEV("label", { 383 className: "flex cursor-pointer items-center gap-2 rounded-lg border border-gray-200 px-3 py-1.5 text-sm dark:border-gray-700", 384 children: [/* @__PURE__ */ _jsxDEV("input", { 385 type: "checkbox", 386 checked: applyFilters, 387 onChange: (e) => setApplyFilters(e.target.checked), 388 className: "h-4 w-4 rounded border-gray-300 text-primary focus:ring-primary" 389 }, void 0, false, { 390 fileName: _jsxFileName, 391 lineNumber: 257, 392 columnNumber: 13 393 }, this), /* @__PURE__ */ _jsxDEV("span", { 394 className: "text-text-secondary", 395 children: "Show with filters only" 396 }, void 0, false, { 397 fileName: _jsxFileName, 398 lineNumber: 263, 399 columnNumber: 13 400 }, this)] 401 }, void 0, true, { 402 fileName: _jsxFileName, 403 lineNumber: 256, 404 columnNumber: 11 405 }, this) 406 ] 407 }, void 0, true, { 408 fileName: _jsxFileName, 409 lineNumber: 225, 410 columnNumber: 9 411 }, this)] 412 }, void 0, true, { 413 fileName: _jsxFileName, 414 lineNumber: 214, 415 columnNumber: 7 416 }
416, this), analyticsLoading || analyticsFetching ? /* @__PURE__ */ _jsxDEV(PageSpinner, {}, void 0, false, { 417 fileName: _jsxFileName, 418 lineNumber: 269, 419 columnNumber: 9 420 }, this) : analyticsError ? /* @__PURE__ */ _jsxDEV("div", { 421 className: "rounded-xl border border-gray-200 bg-white p-8 text-center dark:border-gray-700 dark:bg-gray-800", 422 children: /* @__PURE__ */ _jsxDEV(Text, { 423 className: "text-red-500", 424 children: "Failed to load analytics." 425 }, void 0, false, { 426 fileName: _jsxFileName, 427 lineNumber: 272, 428 columnNumber: 11 429 }, this) 430 }, void 0, false, { 431 fileName: _jsxFileName, 432 lineNumber: 271, 433 columnNumber: 9 434 }, this) : /* @__PURE__ */ _jsxDEV(_Fragment, { children: [ 435 /* @__PURE__ */ _jsxDEV("div", { 436 className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4", 437 children: statCards.map((c) => /* @__PURE__ */ _jsxDEV("div", { 438 className: "rounded-xl border border-gray-200 bg-white p-5 dark:border-gray-700 dark:bg-gray-800", 439 children: [ 440 /* @__PURE__ */ _jsxDEV("div", { 441 className: `mb-3 flex h-10 w-10 items-center justify-center rounded-lg ${c.color}`, 442 children: /* @__PURE__ */ _jsxDEV(c.icon, { className: "h-5 w-5" }, void 0, false, { 443 fileName: _jsxFileName, 444 lineNumber: 280, 445 columnNumber: 19 446 }, this) 447 }, void 0, false, { 448 fileName: _jsxFileName, 449 lineNumber: 279, 450 columnNumber: 17 451 }, this), 452 /* @__PURE__ */ _jsxDEV(Text, { 453 as: "span", 454 variant: "body-lg", 455 weight: "bold", 456 children: c.value 457 }, void 0, false, { 458 fileName: _jsxFileName, 459 lineNumber: 282, 460 columnNumber: 17 461 }, this), 462 /* @__PURE__ */ _jsxDEV(Text, { 463 tone: "secondary", 464 className: "block", 465 children: c.label 466 }, void 0, false, { 467 fileName: _jsxFileName, 468 lineNumber: 283, 469 columnNumber: 17 470 }, this), 471 /* @__PURE__ */ _jsxDEV(Text, { 472 variant: "caption", 473 tone: "light", 474 className: "mt-0.5 block", 475 children: c.sub 476 }, void 0, false, { 477 fileName: _jsxFileName, 478 lineNumber: 284, 479 columnNumber: 17 480 }, this) 481 ] 482 }, c.label, true, { 483 fileName: _jsxFileName, 484 lineNumber: 278, 485 columnNumber: 15 486 }, this)) 487 }, void 0, false, { 488 fileName: _jsxFileName, 489 lineNumber: 276, 490 columnNumber: 11 491 }, this), 492 /* @__PURE__ */ _jsxDEV("div", { 493 className: "grid grid-cols-1 gap-4", 494 children: /* @__PURE__ */ _jsxDEV("div", { 495 className: "rounded-xl border border-gray-200 bg-white p-5 dark:border-gray-700 dark:bg-gray-800", 496 children: [ 497 /* @__PURE__ */ _jsxDEV(Text, { 498 weight: "semibold", 499 className: "mb-4 block", 500 children: "Sentiment Overview" 501 }, void 0, false, { 502 fileName: _jsxFileName, 503 lineNumber: 291, 504 columnNumber: 15 505 }, this), 506 /* @__PURE__ */ _jsxDEV("div", { 507 className: "flex items-center gap-6", 508 children: [/* @__PURE__ */ _jsxDEV("div", { 509 className: "relative h-32 w-32 shrink-0", 510 children: [/* @__PURE__ */ _jsxDEV(Doughnut, { 511 data: { 512 labels: sentimentSplit.map((s) => s.label), 513 datasets: [{ 514 data: sentimentSplit.map((s) => s.percent), 515 backgroundColor: sentimentSplit.map((s) => s.color), 516 borderWidth: 0, 517 // Sits on the ring itself, so it doesn't collide with the center overlay text. 518 datalabels: sliceValueLabels((v) => `${v}%`, 9) 519 }] 520 }, 521 options: { 522 cutout: "72%", 523 plugins: { 524 legend: { display: false }, 525 tooltip: { enabled: true } 526 } 527 } 528 }, void 0, false, { 529 fileName: _jsxFileName, 530 lineNumber: 294, 531 columnNumber: 19 532 }, this), /* @__PURE__ */ _jsxDEV("div", { 533 className: "pointer-events-none absolute inset-0 flex flex-col items-center justify-center", 534 children: [/* @__PURE__ */ _jsxDEV(Text, { 535 as: "span", 536 variant: "body-lg", 537 weight: "bold", 538 children: positivePercent !== null ? `${positivePercent}%` : "â" 539 }, void 0, false, { 540 fileName: _jsxFileName, 541 lineNumber: 311, 542 columnNumber: 21 543 }
543, this), /* @__PURE__ */ _jsxDEV(Text, { 544 as: "span", 545 variant: "caption", 546 tone: "light", 547 children: positivePercent !== null ? "Positive" : tooFewClassified ? "Too few" : "No data" 548 }, void 0, false, { 549 fileName: _jsxFileName, 550 lineNumber: 314, 551 columnNumber: 21 552 }, this)] 553 }, void 0, true, { 554 fileName: _jsxFileName, 555 lineNumber: 310, 556 columnNumber: 19 557 }, this)] 558 }, void 0, true, { 559 fileName: _jsxFileName, 560 lineNumber: 293, 561 columnNumber: 17 562 }, this), /* @__PURE__ */ _jsxDEV("div", { 563 className: "flex-1 space-y-2", 564 children: sentimentSplit.map((s) => /* @__PURE__ */ _jsxDEV("div", { 565 className: "flex items-center gap-2", 566 children: [ 567 /* @__PURE__ */ _jsxDEV("span", { 568 className: "h-2 w-2 shrink-0 rounded-full", 569 style: { backgroundColor: s.color } 570 }, void 0, false, { 571 fileName: _jsxFileName, 572 lineNumber: 322, 573 columnNumber: 23 574 }, this), 575 /* @__PURE__ */ _jsxDEV(Text, { 576 as: "span", 577 variant: "label", 578 className: "w-16 shrink-0", 579 children: s.label 580 }, void 0, false, { 581 fileName: _jsxFileName, 582 lineNumber: 323, 583 columnNumber: 23 584 }, this), 585 /* @__PURE__ */ _jsxDEV("div", { 586 className: "h-1.5 flex-1 overflow-hidden rounded-full bg-gray-100 dark:bg-gray-700", 587 children: /* @__PURE__ */ _jsxDEV("div", { 588 className: "h-full rounded-full", 589 style: { 590 width: `${s.percent}%`, 591 backgroundColor: s.color 592 } 593 }, void 0, false, { 594 fileName: _jsxFileName, 595 lineNumber: 325, 596 columnNumber: 25 597 }, this) 598 }, void 0, false, { 599 fileName: _jsxFileName, 600 lineNumber: 324, 601 columnNumber: 23 602 }, this), 603 /* @__PURE__ */ _jsxDEV(Text, { 604 as: "span", 605 variant: "label", 606 weight: "semibold", 607 className: "w-10 shrink-0 text-right", 608 children: [s.percent, "%"] 609 }, void 0, true, { 610 fileName: _jsxFileName, 611 lineNumber: 327, 612 columnNumber: 23 613 }, this) 614 ] 615 }, s.label, true, { 616 fileName: _jsxFileName, 617 lineNumber: 321, 618 columnNumber: 21 619 }, this)) 620 }, void 0, false, { 621 fileName: _jsxFileName, 622 lineNumber: 319, 623 columnNumber: 17 624 }, this)] 625 }, void 0, true, { 626 fileName: _jsxFileName, 627 lineNumber: 292, 628 columnNumber: 15 629 }, this), 630 /* @__PURE__ */ _jsxDEV(Text, { 631 variant: "caption", 632 tone: "light", 633 className: "mt-3 block", 634 children: analytics ? marginNote(analytics.positiveSentiment) : "No data yet" 635 }, void 0, false, { 636 fileName: _jsxFileName, 637 lineNumber: 332, 638 columnNumber: 15 639 }, this), 640 /* @__PURE__ */ _jsxDEV("div", { 641 className: "mt-5 rounded-lg bg-secondary p-4 dark:bg-gray-900", 642 children: [/* @__PURE__ */ _jsxDEV(Text, { 643 variant: "caption", 644 weight: "semibold", 645 tone: "secondary", 646 className: "block", 647 children: "Sentiment Trend" 648 }, void 0, false, { 649 fileName: _jsxFileName, 650 lineNumber: 337, 651 columnNumber: 17 652 }, this), !analytics || analytics.trend.buckets.length === 0 ? /* @__PURE__ */ _jsxDEV(Text, { 653 variant: "caption", 654 tone: "light", 655 className: "mt-1 block text-center", 656 children: "No trend data for this date range yet." 657 }, void 0, false, { 658 fileName: _jsxFileName, 659 lineNumber: 339, 660 columnNumber: 19 661 }, this) : /* @__PURE__ */ _jsxDEV("div", { 662 className: "mt-2 h-40", 663 children: /* @__PURE__ */ _jsxDEV(Line, { 664 data: { 665 labels: analytics.trend.buckets.map((b) => formatBucketLabel(b, granularity)), 666 datasets: [ 667 { 668 label: "Positive", 669 data: analytics.trend.positive, 670 borderColor: "#22c55e", 671 backgroundColor: "#22c55e", 672 tension: .3, 673 pointRadius: 2, 674 datalabels: lineEndpointLabels(String, 8) 675 }, 676 { 677 label: "Negative", 678 data: analytics.trend.negative, 679 borderColor: "#ef4444", 680 backgroundColor: "#ef4444", 681 tension: .3, 682 pointRadius: 2, 683 datalabels: lineEndpointLabels(String, 8) 684 }, 685 { 686 label: "Neutral", 687 data: analytics.trend.neutral, 688 borderColor: "#9ca3af", 689 backgroundColor: "#9ca3af", 690 tension: .3, 691 pointRadius: 2, 692 datalabels: lineEndpointLabels(String, 8) 693 }, 694 { 695 label: "Unclassified", 696 data: analytics.trend.unclassified, 697 borderColor: "#d1d5db", 698 backgroundColor: "#d1d5db", 699 borderDash: [4, 4], 700 tension: .3, 701 pointRadius: 2, 702 // Text uses a darker gray than the line itself â the line's own 703 // pale hue would be illegible as label text on a white surface. 704 datalabels: lineEndpointLabels(String, 8) 705 } 706 ] 707 }, 708 options: { 709 maintainAspectRatio: false, 710 layout: { padding: { top: 14 } }, 711 scales: { 712 x: { ticks: { font: { size: 10 } } }, 713 y: { 714 beginAtZero: true, 715 grace: "10%", 716 ticks: { font: { size: 10 } } 717 } 718 }, 719 plugins: { legend: { 720 position: "bottom", 721 labels: { 722 boxWidth: 8, 723 font: { size: 10 } 724 } 725 } } 726 } 727 }, void 0, false, { 728 fileName: _jsxFileName, 729 lineNumber: 342, 730 columnNumber: 21 731 }, this) 732 }, void 0, false, { 733 fileName: _jsxFileName, 734 lineNumber: 341, 735 columnNumber: 19 736 }, this)] 737 }, void 0, true, { 738 fileName: _jsxFileName, 739 lineNumber: 336, 740 columnNumber: 15 741 }, this) 742 ] 743 }, void 0, true, { 744 fileName: _jsxFileName, 745 lineNumber: 290, 746 columnNumber: 13 747 }, this) 748 }, void 0, false, { 749 fileName: _jsxFileName, 750 lineNumber: 289, 751 columnNumber: 11 752 }, this),
753 /* @__PURE__ */ _jsxDEV("div", { 754 className: "grid grid-cols-1 gap-4 lg:grid-cols-2", 755 children: [/* @__PURE__ */ _jsxDEV(BreakdownCard, { 756 title: "Emotion Breakdown", 757 icon: Heart, 758 iconColor: "text-pink-500", 759 rows: emotionRows, 760 emptyNote: "No emotion data yet." 761 }, void 0, false, { 762 fileName: _jsxFileName, 763 lineNumber: 404, 764 columnNumber: 13 765 }, this), /* @__PURE__ */ _jsxDEV(BreakdownCard, { 766 title: "Language Breakdown", 767 icon: Globe, 768 iconColor: "text-purple-500", 769 rows: languageRows, 770 emptyNote: "No language data yet." 771 }, void 0, false, { 772 fileName: _jsxFileName, 773 lineNumber: 411, 774 columnNumber: 13 775 }, this)] 776 }, void 0, true, { 777 fileName: _jsxFileName, 778 lineNumber: 403, 779 columnNumber: 11 780 }, this) 781 ] }, void 0, true, { 782 fileName: _jsxFileName, 783 lineNumber: 275, 784 columnNumber: 9 785 }, this)] 786 }, void 0, true, { 787 fileName: _jsxFileName, 788 lineNumber: 213, 789 columnNumber: 5 790 }, this); 791} 792_s(QueryAnalyticsPage, "iBRz0S0UxY7G7MeAYAuIZMC4Nns=", false, function() { 793 return [ 794 useNavigate, 795 useParams, 796 useGetQueryQuery, 797 useGetAnalyticsQuery 798 ]; 799}); 800_c2 = QueryAnalyticsPage; 801var _c, _c2; 802$RefreshReg$(_c, "BreakdownCard"); 803$RefreshReg$(_c2, "QueryAnalyticsPage"); 804import * as RefreshRuntime from "/@react-refresh"; 805const inWebWorker = typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope; 806import * as __vite_react_currentExports from "/src/pages/query-builder/QueryAnalyticsPage.tsx"; 807if (import.meta.hot && !inWebWorker) { 808 if (!window.$RefreshReg$) { 809 throw new Error( 810 "@vitejs/plugin-react can't detect preamble. Something is wrong." 811 ); 812 } 813 814 const currentExports = __vite_react_currentExports; 815 queueMicrotask(() => { 816 RefreshRuntime.registerExportsForReactRefresh("/app/src/pages/query-builder/QueryAnalyticsPage.tsx", currentExports); 817 import.meta.hot.accept((nextExports) => { 818 if (!nextExports) return; 819 const invalidateMessage = RefreshRuntime.validateRefreshBoundaryAndEnqueueUpdate("/app/src/pages/query-builder/QueryAnalyticsPage.tsx", currentExports, nextExports); 820 if (invalidateMessage) import.meta.hot.invalidate(invalidateMessage); 821 }); 822 }); 823} 824function $RefreshReg$(type, id) { return RefreshRuntime.register(type, "/app/src/pages/query-builder/QueryAnalyticsPage.tsx" + ' ' + id); } 825function $RefreshSig$() { return RefreshRuntime.createSignatureFunctionForTransform(); } 826 827//# sourceMappingURL=data:application/json;base64,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LENBQUM7V0FDMUM7V0FDQTtZQUNFLE9BQU87WUFDUCxNQUFNLFVBQVUsTUFBTTtZQUN0QixhQUFhO1lBQ2IsaUJBQWlCO1lBQ2pCLFNBQVM7WUFDVCxhQUFhO1lBQ2IsWUFBWSxtQkFBbUIsUUFBUSxDQUFDO1dBQzFDO1dBQ0E7WUFDRSxPQUFPO1lBQ1AsTUFBTSxVQUFVLE1BQU07WUFDdEIsYUFBYTtZQUNiLGlCQUFpQjtZQUNqQixZQUFZLENBQUMsR0FBRyxDQUFDO1lBQ2pCLFNBQVM7WUFDVCxhQUFhOzs7WUFHYixZQUFZLG1CQUFtQixRQUFRLENBQUM7V0FDMUM7VUFDRjtTQUNGO1NBQ0EsU0FBUztVQUNQLHFCQUFxQjtVQUNyQixRQUFRLEVBQUUsU0FBUyxFQUFFLEtBQUssR0FBRyxFQUFFO1VBQy9CLFFBQVE7V0FDTixHQUFHLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLEdBQUcsRUFBRSxFQUFFO1dBQ25DLEdBQUc7WUFB
827RSxhQUFhO1lBQU0sT0FBTztZQUFPLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxHQUFHLEVBQUU7V0FBRTtVQUN0RTtVQUNBLFNBQVMsRUFBRSxRQUFRO1dBQUUsVUFBVTtXQUFVLFFBQVE7WUFBRSxVQUFVO1lBQUcsTUFBTSxFQUFFLE1BQU0sR0FBRztXQUFFO1VBQUUsRUFBRTtTQUN6RjtRQUNEOzs7OztPQUNFOzs7O2VBRUo7Ozs7OztLQUNGOzs7Ozs7R0FDRjs7Ozs7R0FFTCx3QkFBQyxPQUFEO0lBQUssV0FBVTtjQUFmLENBQ0Usd0JBQUMsZUFBRDtLQUNFLE9BQU07S0FDTixNQUFNO0tBQ04sV0FBVTtLQUNWLE1BQU07S0FDTixXQUFVO0lBQ1g7Ozs7Y0FDRCx3QkFBQyxlQUFEO0tBQ0UsT0FBTTtLQUNOLE1BQU07S0FDTixXQUFVO0tBQ1YsTUFBTTtLQUNOLFdBQVU7SUFDWDs7OztZQUNFOzs7Ozs7RUFDTDs7OztVQUVEOzs7Ozs7QUFFVCIsIm5hbWVzIjpbXSwic291cmNlcyI6WyJRdWVyeUFuYWx5dGljc1BhZ2UudHN4Il0sInZlcnNpb24iOjMsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHVzZVN0YXRlIH0gZnJvbSAncmVhY3QnXG5pbXBvcnQgeyB1c2VOYXZpZ2F0ZSwgdXNlUGFyYW1zIH0gZnJvbSAncmVhY3Qtcm91dGVyLWRvbSdcbmltcG9ydCB7IERvdWdobnV0LCBMaW5lIH0gZnJvbSAncmVhY3QtY2hhcnRqcy0yJ1xuaW1wb3J0IHtcbiAgQ2hhcnQgYXMgQ2hhcnRKUyxcbiAgQXJjRWxlbWVudCxcbiAgQ2F0ZWdvcnlTY2FsZSxcbiAgTGluZWFyU2NhbGUsXG4gIFBvaW50RWxlbWVudCxcbiAgTGluZUVsZW1lbnQsXG4gIFRvb2x0aXAsXG4gIExlZ2VuZCxcbiAgRmlsbGVyLFxufSBmcm9tICdjaGFydC5qcydcbmltcG9ydCBDaGFydERhdGFMYWJlbHMgZnJvbSAnY2hhcnRqcy1wbHVnaW4tZGF0YWxhYmVscydcbmltcG9ydCB7XG4gIEFycm93TGVmdCwgTWVzc2FnZUNpcmNsZSwgQWN0aXZpdHksIFphcCwgSGVhcnQsIEdsb2JlLFxufSBmcm9tICdsdWNpZGUtcmVhY3QnXG5pbXBvcnQgeyBIZWFkaW5nIH0gZnJvbSAnQC9jb21wb25lbnRzL3VpL0hlYWRpbmcnXG5pbXBvcnQgeyBUZXh0IH0gZnJvbSAnQC9jb21wb25lbnRzL3VpL1RleHQnXG5pbXBvcnQgeyBCdXR0b24gfSBmcm9tICdAL2NvbXBvbmVudHMvdWkvQnV0dG9uJ1xuaW1wb3J0IHsgUGFnZVNwaW5uZXIgfSBmcm9tICdAL2NvbXBvbmVudHMvdWkvU3Bpbm5lcidcbmltcG9ydCB7IGNuIH0gZnJvbSAnQC9saWIvdXRpbHMnXG5pbXBvcnQgeyB1c2VHZXRRdWVyeVF1ZXJ5LCB1c2VHZXRBbmFseXRpY3NRdWVyeSB9IGZyb20gJ0Avc3RvcmUvYXBpL3F1ZXJ5QnVpbGRlckFwaSdcbmltcG9ydCB7IGxpbmVFbmRwb2ludExhYmVscywgc2xpY2VWYWx1ZUxhYmVscyB9IGZyb20gJ0AvdXRpbHMvY2hhcnREYXRhTGFiZWxzJ1xuaW1wb3J0IHR5cGUgeyBBbmFseXRpY3NSZXNwb25zZSB9IGZyb20gJ0AvdHlwZXMvcXVlcnlCdWlsZGVyJ1xuXG5DaGFydEpTLnJlZ2lzdGVyKEFyY0VsZW1lbnQsIENhdGVnb3J5U2NhbGUsIExpbmVhclNjYWxlLCBQb2ludEVsZW1lbnQsIExpbmVFbGVtZW50LCBUb29sdGlwLCBMZWdlbmQsIEZpbGxlciwgQ2hhcnREYXRhTGFiZWxzKVxuLy8gVGhlIHBsdWdpbiByZWdpc3RyeSBpcyBwcm9jZXNzLXdpZGUgKGV2ZXJ5IENoYXJ0LmpzIGluc3RhbmNlIGluIHRoZSBhcHAgc2hhcmVzIGl0KSDigJQgb2ZmIGJ5XG4vLyBkZWZhdWx0IGhlcmUsIG9wdGVkIGluIHBlciBkYXRhc2V0IGJlbG93LCBzbyBpdCBjYW4ndCBsZWFrIG9udG8gc29tZSBvdGhlciBjaGFydCB1bmV4cGVjdGVkbHkuXG5DaGFydEpTLmRlZmF1bHRzLnBsdWdpbnMuZGF0YWxhYmVscyA9IHsgZGlzcGxheTogZmFsc2UgfVxuXG4vLyBCYWNrZW5kJ3MgcmVhbCBlbW90aW9uIGxhYmVsIHNldDogYW5nZXIvZmVhci9qb3kvc2FkbmVzcy9kaXNndXN0L3N1cnByaXNlL25vbmUuXG5jb25zdCBFTU9USU9OX0NPTE9SUzogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHtcbiAgam95OiAnYmctb3JhbmdlLTQwMCcsXG4gIHN1cnByaXNlOiAnYmctdmlvbGV0LTUwMCcsXG4gIGFuZ2VyOiAnYmctcmVkLTUwMCcsXG4gIGZlYXI6ICdiZy1ibHVlLTUwMCcsXG4gIHNhZG5lc3M6ICdiZy1ncmF5LTQwMCcsXG4gIGRpc2d1c3Q6ICdiZy1lbWVyYWxkLTUwMCcsXG4gIG5vbmU6ICdiZy1zbGF0ZS0zMDAnLFxufVxuY29uc3QgREVGQVVMVF9FTU9USU9OX0NPTE9SID0gJ2JnLWluZGlnby00MDAnXG5cbmNvbnN0IGxhbmd1YWdlRGlzcGxheU5hbWVzID0gbmV3IEludGwuRGlzcGxheU5hbWVzKFsnZW4nXSwgeyB0eXBlOiAnbGFuZ3VhZ2UnIH0pXG5mdW5jdGlvbiBsYW5ndWFnZU5hbWUoY29kZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gbGFuZ3VhZ2VEaXNwbGF5TmFtZXMub2YoY29kZSkgPz8gY29kZVxuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gY29kZVxuICB9XG59XG5cbmZ1bmN0aW9uIEJyZWFrZG93bkNhcmQoe1xuICB0aXRsZSxcbiAgaWNvbjogSWNvbixcbiAgaWNvbkNvbG9yLFxuICByb3dzLFxuICBlbXB0eU5vdGUsXG59OiB7XG4gIHRpdGxlOiBzdHJpbmdcbiAgaWNvbjogdHlwZW9mIEdsb2JlXG4gIGljb25Db2xvcjogc3RyaW5nXG4gIHJvd3M6IHsgbGFiZWw6IHN0cmluZzsgcGVyY2VudDogbnVtYmVyIH1bXVxuICBlbXB0eU5vdGU6IHN0cmluZ1xufSkge1xuICByZXR1cm4gKFxuICAgIDxkaXYgY2xhc3NOYW1lPVwicm91bmRlZC14bCBib3JkZXIgYm9yZGVyLWdyYXktMjAwIGJnLXdoaXRlIHAtNSBkYXJrOmJvcmRlci1ncmF5LTcwMCBkYXJrOmJnLWdyYXktODAwXCI+XG4gICAgICA8ZGl2IGNsYXNzTmFtZT1cIm1iLTQgZmxleCBpdGVtcy1jZW50ZXIgZ2FwLTJcIj5cbiAgICAgICAgPEljb24gY2xhc3NOYW1lPXtgaC00IHctNCAke2ljb25Db2xvcn1gfSAvPlxuICAgICAgICA8VGV4dCB3ZWlnaHQ9XCJzZW1pYm9sZFwiPnt0aXRsZX08L1RleHQ+XG4gICAgICA8L2Rpdj5cbiAgICAgIHtyb3dzLmxlbmd0aCA9PT0gMCA/IChcbiAgICAgICAgPFRleHQgdG9uZT1cInNlY29uZGFyeVwiPntlbXB0eU5vdGV9PC9UZXh0PlxuICAgICAgKSA6IChcbiAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJzcGFjZS15LTNcIj5cbiAgICAgICAgICB7cm93cy5tYXAociA9PiB7XG4gICAgICAgICAgICBjb25zdCBjb2xvciA9IEVNT1RJT05fQ09MT1JTW3IubGFiZWwudG9Mb3dlckNhc2UoKV0gPz8gREVGQVVMVF9FTU9USU9OX0NPTE9SXG4gICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICA8ZGl2IGtleT17ci5sYWJlbH0gY2xhc3NOYW1lPVwiZmxleCBpdGVtcy1jZW50ZXIgZ2FwLTNcIj5cbiAgICAgICAgICAgICAgICA8c3BhbiBjbGFzc05hbWU9e2NuKCdoLTIgdy0yIHNocmluay0wIHJvdW5kZWQtZnVsbCcsIGNvbG9yKX0gLz5cbiAgICAgICAgICAgICAgICA8VGV4dCBhcz1cInNwYW5cIiB2YXJpYW50PVwibGFiZWxcIiBjbGFzc05hbWU9XCJ3LTE2IHNocmluay0wXCI+e3IubGFiZWx9PC9UZXh0PlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwiaC0xLjUgZmxleC0xIG92ZXJmbG93LWhpZGRlbiByb3VuZGVkLWZ1bGwgYmctZ3JheS0xMDAgZGFyazpiZy1ncmF5LTcwMFwiPlxuICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9e2NuKCdoLWZ1bGwgcm91bmRlZC1mdWxsJywgY29sb3IpfSBzdHlsZT17eyB3aWR0aDogYCR7ci5wZXJjZW50fSVgIH19IC8+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPFRleHQgYXM9XCJzcGFuXCIgdmFyaWFudD1cImxhYmVsXCIgd2VpZ2h0PVwic2VtaWJvbGRcIiBjbGFzc05hbWU9XCJ3LTEwIHNocmluay0wIHRleHQtcmlnaHRcIj57ci5wZXJjZW50fSU8L1RleHQ+XG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgKVxuICAgICAgICAgI
827H0pfVxuICAgICAgICA8L2Rpdj5cbiAgICAgICl9XG4gICAgPC9kaXY+XG4gIClcbn1cblxuZnVuY3Rpb24gY292ZXJhZ2VOb3RlKHM6IEFuYWx5dGljc1Jlc3BvbnNlWydwb3NpdGl2ZVNlbnRpbWVudCddKTogc3RyaW5nIHtcbiAgaWYgKHMudG90YWxNYXRjaGVkIDw9IDApIHJldHVybiAnTm8gbWF0Y2hlZCBwb3N0cyB5ZXQuJ1xuICBpZiAocy5zYW1wbGVUb29TbWFsbCkgcmV0dXJuIGBvbmx5ICR7cy5jbGFzc2lmaWVkQ291bnR9IG9mICR7cy50b3RhbE1hdGNoZWR9IHBvc3RzIGNsYXNzaWZpZWRgXG4gIGNvbnN0IGNvdmVyYWdlUGVyY2VudCA9IE1hdGgucm91bmQoKHMuY2xhc3NpZmllZENvdW50IC8gcy50b3RhbE1hdGNoZWQpICogMTAwKVxuICByZXR1cm4gYMKxJHtzLm1hcmdpblBvaW50c30gcHRzIMK3IGJhc2VkIG9uICR7Y292ZXJhZ2VQZXJjZW50fSUgb2YgbWF0Y2hlZCBwb3N0c2Bcbn1cblxuLyoqIFRoZSBtYXJnaW4gc2VudGVuY2UgdGhhdCBzaXRzIHdpdGggdGhlIG51bWJlciwgbm90IG9uIGFub3RoZXIgc2NyZWVuOiBob3dcbiAqICBmYXIgdGhpcyBwZXJjZW50YWdlIGNvdWxkIGJlIGZyb20gdGhlIHRydXRoLCBhbmQgd2hhdCBpdCB3YXMgbWVhc3VyZWQgb3Zlci5cbiAqICBLZXB0IHZlcmJhbGx5IGRpc3RpbmN0IGZyb20gcGVyLWl0ZW0gbW9kZWwgY29uZmlkZW5jZSDigJQgdGhlIHR3byBhcmVcbiAqICBkaWZmZXJlbnQgcXVhbnRpdGllcyBhbmQgYSByZWFkZXIgbXVzdCBuZXZlciBtZXJnZSB0aGVtLiAqL1xuZnVuY3Rpb24gbWFyZ2luTm90ZShzOiBBbmFseXRpY3NSZXNwb25zZVsncG9zaXRpdmVTZW50aW1lbnQnXSk6IHN0cmluZyB7XG4gIGlmIChzLnRvdGFsTWF0Y2hlZCA8PSAwKSByZXR1cm4gJ05vIG1hdGNoZWQgcG9zdHMgeWV0LidcbiAgaWYgKHMuc2FtcGxlVG9vU21hbGwpIHtcbiAgICByZXR1cm4gYE5vdCBlbm91Z2ggY2xhc3NpZmllZCBwb3N0cyB0byBxdW90ZSBhIHBlcmNlbnRhZ2Ug4oCUICR7cy5jbGFzc2lmaWVkQ291bnR9IG9mICR7cy50b3RhbE1hdGNoZWR9IGNsYXNzaWZpZWQgc28gZmFyLmBcbiAgfVxuICByZXR1cm4gKFxuICAgIGDCsSR7cy5tYXJnaW5Qb2ludHN9IHBvaW50cyBhdCA5NSUgY29uZmlkZW5jZSwgZnJvbSAke3MuY2xhc3NpZmllZENvdW50fSBvZiBgICtcbiAgICBgJHtzLnRvdGFsTWF0Y2hlZH0gbWF0Y2hlZCBwb3N0cyBjbGFzc2lmaWVkLiBUaGlzIGlzIGhvdyBzdXJlIHdlIGFyZSBvZiB0aGUgYCArXG4gICAgYHBlcmNlbnRhZ2UsIG5vdCBob3cgc3VyZSB0aGUgbW9kZWwgaXMgYWJvdXQgYW55IG9uZSBwb3N0LiBQZXJjZW50YWdlcyBgICtcbiAgICBgZGVzY3JpYmUgcG9zdCBjYXB0aW9uczsgYXVkaWVuY2UgcmVhY3Rpb24gaW4gdGhlIGNvbW1lbnRzIGlzIG5vdCBjb3VudGVkIGhlcmUuYFxuICApXG59XG5cbnR5cGUgR3JhbnVsYXJpdHkgPSAnZGF5JyB8ICd3ZWVrJyB8ICdtb250aCdcblxuZnVuY3Rpb24gZm9ybWF0QnVja2V0TGFiZWwoaXNvOiBzdHJpbmcsIGdyYW51bGFyaXR5OiBHcmFudWxhcml0eSk6IHN0cmluZyB7XG4gIGNvbnN0IGRhdGUgPSBuZXcgRGF0ZShpc28pXG4gIGlmIChncmFudWxhcml0eSA9PT0gJ21vbnRoJykgcmV0dXJuIGRhdGUudG9Mb2NhbGVEYXRlU3RyaW5nKHVuZGVmaW5lZCwgeyBtb250aDogJ3Nob3J0JywgeWVhcjogJ251bWVyaWMnIH0pXG4gIHJldHVybiBkYXRlLnRvTG9jYWxlRGF0ZVN0cmluZyh1bmRlZmluZWQsIHsgbW9udGg6ICdzaG9ydCcsIGRheTogJ251bWVyaWMnIH0pXG59XG5cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIFF1ZXJ5QW5hbHl0aWNzUGFnZSgpIHtcbiAgY29uc3QgbmF2aWdhdGUgPSB1c2VOYXZpZ2F0ZSgpXG4gIGNvbnN0IHsgaWQgfSA9IHVzZVBhcmFtczx7IGlkOiBzdHJpbmcgfT4oKVxuICBjb25zdCB7XG4gICAgZGF0YTogcXVlcnksXG4gICAgaXNMb2FkaW5nOiBxdWVyeUxvYWRpbmcsXG4gICAgaXNGZXRjaGluZzogcXVlcnlGZXRjaGluZyxcbiAgfSA9IHVzZUdldFF1ZXJ5UXVlcnkoaWQhLCB7IHNraXA6ICFpZCB9KVxuXG4gIGNvbnN0IFtmcm9tRGF0ZSwgc2V0RnJvbURhdGVdID0gdXNlU3RhdGUoJycpXG4gIGNvbnN0IFt0b0RhdGUsIHNldFRvRGF0ZV0gPSB1c2VTdGF0ZSgnJylcbiAgY29uc3QgW2dyYW51bGFyaXR5LCBzZXRHcmFudWxhcml0eV0gPSB1c2VTdGF0ZTxHcmFudWxhcml0eT4oJ21vbnRoJylcbiAgY29uc3QgW2FwcGx5RmlsdGVycywgc2V0QXBwbHlGaWx0ZXJzXSA9IHVzZVN0YXRlKHRydWUpXG5cbiAgY29uc3Qge1xuICAgIGRhdGE6IGFuYWx5dGljcyxcbiAgICBpc0xvYWRpbmc6IGFuYWx5dGljc0xvYWRpbmcsXG4gICAgaXNGZXRjaGluZzogYW5hbHl0aWNzRmV0Y2hpbmcsXG4gICAgaXNFcnJvcjogYW5hbHl0aWNzRXJyb3IsXG4gIH0gPSB1c2VHZXRBbmFseXRpY3NRdWVyeShcbiAgICB7IGlkOiBpZCEsIGZyb206IGZyb21EYXRlIHx8IHVuZGVmaW5lZCwgdG86IHRvRGF0ZSB8fCB1bmRlZmluZWQsIGdyYW51bGFyaXR5LCBhcHBseUZpbHRlcnMgfSxcbiAgICB7IHNraXA6ICFpZCB9LFxuICApXG5cbiAgLy8gaXNGZXRjaGluZyAobm90IGp1c3QgaXNMb2FkaW5nKSBzbyBzd2l0Y2hpbmcgYmFjayB0byBhblxuICAvLyBhbHJlYWR5LWNhY2hlZCBkYXRlIHJhbmdlL2dyYW51bGFyaXR5IHN0aWxsIHNob3dzIHRoZSBzaGFyZWQgcGFnZVxuICAvLyBsb2FkZXIgaW5zdGVhZCBvZiBzaWxlbnRseSBzaXR0aW5nIG9uIHRoZSBwcmV2aW91cyBzZWxlY3Rpb24ncyBkYXRhLlxuICBpZiAocXVlcnlMb2FkaW5nIHx8IHF1ZXJ5RmV0Y2hpbmcpIHtcbiAgICByZXR1cm4gPFBhZ2VTcGlubmVyIC8+XG4gIH1cblxuICBpZiAoIXF1ZXJ5KSB7XG4gICAgcmV0dXJuIChcbiAgICAgIDxkaXYgY2xhc3NOYW1lPVwicC02XCI+XG4gICAgICAgIDxUZXh0IHRvbmU9XCJzZWNvbmRhcnlcIj5RdWVyeSBub3QgZm91bmQuPC9UZXh0PlxuICAgICAgICA8QnV0dG9uIHZhcmlhbnQ9XCJvdXRsaW5lXCIgY2xhc3NOYW1lPVwibXQtM1wiIG9uQ2xpY2s9eygpID0+IG5hdmlnYXRlKCcvbGlzdGVuL3F1ZXJ5LWJ1aWxkZXInKX0+QmFjayB0byBRdWVyeSBCdWlsZGVyPC9CdXR0b24+XG4gICAgICA8L2Rpdj5cbiAgICApXG4gIH1cblxuICAvLyBBIHBlcmNlbnRhZ2Ugb2ZmIGEgaGFuZGZ1bCBvZiBjbGFzc2lmaWVkIHBvc3RzIGlzIG5vdCBhbiBhbnN3ZXIsIGl0IGlzIGFcbiAgLy8gY29pbmNpZGVuY2Ug4oCUIGJlbG93IHRoZSBiYWNrZW5kJ3MgbWluaW11bSBzYW1wbGUgaXQgaXMgd2l0aGhlbGQgZW50aXJlbHlcbiAgLy8gcmF0aGVyIHR
827oYW4gc2hvd24gd2l0aCBhIGNhdmVhdCBub2JvZHkgcmVhZHMuXG4gIGNvbnN0IHRvb0Zld0NsYXNzaWZpZWQgPSBhbmFseXRpY3M/LnBvc2l0aXZlU2VudGltZW50LnNhbXBsZVRvb1NtYWxsID8/IGZhbHNlXG4gIGNvbnN0IHBvc2l0aXZlUGVyY2VudCA9IHRvb0Zld0NsYXNzaWZpZWQgPyBudWxsIDogYW5hbHl0aWNzPy5wb3NpdGl2ZVNlbnRpbWVudC5wZXJjZW50ID8/IG51bGxcbiAgY29uc3QgbmVnYXRpdmVQZXJjZW50ID0gdG9vRmV3Q2xhc3NpZmllZCA/IG51bGwgOiBhbmFseXRpY3M/Lm5lZ2F0aXZlU2VudGltZW50LnBlcmNlbnQgPz8gbnVsbFxuICBjb25zdCBuZXV0cmFsUGVyY2VudCA9XG4gICAgcG9zaXRpdmVQZXJjZW50ICE9PSBudWxsICYmIG5lZ2F0aXZlUGVyY2VudCAhPT0gbnVsbFxuICAgICAgPyBNYXRoLm1heCgwLCAxMDAgLSBwb3NpdGl2ZVBlcmNlbnQgLSBuZWdhdGl2ZVBlcmNlbnQpXG4gICAgICA6IG51bGxcblxuICBjb25zdCBzZW50aW1lbnRTcGxpdCA9IFtcbiAgICB7IGxhYmVsOiAnUG9zaXRpdmUnLCBwZXJjZW50OiBwb3NpdGl2ZVBlcmNlbnQgPz8gMCwgY29sb3I6ICcjMjJjNTVlJyB9LFxuICAgIHsgbGFiZWw6ICdOZXV0cmFsJywgcGVyY2VudDogbmV1dHJhbFBlcmNlbnQgPz8gMCwgY29sb3I6ICcjOWNhM2FmJyB9LFxuICAgIHsgbGFiZWw6ICdOZWdhdGl2ZScsIHBlcmNlbnQ6IG5lZ2F0aXZlUGVyY2VudCA/PyAwLCBjb2xvcjogJyNlZjQ0NDQnIH0sXG4gIF1cblxuICBjb25zdCBzdGF0Q2FyZHM6IHsgbGFiZWw6IHN0cmluZzsgdmFsdWU6IHN0cmluZzsgc3ViOiBzdHJpbmc7IGljb246IHR5cGVvZiBNZXNzYWdlQ2lyY2xlOyBjb2xvcjogc3RyaW5nIH1bXSA9IFtcbiAgICB7XG4gICAgICBsYWJlbDogJ1RvdGFsIE1lbnRpb25zJyxcbiAgICAgIHZhbHVlOiBhbmFseXRpY3MgPyBhbmFseXRpY3MudG9waWNWb2x1bWUudG9Mb2NhbGVTdHJpbmcoKSA6ICcwJyxcbiAgICAgIHN1YjogYW5hbHl0aWNzID8gJ01hdGNoZWQgdGhpcyBkYXRlIHJhbmdlJyA6ICdObyBkYXRhIHlldCcsXG4gICAgICBpY29uOiBNZXNzYWdlQ2lyY2xlLFxuICAgICAgY29sb3I6ICdiZy1waW5rLTEwMCB0ZXh0LXBpbmstNjAwJyxcbiAgICB9LFxuICAgIHtcbiAgICAgIGxhYmVsOiAnUG9zaXRpdmUgU2VudGltZW50JyxcbiAgICAgIHZhbHVlOiBwb3NpdGl2ZVBlcmNlbnQgIT09IG51bGwgPyBgJHtwb3NpdGl2ZVBlcmNlbnR9JWAgOiAn4oCUJyxcbiAgICAgIHN1YjogYW5hbHl0aWNzID8gY292ZXJhZ2VOb3RlKGFuYWx5dGljcy5wb3NpdGl2ZVNlbnRpbWVudCkgOiAnTm8gZGF0YSB5ZXQnLFxuICAgICAgaWNvbjogQWN0aXZpdHksXG4gICAgICBjb2xvcjogJ2JnLWdyZWVuLTEwMCB0ZXh0LWdyZWVuLTYwMCcsXG4gICAgfSxcbiAgICB7XG4gICAgICBsYWJlbDogJ0VuZ2FnZW1lbnRzJyxcbiAgICAgIHZhbHVlOiBhbmFseXRpY3MgPyBhbmFseXRpY3MuZW5nYWdlbWVudHMudG9Mb2NhbGVTdHJpbmcoKSA6ICcwJyxcbiAgICAgIHN1YjogJ0xpa2VzICsgY29tbWVudHMgKyBzaGFyZXMsIHRoaXMgZGF0ZSByYW5nZScsXG4gICAgICBpY29uOiBaYXAsXG4gICAgICBjb2xvcjogJ2JnLWFtYmVyLTEwMCB0ZXh0LWFtYmVyLTYwMCcsXG4gICAgfSxcbiAgXVxuXG4gIGNvbnN0IGVtb3Rpb25Sb3dzID0gYW5hbHl0aWNzPy5lbW90aW9uQnJlYWtkb3duID8/IFtdXG4gIGNvbnN0IGxhbmd1YWdlUm93cyA9IChhbmFseXRpY3M/Lmxhbmd1YWdlQnJlYWtkb3duID8/IFtdKS5tYXAociA9PiAoeyAuLi5yLCBsYWJlbDogbGFuZ3VhZ2VOYW1lKHIubGFiZWwpIH0pKVxuXG4gIHJldHVybiAoXG4gICAgPGRpdiBjbGFzc05hbWU9XCJzcGFjZS15LTYgcC02XCI+XG4gICAgICA8ZGl2IGNsYXNzTmFtZT1cImZsZXggZmxleC13cmFwIGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWJldHdlZW4gZ2FwLTNcIj5cbiAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJmbGV4IGl0ZW1zLWNlbnRlciBnYXAtM1wiPlxuICAgICAgICAgIDxCdXR0b24gdmFyaWFudD1cImdob3N0XCIgc2l6ZT1cImljb25cIiBvbkNsaWNrPXsoKSA9PiBuYXZpZ2F0ZSgnL2xpc3Rlbi9xdWVyeS1idWlsZGVyJyl9IGFyaWEtbGFiZWw9XCJCYWNrXCI+XG4gICAgICAgICAgICA8QXJyb3dMZWZ0IGNsYXNzTmFtZT1cImgtNSB3LTVcIiAvPlxuICAgICAgICAgIDwvQnV0dG9uPlxuICAgICAgICAgIDxkaXY+XG4gICAgICAgICAgICA8SGVhZGluZyB2YXJpYW50PVwiaDJcIj57cXVlcnkubmFtZX0g4oCUIEFuYWx5dGljczwvSGVhZGluZz5cbiAgICAgICAgICAgIDxUZXh0IHRvbmU9XCJzZWNvbmRhcnlcIj5Gb2xsb3dzIHRoaXMgcXVlcnkncyBvd24gZGF0ZSByYW5nZTwvVGV4dD5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJmbGV4IGZsZXgtd3JhcCBpdGVtcy1jZW50ZXIgZ2FwLTJcIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cImZsZXggaXRlbXMtY2VudGVyIGdhcC0yXCI+XG4gICAgICAgICAgICA8VGV4dCBhcz1cInNwYW5cIiB2YXJpYW50PVwiY2FwdGlvblwiIHRvbmU9XCJsaWdodFwiPkZyb208L1RleHQ+XG4gICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgdHlwZT1cImRhdGVcIlxuICAgICAgICAgICAgICB2YWx1ZT17ZnJvbURhdGV9XG4gICAgICAgICAgICAgIG9uQ2hhbmdlPXtlID0+IHNldEZyb21EYXRlKGUudGFyZ2V0LnZhbHVlKX1cbiAgICAgICAgICAgICAgY2xhc3NOYW1lPVwiaC05IHJvdW5kZWQtbGcgYm9yZGVyIGJvcmRlci1ncmF5LTMwMCBweC0yIHRleHQtc20gZGFyazpib3JkZXItZ3JheS02MDAgZGFyazpiZy1ncmF5LTgwMFwiXG4gICAgICAgICAgICAvPlxuICAgICAgICAgICAgPFRleHQgYXM9XCJzcGFuXCIgdmFyaWFudD1cImNhcHRpb25cIiB0b25lPVwibGlnaHRcIj5UbzwvVGV4dD5cbiAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICB0eXBlPVwiZGF0ZVwiXG4gICAgICAgICAgICAgIHZhbHVlPXt0b0RhdGV9XG4gICAgICAgICAgICAgIG9uQ2hhbmdlPXtlID0+IHNldFRvRGF0ZShlLnRhcmdldC52YWx1ZSl9XG4gICAgICAgICAgICAgIGNsYXNzTmFtZT1cImgtOSByb3VuZGVkLWxnIGJvcmRlciBib3JkZXItZ3JheS0zMDAgcHgtMiB0ZXh0LXNtIGRhcms6Ym9yZGVyLWdyYXktNjAwIGRhcms6YmctZ3JheS04MDBcIlxuICAgICAgICAgICAgLz5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cImZsZXggaXRlbXMtY2VudGVyIGdhcC0x
827IHJvdW5kZWQtbGcgYm9yZGVyIGJvcmRlci1ncmF5LTIwMCBwLTEgZGFyazpib3JkZXItZ3JheS03MDBcIj5cbiAgICAgICAgICAgIHsoWydkYXknLCAnd2VlaycsICdtb250aCddIGFzIEdyYW51bGFyaXR5W10pLm1hcChnID0+IChcbiAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgIGtleT17Z31cbiAgICAgICAgICAgICAgICBvbkNsaWNrPXsoKSA9PiBzZXRHcmFudWxhcml0eShnKX1cbiAgICAgICAgICAgICAgICBjbGFzc05hbWU9e2NuKFxuICAgICAgICAgICAgICAgICAgJ3JvdW5kZWQtbWQgcHgtMyBweS0xIHRleHQtc20gZm9udC1tZWRpdW0gY2FwaXRhbGl6ZSB0cmFuc2l0aW9uLWNvbG9ycycsXG4gICAgICAgICAgICAgICAgICBncmFudWxhcml0eSA9PT0gZyA/ICdiZy1wcmltYXJ5IHRleHQtd2hpdGUnIDogJ3RleHQtdGV4dC1zZWNvbmRhcnkgaG92ZXI6Ymctc2Vjb25kYXJ5JyxcbiAgICAgICAgICAgICAgICApfVxuICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAge2d9XG4gICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgKSl9XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPGxhYmVsIGNsYXNzTmFtZT1cImZsZXggY3Vyc29yLXBvaW50ZXIgaXRlbXMtY2VudGVyIGdhcC0yIHJvdW5kZWQtbGcgYm9yZGVyIGJvcmRlci1ncmF5LTIwMCBweC0zIHB5LTEuNSB0ZXh0LXNtIGRhcms6Ym9yZGVyLWdyYXktNzAwXCI+XG4gICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgdHlwZT1cImNoZWNrYm94XCJcbiAgICAgICAgICAgICAgY2hlY2tlZD17YXBwbHlGaWx0ZXJzfVxuICAgICAgICAgICAgICBvbkNoYW5nZT17ZSA9PiBzZXRBcHBseUZpbHRlcnMoZS50YXJnZXQuY2hlY2tlZCl9XG4gICAgICAgICAgICAgIGNsYXNzTmFtZT1cImgtNCB3LTQgcm91bmRlZCBib3JkZXItZ3JheS0zMDAgdGV4dC1wcmltYXJ5IGZvY3VzOnJpbmctcHJpbWFyeVwiXG4gICAgICAgICAgICAvPlxuICAgICAgICAgICAgPHNwYW4gY2xhc3NOYW1lPVwidGV4dC10ZXh0LXNlY29uZGFyeVwiPlNob3cgd2l0aCBmaWx0ZXJzIG9ubHk8L3NwYW4+XG4gICAgICAgICAgPC9sYWJlbD5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cblxuICAgICAge2FuYWx5dGljc0xvYWRpbmcgfHwgYW5hbHl0aWNzRmV0Y2hpbmcgPyAoXG4gICAgICAgIDxQYWdlU3Bpbm5lciAvPlxuICAgICAgKSA6IGFuYWx5dGljc0Vycm9yID8gKFxuICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cInJvdW5kZWQteGwgYm9yZGVyIGJvcmRlci1ncmF5LTIwMCBiZy13aGl0ZSBwLTggdGV4dC1jZW50ZXIgZGFyazpib3JkZXItZ3JheS03MDAgZGFyazpiZy1ncmF5LTgwMFwiPlxuICAgICAgICAgIDxUZXh0IGNsYXNzTmFtZT1cInRleHQtcmVkLTUwMFwiPkZhaWxlZCB0byBsb2FkIGFuYWx5dGljcy48L1RleHQ+XG4gICAgICAgIDwvZGl2PlxuICAgICAgKSA6IChcbiAgICAgICAgPD5cbiAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cImdyaWQgZ3JpZC1jb2xzLTEgZ2FwLTQgc206Z3JpZC1jb2xzLTIgbGc6Z3JpZC1jb2xzLTRcIj5cbiAgICAgICAgICAgIHtzdGF0Q2FyZHMubWFwKGMgPT4gKFxuICAgICAgICAgICAgICA8ZGl2IGtleT17Yy5sYWJlbH0gY2xhc3NOYW1lPVwicm91bmRlZC14bCBib3JkZXIgYm9yZGVyLWdyYXktMjAwIGJnLXdoaXRlIHAtNSBkYXJrOmJvcmRlci1ncmF5LTcwMCBkYXJrOmJnLWdyYXktODAwXCI+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9e2BtYi0zIGZsZXggaC0xMCB3LTEwIGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNlbnRlciByb3VuZGVkLWxnICR7Yy5jb2xvcn1gfT5cbiAgICAgICAgICAgICAgICAgIDxjLmljb24gY2xhc3NOYW1lPVwiaC01IHctNVwiIC8+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPFRleHQgYXM9XCJzcGFuXCIgdmFyaWFudD1cImJvZHktbGdcIiB3ZWlnaHQ9XCJib2xkXCI+e2MudmFsdWV9PC9UZXh0PlxuICAgICAgICAgICAgICAgIDxUZXh0IHRvbmU9XCJzZWNvbmRhcnlcIiBjbGFzc05hbWU9XCJibG9ja1wiPntjLmxhYmVsfTwvVGV4dD5cbiAgICAgICAgICAgICAgICA8VGV4dCB2YXJpYW50PVwiY2FwdGlvblwiIHRvbmU9XCJsaWdodFwiIGNsYXNzTmFtZT1cIm10LTAuNSBibG9ja1wiPntjLnN1Yn08L1RleHQ+XG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgKSl9XG4gICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cImdyaWQgZ3JpZC1jb2xzLTEgZ2FwLTRcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwicm91bmRlZC14bCBib3JkZXIgYm9yZGVyLWdyYXktMjAwIGJnLXdoaXRlIHAtNSBkYXJrOmJvcmRlci1ncmF5LTcwMCBkYXJrOmJnLWdyYXktODAwXCI+XG4gICAgICAgICAgICAgIDxUZXh0IHdlaWdodD1cInNlbWlib2xkXCIgY2xhc3NOYW1lPVwibWItNCBibG9ja1wiPlNlbnRpbWVudCBPdmVydmlldzwvVGV4dD5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJmbGV4IGl0ZW1zLWNlbnRlciBnYXAtNlwiPlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwicmVsYXRpdmUgaC0zMiB3LTMyIHNocmluay0wXCI+XG4gICAgICAgICAgICAgICAgICA8RG91Z2hudXRcbiAgICAgICAgICAgICAgICAgICAgZGF0YT17e1xuICAgICAgICAgICAgICAgICAgICAgIGxhYmVsczogc2VudGltZW50U3BsaXQubWFwKHMgPT4gcy5sYWJlbCksXG4gICAgICAgICAgICAgICAgICAgICAgZGF0YXNldHM6IFt7XG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRhOiBzZW50aW1lbnRTcGxpdC5tYXAocyA9PiBzLnBlcmNlbnQpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYmFja2dyb3VuZENvbG9yOiBzZW50aW1lbnRTcGxpdC5tYXAocyA9PiBzLmNvbG9yKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGJvcmRlcldpZHRoOiAwLFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2l0cyBvbiB0aGUgcmluZyBpdHNlbGYsIHNvIGl0IGRvZXNuJ3QgY29sbGlkZSB3aXRoIHRoZSBjZW50ZXIgb3ZlcmxheSB0ZXh0LlxuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YWxhYmVsczogc2xpY2VWYWx1ZUxhYmVscygodikgPT4gYCR7dn0lYCwgOSksXG4gICAgICAgICAgICAgICAgICAgICAgfV0sXG4gICAgICAgICAgICAgICAgICAgI
827H19XG4gICAgICAgICAgICAgICAgICAgIG9wdGlvbnM9e3tcbiAgICAgICAgICAgICAgICAgICAgICBjdXRvdXQ6ICc3MiUnLFxuICAgICAgICAgICAgICAgICAgICAgIHBsdWdpbnM6IHsgbGVnZW5kOiB7IGRpc3BsYXk6IGZhbHNlIH0sIHRvb2x0aXA6IHsgZW5hYmxlZDogdHJ1ZSB9IH0sXG4gICAgICAgICAgICAgICAgICAgIH19XG4gICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJwb2ludGVyLWV2ZW50cy1ub25lIGFic29sdXRlIGluc2V0LTAgZmxleCBmbGV4LWNvbCBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXJcIj5cbiAgICAgICAgICAgICAgICAgICAgPFRleHQgYXM9XCJzcGFuXCIgdmFyaWFudD1cImJvZHktbGdcIiB3ZWlnaHQ9XCJib2xkXCI+XG4gICAgICAgICAgICAgICAgICAgICAge3Bvc2l0aXZlUGVyY2VudCAhPT0gbnVsbCA/IGAke3Bvc2l0aXZlUGVyY2VudH0lYCA6ICfigJQnfVxuICAgICAgICAgICAgICAgICAgICA8L1RleHQ+XG4gICAgICAgICAgICAgICAgICAgIDxUZXh0IGFzPVwic3BhblwiIHZhcmlhbnQ9XCJjYXB0aW9uXCIgdG9uZT1cImxpZ2h0XCI+XG4gICAgICAgICAgICAgICAgICAgICAge3Bvc2l0aXZlUGVyY2VudCAhPT0gbnVsbCA/ICdQb3NpdGl2ZScgOiB0b29GZXdDbGFzc2lmaWVkID8gJ1RvbyBmZXcnIDogJ05vIGRhdGEnfVxuICAgICAgICAgICAgICAgICAgICA8L1RleHQ+XG4gICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cImZsZXgtMSBzcGFjZS15LTJcIj5cbiAgICAgICAgICAgICAgICAgIHtzZW50aW1lbnRTcGxpdC5tYXAocyA9PiAoXG4gICAgICAgICAgICAgICAgICAgIDxkaXYga2V5PXtzLmxhYmVsfSBjbGFzc05hbWU9XCJmbGV4IGl0ZW1zLWNlbnRlciBnYXAtMlwiPlxuICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzTmFtZT1cImgtMiB3LTIgc2hyaW5rLTAgcm91bmRlZC1mdWxsXCIgc3R5bGU9e3sgYmFja2dyb3VuZENvbG9yOiBzLmNvbG9yIH19IC8+XG4gICAgICAgICAgICAgICAgICAgICAgPFRleHQgYXM9XCJzcGFuXCIgdmFyaWFudD1cImxhYmVsXCIgY2xhc3NOYW1lPVwidy0xNiBzaHJpbmstMFwiPntzLmxhYmVsfTwvVGV4dD5cbiAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cImgtMS41IGZsZXgtMSBvdmVyZmxvdy1oaWRkZW4gcm91bmRlZC1mdWxsIGJnLWdyYXktMTAwIGRhcms6YmctZ3JheS03MDBcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwiaC1mdWxsIHJvdW5kZWQtZnVsbFwiIHN0eWxlPXt7IHdpZHRoOiBgJHtzLnBlcmNlbnR9JWAsIGJhY2tncm91bmRDb2xvcjogcy5jb2xvciB9fSAvPlxuICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgIDxUZXh0IGFzPVwic3BhblwiIHZhcmlhbnQ9XCJsYWJlbFwiIHdlaWdodD1cInNlbWlib2xkXCIgY2xhc3NOYW1lPVwidy0xMCBzaHJpbmstMCB0ZXh0LXJpZ2h0XCI+e3MucGVyY2VudH0lPC9UZXh0PlxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICkpfVxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgPFRleHQgdmFyaWFudD1cImNhcHRpb25cIiB0b25lPVwibGlnaHRcIiBjbGFzc05hbWU9XCJtdC0zIGJsb2NrXCI+XG4gICAgICAgICAgICAgICAge2FuYWx5dGljcyA/IG1hcmdpbk5vdGUoYW5hbHl0aWNzLnBvc2l0aXZlU2VudGltZW50KSA6ICdObyBkYXRhIHlldCd9XG4gICAgICAgICAgICAgIDwvVGV4dD5cblxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cIm10LTUgcm91bmRlZC1sZyBiZy1zZWNvbmRhcnkgcC00IGRhcms6YmctZ3JheS05MDBcIj5cbiAgICAgICAgICAgICAgICA8VGV4dCB2YXJpYW50PVwiY2FwdGlvblwiIHdlaWdodD1cInNlbWlib2xkXCIgdG9uZT1cInNlY29uZGFyeVwiIGNsYXNzTmFtZT1cImJsb2NrXCI+U2VudGltZW50IFRyZW5kPC9UZXh0PlxuICAgICAgICAgICAgICAgIHshYW5hbHl0aWNzIHx8IGFuYWx5dGljcy50cmVuZC5idWNrZXRzLmxlbmd0aCA9PT0gMCA/IChcbiAgICAgICAgICAgICAgICAgIDxUZXh0IHZhcmlhbnQ9XCJjYXB0aW9uXCIgdG9uZT1cImxpZ2h0XCIgY2xhc3NOYW1lPVwibXQtMSBibG9jayB0ZXh0LWNlbnRlclwiPk5vIHRyZW5kIGRhdGEgZm9yIHRoaXMgZGF0ZSByYW5nZSB5ZXQuPC9UZXh0PlxuICAgICAgICAgICAgICAgICkgOiAoXG4gICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cIm10LTIgaC00MFwiPlxuICAgICAgICAgICAgICAgICAgICA8TGluZVxuICAgICAgICAgICAgICAgICAgICAgIGRhdGE9e3tcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsczogYW5hbHl0aWNzLnRyZW5kLmJ1Y2tldHMubWFwKChiKSA9PiBmb3JtYXRCdWNrZXRMYWJlbChiLCBncmFudWxhcml0eSkpLFxuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YXNldHM6IFtcbiAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsOiAnUG9zaXRpdmUnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGE6IGFuYWx5dGljcy50cmVuZC5wb3NpdGl2ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBib3JkZXJDb2xvcjogJyMyMmM1NWUnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhY2tncm91bmRDb2xvcjogJyMyMmM1NWUnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRlbnNpb246IDAuMyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb2ludFJhZGl1czogMixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhbGFiZWxzOiBsaW5lRW5kcG9pbnRMYWJlbHMoU3RyaW5nLCA4KSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsOiAnTmVnYXRpdmUnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGE6IGFuYWx5dGljcy50cmVuZC5uZWdhdGl2ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBib3JkZXJDb2xvcjogJyNlZjQ0NDQnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhY2tncm91bmRDb2xvcjogJyNlZjQ0NDQnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgI
827HRlbnNpb246IDAuMyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb2ludFJhZGl1czogMixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhbGFiZWxzOiBsaW5lRW5kcG9pbnRMYWJlbHMoU3RyaW5nLCA4KSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsOiAnTmV1dHJhbCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YTogYW5hbHl0aWNzLnRyZW5kLm5ldXRyYWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYm9yZGVyQ29sb3I6ICcjOWNhM2FmJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiYWNrZ3JvdW5kQ29sb3I6ICcjOWNhM2FmJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZW5zaW9uOiAwLjMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9pbnRSYWRpdXM6IDIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YWxhYmVsczogbGluZUVuZHBvaW50TGFiZWxzKFN0cmluZywgOCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbDogJ1VuY2xhc3NpZmllZCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YTogYW5hbHl0aWNzLnRyZW5kLnVuY2xhc3NpZmllZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBib3JkZXJDb2xvcjogJyNkMWQ1ZGInLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhY2tncm91bmRDb2xvcjogJyNkMWQ1ZGInLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJvcmRlckRhc2g6IFs0LCA0XSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZW5zaW9uOiAwLjMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9pbnRSYWRpdXM6IDIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGV4dCB1c2VzIGEgZGFya2VyIGdyYXkgdGhhbiB0aGUgbGluZSBpdHNlbGYg4oCUIHRoZSBsaW5lJ3Mgb3duXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gcGFsZSBodWUgd291bGQgYmUgaWxsZWdpYmxlIGFzIGxhYmVsIHRleHQgb24gYSB3aGl0ZSBzdXJmYWNlLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGFsYWJlbHM6IGxpbmVFbmRwb2ludExhYmVscyhTdHJpbmcsIDgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgICAgICAgICB9fVxuICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnM9e3tcbiAgICAgICAgICAgICAgICAgICAgICAgIG1haW50YWluQXNwZWN0UmF0aW86IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgbGF5b3V0OiB7IHBhZGRpbmc6IHsgdG9wOiAxNCB9IH0sXG4gICAgICAgICAgICAgICAgICAgICAgICBzY2FsZXM6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgeDogeyB0aWNrczogeyBmb250OiB7IHNpemU6IDEwIH0gfSB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICB5OiB7IGJlZ2luQXRaZXJvOiB0cnVlLCBncmFjZTogJzEwJScsIHRpY2tzOiB7IGZvbnQ6IHsgc2l6ZTogMTAgfSB9IH0sXG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgcGx1Z2luczogeyBsZWdlbmQ6IHsgcG9zaXRpb246ICdib3R0b20nLCBsYWJlbHM6IHsgYm94V2lkdGg6IDgsIGZvbnQ6IHsgc2l6ZTogMTAgfSB9IH0gfSxcbiAgICAgICAgICAgICAgICAgICAgICB9fVxuICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgKX1cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwiZ3JpZCBncmlkLWNvbHMtMSBnYXAtNCBsZzpncmlkLWNvbHMtMlwiPlxuICAgICAgICAgICAgPEJyZWFrZG93bkNhcmRcbiAgICAgICAgICAgICAgdGl0bGU9XCJFbW90aW9uIEJyZWFrZG93blwiXG4gICAgICAgICAgICAgIGljb249e0hlYXJ0fVxuICAgICAgICAgICAgICBpY29uQ29sb3I9XCJ0ZXh0LXBpbmstNTAwXCJcbiAgICAgICAgICAgICAgcm93cz17ZW1vdGlvblJvd3N9XG4gICAgICAgICAgICAgIGVtcHR5Tm90ZT1cIk5vIGVtb3Rpb24gZGF0YSB5ZXQuXCJcbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgICA8QnJlYWtkb3duQ2FyZFxuICAgICAgICAgICAgICB0aXRsZT1cIkxhbmd1YWdlIEJyZWFrZG93blwiXG4gICAgICAgICAgICAgIGljb249e0dsb2JlfVxuICAgICAgICAgICAgICBpY29uQ29sb3I9XCJ0ZXh0LXB1cnBsZS01MDBcIlxuICAgICAgICAgICAgICByb3dzPXtsYW5ndWFnZVJvd3N9XG4gICAgICAgICAgICAgIGVtcHR5Tm90ZT1cIk5vIGxhbmd1YWdlIGRhdGEgeWV0LlwiXG4gICAgICAgICAgICAvPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8Lz5cbiAgICAgICl9XG4gICAgPC9kaXY+XG4gIClcbn1cbiJdfQ==
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.