1<!DOCTYPE html> 2<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head> 3 4<meta charset="utf-8"> 5<meta name="generator" content="quarto-1.6.40"> 6 7<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes"> 8 9<meta name="author" content="Biagio Palese"> 10 11<title>Intro to Data Viz in R â Workshops portfolio</title> 12<style> 13code{white-space: pre-wrap;} 14span.smallcaps{font-variant: small-caps;} 15div.columns{display: flex; gap: min(4vw, 1.5em);} 16div.column{flex: auto; overflow-x: auto;} 17div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;} 18ul.task-list{list-style: none;} 19ul.task-list li input[type="checkbox"] { 20 width: 0.8em; 21 margin: 0 0.8em 0.2em -1em; /* quarto-specific, see https://github.com/quarto-dev/quarto-cli/issues/4556 */ 22 vertical-align: middle; 23} 24</style> 25 26
27<script src="site_libs/quarto-nav/quarto-nav.js"></script>
vendor: 1 bytes, line 27
27
28<script src="site_libs/quarto-nav/headroom.min.js"></script>
vendor: 1 bytes, line 28
28
29<script src="site_libs/clipboard/clipboard.min.js"></script>
vendor: 1 bytes, line 29
29
30<script src="site_libs/quarto-search/autocomplete.umd.js"></script>
vendor: 1 bytes, line 30
30
31<script src="site_libs/quarto-search/fuse.min.js"></script>
vendor: 1 bytes, line 31
31
32<script src="site_libs/quarto-search/quarto-search.js"></script>
32 33<meta name="quarto:offset" content="./">
34<script src="site_libs/quarto-html/quarto.js"></script>
vendor: 1 bytes, line 34
34
35<script src="site_libs/quarto-html/popper.min.js"></script>
vendor: 1 bytes, line 35
35
36<script src="site_libs/quarto-html/tippy.umd.min.js"></script>
vendor: 1 bytes, line 36
36
37<script src="site_libs/quarto-html/anchor.min.js"></script>
37 38<link href="site_libs/quarto-html/tippy.css" rel="stylesheet"> 39<link href="site_libs/quarto-html/quarto-syntax-highlighting-549806ee2085284f45b00abea8c6df48.css" rel="stylesheet" id="quarto-text-highlighting-styles">
40<script src="site_libs/bootstrap/bootstrap.min.js"></script>
40 41<link href="site_libs/bootstrap/bootstrap-icons.css" rel="stylesheet"> 42<link href="site_libs/bootstrap/bootstrap-06d8547008b8703a04e10d11caa4a571.min.css" rel="stylesheet" append-hash="true" id="quarto-bootstrap" data-mode="light">
43<script src="site_libs/quarto-contrib/live-runtime/live-runtime.js" type="module"></script>
43 44<link href="site_libs/quarto-contrib/live-runtime/live-runtime.css" rel="stylesheet">
45<script id="quarto-search-options" type="application/json">{ 46 "location": "navbar", 47 "copy-button": false, 48 "collapse-after": 3, 49 "panel-placement": "end", 50 "type": "overlay", 51 "limit": 50, 52 "keyboard-shortcut": [ 53 "f", 54 "/", 55 "s" 56 ], 57 "show-item-context": false, 58 "language": { 59 "search-no-results-text": "No results", 60 "search-matching-documents-text": "matching documents", 61 "search-copy-link-title": "Copy link to search", 62 "search-hide-matches-text": "Hide additional matches", 63 "search-more-match-text": "more match in this document", 64 "search-more-matches-text": "more matches in this document", 65 "search-clear-button-title": "Clear", 66 "search-text-placeholder": "", 67 "search-detached-cancel-button-title": "Cancel", 68 "search-submit-button-title": "Submit", 69 "search-label": "Search" 70 } 71}</script>
vendor: 1 bytes, line 71
71
72<script type="module" src="site_libs/quarto-ojs/quarto-ojs-runtime.js"></script>
72 73<link href="site_libs/quarto-ojs/quarto-ojs.css" rel="stylesheet"> 74 75 76</head> 77 78<body class="nav-fixed fullcontent"> 79 80<div id="quarto-search-results"></div> 81 <header id="quarto-header" class="headroom fixed-top"> 82 <nav class="navbar navbar-expand-lg " data-bs-theme="dark"> 83 <div class="navbar-container container-fluid"> 84 <div class="navbar-brand-container mx-auto"> 85 <a class="navbar-brand" href="./index.html"> 86 <span class="navbar-title">Workshops portfolio</span> 87 </a> 88 </div> 89 <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" role="menu" aria-expanded="false" aria-label="Toggle navigation" onclick="if (window.quartoToggleHeadroom) { window.quartoToggleHeadroom(); }"> 90 <span class="navbar-toggler-icon"></span> 91</button> 92 <div class="collapse navbar-collapse" id="navbarCollapse"> 93 <ul class="navbar-nav navbar-nav-scroll me-auto"> 94 <li class="nav-item"> 95 <a class="nav-link active" href="./index.html" aria-current="page"> 96<span class="menu-text">Basic Data Viz Demo</span></a> 97 </li> 98</ul> 99 <ul class="navbar-nav navbar-nav-scroll ms-auto"> 100 <li class="nav-item"> 101 <a class="nav-link" href="https://biagio-palese.netlify.app"> 102<span class="menu-text">Back to the Dr. B Website</span></a> 103 </li> 104</ul> 105 </div> <!-- /navcollapse --> 106 <div class="quarto-navbar-tools"> 107</div> 108 </div> <!-- /container-fluid --> 109 </nav> 110</header> 111<!-- content --> 112<div id="quarto-content" class="quarto-container page-columns page-rows-contents page-layout-article page-navbar"> 113<!-- sidebar --> 114<!-- margin-sidebar --> 115 116<!-- main --> 117<main class="content" id="quarto-document-content"> 118 119<header id="title-block-header" class="quarto-title-block default"> 120<div class="quarto-title"> 121<h1 class="title">Intro to Data Viz in R</h1> 122</div> 123 124 125 126<div class="quarto-title-meta"> 127 128 <div> 129 <div class="quarto-title-meta-heading">Author</div> 130 <div class="quarto-title-meta-contents"> 131 <p>Biagio Palese </p> 132 </div> 133 </div> 134 135 136 137 </div> 138 139 140 141</header> 142 143 144<style> 145/* Target the first tab (Demo) */ 146.nav-pills .nav-item:nth-child(1) .nav-link { 147 background-color: #FFC20A; /* Yellow */ 148 color: white; 149} 150 151/* Target the second tab (Example) */ 152.nav-pills .nav-item:nth-child(2) .nav-link { 153 background-color: #5D3A9B; /* Purple */ 154 color: white; 155} 156 157/* Target the third tab (Exercise) */ 158.nav-pills .nav-item:nth-child(3) .nav-link { 159 background-color: #0C7BDC; /* Blue */ 160 color: white; 161} 162 163/* Target the fourth tab (Activity) */ 164.nav-pills .nav-item:nth-child(4) .nav-link { 165 background-color: #E66100; /* Orange */ 166 color: white; 167} 168 169/* Target the fifth tab (Activity2) */ 170.nav-pills .nav-item:nth-child(5) .nav-link { 171 background-color: #40B0A6; /* teal */ 172 color: white; 173} 174 175/* Active tab styling */ 176.nav-pills .nav-link.active { 177 background-color: #2E7D32; /* Customize active tab color */ 178 color: white; 179} 180</style> 181<section id="welcome-to-the-magic-world-of-ggplot2" class="level2"> 182<h2 class="anchored" data-anchor-id="welcome-to-the-magic-world-of-ggplot2">Welcome to the Magic World of ggplot2</h2> 183<div class="quarto-figure quarto-figure-left"> 184<figure class="figure"> 185<p><img src="images/ggplot2.png" class="img-fluid figure-img" width="700"></p> 186<figcaption>Itâs ggplot time: Artwork by <span class="citation" data-cites="allison_horst">@allison_horst</span></figcaption> 187</figure> 188</div> 189<p>In this workshop, weâll focus on the <code>ggplot2</code> package, a cornerstone of the <code>tidyverse</code> package. With ggplot2, we can turn raw numbers into compelling visual stories, effortlessly communicating complex data. Whether weâre examining distributions, relationships, rankings, or trends over time, visualization helps us see what the data is truly saying.</p> 190<p>Throughout this workshop, Iâll use the terms chart, plot, and graph interchangeably. While they may take different forms, they all share the same purpose: transforming data into something meaningful and impactful.</p> 191</section> 192<section id="load-packages" class="level2"> 193<h2 class="anchored" data-anchor-id="load-packages">Load packages</h2> 194<p>This is a critical task:</p> 195<ul> 196<li><p>Every time you open a new R session you will need to load the packages.</p></li> 197<li><p>Failing to do so will incur in the most common errors among beginners (e.g., â could not find function âxâ â or âobject âyâ not foundâ
197).</p></li> 198<li><p>So please always remember to load your packages by running the <code>library</code> function for each package you will use in that specific session ð¤</p></li> 199</ul> 200<div class="cell" data-autorun="false" data-startover="false"> 201<div> 202<div id="webr-1" class="exercise-cell"> 203 204</div>
205<script type="webr-1-contents"> 206eyJhdHRyIjp7ImF1dG9ydW4iOmZhbHNlLCJlZGl0Ijp0cnVlLCJldmFsIjp0cnVlLCJzdGFydG92ZXIiOmZhbHNlfSwiY29kZSI6ImxpYnJhcnkodGlkeXZlcnNlKSJ9 207</script>
207 208</div> 209</div> 210<p>We will use the <code>mpg</code> data frame available in the <code>ggplot2</code> package. ggplot2 is always loaded if you load the <code>tidyverse</code> package.</p> 211<p>What is the first step when you start working with a new dataset?</p> 212</section> 213<section id="getting-to-know-the-data" class="level2"> 214<h2 class="anchored" data-anchor-id="getting-to-know-the-data">Getting to know the data</h2> 215<div class="cell" data-autorun="false" data-completion="true" data-min-lines="3"> 216<div> 217<div id="webr-2" class="exercise-cell"> 218 219</div>
220<script type="webr-2-contents"> 221eyJhdHRyIjp7ImF1dG9ydW4iOmZhbHNlLCJjb21wbGV0aW9uIjp0cnVlLCJlZGl0Ijp0cnVlLCJldmFsIjp0cnVlLCJtaW4tbGluZXMiOjN9LCJjb2RlIjoibXBnXG4/bXBnI2Rpc3BsLCBhIGNhcuKAmXMgZW5naW5lIHNpemUsIGluIGxpdHJlcy5od3ksIGEgY2Fy4oCZcyBmdWVsIGVmZmljaWVuY3kgb24gdGhlIGhpZ2h3YXksIGluIG1pbGVzIHBlciBnYWxsb24gKG1wZykifQ== 222</script>
222 223</div> 224</div> 225<p>It is also possible to get more info about the dataset by running the below code:</p> 226<div class="cell" data-autorun="false" data-completion="true" data-min-lines="3"> 227<div> 228<div id="webr-3" class="exercise-cell"> 229 230</div>
231<script type="webr-3-contents"> 232eyJhdHRyIjp7ImF1dG9ydW4iOmZhbHNlLCJjb21wbGV0aW9uIjp0cnVlLCJlZGl0Ijp0cnVlLCJldmFsIjp0cnVlLCJtaW4tbGluZXMiOjN9LCJjb2RlIjoibXBnIHw+IGdsaW1wc2UoKVxubXBnIHw+IHN0cigpXG5tcGcgfD4gcHJpbnQod2lkdGggPSBJbmYpXG5jb2xuYW1lcyhtcGcpIn0= 233</script>
233 234</div> 235</div> 236<p>Now that we got to know the data more it is time to begin our exploratory analysis using visualizations!!!</p> 237</section> 238<section id="creating-your-first-ggplot-chart" class="level2"> 239<h2 class="anchored" data-anchor-id="creating-your-first-ggplot-chart">Creating your first ggplot chart</h2> 240<p>Creating a data visualization with ggplot2 is a lot like painting. You start with a blank canvas, and just like an artist, you add layers one step at a time until the picture takes shape. At first, thereâs nothing there but potential.. a canvas waiting to be filled.</p> 241<p>Each step in the process, whether itâs deciding on the chart type or choosing the colors and elements, is like adding layers of paint to a canvas. You gradually build up details, adding depth and clarity to your creation. Just as a painter chooses which areas to highlight or leave in shadow, we use tools in ggplot to emphasize different aspects of the data.</p> 242<p>By the end, what started as a blank space becomes a visual storyâa piece of art that not only looks good but also communicates meaning, helping others understand the data in a way that numbers alone canât. Enough with the theory.. letâs see how ggplot2 works in practice:</p> 243<div class="quarto-figure quarto-figure-left"> 244<figure class="figure"> 245<p><img src="images/ggplot1.png" class="img-fluid figure-img" width="700"></p> 246<figcaption>Ggplot in action: Artwork by <span class="citation" data-cites="allison_horst">@allison_horst</span></figcaption> 247</figure> 248</div> 249<p>With ggplot2, you always begin your plot with:</p> 250<div class="tabset-margin-container"></div><div class="panel-tabset nav-pills"> 251<ul class="nav nav-tabs" role="tablist"><li class="nav-item" role="presentation"><a class="nav-link active" id="tabset-1-1-tab" data-bs-toggle="tab" data-bs-target="#tabset-1-1" role="tab" aria-controls="tabset-1-1" aria-selected="true">Blank canvas</a></li><li class="nav-item" role="presentation"><a class="nav-link" id="tabset-1-2-tab" data-bs-toggle="tab" data-bs-target="#tabset-1-2" role="tab" aria-controls="tabset-1-2" aria-selected="false">Add the data</a></li><li class="nav-item" role="presentation"><a class="nav-link" id="tabset-1-3-tab" data-bs-toggle="tab" data-bs-target="#tabset-1-3" role="tab" aria-controls="tabset-1-3" aria-selected="false">Add the axes</a></li><li class="nav-item" role="presentation"><a class="nav-link" id="tabset-1-4-tab" data-bs-toggle="tab" data-bs-target="#tabset-1-4" role="tab" aria-controls="tabset-1-4" aria-selected="false">Add the geom</a></li></ul> 252<div class="tab-content nav-pills"> 253<div id="tabset-1-1" class="tab-pane active" role="tabpanel" aria-labelledby="tabset-1-1-tab"> 254<div class="cell" data-autorun="false" data-completion="true" data-min-lines="3"> 255<div> 256<div id="webr-4" class="exercise-cell"> 257 258</div>
259<script type="webr-4-contents"> 260eyJhdHRyIjp7ImF1dG9ydW4iOmZhbHNlLCJjb21wbGV0aW9uIjp0cnVlLCJlZGl0Ijp0cnVlLCJldmFsIjp0cnVlLCJtaW4tbGluZXMiOjN9LCJjb2RlIjoiZ2dwbG90KCkgIn0= 261</script>
261 262</div> 263</div> 264<ul> 265<li>the function ggplot() creates a coordinate system, your empty canvas, that you can add layers to.</li> 266</ul> 267</div> 268<div id="tabset-1-2" class="tab-pane" role="tabpanel" aria-labelledby="tabset-1-2-tab"> 269<div class="cell" data-autorun="false" data-completion="true" data-min-lines="3"> 270<div> 271<div id="webr-5" class="exercise-cell"> 272 273</div>
274<script type="webr-5-contents"> 275eyJhdHRyIjp7ImF1dG9ydW4iOmZhbHNlLCJjb21wbGV0aW9uIjp0cnVlLCJlZGl0Ijp0cnVlLCJldmFsIjp0cnVlLCJtaW4tbGluZXMiOjN9LCJjb2RlIjoiZ2dwbG90KGRhdGEgPSBtcGcpIn0= 276</script>
276 277</div> 278</div> 279<ul> 280<li>the first argument we add to our ggplot() chart is the dataset to use in the graph. While the chart is still empty now the data are loaded in the background and ready to be visualized.</li> 281</ul> 282</div> 283<div id="tabset-1-3" class="tab-pane" role="tabpanel" aria-labelledby="tabset-1-3-tab"> 284<div class="cell" data-autorun="false" data-completion="true" data-min-lines="3"> 285<div> 286<div id="webr-6" class="exercise-cell"> 287 288</div>
289<script type="webr-6-contents"> 290eyJhdHRyIjp7ImF1dG9ydW4iOmZhbHNlLCJjb21wbGV0aW9uIjp0cnVlLCJlZGl0Ijp0cnVlLCJldmFsIjp0cnVlLCJtaW4tbGluZXMiOjN9LCJjb2RlIjoiZ2dwbG90KGRhdGEgPSBtcGcsIG1hcHBpbmc9IGFlcyh5PW1hbnVmYWN0dXJlcikpIn0= 291</script>
291 292</div> 293</div> 294<ul> 295<li>then we need to map what variables we want to visualize on our axes. So ggplot(data = mpg, mapping= aes(y=manufacturer)). While the chart core of the chart is still empty, now the axes and their scales are visible.</li> 296</ul> 297</div> 298<div id="tabset-1-4" class="tab-pane" role="tabpanel" aria-labelledby="tabset-1-4-tab"> 299<div class="cell" data-autorun="false" data-completion="true" data-min-lines="3"> 300<div> 301<div id="webr-7" class="exercise-cell"> 302 303</div>
304<script type="webr-7-contents"> 305eyJhdHRyIjp7ImF1dG9ydW4iOmZhbHNlLCJjb21wbGV0aW9uIjp0cnVlLCJlZGl0Ijp0cnVlLCJldmFsIjp0cnVlLCJtaW4tbGluZXMiOjN9LCJjb2RlIjoiZ2dwbG90KGRhdGEgPSBtcGcsIG1hcHBpbmc9IGFlcyh5PW1hbnVmYWN0dXJlcikpK1xuICBnZW9tX2JhcigpIn0= 306</script>
306 307</div> 308</div> 309<ul> 310<li>The graph takes shape by choosing the type of chart you want to create. In this layer, we add the geom (short for geometric object or representation), which determines the visual structure/shape of the chart. For example, using geom_bar() adds a layer of bars, creating a bar plot. While geom_point() adds a layer of points to your plot, which creates a scatterplot.</li> 311</ul> 312</div> 313</div> 314</div> 315<p>Letâs create a few more charts to visually explore our new dataset:</p> 316<div class="tabset-margin-container"></div><div class="panel-tabset nav-pills"> 317<ul class="nav nav-tabs" role="tablist"><li class="nav-item" role="presentation"><a class="nav-link active" id="tabset-2-1-tab" data-bs-toggle="tab" data-bs-target="#tabset-2-1" role="tab" aria-controls="tabset-2-1" aria-selected="true">Example 1</a></li><li class="nav-item" role="presentation"><a class="nav-link" id="tabset-2-2-tab" data-bs-toggle="tab" data-bs-target="#tabset-2-2" role="tab" aria-controls="tabset-2-2" aria-selected="false">Example 2</a></li><li class="nav-item" role="presentation"><a class="nav-link" id="tabset-2-3-tab" data-bs-toggle="tab" data-bs-target="#tabset-2-3" role="tab" aria-controls="tabset-2-3" aria-selected="false">Example 3</a></li><li class="nav-item" role="presentation"><a class="nav-link" id="tabset-2-4-tab" data-bs-toggle="tab" data-bs-target="#tabset-2-4" role="tab" aria-controls="tabset-2-4" aria-selected="false">Example 4</a></li></ul> 318<div class="tab-content nav-pills"> 319<div id="tabset-2-1" class="tab-pane active" role="tabpanel" aria-labelledby="tabset-2-1-tab"> 320<p>Letâs now check the distribution of highway fuel efficiency among the cars in this dataset:</p> 321<div class="cell" data-autorun="false" data-completion="true" data-min-lines="3"> 322<div> 323<div id="webr-8" class="exercise-cell"> 324 325</div>
326<script type="webr-8-contents"> 327eyJhdHRyIjp7ImF1dG9ydW4iOmZhbHNlLCJjb21wbGV0aW9uIjp0cnVlLCJlZGl0Ijp0cnVlLCJldmFsIjp0cnVlLCJtaW4tbGluZXMiOjN9LCJjb2RlIjoiZ2dwbG90KGRhdGEgPSBtcGcsIG1hcHBpbmcgPSBhZXMoeCA9IGh3eSkpICsgXG4gIGdlb21faGlzdG9ncmFtKCkifQ== 328</script>
328 329</div> 330</div> 331<div class="callout callout-style-default callout-note callout-titled"> 332<div class="callout-header d-flex align-content-center"> 333<div class="callout-icon-container"> 334<i class="callout-icon"></i> 335</div> 336<div class="callout-title-container flex-fill"> 337Note 338</div> 339</div> 340<div class="callout-body-container callout-body"> 341<p>Notice that I have used geom_histogram and not geom_bar in this case. We will learn more about which chart is the most appropriate given the column data type later in this class.</p> 342</div> 343</div> 344</div> 345<div id="tabset-2-2" class="tab-pane" role="tabpanel" aria-labelledby="tabset-2-2-tab"> 346<p>Letâs now check the relation between engine size and highway fuel efficiency. Any surprise?</p> 347<div class="cell" data-autorun="false" data-completion="true" data-min-lines="3"> 348<div> 349<div id="webr-9" class="exercise-cell"> 350 351</div>
352<script type="webr-9-contents"> 353eyJhdHRyIjp7ImF1dG9ydW4iOmZhbHNlLCJjb21wbGV0aW9uIjp0cnVlLCJlZGl0Ijp0cnVlLCJldmFsIjp0cnVlLCJtaW4tbGluZXMiOjN9LCJjb2RlIjoiXG5nZ3Bsb3QoZGF0YSA9IG1wZywgbWFwcGluZyA9IGFlcyh4ID0gZGlzcGwsIHkgPSBod3kpKSArIFxuICBnZW9tX3BvaW50KCkifQ== 354</script>
354 355</div> 356</div> 357<p>Cars with big engines seem to use more fuel. But⦠there are a small number of cars with large engine that still have pretty good highway fuel efficiency.</p> 358</div> 359<div id="tabset-2-3" class="tab-pane" role="tabpanel" aria-labelledby="tabset-2-3-tab"> 360<p>Create a histogram chart that show the distribution of the city fuel efficiency (cty) variable</p> 361<div class="cell" data-autorun="false" data-completion="true" data-min-lines="3"> 362<div> 363<div id="webr-10" class="exercise-cell"> 364 365</div>
366<script type="webr-10-contents"> 367eyJhdHRyIjp7ImF1dG9ydW4iOmZhbHNlLCJjb21wbGV0aW9uIjp0cnVlLCJlZGl0Ijp0cnVlLCJldmFsIjp0cnVlLCJtaW4tbGluZXMiOjN9LCJjb2RlIjoiIn0= 368</script>
368 369</div> 370</div> 371</div> 372<div id="tabset-2-4" class="tab-pane" role="tabpanel" aria-labelledby="tabset-2-4-tab"> 373<p>Create a scatterplot that shows the relationship between engine size and city fuel efficiency</p> 374<div class="cell" data-autorun="false" data-completion="true" data-min-lines="3"> 375<div> 376<div id="webr-11" class="exercise-cell"> 377 378</div>
379<script type="webr-11-contents"> 380eyJhdHRyIjp7ImF1dG9ydW4iOmZhbHNlLCJjb21wbGV0aW9uIjp0cnVlLCJlZGl0Ijp0cnVlLCJldmFsIjp0cnVlLCJtaW4tbGluZXMiOjN9LCJjb2RlIjoiIn0= 381</script>
381 382</div> 383</div> 384</div> 385</div> 386</div> 387<section id="activity-1-a-b-in-class-c-d-at-home-basic-charts---5-minutes" class="level4"> 388<h4 class="anchored">Activity 1 (a & b in class c & d at home): Basic Charts - 5 minutes:</h4> 389<p><em>[Write code just below each instruction; finally use MS Teams R - Forum channel for help on the in class activities/homework or if you have other questions]</em></p> 390<div class="tabset-margin-container"></div><div class="panel-tabset nav-pills"> 391<ul class="nav nav-tabs" role="tablist"><li class="nav-item" role="presentation"><a class="nav-link active" id="tabset-3-1-tab" data-bs-toggle="tab" data-bs-target="#tabset-3-1" role="tab" aria-controls="tabset-3-1" aria-selected="true">Activity 1a.</a></li><li class="nav-item" role="presentation"><a class="nav-link" id="tabset-3-2-tab" data-bs-toggle="tab" data-bs-target="#tabset-3-2" role="tab" aria-controls="tabset-3-2" aria-selected="false">Activity 1b.</a></li><li class="nav-item" role="presentation"><a class="nav-link" id="tabset-3-3-tab" data-bs-toggle="tab" data-bs-target="#tabset-3-3" role="tab" aria-controls="tabset-3-3" aria-selected="false">Activity 1c.</a></li><li class="nav-item" role="presentation"><a class="nav-link" id="tabset-3-4-tab" data-bs-toggle="tab" data-bs-target="#tabset-3-4" role="tab" aria-controls="tabset-3-4" aria-selected="false">Activity 1d.</a></li></ul> 392<div class="tab-content nav-pills"> 393<div id="tabset-3-1" class="tab-pane active" role="tabpanel" aria-labelledby="tabset-3-1-tab"> 394<p>Create a bar chart for the <code>class</code> variable.</p> 395<div class="cell" data-autorun="false" data-completion="true" data-min-lines="3"> 396<div> 397<div id="webr-12" class="exercise-cell"> 398 399</div>
400<script type="webr-12-contents"> 401eyJhdHRyIjp7ImF1dG9ydW4iOmZhbHNlLCJjb21wbGV0aW9uIjp0cnVlLCJlZGl0Ijp0cnVlLCJldmFsIjp0cnVlLCJtaW4tbGluZXMiOjN9LCJjb2RlIjoiZ2dwbG90KGRhdGE9bXBnLCBtYXBwaW5nPSBhZXMoeD0gY2xhc3MpKStcbiAgZ2VvbV9iYXIoKSJ9 402</script>
402 403</div> 404</div> 405</div> 406<div id="tabset-3-2" class="tab-pane" role="tabpanel" aria-labelledby="tabset-3-2-tab"> 407<p>Create a scatterplot between the highway fuel efficiency and number of cylinders.</p> 408<div class="cell" data-autorun="false" data-completion="true" data-min-lines="3"> 409<div> 410<div id="webr-13" class="exercise-cell"> 411 412</div>
413<script type="webr-13-contents"> 414eyJhdHRyIjp7ImF1dG9ydW4iOmZhbHNlLCJjb21wbGV0aW9uIjp0cnVlLCJlZGl0Ijp0cnVlLCJldmFsIjp0cnVlLCJtaW4tbGluZXMiOjN9LCJjb2RlIjoiZ2dwbG90KGRhdGE9bXBnLCBtYXBwaW5nPSBhZXMoeD0gY3lsLCB5PWh3eSkpK1xuICBnZW9tX3BvaW50KCkifQ== 415</script>
415 416</div> 417</div> 418<p>What do you notice?</p> 419</div> 420<div id="tabset-3-3" class="tab-pane" role="tabpanel" aria-labelledby="tabset-3-3-tab"> 421<p>Create a boxplot that show the distribution of the city fuel efficiency (cty) variable.</p> 422<div class="cell" data-autorun="false" data-completion="true" data-min-lines="3"> 423<div> 424<div id="webr-14" class="exercise-cell"> 425 426</div>
427<script type="webr-14-contents"> 428eyJhdHRyIjp7ImF1dG9ydW4iOmZhbHNlLCJjb21wbGV0aW9uIjp0cnVlLCJlZGl0Ijp0cnVlLCJldmFsIjp0cnVlLCJtaW4tbGluZXMiOjN9LCJjb2RlIjoiZ2dwbG90KGRhdGE9bXBnLCBtYXBwaW5nPSBhZXMoeT0gY3R5KSkrXG4gIGdlb21fYm94cGxvdCgpIn0= 429</script>
429 430</div> 431</div> 432</div> 433<div id="tabset-3-4" class="tab-pane" role="tabpanel" aria-labelledby="tabset-3-4-tab"> 434<p>Create a bar chart for the <code>fl</code> variable.</p> 435<div class="cell" data-autorun="false" data-completion="true" data-min-lines="3"> 436<div> 437<div id="webr-15" class="exercise-cell"> 438 439</div>
440<script type="webr-15-contents"> 441eyJhdHRyIjp7ImF1dG9ydW4iOmZhbHNlLCJjb21wbGV0aW9uIjp0cnVlLCJlZGl0Ijp0cnVlLCJldmFsIjp0cnVlLCJtaW4tbGluZXMiOjN9LCJjb2RlIjoiZ2dwbG90KGRhdGE9bXBnLCBtYXBwaW5nPSBhZXMoeD0gZmwpKStcbiAgZ2VvbV9iYXIoKSJ9 442</script>
442 443</div> 444</div> 445</div> 446</div> 447</div> 448<div class="cell" data-autorun="false" data-min-lines="3"> 449<div> 450<div id="webr-16" class="exercise-cell"> 451 452</div>
453<script type="webr-16-contents"> 454eyJhdHRyIjp7ImF1dG9ydW4iOmZhbHNlLCJlZGl0Ijp0cnVlLCJldmFsIjp0cnVlLCJtaW4tbGluZXMiOjN9LCJjb2RlIjoiXG5cbiNDb2RlIFByYWN0aWNlIENodW5rIn0= 455</script>
455 456</div> 457</div> 458<p><em>Knowledge Check 1</em></p> 459<div class="quarto-figure quarto-figure-center"> 460<figure class="figure"> 461<p><img src="images/knowledgecheck1.png" class="img-fluid figure-img"></p> 462<figcaption>Figure 2. Knowledge Check 1</figcaption> 463</figure> 464</div> 465<p>Question: What geom was used in the chart above?</p> 466<pre><code>- answer 1: geom_bar, 467- answer 2: geom_point, 468- answer 3: geom_boxplot, 469- answer 4: geom_plot</code></pre> 470<div class="callout callout-style-default callout-important callout-titled"> 471<div class="callout-header d-flex align-content-center"> 472<div class="callout-icon-container"> 473<i class="callout-icon"></i> 474</div> 475<div class="callout-title-container flex-fill"> 476Important 477</div> 478</div> 479<div class="callout-body-container callout-body"> 480<p>Please remember that this is just a demo of the workshop I run and their style. If you or your company want more info about the workshop do not hesitate to click on the Get in Touch button.</p> 481</div> 482</div> 483<button id="contact-button" class="open-button"> 484Get in Touch 485</button> 486<div id="contact-form" class="form-popup"> 487<form class='form-container' method='POST' name='contact-workshop'> 488<h2 class="anchored" data-anchor-id="activity-1-a-b-in-class-c-d-at-home-basic-charts---5-minutes"> 489Contact Me 490</h2> 491<input type="hidden" name="form-name" value="contact-workshop"> <input type="text" placeholder="Name" name="name" required=""> <input type="email" placeholder="Email" name="email" required=""> 492<textarea placeholder="Message" name="message" required=""></textarea> 493<button type="submit" class="btn"> 494Send 495</button> 496<button type="button" class="btn cancel" onclick="closeForm()"> 497Close 498</button> 499</form> 500</div> 501<style> 502.open-button { 503 background-color: #555; 504 color: white; 505 padding: 16px 20px; 506 border: none; 507 cursor: pointer; 508 position: fixed; 509 bottom: 23px; 510 right: 28px; 511 z-index: 9; 512} 513 514.form-popup { 515 display: none; 516 position: fixed; 517 top: 50%; 518 left: 50%; 519 transform: translate(-50%, -50%); 520 border: 3px solid #f1f1f1; 521 z-index: 10; 522 max-width: 400px; 523 width: 90%; 524} 525 526.form-container { 527 padding: 20px; 528 background-color: white; 529} 530 531.form-container input[type=text], .form-container input[type=email], .form-container textarea { 532 width: 100%; 533 padding: 12px; 534 margin: 8px 0; 535 border: 1px solid #ccc; 536 background: #f8f8f8; 537} 538 539.form-container textarea { 540 height: 100px; 541} 542 543.form-container .btn { 544 background-color: #04AA6D; 545 color: white; 546 padding: 12px 20px; 547 border: none; 548 cursor: pointer; 549 width: 100%; 550 margin-bottom: 10px; 551 opacity: 0.8; 552} 553 554.form-container .cancel { 555 background-color: #ff4d4d; 556} 557 558.form-container .btn:hover, .open-button:hover { 559 opacity: 1; 560} 561</style>
562<script> 563function openForm() { 564 document.getElementById("contact-form").style.display = "block"; 565} 566 567function closeForm() { 568 document.getElementById("contact-form").style.display = "none"; 569} 570 571document.addEventListener('DOMContentLoaded', function() { 572 document.getElementById("contact-button").addEventListener("click", openForm); 573}); 574</script>
574 575<div class="quarto-figure quarto-figure-left"> 576<figure class="figure"> 577<p><img src="gif/congrats.webp" class="img-fluid figure-img" width="700"></p> 578<figcaption><strong>On completing the workshop</strong></figcaption> 579</figure> 580</div>
581<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/confetti.browser.min.js"></script>
vendor: 1 bytes, line 581
581
582<script> 583 var confettiTriggered = false; 584 var duration = 15 * 1000; 585 var animationEnd = Date.now() + duration; 586 var defaults = { startVelocity: 30, spread: 360, ticks: 60, zIndex: 0 }; 587 588 function randomInRange(min, max) { 589 return Math.random() * (max - min) + min; 590 } 591 592 // Function to start the confetti effect 593 function startConfetti() { 594 if (!confettiTriggered) { 595 confettiTriggered = true; // Prevent confetti from starting multiple times 596 var interval = setInterval(function() { 597 var timeLeft = animationEnd - Date.now(); 598 599 if (timeLeft <= 0) { 600 clearInterval(interval); // Stop the animation when the duration ends 601 } 602 603 var particleCount = 50 * (timeLeft / duration); 604 // Since particles fall down, start a bit higher than random 605 confetti({ 606 ...defaults, 607 particleCount, 608 origin: { x: randomInRange(0.1, 0.3), y: Math.random() - 0.2 } 609 }); 610 confetti({ 611 ...defaults, 612 particleCount, 613 origin: { x: randomInRange(0.7, 0.9), y: Math.random() - 0.2 } 614 }); 615 }, 250); 616 } 617 } 618 619 // Event listener to detect when the user scrolls to the bottom of the page 620 window.addEventListener("scroll", function() { 621 // Check if the user has scrolled to the bottom of the page 622 if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) { 623 startConfetti(); 624 } 625 }); 626</script>
626 627 628
629<script type="webr-data"> 630eyJvcHRpb25zIjp7ImJhc2VVcmwiOiJodHRwczovL3dlYnIuci13YXNtLm9yZy92MC40LjIvIn0sInBhY2thZ2VzIjp7InBrZ3MiOlsiZXZhbHVhdGUiLCJrbml0ciIsImh0bWx0b29scyIsInRpZHl2ZXJzZSIsImphbml0b3IiXSwicmVwb3MiOltdfSwicmVuZGVyX2RmIjoiZGVmYXVsdCJ9 631</script>
vendor: 1 bytes, line 631
631
632<script type="ojs-module-contents"> 633eyJjb250ZW50cyI6W3siY2VsbE5hbWUiOiJ3ZWJyLXdpZGdldC0xNiIsImlubGluZSI6ZmFsc2UsIm1ldGhvZE5hbWUiOiJpbnRlcnByZXRRdWlldCIsInNvdXJjZSI6IntcbiAgLy8gV2FpdCBmb3Igb3V0cHV0IHRvIGJlIHdyaXR0ZW4gdG8gdGhlIERPTSwgdGhlbiB0cmlnZ2VyIHdpZGdldCByZW5kZXJpbmdcbiAgYXdhaXQgX3dlYnJfdmFsdWVfMTY7XG4gIGlmICh3aW5kb3cuSFRNTFdpZGdldHMpIHtcbiAgICB3aW5kb3cuSFRNTFdpZGdldHMuc3RhdGljUmVuZGVyKCk7XG4gIH1cbiAgaWYgKHdpbmRvdy5QYWdlZFRhYmxlRG9jKSB7XG4gICAgd2luZG93LlBhZ2VkVGFibGVEb2MuaW5pdEFsbCgpO1xuICB9XG59XG4ifSx7ImNlbGxOYW1lIjoid2Vici0xNiIsImlubGluZSI6ZmFsc2UsIm1ldGhvZE5hbWUiOiJpbnRlcnByZXQiLCJzb3VyY2UiOiJ2aWV3b2YgX3dlYnJfZWRpdG9yXzE2ID0ge1xuICBjb25zdCB7IFdlYlJFeGVyY2lzZUVkaXRvciwgYjY0RGVjb2RlIH0gPSB3aW5kb3cuX2V4ZXJjaXNlX29qc19ydW50aW1lO1xuICBjb25zdCBzY3JpcHRDb250ZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3Rvcihgc2NyaXB0W3R5cGU9XFxcIndlYnItMTYtY29udGVudHNcXFwiXWApLnRleHRDb250ZW50O1xuICBjb25zdCBibG9jayA9IEpTT04ucGFyc2UoYjY0RGVjb2RlKHNjcmlwdENvbnRlbnQpKTtcblxuICBjb25zdCBvcHRpb25zID0gT2JqZWN0LmFzc2lnbih7IGlkOiBgd2Vici0xNi1jb250ZW50c2AgfSwgYmxvY2suYXR0cik7XG4gIGNvbnN0IGVkaXRvciA9IG5ldyBXZWJSRXhlcmNpc2VFZGl0b3Iod2ViUk9qcy53ZWJSUHJvbWlzZSwgYmxvY2suY29kZSwgb3B0aW9ucyk7XG5cbiAgcmV0dXJuIGVkaXRvci5jb250YWluZXI7XG59XG5fd2Vicl92YWx1ZV8xNiA9IHdlYlJPanMucHJvY2Vzcyhfd2Vicl9lZGl0b3JfMTYsIHt9KTtcbiJ9LHsiY2VsbE5hbWUiOiJ3ZWJyLXdpZGdldC0xNSIsImlubGluZSI6ZmFsc2UsIm1ldGhvZE5hbWUiOiJpbnRlcnByZXRRdWlldCIsInNvdXJjZSI6IntcbiAgLy8gV2FpdCBmb3Igb3V0cHV0IHRvIGJlIHdyaXR0ZW4gdG8gdGhlIERPTSwgdGhlbiB0cmlnZ2VyIHdpZGdldCByZW5kZXJpbmdcbiAgYXdhaXQgX3dlYnJfdmFsdWVfMTU7XG4gIGlmICh3aW5kb3cuSFRNTFdpZGdldHMpIHtcbiAgICB3aW5kb3cuSFRNTFdpZGdldHMuc3RhdGljUmVuZGVyKCk7XG4gIH1cbiAgaWYgKHdpbmRvdy5QYWdlZFRhYmxlRG9jKSB7XG4gICAgd2luZG93LlBhZ2VkVGFibGVEb2MuaW5pdEFsbCgpO1xuICB9XG59XG4ifSx7ImNlbGxOYW1lIjoid2Vici0xNSIsImlubGluZSI6ZmFsc2UsIm1ldGhvZE5hbWUiOiJpbnRlcnByZXQiLCJzb3VyY2UiOiJ2aWV3b2YgX3dlYnJfZWRpdG9yXzE1ID0ge1xuICBjb25zdCB7IFdlYlJFeGVyY2lzZUVkaXRvciwgYjY0RGVjb2RlIH0gPSB3aW5kb3cuX2V4ZXJjaXNlX29qc19ydW50aW1lO1xuICBjb25zdCBzY3JpcHRDb250ZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3Rvcihgc2NyaXB0W3R5cGU9XFxcIndlYnItMTUtY29udGVudHNcXFwiXWApLnRleHRDb250ZW50O1xuICBjb25zdCBibG9jayA9IEpTT04ucGFyc2UoYjY0RGVjb2RlKHNjcmlwdENvbnRlbnQpKTtcblxuICBjb25zdCBvcHRpb25zID0gT2JqZWN0LmFzc2lnbih7IGlkOiBgd2Vici0xNS1jb250ZW50c2AgfSwgYmxvY2suYXR0cik7XG4gIGNvbnN0IGVkaXRvciA9IG5ldyBXZWJSRXhlcmNpc2VFZGl0b3Iod2ViUk9qcy53ZWJSUHJvbWlzZSwgYmxvY2suY29kZSwgb3B0aW9ucyk7XG5cbiAgcmV0dXJuIGVkaXRvci5jb250YWluZXI7XG59XG5fd2Vicl92YWx1ZV8xNSA9IHdlYlJPanMucHJvY2Vzcyhfd2Vicl9lZGl0b3JfMTUsIHt9KTtcbiJ9LHsiY2VsbE5hbWUiOiJ3ZWJyLXdpZGdldC0xNCIsImlubGluZSI6ZmFsc2UsIm1ldGhvZE5hbWUiOiJpbnRlcnByZXRRdWlldCIsInNvdXJjZSI6IntcbiAgLy8gV2FpdCBmb3Igb3V0cHV0IHRvIGJlIHdyaXR0ZW4gdG8gdGhlIERPTSwgdGhlbiB0cmlnZ2VyIHdpZGdldCByZW5kZXJpbmdcbiAgYXdhaXQgX3dlYnJfdmFsdWVfMTQ7XG4gIGlmICh3aW5kb3cuSFRNTFdpZGdldHMpIHtcbiAgICB3aW5kb3cuSFRNTFdpZGdldHMuc3RhdGljUmVuZGVyKCk7XG4gIH1cbiAgaWYgKHdpbmRvdy5QYWdlZFRhYmxlRG9jKSB7XG4gICAgd2luZG93LlBhZ2VkVGFibGVEb2MuaW5pdEFsbCgpO1xuICB9XG59XG4ifSx7ImNlbGxOYW1lIjoid2Vici0xNCIsImlubGluZSI6ZmFsc2UsIm1ldGhvZE5hbWUiOiJpbnRlcnByZXQiLCJzb3VyY2UiOiJ2aWV3b2YgX3dlYnJfZWRpdG9yXzE0ID0ge1xuICBjb25zdCB7IFdlYlJFeGVyY2lzZUVkaXRvciwgYjY0RGVjb2RlIH0gPSB3aW5kb3cuX2V4ZXJjaXNlX29qc19ydW50aW1lO1xuICBjb25zdCBzY3JpcHRDb250ZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3Rvcihgc2NyaXB0W3R5cGU9XFxcIndlYnItMTQtY29udGVudHNcXFwiXWApLnRleHRDb250ZW50O1xuICBjb25zdCBibG9jayA9IEpTT04ucGFyc2UoYjY0RGVjb2RlKHNjcmlwdENvbnRlbnQpKTtcblxuICBjb25zdCBvcHRpb25zID0gT2JqZWN0LmFzc2lnbih7IGlkOiBgd2Vici0xNC1jb250ZW50c2AgfSwgYmxvY2suYXR0cik7XG4gIGNvbnN0IGVkaXRvciA9IG5ldyBXZWJSRXhlcmNpc2VFZGl0b3Iod2ViUk9qcy53ZWJSUHJvbWlzZSwgYmxvY2suY29kZSwgb3B0aW9ucyk7XG5cbiAgcmV0dXJuIGVkaXRvci5jb250YWluZXI7XG59XG5fd2Vicl92YWx1ZV8xNCA9IHdlYlJPanMucHJvY2Vzcyhfd2Vicl9lZGl0b3JfMTQsIHt9KTtcbiJ9LHsiY2VsbE5hbWUiOiJ3ZWJyLXdpZGdldC0xMyIsImlubGluZSI6ZmFsc2UsIm1ldGhvZE5hbWUiOiJpbnRlcnByZXRRdWlldCIsInNvdXJjZSI6IntcbiAgLy8gV2FpdCBmb3Igb3V0cHV0IHRvIGJlIHdyaXR0ZW4gdG8gdGhlIERPTSwgdGhlbiB0cmlnZ2VyIHdpZGdldCByZW5kZXJpbmdcbiAgYXdhaXQgX3dlYnJfdmFsdWVfMTM7XG4gIGlmICh3aW5kb3cuSFRNTFdpZGdldHMpIHtcbiAgICB3aW5kb3cuSFRNTFdpZGdldHMuc3RhdGljUmVuZGVyKCk7XG4gIH1cbiAgaWYgKHdpbmRvdy5QYWdlZFRhYmxlRG9jKSB7XG4gICAgd2luZG93LlBhZ2VkVGFibGVEb2MuaW5pdEFsbCgpO1xuICB9XG59XG4ifSx7ImNlbGxOYW1lIjoid2Vici0xMyIsImlubGluZSI6ZmFsc2UsIm1ldGhvZE5hbWUiOiJpbnRlcnByZXQiLCJzb3VyY2UiOiJ2aWV3b2YgX3dlYnJfZWRpdG9yXzEzID0ge1xuICBjb25zdCB7IFdlYlJFeGVyY2lzZUVkaXRvciwgYjY0RGVjb2RlIH0gPSB3aW5kb3cuX2V4ZXJjaXNlX29qc19ydW50aW1lO1xuICBjb25zdCBzY3JpcHRDb250ZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3Rvcihgc2NyaXB0W3R5cGU9XFxcIndlYnItMTMtY29udGVudHNcXFwiXWApLnRleHRDb250ZW50O1xuICBjb25zdCBibG9jayA9IEpTT04ucGFyc2UoYjY0RGVjb2RlKHNjcmlwdENvb
633nRlbnQpKTtcblxuICBjb25zdCBvcHRpb25zID0gT2JqZWN0LmFzc2lnbih7IGlkOiBgd2Vici0xMy1jb250ZW50c2AgfSwgYmxvY2suYXR0cik7XG4gIGNvbnN0IGVkaXRvciA9IG5ldyBXZWJSRXhlcmNpc2VFZGl0b3Iod2ViUk9qcy53ZWJSUHJvbWlzZSwgYmxvY2suY29kZSwgb3B0aW9ucyk7XG5cbiAgcmV0dXJuIGVkaXRvci5jb250YWluZXI7XG59XG5fd2Vicl92YWx1ZV8xMyA9IHdlYlJPanMucHJvY2Vzcyhfd2Vicl9lZGl0b3JfMTMsIHt9KTtcbiJ9LHsiY2VsbE5hbWUiOiJ3ZWJyLXdpZGdldC0xMiIsImlubGluZSI6ZmFsc2UsIm1ldGhvZE5hbWUiOiJpbnRlcnByZXRRdWlldCIsInNvdXJjZSI6IntcbiAgLy8gV2FpdCBmb3Igb3V0cHV0IHRvIGJlIHdyaXR0ZW4gdG8gdGhlIERPTSwgdGhlbiB0cmlnZ2VyIHdpZGdldCByZW5kZXJpbmdcbiAgYXdhaXQgX3dlYnJfdmFsdWVfMTI7XG4gIGlmICh3aW5kb3cuSFRNTFdpZGdldHMpIHtcbiAgICB3aW5kb3cuSFRNTFdpZGdldHMuc3RhdGljUmVuZGVyKCk7XG4gIH1cbiAgaWYgKHdpbmRvdy5QYWdlZFRhYmxlRG9jKSB7XG4gICAgd2luZG93LlBhZ2VkVGFibGVEb2MuaW5pdEFsbCgpO1xuICB9XG59XG4ifSx7ImNlbGxOYW1lIjoid2Vici0xMiIsImlubGluZSI6ZmFsc2UsIm1ldGhvZE5hbWUiOiJpbnRlcnByZXQiLCJzb3VyY2UiOiJ2aWV3b2YgX3dlYnJfZWRpdG9yXzEyID0ge1xuICBjb25zdCB7IFdlYlJFeGVyY2lzZUVkaXRvciwgYjY0RGVjb2RlIH0gPSB3aW5kb3cuX2V4ZXJjaXNlX29qc19ydW50aW1lO1xuICBjb25zdCBzY3JpcHRDb250ZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3Rvcihgc2NyaXB0W3R5cGU9XFxcIndlYnItMTItY29udGVudHNcXFwiXWApLnRleHRDb250ZW50O1xuICBjb25zdCBibG9jayA9IEpTT04ucGFyc2UoYjY0RGVjb2RlKHNjcmlwdENvbnRlbnQpKTtcblxuICBjb25zdCBvcHRpb25zID0gT2JqZWN0LmFzc2lnbih7IGlkOiBgd2Vici0xMi1jb250ZW50c2AgfSwgYmxvY2suYXR0cik7XG4gIGNvbnN0IGVkaXRvciA9IG5ldyBXZWJSRXhlcmNpc2VFZGl0b3Iod2ViUk9qcy53ZWJSUHJvbWlzZSwgYmxvY2suY29kZSwgb3B0aW9ucyk7XG5cbiAgcmV0dXJuIGVkaXRvci5jb250YWluZXI7XG59XG5fd2Vicl92YWx1ZV8xMiA9IHdlYlJPanMucHJvY2Vzcyhfd2Vicl9lZGl0b3JfMTIsIHt9KTtcbiJ9LHsiY2VsbE5hbWUiOiJ3ZWJyLXdpZGdldC0xMSIsImlubGluZSI6ZmFsc2UsIm1ldGhvZE5hbWUiOiJpbnRlcnByZXRRdWlldCIsInNvdXJjZSI6IntcbiAgLy8gV2FpdCBmb3Igb3V0cHV0IHRvIGJlIHdyaXR0ZW4gdG8gdGhlIERPTSwgdGhlbiB0cmlnZ2VyIHdpZGdldCByZW5kZXJpbmdcbiAgYXdhaXQgX3dlYnJfdmFsdWVfMTE7XG4gIGlmICh3aW5kb3cuSFRNTFdpZGdldHMpIHtcbiAgICB3aW5kb3cuSFRNTFdpZGdldHMuc3RhdGljUmVuZGVyKCk7XG4gIH1cbiAgaWYgKHdpbmRvdy5QYWdlZFRhYmxlRG9jKSB7XG4gICAgd2luZG93LlBhZ2VkVGFibGVEb2MuaW5pdEFsbCgpO1xuICB9XG59XG4ifSx7ImNlbGxOYW1lIjoid2Vici0xMSIsImlubGluZSI6ZmFsc2UsIm1ldGhvZE5hbWUiOiJpbnRlcnByZXQiLCJzb3VyY2UiOiJ2aWV3b2YgX3dlYnJfZWRpdG9yXzExID0ge1xuICBjb25zdCB7IFdlYlJFeGVyY2lzZUVkaXRvciwgYjY0RGVjb2RlIH0gPSB3aW5kb3cuX2V4ZXJjaXNlX29qc19ydW50aW1lO1xuICBjb25zdCBzY3JpcHRDb250ZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3Rvcihgc2NyaXB0W3R5cGU9XFxcIndlYnItMTEtY29udGVudHNcXFwiXWApLnRleHRDb250ZW50O1xuICBjb25zdCBibG9jayA9IEpTT04ucGFyc2UoYjY0RGVjb2RlKHNjcmlwdENvbnRlbnQpKTtcblxuICBjb25zdCBvcHRpb25zID0gT2JqZWN0LmFzc2lnbih7IGlkOiBgd2Vici0xMS1jb250ZW50c2AgfSwgYmxvY2suYXR0cik7XG4gIGNvbnN0IGVkaXRvciA9IG5ldyBXZWJSRXhlcmNpc2VFZGl0b3Iod2ViUk9qcy53ZWJSUHJvbWlzZSwgYmxvY2suY29kZSwgb3B0aW9ucyk7XG5cbiAgcmV0dXJuIGVkaXRvci5jb250YWluZXI7XG59XG5fd2Vicl92YWx1ZV8xMSA9IHdlYlJPanMucHJvY2Vzcyhfd2Vicl9lZGl0b3JfMTEsIHt9KTtcbiJ9LHsiY2VsbE5hbWUiOiJ3ZWJyLXdpZGdldC0xMCIsImlubGluZSI6ZmFsc2UsIm1ldGhvZE5hbWUiOiJpbnRlcnByZXRRdWlldCIsInNvdXJjZSI6IntcbiAgLy8gV2FpdCBmb3Igb3V0cHV0IHRvIGJlIHdyaXR0ZW4gdG8gdGhlIERPTSwgdGhlbiB0cmlnZ2VyIHdpZGdldCByZW5kZXJpbmdcbiAgYXdhaXQgX3dlYnJfdmFsdWVfMTA7XG4gIGlmICh3aW5kb3cuSFRNTFdpZGdldHMpIHtcbiAgICB3aW5kb3cuSFRNTFdpZGdldHMuc3RhdGljUmVuZGVyKCk7XG4gIH1cbiAgaWYgKHdpbmRvdy5QYWdlZFRhYmxlRG9jKSB7XG4gICAgd2luZG93LlBhZ2VkVGFibGVEb2MuaW5pdEFsbCgpO1xuICB9XG59XG4ifSx7ImNlbGxOYW1lIjoid2Vici0xMCIsImlubGluZSI6ZmFsc2UsIm1ldGhvZE5hbWUiOiJpbnRlcnByZXQiLCJzb3VyY2UiOiJ2aWV3b2YgX3dlYnJfZWRpdG9yXzEwID0ge1xuICBjb25zdCB7IFdlYlJFeGVyY2lzZUVkaXRvciwgYjY0RGVjb2RlIH0gPSB3aW5kb3cuX2V4ZXJjaXNlX29qc19ydW50aW1lO1xuICBjb25zdCBzY3JpcHRDb250ZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3Rvcihgc2NyaXB0W3R5cGU9XFxcIndlYnItMTAtY29udGVudHNcXFwiXWApLnRleHRDb250ZW50O1xuICBjb25zdCBibG9jayA9IEpTT04ucGFyc2UoYjY0RGVjb2RlKHNjcmlwdENvbnRlbnQpKTtcblxuICBjb25zdCBvcHRpb25zID0gT2JqZWN0LmFzc2lnbih7IGlkOiBgd2Vici0xMC1jb250ZW50c2AgfSwgYmxvY2suYXR0cik7XG4gIGNvbnN0IGVkaXRvciA9IG5ldyBXZWJSRXhlcmNpc2VFZGl0b3Iod2ViUk9qcy53ZWJSUHJvbWlzZSwgYmxvY2suY29kZSwgb3B0aW9ucyk7XG5cbiAgcmV0dXJuIGVkaXRvci5jb250YWluZXI7XG59XG5fd2Vicl92YWx1ZV8xMCA9IHdlYlJPanMucHJvY2Vzcyhfd2Vicl9lZGl0b3JfMTAsIHt9KTtcbiJ9LHsiY2VsbE5hbWUiOiJ3ZWJyLXdpZGdldC05IiwiaW5saW5lIjpmYWxzZSwibWV0aG9kTmFtZSI6ImludGVycHJldFF1aWV0Iiwic291cmNlIjoie1xuICAvLyBXYWl0IGZvciBvdXRwdXQgdG8gYmUgd3JpdHRlbiB0byB0aGUgRE9NLCB0aGVuIHRyaWdnZXIgd2lkZ2V0IHJlbmRlcmluZ1xuICBhd2FpdCBfd2Vicl92YWx1ZV85O1xuICBpZiAod2luZG93LkhUTUxXaWRnZXRzKSB7XG4gICAgd2luZG93LkhUTUxXaWRnZXRzLnN0YXRpY1JlbmRlcigpO1xuICB9XG4gIGlmICh3aW5kb3cuUGFnZWRUYWJsZURvYykge1xuICAgIHdpbmRvdy5QYWdlZFRhYmxlRG9jLmluaXRBbGwoKTtcbiAgfVxufVxuIn0seyJjZWxsTmFtZSI6IndlYnItOSIsImlubGluZSI6ZmFsc2UsIm1ldGhvZE5hbWUiOiJpbnRlcnByZXQiLCJzb3VyY2UiOiJ2aWV3b2YgX3dlYnJfZWRpdG9yXzkgPSB7XG4gIGNvbnN0IHsgV2ViUkV4ZXJjaXNlRWRpdG9yLCBiNjREZWNvZGUgfSA9IHdpbmRvdy5fZXhlcmNpc2Vfb2pzX3J1bnRpbWU7XG4gIGNvbnN0IHNjcmlwdENvb
633nRlbnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKGBzY3JpcHRbdHlwZT1cXFwid2Vici05LWNvbnRlbnRzXFxcIl1gKS50ZXh0Q29udGVudDtcbiAgY29uc3QgYmxvY2sgPSBKU09OLnBhcnNlKGI2NERlY29kZShzY3JpcHRDb250ZW50KSk7XG5cbiAgY29uc3Qgb3B0aW9ucyA9IE9iamVjdC5hc3NpZ24oeyBpZDogYHdlYnItOS1jb250ZW50c2AgfSwgYmxvY2suYXR0cik7XG4gIGNvbnN0IGVkaXRvciA9IG5ldyBXZWJSRXhlcmNpc2VFZGl0b3Iod2ViUk9qcy53ZWJSUHJvbWlzZSwgYmxvY2suY29kZSwgb3B0aW9ucyk7XG5cbiAgcmV0dXJuIGVkaXRvci5jb250YWluZXI7XG59XG5fd2Vicl92YWx1ZV85ID0gd2ViUk9qcy5wcm9jZXNzKF93ZWJyX2VkaXRvcl85LCB7fSk7XG4ifSx7ImNlbGxOYW1lIjoid2Vici13aWRnZXQtOCIsImlubGluZSI6ZmFsc2UsIm1ldGhvZE5hbWUiOiJpbnRlcnByZXRRdWlldCIsInNvdXJjZSI6IntcbiAgLy8gV2FpdCBmb3Igb3V0cHV0IHRvIGJlIHdyaXR0ZW4gdG8gdGhlIERPTSwgdGhlbiB0cmlnZ2VyIHdpZGdldCByZW5kZXJpbmdcbiAgYXdhaXQgX3dlYnJfdmFsdWVfODtcbiAgaWYgKHdpbmRvdy5IVE1MV2lkZ2V0cykge1xuICAgIHdpbmRvdy5IVE1MV2lkZ2V0cy5zdGF0aWNSZW5kZXIoKTtcbiAgfVxuICBpZiAod2luZG93LlBhZ2VkVGFibGVEb2MpIHtcbiAgICB3aW5kb3cuUGFnZWRUYWJsZURvYy5pbml0QWxsKCk7XG4gIH1cbn1cbiJ9LHsiY2VsbE5hbWUiOiJ3ZWJyLTgiLCJpbmxpbmUiOmZhbHNlLCJtZXRob2ROYW1lIjoiaW50ZXJwcmV0Iiwic291cmNlIjoidmlld29mIF93ZWJyX2VkaXRvcl84ID0ge1xuICBjb25zdCB7IFdlYlJFeGVyY2lzZUVkaXRvciwgYjY0RGVjb2RlIH0gPSB3aW5kb3cuX2V4ZXJjaXNlX29qc19ydW50aW1lO1xuICBjb25zdCBzY3JpcHRDb250ZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3Rvcihgc2NyaXB0W3R5cGU9XFxcIndlYnItOC1jb250ZW50c1xcXCJdYCkudGV4dENvbnRlbnQ7XG4gIGNvbnN0IGJsb2NrID0gSlNPTi5wYXJzZShiNjREZWNvZGUoc2NyaXB0Q29udGVudCkpO1xuXG4gIGNvbnN0IG9wdGlvbnMgPSBPYmplY3QuYXNzaWduKHsgaWQ6IGB3ZWJyLTgtY29udGVudHNgIH0sIGJsb2NrLmF0dHIpO1xuICBjb25zdCBlZGl0b3IgPSBuZXcgV2ViUkV4ZXJjaXNlRWRpdG9yKHdlYlJPanMud2ViUlByb21pc2UsIGJsb2NrLmNvZGUsIG9wdGlvbnMpO1xuXG4gIHJldHVybiBlZGl0b3IuY29udGFpbmVyO1xufVxuX3dlYnJfdmFsdWVfOCA9IHdlYlJPanMucHJvY2Vzcyhfd2Vicl9lZGl0b3JfOCwge30pO1xuIn0seyJjZWxsTmFtZSI6IndlYnItd2lkZ2V0LTciLCJpbmxpbmUiOmZhbHNlLCJtZXRob2ROYW1lIjoiaW50ZXJwcmV0UXVpZXQiLCJzb3VyY2UiOiJ7XG4gIC8vIFdhaXQgZm9yIG91dHB1dCB0byBiZSB3cml0dGVuIHRvIHRoZSBET00sIHRoZW4gdHJpZ2dlciB3aWRnZXQgcmVuZGVyaW5nXG4gIGF3YWl0IF93ZWJyX3ZhbHVlXzc7XG4gIGlmICh3aW5kb3cuSFRNTFdpZGdldHMpIHtcbiAgICB3aW5kb3cuSFRNTFdpZGdldHMuc3RhdGljUmVuZGVyKCk7XG4gIH1cbiAgaWYgKHdpbmRvdy5QYWdlZFRhYmxlRG9jKSB7XG4gICAgd2luZG93LlBhZ2VkVGFibGVEb2MuaW5pdEFsbCgpO1xuICB9XG59XG4ifSx7ImNlbGxOYW1lIjoid2Vici03IiwiaW5saW5lIjpmYWxzZSwibWV0aG9kTmFtZSI6ImludGVycHJldCIsInNvdXJjZSI6InZpZXdvZiBfd2Vicl9lZGl0b3JfNyA9IHtcbiAgY29uc3QgeyBXZWJSRXhlcmNpc2VFZGl0b3IsIGI2NERlY29kZSB9ID0gd2luZG93Ll9leGVyY2lzZV9vanNfcnVudGltZTtcbiAgY29uc3Qgc2NyaXB0Q29udGVudCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoYHNjcmlwdFt0eXBlPVxcXCJ3ZWJyLTctY29udGVudHNcXFwiXWApLnRleHRDb250ZW50O1xuICBjb25zdCBibG9jayA9IEpTT04ucGFyc2UoYjY0RGVjb2RlKHNjcmlwdENvbnRlbnQpKTtcblxuICBjb25zdCBvcHRpb25zID0gT2JqZWN0LmFzc2lnbih7IGlkOiBgd2Vici03LWNvbnRlbnRzYCB9LCBibG9jay5hdHRyKTtcbiAgY29uc3QgZWRpdG9yID0gbmV3IFdlYlJFeGVyY2lzZUVkaXRvcih3ZWJST2pzLndlYlJQcm9taXNlLCBibG9jay5jb2RlLCBvcHRpb25zKTtcblxuICByZXR1cm4gZWRpdG9yLmNvbnRhaW5lcjtcbn1cbl93ZWJyX3ZhbHVlXzcgPSB3ZWJST2pzLnByb2Nlc3MoX3dlYnJfZWRpdG9yXzcsIHt9KTtcbiJ9LHsiY2VsbE5hbWUiOiJ3ZWJyLXdpZGdldC02IiwiaW5saW5lIjpmYWxzZSwibWV0aG9kTmFtZSI6ImludGVycHJldFF1aWV0Iiwic291cmNlIjoie1xuICAvLyBXYWl0IGZvciBvdXRwdXQgdG8gYmUgd3JpdHRlbiB0byB0aGUgRE9NLCB0aGVuIHRyaWdnZXIgd2lkZ2V0IHJlbmRlcmluZ1xuICBhd2FpdCBfd2Vicl92YWx1ZV82O1xuICBpZiAod2luZG93LkhUTUxXaWRnZXRzKSB7XG4gICAgd2luZG93LkhUTUxXaWRnZXRzLnN0YXRpY1JlbmRlcigpO1xuICB9XG4gIGlmICh3aW5kb3cuUGFnZWRUYWJsZURvYykge1xuICAgIHdpbmRvdy5QYWdlZFRhYmxlRG9jLmluaXRBbGwoKTtcbiAgfVxufVxuIn0seyJjZWxsTmFtZSI6IndlYnItNiIsImlubGluZSI6ZmFsc2UsIm1ldGhvZE5hbWUiOiJpbnRlcnByZXQiLCJzb3VyY2UiOiJ2aWV3b2YgX3dlYnJfZWRpdG9yXzYgPSB7XG4gIGNvbnN0IHsgV2ViUkV4ZXJjaXNlRWRpdG9yLCBiNjREZWNvZGUgfSA9IHdpbmRvdy5fZXhlcmNpc2Vfb2pzX3J1bnRpbWU7XG4gIGNvbnN0IHNjcmlwdENvbnRlbnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKGBzY3JpcHRbdHlwZT1cXFwid2Vici02LWNvbnRlbnRzXFxcIl1gKS50ZXh0Q29udGVudDtcbiAgY29uc3QgYmxvY2sgPSBKU09OLnBhcnNlKGI2NERlY29kZShzY3JpcHRDb250ZW50KSk7XG5cbiAgY29uc3Qgb3B0aW9ucyA9IE9iamVjdC5hc3NpZ24oeyBpZDogYHdlYnItNi1jb250ZW50c2AgfSwgYmxvY2suYXR0cik7XG4gIGNvbnN0IGVkaXRvciA9IG5ldyBXZWJSRXhlcmNpc2VFZGl0b3Iod2ViUk9qcy53ZWJSUHJvbWlzZSwgYmxvY2suY29kZSwgb3B0aW9ucyk7XG5cbiAgcmV0dXJuIGVkaXRvci5jb250YWluZXI7XG59XG5fd2Vicl92YWx1ZV82ID0gd2ViUk9qcy5wcm9jZXNzKF93ZWJyX2VkaXRvcl82LCB7fSk7XG4ifSx7ImNlbGxOYW1lIjoid2Vici13aWRnZXQtNSIsImlubGluZSI6ZmFsc2UsIm1ldGhvZE5hbWUiOiJpbnRlcnByZXRRdWlldCIsInNvdXJjZSI6IntcbiAgLy8gV2FpdCBmb3Igb3V0cHV0IHRvIGJlIHdyaXR0ZW4gdG8gdGhlIERPTSwgdGhlbiB0cmlnZ2VyIHdpZGdldCByZW5kZXJpbmdcbiAgYXdhaXQgX3dlYnJfdmFsdWVfNTtcbiAgaWYgKHdpbmRvdy5IVE1MV2lkZ2V0cykge1xuICAgIHdpbmRvdy5IVE1MV2lkZ2V0cy5zdGF0aWNSZW5kZXIoKTtcbiAgfVxuICBpZiAod2luZG93LlBhZ2VkVGFibGVEb2MpIHtcbiAgICB3aW5kb3cuUGFnZWRUYWJsZURvYy5pbml0QWxsKCk7XG4gIH1cbn1cbiJ9LHsiY2VsbE5hbWUiOiJ3ZWJyLTUiLCJpbmxpbmUiOmZhbHNlLCJtZXRob2ROYW1lIjoiaW50ZXJwcmV0Iiwic291cmNlIjoidmlld29mIF93ZWJyX2VkaXRvcl81ID0ge1xuICBjb25zdCB7IFdlYlJFeGVyY2lzZUVkaXRvciwgYjY0RGVjb2RlIH0gPSB3aW5kb3cuX2V4ZXJjaXNlX29qc19ydW50aW1lO1xuICBjb25zdCBzY3JpcHRDb250ZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3Rvcihgc2NyaXB0W3R5cGU9XFxcIndlYnItNS1jb250ZW50c1xcXCJdYCkudGV4dENvbnRlbnQ7XG4gIGNvbnN0IGJsb2NrID0gSlNPTi5wYXJzZShiNjREZWNvZGUoc2NyaXB0Q29udGVudCkpO1xuXG4gIGNvbnN0IG9wdGlvbnMgPSBPYmplY3QuYXNzaWduKHsgaWQ6IGB3ZWJyLTUtY29udGVudHNgIH0sIGJsb2NrLmF0dHIpO1xuICBjb25zdCBlZGl0b3IgPSBuZXcgV2ViUkV4ZXJjaXNlRWRpdG9yKHdlYlJPanMud2ViUlByb21pc2UsIGJsb2NrLmNvZGUsIG9wdGlvbnMpO1xuXG4gIHJldHVybi
633BlZGl0b3IuY29udGFpbmVyO1xufVxuX3dlYnJfdmFsdWVfNSA9IHdlYlJPanMucHJvY2Vzcyhfd2Vicl9lZGl0b3JfNSwge30pO1xuIn0seyJjZWxsTmFtZSI6IndlYnItd2lkZ2V0LTQiLCJpbmxpbmUiOmZhbHNlLCJtZXRob2ROYW1lIjoiaW50ZXJwcmV0UXVpZXQiLCJzb3VyY2UiOiJ7XG4gIC8vIFdhaXQgZm9yIG91dHB1dCB0byBiZSB3cml0dGVuIHRvIHRoZSBET00sIHRoZW4gdHJpZ2dlciB3aWRnZXQgcmVuZGVyaW5nXG4gIGF3YWl0IF93ZWJyX3ZhbHVlXzQ7XG4gIGlmICh3aW5kb3cuSFRNTFdpZGdldHMpIHtcbiAgICB3aW5kb3cuSFRNTFdpZGdldHMuc3RhdGljUmVuZGVyKCk7XG4gIH1cbiAgaWYgKHdpbmRvdy5QYWdlZFRhYmxlRG9jKSB7XG4gICAgd2luZG93LlBhZ2VkVGFibGVEb2MuaW5pdEFsbCgpO1xuICB9XG59XG4ifSx7ImNlbGxOYW1lIjoid2Vici00IiwiaW5saW5lIjpmYWxzZSwibWV0aG9kTmFtZSI6ImludGVycHJldCIsInNvdXJjZSI6InZpZXdvZiBfd2Vicl9lZGl0b3JfNCA9IHtcbiAgY29uc3QgeyBXZWJSRXhlcmNpc2VFZGl0b3IsIGI2NERlY29kZSB9ID0gd2luZG93Ll9leGVyY2lzZV9vanNfcnVudGltZTtcbiAgY29uc3Qgc2NyaXB0Q29udGVudCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoYHNjcmlwdFt0eXBlPVxcXCJ3ZWJyLTQtY29udGVudHNcXFwiXWApLnRleHRDb250ZW50O1xuICBjb25zdCBibG9jayA9IEpTT04ucGFyc2UoYjY0RGVjb2RlKHNjcmlwdENvbnRlbnQpKTtcblxuICBjb25zdCBvcHRpb25zID0gT2JqZWN0LmFzc2lnbih7IGlkOiBgd2Vici00LWNvbnRlbnRzYCB9LCBibG9jay5hdHRyKTtcbiAgY29uc3QgZWRpdG9yID0gbmV3IFdlYlJFeGVyY2lzZUVkaXRvcih3ZWJST2pzLndlYlJQcm9taXNlLCBibG9jay5jb2RlLCBvcHRpb25zKTtcblxuICByZXR1cm4gZWRpdG9yLmNvbnRhaW5lcjtcbn1cbl93ZWJyX3ZhbHVlXzQgPSB3ZWJST2pzLnByb2Nlc3MoX3dlYnJfZWRpdG9yXzQsIHt9KTtcbiJ9LHsiY2VsbE5hbWUiOiJ3ZWJyLXdpZGdldC0zIiwiaW5saW5lIjpmYWxzZSwibWV0aG9kTmFtZSI6ImludGVycHJldFF1aWV0Iiwic291cmNlIjoie1xuICAvLyBXYWl0IGZvciBvdXRwdXQgdG8gYmUgd3JpdHRlbiB0byB0aGUgRE9NLCB0aGVuIHRyaWdnZXIgd2lkZ2V0IHJlbmRlcmluZ1xuICBhd2FpdCBfd2Vicl92YWx1ZV8zO1xuICBpZiAod2luZG93LkhUTUxXaWRnZXRzKSB7XG4gICAgd2luZG93LkhUTUxXaWRnZXRzLnN0YXRpY1JlbmRlcigpO1xuICB9XG4gIGlmICh3aW5kb3cuUGFnZWRUYWJsZURvYykge1xuICAgIHdpbmRvdy5QYWdlZFRhYmxlRG9jLmluaXRBbGwoKTtcbiAgfVxufVxuIn0seyJjZWxsTmFtZSI6IndlYnItMyIsImlubGluZSI6ZmFsc2UsIm1ldGhvZE5hbWUiOiJpbnRlcnByZXQiLCJzb3VyY2UiOiJ2aWV3b2YgX3dlYnJfZWRpdG9yXzMgPSB7XG4gIGNvbnN0IHsgV2ViUkV4ZXJjaXNlRWRpdG9yLCBiNjREZWNvZGUgfSA9IHdpbmRvdy5fZXhlcmNpc2Vfb2pzX3J1bnRpbWU7XG4gIGNvbnN0IHNjcmlwdENvbnRlbnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKGBzY3JpcHRbdHlwZT1cXFwid2Vici0zLWNvbnRlbnRzXFxcIl1gKS50ZXh0Q29udGVudDtcbiAgY29uc3QgYmxvY2sgPSBKU09OLnBhcnNlKGI2NERlY29kZShzY3JpcHRDb250ZW50KSk7XG5cbiAgY29uc3Qgb3B0aW9ucyA9IE9iamVjdC5hc3NpZ24oeyBpZDogYHdlYnItMy1jb250ZW50c2AgfSwgYmxvY2suYXR0cik7XG4gIGNvbnN0IGVkaXRvciA9IG5ldyBXZWJSRXhlcmNpc2VFZGl0b3Iod2ViUk9qcy53ZWJSUHJvbWlzZSwgYmxvY2suY29kZSwgb3B0aW9ucyk7XG5cbiAgcmV0dXJuIGVkaXRvci5jb250YWluZXI7XG59XG5fd2Vicl92YWx1ZV8zID0gd2ViUk9qcy5wcm9jZXNzKF93ZWJyX2VkaXRvcl8zLCB7fSk7XG4ifSx7ImNlbGxOYW1lIjoid2Vici13aWRnZXQtMiIsImlubGluZSI6ZmFsc2UsIm1ldGhvZE5hbWUiOiJpbnRlcnByZXRRdWlldCIsInNvdXJjZSI6IntcbiAgLy8gV2FpdCBmb3Igb3V0cHV0IHRvIGJlIHdyaXR0ZW4gdG8gdGhlIERPTSwgdGhlbiB0cmlnZ2VyIHdpZGdldCByZW5kZXJpbmdcbiAgYXdhaXQgX3dlYnJfdmFsdWVfMjtcbiAgaWYgKHdpbmRvdy5IVE1MV2lkZ2V0cykge1xuICAgIHdpbmRvdy5IVE1MV2lkZ2V0cy5zdGF0aWNSZW5kZXIoKTtcbiAgfVxuICBpZiAod2luZG93LlBhZ2VkVGFibGVEb2MpIHtcbiAgICB3aW5kb3cuUGFnZWRUYWJsZURvYy5pbml0QWxsKCk7XG4gIH1cbn1cbiJ9LHsiY2VsbE5hbWUiOiJ3ZWJyLTIiLCJpbmxpbmUiOmZhbHNlLCJtZXRob2ROYW1lIjoiaW50ZXJwcmV0Iiwic291cmNlIjoidmlld29mIF93ZWJyX2VkaXRvcl8yID0ge1xuICBjb25zdCB7IFdlYlJFeGVyY2lzZUVkaXRvciwgYjY0RGVjb2RlIH0gPSB3aW5kb3cuX2V4ZXJjaXNlX29qc19ydW50aW1lO1xuICBjb25zdCBzY3JpcHRDb250ZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3Rvcihgc2NyaXB0W3R5cGU9XFxcIndlYnItMi1jb250ZW50c1xcXCJdYCkudGV4dENvbnRlbnQ7XG4gIGNvbnN0IGJsb2NrID0gSlNPTi5wYXJzZShiNjREZWNvZGUoc2NyaXB0Q29udGVudCkpO1xuXG4gIGNvbnN0IG9wdGlvbnMgPSBPYmplY3QuYXNzaWduKHsgaWQ6IGB3ZWJyLTItY29udGVudHNgIH0sIGJsb2NrLmF0dHIpO1xuICBjb25zdCBlZGl0b3IgPSBuZXcgV2ViUkV4ZXJjaXNlRWRpdG9yKHdlYlJPanMud2ViUlByb21pc2UsIGJsb2NrLmNvZGUsIG9wdGlvbnMpO1xuXG4gIHJldHVybiBlZGl0b3IuY29udGFpbmVyO1xufVxuX3dlYnJfdmFsdWVfMiA9IHdlYlJPanMucHJvY2Vzcyhfd2Vicl9lZGl0b3JfMiwge30pO1xuIn0seyJjZWxsTmFtZSI6IndlYnItd2lkZ2V0LTEiLCJpbmxpbmUiOmZhbHNlLCJtZXRob2ROYW1lIjoiaW50ZXJwcmV0UXVpZXQiLCJzb3VyY2UiOiJ7XG4gIC8vIFdhaXQgZm9yIG91dHB1dCB0byBiZSB3cml0dGVuIHRvIHRoZSBET00sIHRoZW4gdHJpZ2dlciB3aWRnZXQgcmVuZGVyaW5nXG4gIGF3YWl0IF93ZWJyX3ZhbHVlXzE7XG4gIGlmICh3aW5kb3cuSFRNTFdpZGdldHMpIHtcbiAgICB3aW5kb3cuSFRNTFdpZGdldHMuc3RhdGljUmVuZGVyKCk7XG4gIH1cbiAgaWYgKHdpbmRvdy5QYWdlZFRhYmxlRG9jKSB7XG4gICAgd2luZG93LlBhZ2VkVGFibGVEb2MuaW5pdEFsbCgpO1xuICB9XG59XG4ifSx7ImNlbGxOYW1lIjoid2Vici0xIiwiaW5saW5lIjpmYWxzZSwibWV0aG9kTmFtZSI6ImludGVycHJldCIsInNvdXJjZSI6InZpZXdvZiBfd2Vicl9lZGl0b3JfMSA9IHtcbiAgY29uc3QgeyBXZWJSRXhlcmNpc2VFZGl0b3IsIGI2NERlY29kZSB9ID0gd2luZG93Ll9leGVyY2lzZV9vanNfcnVudGltZTtcbiAgY29uc3Qgc2NyaXB0Q29udGVudCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoYHNjcmlwdFt0eXBlPVxcXCJ3ZWJyLTEtY29udGVudHNcXFwiXWApLnRleHRDb250ZW50O1xuICBjb25zdCBibG9jayA9IEpTT04ucGFyc2UoYjY0RGVjb2RlKHNjcmlwdENvb
633nRlbnQpKTtcblxuICBjb25zdCBvcHRpb25zID0gT2JqZWN0LmFzc2lnbih7IGlkOiBgd2Vici0xLWNvbnRlbnRzYCB9LCBibG9jay5hdHRyKTtcbiAgY29uc3QgZWRpdG9yID0gbmV3IFdlYlJFeGVyY2lzZUVkaXRvcih3ZWJST2pzLndlYlJQcm9taXNlLCBibG9jay5jb2RlLCBvcHRpb25zKTtcblxuICByZXR1cm4gZWRpdG9yLmNvbnRhaW5lcjtcbn1cbl93ZWJyX3ZhbHVlXzEgPSB3ZWJST2pzLnByb2Nlc3MoX3dlYnJfZWRpdG9yXzEsIHt9KTtcbiJ9LHsiY2VsbE5hbWUiOiJ3ZWJyLXByZWx1ZGUiLCJpbmxpbmUiOmZhbHNlLCJtZXRob2ROYW1lIjoiaW50ZXJwcmV0UXVpZXQiLCJzb3VyY2UiOiJ3ZWJST2pzID0ge1xuICBjb25zdCB7IFdlYlIsIENoYW5uZWxUeXBlIH0gPSB3aW5kb3cuX2V4ZXJjaXNlX29qc19ydW50aW1lLldlYlI7XG4gIGNvbnN0IHtcbiAgICBXZWJSRXZhbHVhdG9yLFxuICAgIFdlYlJFbnZpcm9ubWVudE1hbmFnZXIsXG4gICAgc2V0dXBSLFxuICAgIGI2NERlY29kZSxcbiAgICBjb2xsYXBzZVBhdGhcbiAgfSA9IHdpbmRvdy5fZXhlcmNpc2Vfb2pzX3J1bnRpbWU7XG5cbiAgY29uc3Qgc3RhdHVzQ29udGFpbmVyID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJleGVyY2lzZS1sb2FkaW5nLXN0YXR1c1wiKTtcbiAgY29uc3QgaW5kaWNhdG9yQ29udGFpbmVyID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJleGVyY2lzZS1sb2FkaW5nLWluZGljYXRvclwiKTtcbiAgaW5kaWNhdG9yQ29udGFpbmVyLmNsYXNzTGlzdC5yZW1vdmUoXCJkLW5vbmVcIik7XG5cbiAgbGV0IHN0YXR1c1RleHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpXG4gIHN0YXR1c1RleHQuY2xhc3NMaXN0ID0gXCJleGVyY2lzZS1sb2FkaW5nLWRldGFpbHNcIjtcbiAgc3RhdHVzVGV4dCA9IHN0YXR1c0NvbnRhaW5lci5hcHBlbmRDaGlsZChzdGF0dXNUZXh0KTtcbiAgc3RhdHVzVGV4dC50ZXh0Q29udGVudCA9IGBJbml0aWFsaXNlYDtcblxuICAvLyBIb2lzdCBpbmRpY2F0b3Igb3V0IGZyb20gZmluYWwgc2xpZGUgd2hlbiBydW5uaW5nIHVuZGVyIHJldmVhbFxuICBjb25zdCByZXZlYWxTdGF0dXMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiLnJldmVhbCAuZXhlcmNpc2UtbG9hZGluZy1pbmRpY2F0b3JcIik7XG4gIGlmIChyZXZlYWxTdGF0dXMpIHtcbiAgICByZXZlYWxTdGF0dXMucmVtb3ZlKCk7XG4gICAgZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIi5yZXZlYWwgPiAuc2xpZGVzXCIpLmFwcGVuZENoaWxkKHJldmVhbFN0YXR1cyk7XG4gIH1cblxuICAvLyBNYWtlIGFueSByZXZlYWwgc2xpZGVzIHdpdGggbGl2ZSBjZWxscyBzY3JvbGxhYmxlXG4gIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoXCIucmV2ZWFsIC5leGVyY2lzZS1jZWxsXCIpLmZvckVhY2goKGVsKSA9PiB7XG4gICAgZWwuY2xvc2VzdCgnc2VjdGlvbi5zbGlkZScpLmNsYXNzTGlzdC5hZGQoXCJzY3JvbGxhYmxlXCIpO1xuICB9KVxuXG4gIC8vIHdlYlIgc3VwcGxlbWVudGFsIGRhdGEgYW5kIG9wdGlvbnNcbiAgY29uc3QgZGF0YUNvbnRlbnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKGBzY3JpcHRbdHlwZT1cXFwid2Vici1kYXRhXFxcIl1gKS50ZXh0Q29udGVudDtcbiAgY29uc3QgZGF0YSA9IEpTT04ucGFyc2UoYjY0RGVjb2RlKGRhdGFDb250ZW50KSk7XG5cbiAgLy8gR3JhYiBsaXN0IG9mIHJlc291cmNlcyB0byBiZSBkb3dubG9hZGVkXG4gIGNvbnN0IGZpbGVzQ29udGVudCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoYHNjcmlwdFt0eXBlPVxcXCJ2ZnMtZmlsZVxcXCJdYCkudGV4dENvbnRlbnQ7XG4gIGNvbnN0IGZpbGVzID0gSlNPTi5wYXJzZShiNjREZWNvZGUoZmlsZXNDb250ZW50KSk7XG5cbiAgLy8gVXNlIFBvc3RNZXNzYWdlIGNoYW5uZWwgZm9yIGFzeW5jIGNvbW11bmljYXRpb25cbiAgLy8gV2UgZG8gbm90IGV4cGVjdCB0byB0YWtlIG5lc3RlZCBwcm9tcHQgaW5wdXQgaW4gUXVhcnRvIExpdmUgY2VsbHNcbiAgZGF0YS5vcHRpb25zLmNoYW5uZWxUeXBlID0gQ2hhbm5lbFR5cGUuUG9zdE1lc3NhZ2U7XG5cbiAgLy8gSW5pdGlhbGlzZSB3ZWJSIGFuZCBzZXR1cCBmb3IgUiBjb2RlIGV2YWx1YXRpb25cbiAgbGV0IHdlYlJQcm9taXNlID0gKGFzeW5jICh3ZWJSKSA9PiB7XG4gICAgc3RhdHVzVGV4dC50ZXh0Q29udGVudCA9IGBEb3dubG9hZGluZyB3ZWJSYDtcbiAgICBhd2FpdCB3ZWJSLmluaXQoKTtcblxuICAgIC8vIEluc3RhbGwgcHJvdmlkZWQgbGlzdCBvZiBwYWNrYWdlc1xuICAgIC8vIEVuc3VyZSB3ZWJSIGRlZmF1bHQgcmVwbyBpcyBpbmNsdWRlZFxuICAgIGRhdGEucGFja2FnZXMucmVwb3MucHVzaChcImh0dHBzOi8vcmVwby5yLXdhc20ub3JnXCIpXG4gICAgYXdhaXQgZGF0YS5wYWNrYWdlcy5wa2dzLm1hcCgocGtnKSA9PiAoKSA9PiB7XG4gICAgICBzdGF0dXNUZXh0LnRleHRDb250ZW50ID0gYERvd25sb2FkaW5nIHBhY2thZ2U6ICR7cGtnfWA7XG4gICAgICByZXR1cm4gd2ViUi5ldmFsUlZvaWQoYFxuICAgICAgICB3ZWJyOjppbnN0YWxsKHBrZywgcmVwb3MgPSByZXBvcylcbiAgICAgICAgbGlicmFyeShwa2csIGNoYXJhY3Rlci5vbmx5ID0gVFJVRSlcbiAgICAgIGAsIHsgZW52OiB7XG4gICAgICAgIHBrZzogcGtnLFxuICAgICAgICByZXBvczogZGF0YS5wYWNrYWdlcy5yZXBvcyxcbiAgICAgIH19KTtcbiAgICB9KS5yZWR1Y2UoKGN1ciwgbmV4dCkgPT4gY3VyLnRoZW4obmV4dCksIFByb21pc2UucmVzb2x2ZSgpKTtcblxuICAgIC8vIERvd25sb2FkIGFuZCBpbnN0YWxsIHJlc291cmNlc1xuICAgIGF3YWl0IGZpbGVzLm1hcCgoZmlsZSkgPT4gYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgbmFtZSA9IGZpbGUuc3Vic3RyaW5nKGZpbGUubGFzdEluZGV4T2YoJy8nKSArIDEpO1xuICAgICAgc3RhdHVzVGV4dC50ZXh0Q29udGVudCA9IGBEb3dubG9hZGluZyByZXNvdXJjZTogJHtuYW1lfWA7XG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKGZpbGUpO1xuICAgICAgaWYgKCFyZXNwb25zZS5vaykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbid0IGRvd25sb2FkIFxcYCR7ZmlsZX1cXGAuIEVycm9yICR7cmVzcG9uc2Uuc3RhdHVzfTogXCIke3Jlc3BvbnNlLnN0YXR1c1RleHR9XCIuYCk7XG4gICAgICB9XG4gICAgICBjb25zdCBkYXRhID0gYXdhaXQgcmVzcG9uc2UuYXJyYXlCdWZmZXIoKTtcblxuICAgICAgLy8gU3RvcmUgVVJMcyBpbiB0aGUgY3dkIHdpdGhvdXQgYW55IHN1YmRpcmVjdG9yeSBzdHJ1Y3R1cmVcbiAgICAgIGlmIChmaWxlLmluY2x1ZGVzKFwiOi8vXCIpKSB7XG4gICAgICAgIGZpbGUgP
633SBuYW1lO1xuICAgICAgfVxuXG4gICAgICAvLyBDb2xsYXBzZSBoaWdoZXIgZGlyZWN0b3J5IHN0cnVjdHVyZVxuICAgICAgZmlsZSA9IGNvbGxhcHNlUGF0aChmaWxlKTtcblxuICAgICAgLy8gQ3JlYXRlIGRpcmVjdG9yeSB0cmVlLCBpZ25vcmluZyBcImRpcmVjdG9yeSBleGlzdHNcIiBWRlMgZXJyb3JzXG4gICAgICBjb25zdCBwYXJ0cyA9IGZpbGUuc3BsaXQoJy8nKS5zbGljZSgwLCAtMSk7XG4gICAgICBsZXQgcGF0aCA9ICcnO1xuICAgICAgd2hpbGUgKHBhcnRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgcGF0aCArPSBwYXJ0cy5zaGlmdCgpICsgJy8nO1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IHdlYlIuRlMubWtkaXIocGF0aCk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBpZiAoIWUubWVzc2FnZS5pbmNsdWRlcyhcIkZTIGVycm9yXCIpKSB7XG4gICAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBXcml0ZSB0aGlzIGZpbGUgdG8gdGhlIFZGU1xuICAgICAgcmV0dXJuIGF3YWl0IHdlYlIuRlMud3JpdGVGaWxlKGZpbGUsIG5ldyBVaW50OEFycmF5KGRhdGEpKTtcbiAgICB9KS5yZWR1Y2UoKGN1ciwgbmV4dCkgPT4gY3VyLnRoZW4obmV4dCksIFByb21pc2UucmVzb2x2ZSgpKTtcblxuICAgIHN0YXR1c1RleHQudGV4dENvbnRlbnQgPSBgSW5zdGFsbGluZyB3ZWJSIHNoaW1zYDtcbiAgICBhd2FpdCB3ZWJSLmV2YWxSVm9pZChgd2Vicjo6c2hpbV9pbnN0YWxsKClgKTtcblxuICAgIHN0YXR1c1RleHQudGV4dENvbnRlbnQgPSBgV2ViUiBlbnZpcm9ubWVudCBzZXR1cGA7XG4gICAgYXdhaXQgc2V0dXBSKHdlYlIsIGRhdGEpO1xuXG4gICAgc3RhdHVzVGV4dC5yZW1vdmUoKTtcbiAgICBpZiAoc3RhdHVzQ29udGFpbmVyLmNoaWxkcmVuLmxlbmd0aCA9PSAwKSB7XG4gICAgICBzdGF0dXNDb250YWluZXIucGFyZW50Tm9kZS5yZW1vdmUoKTtcbiAgICB9XG4gICAgcmV0dXJuIHdlYlI7XG4gIH0pKG5ldyBXZWJSKGRhdGEub3B0aW9ucykpO1xuXG4gIC8vIEtlZXAgdHJhY2sgb2YgaW5pdGlhbCBPSlMgYmxvY2sgcmVuZGVyXG4gIGNvbnN0IHJlbmRlcmVkT2pzID0ge307XG5cbiAgY29uc3QgcHJvY2VzcyA9IGFzeW5jIChjb250ZXh0LCBpbnB1dHMpID0+IHtcbiAgICBjb25zdCB3ZWJSID0gYXdhaXQgd2ViUlByb21pc2U7XG4gICAgY29uc3QgZXZhbHVhdG9yID0gbmV3IFdlYlJFdmFsdWF0b3Iod2ViUiwgY29udGV4dClcbiAgICBhd2FpdCBldmFsdWF0b3IucHJvY2VzcyhpbnB1dHMpO1xuICAgIHJldHVybiBldmFsdWF0b3IuY29udGFpbmVyO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBwcm9jZXNzLFxuICAgIHdlYlJQcm9taXNlLFxuICAgIHJlbmRlcmVkT2pzLFxuICB9O1xufVxuIn1dfQ== 634</script>
634 635<div id="exercise-loading-indicator" class="exercise-loading-indicator d-none d-flex align-items-center gap-2"> 636<div id="exercise-loading-status" class="d-flex gap-2"> 637 638</div> 639<div class="spinner-grow spinner-grow-sm"> 640 641</div> 642</div>
643<script type="vfs-file"> 644W10= 645</script>
645 646</section> 647</section> 648 649</main> <!-- /main -->
650<script type="ojs-module-contents"> 651eyJjb250ZW50cyI6W119 652</script>
vendor: 1 bytes, line 652
652
653<script type="module"> 654if (window.location.protocol === "file:") { alert("The OJS runtime does not work with file:// URLs. Please use a web server to view this document."); } 655window._ojs.paths.runtimeToDoc = "../.."; 656window._ojs.paths.runtimeToRoot = "../.."; 657window._ojs.paths.docToRoot = ""; 658window._ojs.selfContained = false; 659window._ojs.runtime.interpretFromScriptTags(); 660</script>
vendor: 1 bytes, line 660
660
661<script id="quarto-html-after-body" type="application/javascript"> 662window.document.addEventListener("DOMContentLoaded", function (event) { 663 const toggleBodyColorMode = (bsSheetEl) => { 664 const mode = bsSheetEl.getAttribute("data-mode"); 665 const bodyEl = window.document.querySelector("body"); 666 if (mode === "dark") { 667 bodyEl.classList.add("quarto-dark"); 668 bodyEl.classList.remove("quarto-light"); 669 } else { 670 bodyEl.classList.add("quarto-light"); 671 bodyEl.classList.remove("quarto-dark"); 672 } 673 } 674 const toggleBodyColorPrimary = () => { 675 const bsSheetEl = window.document.querySelector("link#quarto-bootstrap"); 676 if (bsSheetEl) { 677 toggleBodyColorMode(bsSheetEl); 678 } 679 } 680 toggleBodyColorPrimary(); 681 const icon = "î§"; 682 const anchorJS = new window.AnchorJS(); 683 anchorJS.options = { 684 placement: 'right', 685 icon: icon 686 }; 687 anchorJS.add('.anchored'); 688 const isCodeAnnotation = (el) => { 689 for (const clz of el.classList) { 690 if (clz.startsWith('code-annotation-')) { 691 return true; 692 } 693 } 694 return false; 695 } 696 const onCopySuccess = function(e) { 697 // button target 698 const button = e.trigger; 699 // don't keep focus 700 button.blur(); 701 // flash "checked" 702 button.classList.add('code-copy-button-checked'); 703 var currentTitle = button.getAttribute("title"); 704 button.setAttribute("title", "Copied!"); 705 let tooltip; 706 if (window.bootstrap) { 707 button.setAttribute("data-bs-toggle", "tooltip"); 708 button.setAttribute("data-bs-placement", "left"); 709 button.setAttribute("data-bs-title", "Copied!"); 710 tooltip = new bootstrap.Tooltip(button, 711 { trigger: "manual", 712 customClass: "code-copy-button-tooltip", 713 offset: [0, -8]}); 714 tooltip.show(); 715 } 716 setTimeout(function() { 717 if (tooltip) { 718 tooltip.hide(); 719 button.removeAttribute("data-bs-title"); 720 button.removeAttribute("data-bs-toggle"); 721 button.removeAttribute("data-bs-placement"); 722 } 723 button.setAttribute("title", currentTitle); 724 button.classList.remove('code-copy-button-checked'); 725 }, 1000); 726 // clear code selection 727 e.clearSelection(); 728 } 729 const getTextToCopy = function(trigger) { 730 const codeEl = trigger.previousElementSibling.cloneNode(true); 731 for (const childEl of codeEl.children) { 732 if (isCodeAnnotation(childEl)) { 733 childEl.remove(); 734 } 735 } 736 return codeEl.innerText; 737 } 738 const clipboard = new window.ClipboardJS('.code-copy-button:not([data-in-quarto-modal])', { 739 text: getTextToCopy 740 }); 741 clipboard.on('success', onCopySuccess); 742 if (window.document.getElementById('quarto-embedded-source-code-modal')) { 743 const clipboardModal = new window.ClipboardJS('.code-copy-button[data-in-quarto-modal]', { 744 text: getTextToCopy, 745 container: window.document.getElementById('quarto-embedded-source-code-modal') 746 }); 747 clipboardModal.on('success', onCopySuccess); 748 } 749 var localhostRegex = new RegExp(/^(?:http|https):\/\/localhost\:?[0-9]*\//); 750 var mailtoRegex = new RegExp(/^mailto:/); 751 var filterRegex = new RegExp("https:\/\/drb-workshops-portfolio\.netlify\.app"); 752 var isInternal = (href) => { 753 return filterRegex.test(href) || localhostRegex.test(href) || mailtoRegex.test(href); 754 } 755 // Inspect non-navigation links and adorn them if external 756 var links = window.document.querySelectorAll('a[href]:not(.nav-link):not(.navbar-brand):not(.toc-action):not(.sidebar-link):not(.sidebar-item-toggle):not(.pagination-link):not(.no-external):not([aria-hidden]):not(.dropdown-item):not(.quarto-navigation-tool):not(.about-link)'); 757 for (var i=0; i<links.length; i++) { 758 const link = links[i]; 759 if (!isInternal(link.href)) { 760 // undo the damage that might have been done by quarto-nav.js in the case of 761 // links that we want to consider external 762 if (link.dataset.originalHref !== undefined) { 763 link.href = link.dataset.originalHref; 764 } 765 } 766 } 767 function tippyHover(el, contentFn, onTriggerFn, onUntriggerFn) { 768 const config = { 769 allowHTML: true, 770 maxWidth: 500, 771 delay: 100,
772 arrow: false, 773 appendTo: function(el) { 774 return el.parentElement; 775 }, 776 interactive: true, 777 interactiveBorder: 10, 778 theme: 'quarto', 779 placement: 'bottom-start', 780 }; 781 if (contentFn) { 782 config.content = contentFn; 783 } 784 if (onTriggerFn) { 785 config.onTrigger = onTriggerFn; 786 } 787 if (onUntriggerFn) { 788 config.onUntrigger = onUntriggerFn; 789 } 790 window.tippy(el, config); 791 } 792 const noterefs = window.document.querySelectorAll('a[role="doc-noteref"]'); 793 for (var i=0; i<noterefs.length; i++) { 794 const ref = noterefs[i]; 795 tippyHover(ref, function() { 796 // use id or data attribute instead here 797 let href = ref.getAttribute('data-footnote-href') || ref.getAttribute('href'); 798 try { href = new URL(href).hash; } catch {} 799 const id = href.replace(/^#\/?/, ""); 800 const note = window.document.getElementById(id); 801 if (note) { 802 return note.innerHTML; 803 } else { 804 return ""; 805 } 806 }); 807 } 808 const xrefs = window.document.querySelectorAll('a.quarto-xref'); 809 const processXRef = (id, note) => { 810 // Strip column container classes 811 const stripColumnClz = (el) => { 812 el.classList.remove("page-full", "page-columns"); 813 if (el.children) { 814 for (const child of el.children) { 815 stripColumnClz(child); 816 } 817 } 818 } 819 stripColumnClz(note) 820 if (id === null || id.startsWith('sec-')) { 821 // Special case sections, only their first couple elements 822 const container = document.createElement("div"); 823 if (note.children && note.children.length > 2) { 824 container.appendChild(note.children[0].cloneNode(true)); 825 for (let i = 1; i < note.children.length; i++) { 826 const child = note.children[i]; 827 if (child.tagName === "P" && child.innerText === "") { 828 continue; 829 } else { 830 container.appendChild(child.cloneNode(true)); 831 break; 832 } 833 } 834 if (window.Quarto?.typesetMath) { 835 window.Quarto.typesetMath(container); 836 } 837 return container.innerHTML 838 } else { 839 if (window.Quarto?.typesetMath) { 840 window.Quarto.typesetMath(note); 841 } 842 return note.innerHTML; 843 } 844 } else { 845 // Remove any anchor links if they are present 846 const anchorLink = note.querySelector('a.anchorjs-link'); 847 if (anchorLink) { 848 anchorLink.remove(); 849 } 850 if (window.Quarto?.typesetMath) { 851 window.Quarto.typesetMath(note); 852 } 853 if (note.classList.contains("callout")) { 854 return note.outerHTML; 855 } else { 856 return note.innerHTML; 857 } 858 } 859 } 860 for (var i=0; i<xrefs.length; i++) { 861 const xref = xrefs[i]; 862 tippyHover(xref, undefined, function(instance) { 863 instance.disable(); 864 let url = xref.getAttribute('href'); 865 let hash = undefined; 866 if (url.startsWith('#')) { 867 hash = url; 868 } else { 869 try { hash = new URL(url).hash; } catch {} 870 } 871 if (hash) { 872 const id = hash.replace(/^#\/?/, ""); 873 const note = window.document.getElementById(id); 874 if (note !== null) { 875 try { 876 const html = processXRef(id, note.cloneNode(true)); 877 instance.setContent(html); 878 } finally { 879 instance.enable(); 880 instance.show(); 881 } 882 } else { 883 // See if we can fetch this 884 fetch(url.split('#')[0]) 885 .then(res => res.text()) 886 .then(html => { 887 const parser = new DOMParser(); 888 const htmlDoc = parser.parseFromString(html, "text/html"); 889 const note = htmlDoc.getElementById(id); 890 if (note !== null) { 891 const html = processXRef(id, note); 892 instance.setContent(html); 893 } 894 }).finally(() => { 895 instance.enable(); 896 instance.show(); 897 }); 898 } 899 } else { 900 // See if we can fetch a full url (with no hash to target)
901 // This is a special case and we should probably do some content thinning / targeting 902 fetch(url) 903 .then(res => res.text()) 904 .then(html => { 905 const parser = new DOMParser(); 906 const htmlDoc = parser.parseFromString(html, "text/html"); 907 const note = htmlDoc.querySelector('main.content'); 908 if (note !== null) { 909 // This should only happen for chapter cross references 910 // (since there is no id in the URL) 911 // remove the first header 912 if (note.children.length > 0 && note.children[0].tagName === "HEADER") { 913 note.children[0].remove(); 914 } 915 const html = processXRef(null, note); 916 instance.setContent(html); 917 } 918 }).finally(() => { 919 instance.enable(); 920 instance.show(); 921 }); 922 } 923 }, function(instance) { 924 }); 925 } 926 let selectedAnnoteEl; 927 const selectorForAnnotation = ( cell, annotation) => { 928 let cellAttr = 'data-code-cell="' + cell + '"'; 929 let lineAttr = 'data-code-annotation="' + annotation + '"'; 930 const selector = 'span[' + cellAttr + '][' + lineAttr + ']'; 931 return selector; 932 } 933 const selectCodeLines = (annoteEl) => { 934 const doc = window.document; 935 const targetCell = annoteEl.getAttribute("data-target-cell"); 936 const targetAnnotation = annoteEl.getAttribute("data-target-annotation"); 937 const annoteSpan = window.document.querySelector(selectorForAnnotation(targetCell, targetAnnotation)); 938 const lines = annoteSpan.getAttribute("data-code-lines").split(","); 939 const lineIds = lines.map((line) => { 940 return targetCell + "-" + line; 941 }) 942 let top = null; 943 let height = null; 944 let parent = null; 945 if (lineIds.length > 0) { 946 //compute the position of the single el (top and bottom and make a div) 947 const el = window.document.getElementById(lineIds[0]); 948 top = el.offsetTop; 949 height = el.offsetHeight; 950 parent = el.parentElement.parentElement; 951 if (lineIds.length > 1) { 952 const lastEl = window.document.getElementById(lineIds[lineIds.length - 1]); 953 const bottom = lastEl.offsetTop + lastEl.offsetHeight; 954 height = bottom - top; 955 } 956 if (top !== null && height !== null && parent !== null) { 957 // cook up a div (if necessary) and position it 958 let div = window.document.getElementById("code-annotation-line-highlight"); 959 if (div === null) { 960 div = window.document.createElement("div"); 961 div.setAttribute("id", "code-annotation-line-highlight"); 962 div.style.position = 'absolute'; 963 parent.appendChild(div); 964 } 965 div.style.top = top - 2 + "px"; 966 div.style.height = height + 4 + "px"; 967 div.style.left = 0; 968 let gutterDiv = window.document.getElementById("code-annotation-line-highlight-gutter"); 969 if (gutterDiv === null) { 970 gutterDiv = window.document.createElement("div"); 971 gutterDiv.setAttribute("id", "code-annotation-line-highlight-gutter"); 972 gutterDiv.style.position = 'absolute'; 973 const codeCell = window.document.getElementById(targetCell); 974 const gutter = codeCell.querySelector('.code-annotation-gutter'); 975 gutter.appendChild(gutterDiv); 976 } 977 gutterDiv.style.top = top - 2 + "px"; 978 gutterDiv.style.height = height + 4 + "px"; 979 } 980 selectedAnnoteEl = annoteEl; 981 } 982 }; 983 const unselectCodeLines = () => { 984 const elementsIds = ["code-annotation-line-highlight", "code-annotation-line-highlight-gutter"]; 985 elementsIds.forEach((elId) => { 986 const div = window.document.getElementById(elId); 987 if (div) { 988 div.remove(); 989 } 990 }); 991 selectedAnnoteEl = undefined; 992 }; 993 // Handle positioning of the toggle 994 window.addEventListener( 995 "resize", 996 throttle(() => { 997 elRect = undefined; 998 if (selectedAnnoteEl) { 999 selectCodeLines(selectedAnnoteEl); 1000 } 1001 }, 10) 1002 ); 1003 function throttle(fn, ms) { 1004 let throttle = false;
1005 let timer; 1006 return (...args) => { 1007 if(!throttle) { // first call gets through 1008 fn.apply(this, args); 1009 throttle = true; 1010 } else { // all the others get throttled 1011 if(timer) clearTimeout(timer); // cancel #2 1012 timer = setTimeout(() => { 1013 fn.apply(this, args); 1014 timer = throttle = false; 1015 }, ms); 1016 } 1017 }; 1018 } 1019 // Attach click handler to the DT 1020 const annoteDls = window.document.querySelectorAll('dt[data-target-cell]'); 1021 for (const annoteDlNode of annoteDls) { 1022 annoteDlNode.addEventListener('click', (event) => { 1023 const clickedEl = event.target; 1024 if (clickedEl !== selectedAnnoteEl) { 1025 unselectCodeLines(); 1026 const activeEl = window.document.querySelector('dt[data-target-cell].code-annotation-active'); 1027 if (activeEl) { 1028 activeEl.classList.remove('code-annotation-active'); 1029 } 1030 selectCodeLines(clickedEl); 1031 clickedEl.classList.add('code-annotation-active'); 1032 } else { 1033 // Unselect the line 1034 unselectCodeLines(); 1035 clickedEl.classList.remove('code-annotation-active'); 1036 } 1037 }); 1038 } 1039 const findCites = (el) => { 1040 const parentEl = el.parentElement; 1041 if (parentEl) { 1042 const cites = parentEl.dataset.cites; 1043 if (cites) { 1044 return { 1045 el, 1046 cites: cites.split(' ') 1047 }; 1048 } else { 1049 return findCites(el.parentElement) 1050 } 1051 } else { 1052 return undefined; 1053 } 1054 }; 1055 var bibliorefs = window.document.querySelectorAll('a[role="doc-biblioref"]'); 1056 for (var i=0; i<bibliorefs.length; i++) { 1057 const ref = bibliorefs[i]; 1058 const citeInfo = findCites(ref); 1059 if (citeInfo) { 1060 tippyHover(citeInfo.el, function() { 1061 var popup = window.document.createElement('div'); 1062 citeInfo.cites.forEach(function(cite) { 1063 var citeDiv = window.document.createElement('div'); 1064 citeDiv.classList.add('hanging-indent'); 1065 citeDiv.classList.add('csl-entry'); 1066 var biblioDiv = window.document.getElementById('ref-' + cite); 1067 if (biblioDiv) { 1068 citeDiv.innerHTML = biblioDiv.innerHTML; 1069 } 1070 popup.appendChild(citeDiv); 1071 }); 1072 return popup.innerHTML; 1073 }); 1074 } 1075 } 1076}); 1077</script>
1077 1078</div> <!-- /content --> 1079 1080 1081 1082 1083</body></html>
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.