PageSourceSearch

https://dnguyen-td.github.io/about.html

html dnguyen-td.github.io collected 2026-10-03 09:01:48 UTC 34,606 bytes, 805 lines download raw bytes

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.8.25">
6
7<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
8
9
10<title>Personal – Jun Nguyen</title>
11<style>
12code{white-space: pre-wrap;}
13span.smallcaps{font-variant: small-caps;}
14div.columns{display: flex; gap: min(4vw, 1.5em);}
15div.column{flex: auto; overflow-x: auto;}
16div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
17ul.task-list{list-style: none;}
18ul.task-list li input[type="checkbox"] {
19  width: 0.8em;
20  margin: 0 0.8em 0.2em -1em; /* quarto-specific, see https://github.com/quarto-dev/quarto-cli/issues/4556 */ 
21  vertical-align: middle;
22}
23</style>
24
25
26<script src="site_libs/quarto-nav/quarto-nav.js"></script>
vendor: 1 bytes, line 26
26
27<script src="site_libs/quarto-nav/headroom.min.js"></script>
vendor: 1 bytes, line 27
27
28<script src="site_libs/clipboard/clipboard.min.js"></script>
vendor: 1 bytes, line 28
28
29<script src="site_libs/quarto-search/autocomplete.umd.js"></script>
vendor: 1 bytes, line 29
29
30<script src="site_libs/quarto-search/fuse.min.js"></script>
vendor: 1 bytes, line 30
30
31<script src="site_libs/quarto-search/quarto-search.js"></script>
31
32<meta name="quarto:offset" content="./">
33<script src="site_libs/quarto-html/quarto.js" type="module"></script>
vendor: 1 bytes, line 33
33
34<script src="site_libs/quarto-html/tabsets/tabsets.js" type="module"></script>
vendor: 1 bytes, line 34
34
35<script src="site_libs/quarto-html/axe/axe-check.js" type="module"></script>
vendor: 1 bytes, line 35
35
36<script src="site_libs/quarto-html/popper.min.js"></script>
vendor: 1 bytes, line 36
36
37<script src="site_libs/quarto-html/tippy.umd.min.js"></script>
vendor: 1 bytes, line 37
37
38<script src="site_libs/quarto-html/anchor.min.js"></script>
38
39<link href="site_libs/quarto-html/tippy.css" rel="stylesheet">
40<link href="site_libs/quarto-html/quarto-syntax-highlighting-7b89279ff1a6dce999919e0e67d4d9ec.css" rel="stylesheet" class="quarto-color-scheme" id="quarto-text-highlighting-styles">
41<link href="site_libs/quarto-html/quarto-syntax-highlighting-dark-707d8167ce6003fca903bfe2be84ab7f.css" rel="stylesheet" class="quarto-color-scheme quarto-color-alternate" id="quarto-text-highlighting-styles">
42<link href="site_libs/quarto-html/quarto-syntax-highlighting-7b89279ff1a6dce999919e0e67d4d9ec.css" rel="stylesheet" class="quarto-color-scheme-extra" id="quarto-text-highlighting-styles">
43<script src="site_libs/bootstrap/bootstrap.min.js"></script>
43
44<link href="site_libs/bootstrap/bootstrap-icons.css" rel="stylesheet">
45<link href="site_libs/bootstrap/bootstrap-fc7bbb11cac6d7b69550556e10780547.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme" id="quarto-bootstrap" data-mode="light">
46<link href="site_libs/bootstrap/bootstrap-dark-c1a677d7157a83f627c616e58601fb42.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme quarto-color-alternate" id="quarto-bootstrap" data-mode="dark">
47<link href="site_libs/bootstrap/bootstrap-fc7bbb11cac6d7b69550556e10780547.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme-extra" id="quarto-bootstrap" data-mode="light">
48<script id="quarto-search-options" type="application/json">{
49  "location": "navbar",
50  "copy-button": false,
51  "collapse-after": 3,
52  "panel-placement": "end",
53  "type": "overlay",
54  "limit": 50,
55  "keyboard-shortcut": [
56    "f",
57    "/",
58    "s"
59  ],
60  "show-item-context": false,
61  "language": {
62    "search-no-results-text": "No results",
63    "search-matching-documents-text": "matching documents",
64    "search-copy-link-title": "Copy link to search",
65    "search-hide-matches-text": "Hide additional matches",
66    "search-more-match-text": "more match in this document",
67    "search-more-matches-text": "more matches in this document",
68    "search-clear-button-title": "Clear",
69    "search-text-placeholder": "",
70    "search-detached-cancel-button-title": "Cancel",
71    "search-submit-button-title": "Submit",
72    "search-label": "Search"
73  }
74}</script>
74
75<link href="site_libs/htmltools-fill-0.5.9/fill.css" rel="stylesheet">
76<script src="site_libs/htmlwidgets-1.6.4/htmlwidgets.js"></script>
vendor: 1 bytes, line 76
76
77<script src="site_libs/jquery-3.6.0/jquery-3.6.0.min.js"></script>
77
78<link href="site_libs/leaflet-1.3.1/leaflet.css" rel="stylesheet">
79<script src="site_libs/leaflet-1.3.1/leaflet.js"></script>
79
80<link href="site_libs/leafletfix-1.0.0/leafletfix.css" rel="stylesheet">
81<script src="site_libs/proj4-2.6.2/proj4.min.js"></script>
vendor: 1 bytes, line 81
81
82<script src="site_libs/Proj4Leaflet-1.0.1/proj4leaflet.js"></script>
82
83<link href="site_libs/rstudio_leaflet-1.3.1/rstudio_leaflet.css" rel="stylesheet">
84<script src="site_libs/leaflet-binding-2.2.3/leaflet.js"></script>
vendor: 1 bytes, line 84
84
85<script src="site_libs/leaflet-providers-3.0.0/leaflet-providers.js"></script>
vendor: 1 bytes, line 85
85
86<script src="site_libs/leaflet-providers-plugin-2.2.3/leaflet-providers-plugin.js"></script>
86
87<link href="site_libs/leaflet-awesomemarkers-2.0.3/leaflet.awesome-markers.css" rel="stylesheet">
88<script src="site_libs/leaflet-awesomemarkers-2.0.3/leaflet.awesome-markers.min.js"></script>
88
89<link href="site_libs/ionicons-2.0.1/ionicons.min.css" rel="stylesheet">
90
91
92<link rel="stylesheet" href="styles.css">
93</head>
94
95<body class="nav-fixed quarto-light">
95<script id="quarto-html-before-body" type="application/javascript">
96    const toggleBodyColorMode = (bsSheetEl) => {
97      const mode = bsSheetEl.getAttribute("data-mode");
98      const bodyEl = window.document.querySelector("body");
99      if (mode === "dark") {
100        bodyEl.classList.add("quarto-dark");
101        bodyEl.classList.remove("quarto-light");
102      } else {
103        bodyEl.classList.add("quarto-light");
104        bodyEl.classList.remove("quarto-dark");
105      }
106    }
107    const toggleBodyColorPrimary = () => {
108      const bsSheetEl = window.document.querySelector("link#quarto-bootstrap:not([rel=disabled-stylesheet])");
109      if (bsSheetEl) {
110        toggleBodyColorMode(bsSheetEl);
111      }
112    }
113    const setColorSchemeToggle = (alternate) => {
114      const toggles = window.document.querySelectorAll('.quarto-color-scheme-toggle');
115      for (let i=0; i < toggles.length; i++) {
116        const toggle = toggles[i];
117        if (toggle) {
118          if (alternate) {
119            toggle.classList.add("alternate");
120          } else {
121            toggle.classList.remove("alternate");
122          }
123        }
124      }
125    };
126    const toggleColorMode = (alternate) => {
127      // Switch the stylesheets
128      const primaryStylesheets = window.document.querySelectorAll('link.quarto-color-scheme:not(.quarto-color-alternate)');
129      const alternateStylesheets = window.document.querySelectorAll('link.quarto-color-scheme.quarto-color-alternate');
130      manageTransitions('#quarto-margin-sidebar .nav-link', false);
131      if (alternate) {
132        // note: dark is layered on light, we don't disable primary!
133        enableStylesheet(alternateStylesheets);
134        for (const sheetNode of alternateStylesheets) {
135          if (sheetNode.id === "quarto-bootstrap") {
136            toggleBodyColorMode(sheetNode);
137          }
138        }
139      } else {
140        disableStylesheet(alternateStylesheets);
141        enableStylesheet(primaryStylesheets)
142        toggleBodyColorPrimary();
143      }
144      manageTransitions('#quarto-margin-sidebar .nav-link', true);
145      // Switch the toggles
146      setColorSchemeToggle(alternate)
147      // Hack to workaround the fact that safari doesn't
148      // properly recolor the scrollbar when toggling (#1455)
149      if (navigator.userAgent.indexOf('Safari') > 0 && navigator.userAgent.indexOf('Chrome') == -1) {
150        manageTransitions("body", false);
151        window.scrollTo(0, 1);
152        setTimeout(() => {
153          window.scrollTo(0, 0);
154          manageTransitions("body", true);
155        }, 40);
156      }
157    }
158    const disableStylesheet = (stylesheets) => {
159      for (let i=0; i < stylesheets.length; i++) {
160        const stylesheet = stylesheets[i];
161        stylesheet.rel = 'disabled-stylesheet';
162      }
163    }
164    const enableStylesheet = (stylesheets) => {
165      for (let i=0; i < stylesheets.length; i++) {
166        const stylesheet = stylesheets[i];
167        if(stylesheet.rel !== 'stylesheet') { // for Chrome, which will still FOUC without this check
168          stylesheet.rel = 'stylesheet';
169        }
170      }
171    }
172    const manageTransitions = (selector, allowTransitions) => {
173      const els = window.document.querySelectorAll(selector);
174      for (let i=0; i < els.length; i++) {
175        const el = els[i];
176        if (allowTransitions) {
177          el.classList.remove('notransition');
178        } else {
179          el.classList.add('notransition');
180        }
181      }
182    }
183    const isFileUrl = () => {
184      return window.location.protocol === 'file:';
185    }
186    const hasAlternateSentinel = () => {
187      let styleSentinel = getColorSchemeSentinel();
188      if (styleSentinel !== null) {
189        return styleSentinel === "alternate";
190      } else {
191        return false;
192      }
193    }
194    const setStyleSentinel = (alternate) => {
195      const value = alternate ? "alternate" : "default";
196      if (!isFileUrl()) {
197        window.localStorage.setItem("quarto-color-scheme", value);
198      } else {
199        localAlternateSentinel = value;
200      }
201    }
202    const getColorSchemeSentinel = () => {
203      if (!isFileUrl()) {
204        const storageValue = window.localStorage.getItem("quarto-color-scheme");
205        return storageValue != null ? storageValue : localAlternateSentinel;
206      } else {
207        return localAlternateSentinel;
208      }
209    }
210    const toggleGiscusIfUsed = (isAlternate, darkModeDefault) => {
211      const baseTheme = document.querySelector('#giscus-base-theme')?.value ?? 'light';
212      const alternateTheme = document.querySelector('#giscus-alt-theme')?.value ?? 'dark';
213      let newTheme = '';
214      if(authorPrefersDark) {
215        newTheme = isAlternate ? baseTheme : alternateTheme;
216      } else {
217        newTheme = isAlternate ? alternateTheme : baseTheme;
218      }
219      const changeGiscusTheme = () => {
220        // From: https://github.com/giscus/giscus/issues/336
221        const sendMessage = (message) => {
222          const iframe = document.querySelector('iframe.giscus-frame');
223          if (!iframe) return;
224          iframe.contentWindow.postMessage({ giscus: message }, 'https://giscus.app');
225        }
226        sendMessage({
227          setConfig: {
228            theme: newTheme
229          }
230        });
231      }
232      const isGiscussLoaded = window.document.querySelector('iframe.giscus-frame') !== null;
233      if (isGiscussLoaded) {
234        changeGiscusTheme();
235      }
236    };
237    const authorPrefersDark = false;
238    const darkModeDefault = authorPrefersDark;
239      document.querySelector('link#quarto-text-highlighting-styles.quarto-color-scheme-extra').rel = 'disabled-stylesheet';
240      document.querySelector('link#quarto-bootstrap.quarto-color-scheme-extra').rel = 'disabled-stylesheet';
241    let localAlternateSentinel = darkModeDefault ? 'alternate' : 'default';
242    // Dark / light mode switch
243    window.quartoToggleColorScheme = () => {
244      // Read the current dark / light value
245      let toAlternate = !hasAlternateSentinel();
246      toggleColorMode(toAlternate);
247      setStyleSentinel(toAlternate);
248      toggleGiscusIfUsed(toAlternate, darkModeDefault);
249      window.dispatchEvent(new Event('resize'));
250    };
251    // Switch to dark mode if need be
252    if (hasAlternateSentinel()) {
253      toggleColorMode(true);
254    } else {
255      toggleColorMode(false);
256    }
257  </script>
257
258
259<div id="quarto-search-results"></div>
260  <header id="quarto-header" class="headroom fixed-top">
261    <nav class="navbar navbar-expand-lg " data-bs-theme="dark">
262      <div class="navbar-container container-fluid">
263      <div class="navbar-brand-container mx-auto">
264    <a href="./index.html" class="navbar-brand navbar-brand-logo">
265    </a>
266    <a class="navbar-brand" href="./index.html">
267    <span class="navbar-title">Jun Nguyen</span>
268    </a>
269  </div>
270            <div id="quarto-search" class="" title="Search"></div>
271          <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(); }">
272  <span class="navbar-toggler-icon"></span>
273</button>
274          <div class="collapse navbar-collapse" id="navbarCollapse">
275            <ul class="navbar-nav navbar-nav-scroll ms-auto">
276  <li class="nav-item">
277    <a class="nav-link" href="./index.html"> 
278<span class="menu-text">Home</span></a>
279  </li>  
280  <li class="nav-item">
281    <a class="nav-link" href="./research.html"> 
282<span class="menu-text">Research</span></a>
283  </li>  
284  <li class="nav-item">
285    <a class="nav-link" href="./teaching.html"> 
286<span class="menu-text">Teaching</span></a>
287  </li>  
288  <li class="nav-item">
289    <a class="nav-link active" href="./about.html" aria-current="page"> 
290<span class="menu-text">Personal</span></a>
291  </li>  
292</ul>
293          </div> <!-- /navcollapse -->
294            <div class="quarto-navbar-tools">
295  <a href="" class="quarto-color-scheme-toggle quarto-navigation-tool  px-1" onclick="window.quartoToggleColorScheme(); return false;" title="Toggle dark mode"><i class="bi"></i></a>
296</div>
297      </div> <!-- /container-fluid -->
298    </nav>
299</header>
300<!-- content -->
301<div id="quarto-content" class="quarto-container page-columns page-rows-contents page-layout-full page-navbar">
302<!-- sidebar -->
303<!-- margin-sidebar -->
304    <div id="quarto-margin-sidebar" class="sidebar margin-sidebar zindex-bottom">
305        
306    </div>
307<!-- main -->
308<main class="content column-page" id="quarto-document-content">
309
310
311<header id="title-block-header" class="quarto-title-block default">
312<div class="quarto-title">
313<h1 class="title">Personal</h1>
314</div>
315
316
317
318<div class="quarto-title-meta column-page">
319
320    
321  
322    
323  </div>
324  
325
326
327</header>
328
329
330<div class="tabset-margin-container"></div><div class="panel-tabset">
331<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" href="">Travel</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" href="">Hobbies</a></li></ul>
332<div class="tab-content">
333<div id="tabset-1-1" class="tab-pane active" role="tabpanel" aria-labelledby="tabset-1-1-tab">
334<p>I’d love to travel and explore the diverse local cultures and cuisines around the world. Being in academia not only enables me to journey across the globe but also give me a chance to meet new people from various countries and cultural backgrounds. Here is an interactive map showing the footprints of my journeys thus far!</p>
335<div class="cell">
336<div class="cell-output-display">
337<div class="leaflet html-widget html-fill-item" id="htmlwidget-574e7852d9eb14bd129d" style="width:100%;height:464px;"></div>
338<script type="application/json" data-for="htmlwidget-574e7852d9eb14bd129d">{"x":{"options":{"crs":{"crsClass":"L.CRS.EPSG3857","code":null,"proj4def":null,"projectedBounds":null,"options":{}}},"calls":[{"method":"addProviderTiles","args":["Esri.WorldPhysical",null,null,{"errorTileUrl":"","noWrap":false,"detectRetina":false}]},{"method":"addProviderTiles","args":["CartoDB.PositronOnlyLabels",null,null,{"errorTileUrl":"","noWrap":false,"detectRetina":false}]},{"method":"addAwesomeMarkers","args":[[60.1695,48.1351,52.3676,38.7223,41.3851,41.1167,43.4623,38.3452,42.8782,42.3372,39.9864,37.7749,37.3382,30.2672,29.6516,10.8231,21.0285,16.0544,16.4637,15.8801,20.8449,21.0069,12.2388,10.2899,10.3459,10.933,51.4545,50.0755,29.4241,21.3069,35.2271,41.9028,55.6761],[24.9354,11.582,4.9041,-9.1393,2.1734,1.2494,-3.8104,-0.481,-8.5448,-7.8645,-0.0513,-122.4194,-121.8863,-97.7431,-82.3248,106.6297,105.8542,108.2022,107.5909,108.338,106.6881,107.2925,109.1966,103.984,107.0842,108.1,2.5879,14.4378,-98.4936,-157.8583,-80.84310000000001,12.4964,12.5683],{"icon":"ios-close","markerColor":"green","iconColor":"black","spin":false,"squareMarker":false,"iconRotate":0,"font":"monospace","prefix":"ion"},null,null,{"interactive":true,"draggable":false,"keyboard":true,"title":"","alt":"","zIndexOffset":0,"opacity":1,"riseOnHover":false,"riseOffset":250},null,null,null,null,["Helsinki","Munich","Amsterdam","Lisbon","Barcelona","Tarragona","Santander","Alicante","Santiago","Ourense","Castellón","San Francisco","San Jose","Austin","Gaineville","Ho Chi Minh","Ha Noi","Da Nang","Hue","Hoi An","Hai Phong","Quang Ninh","Nha Trang","Phu Quoc","Vung Tau","Binh Thuan","Bristol","Prague","San Antonio","Honolulu","Charlotte","Rome","Copenhagen"],{"interactive":false,"permanent":false,"direction":"auto","opacity":1,"offset":[0,0],"textsize":"10px","textOnly":false,"className":"","sticky":true},null]}],"limits":{"lat":[10.2899,60.1695],"lng":[-157.8583,109.1966]}},"evals":[],"jsHooks":[]}</script>
338
339</div>
340</div>
341</div>
342<div id="tabset-1-2" class="tab-pane" role="tabpanel" aria-labelledby="tabset-1-2-tab">
343<p>Can you perceive the aroma of food wafting from these photos? I enjoy cooking and having culinary experiences at various restaurants everywhere I travel with my closed friends. Another hobby I love is creating art in Procreate and watching time-lapse videos to see the process of how things are made. I also make time for Zumba fitness and swimming to maintain a healthy work-life balance.</p>
344<div class="quarto-layout-panel" data-layout-ncol="2">
345<div class="quarto-layout-row">
346<div class="quarto-layout-cell" style="flex-basis: 50.0%;justify-content: center;">
347<p><img src="image/DSC00188.JPG" class="img-fluid"></p>
348</div>
349<div class="quarto-layout-cell" style="flex-basis: 50.0%;justify-content: center;">
350<p><img src="image/DSC08126.JPG" class="img-fluid"></p>
351</div>
352</div>
353<div class="quarto-layout-row">
354<div class="quarto-layout-cell" style="flex-basis: 50.0%;justify-content: center;">
355<p><img src="image/IMG-2239.jpg" class="img-fluid"></p>
356</div>
357<div class="quarto-layout-cell" style="flex-basis: 50.0%;justify-content: center;">
358<p><img src="image/IMG-3064.JPG" class="img-fluid"></p>
359</div>
360</div>
361<div class="quarto-layout-row">
362<div class="quarto-layout-cell" style="flex-basis: 50.0%;justify-content: center;">
363<p><img src="image/DSC08130.JPG" class="img-fluid"></p>
364</div>
365</div>
366</div>
367</div>
368</div>
369</div>
370
371
372
373</main> <!-- /main -->
374<script id="quarto-html-after-body" type="application/javascript">
375  window.document.addEventListener("DOMContentLoaded", function (event) {
376    // Ensure there is a toggle, if there isn't float one in the top right
377    if (window.document.querySelector('.quarto-color-scheme-toggle') === null) {
378      const a = window.document.createElement('a');
379      a.classList.add('top-right');
380      a.classList.add('quarto-color-scheme-toggle');
381      a.href = "";
382      a.onclick = function() { try { window.quartoToggleColorScheme(); } catch {} return false; };
383      const i = window.document.createElement("i");
384      i.classList.add('bi');
385      a.appendChild(i);
386      window.document.body.appendChild(a);
387    }
388    setColorSchemeToggle(hasAlternateSentinel())
389    const icon = "";
390    const anchorJS = new window.AnchorJS();
391    anchorJS.options = {
392      placement: 'right',
393      icon: icon
394    };
395    anchorJS.add('.anchored');
396    const isCodeAnnotation = (el) => {
397      for (const clz of el.classList) {
398        if (clz.startsWith('code-annotation-')) {                     
399          return true;
400        }
401      }
402      return false;
403    }
404    const onCopySuccess = function(e) {
405      // button target
406      const button = e.trigger;
407      // don't keep focus
408      button.blur();
409      // flash "checked"
410      button.classList.add('code-copy-button-checked');
411      var currentTitle = button.getAttribute("title");
412      button.setAttribute("title", "Copied!");
413      let tooltip;
414      if (window.bootstrap) {
415        button.setAttribute("data-bs-toggle", "tooltip");
416        button.setAttribute("data-bs-placement", "left");
417        button.setAttribute("data-bs-title", "Copied!");
418        tooltip = new bootstrap.Tooltip(button, 
419          { trigger: "manual", 
420            customClass: "code-copy-button-tooltip",
421            offset: [0, -8]});
422        tooltip.show();    
423      }
424      setTimeout(function() {
425        if (tooltip) {
426          tooltip.hide();
427          button.removeAttribute("data-bs-title");
428          button.removeAttribute("data-bs-toggle");
429          button.removeAttribute("data-bs-placement");
430        }
431        button.setAttribute("title", currentTitle);
432        button.classList.remove('code-copy-button-checked');
433      }, 1000);
434      // clear code selection
435      e.clearSelection();
436    }
437    const getTextToCopy = function(trigger) {
438      const outerScaffold = trigger.parentElement.cloneNode(true);
439      const codeEl = outerScaffold.querySelector('code');
440      for (const childEl of codeEl.children) {
441        if (isCodeAnnotation(childEl)) {
442          childEl.remove();
443        }
444      }
445      return codeEl.innerText;
446    }
447    const clipboard = new window.ClipboardJS('.code-copy-button:not([data-in-quarto-modal])', {
448      text: getTextToCopy
449    });
450    clipboard.on('success', onCopySuccess);
451    if (window.document.getElementById('quarto-embedded-source-code-modal')) {
452      const clipboardModal = new window.ClipboardJS('.code-copy-button[data-in-quarto-modal]', {
453        text: getTextToCopy,
454        container: window.document.getElementById('quarto-embedded-source-code-modal')
455      });
456      clipboardModal.on('success', onCopySuccess);
457    }
458      var localhostRegex = new RegExp(/^(?:http|https):\/\/localhost\:?[0-9]*\//);
459      var mailtoRegex = new RegExp(/^mailto:/);
460        var filterRegex = new RegExp('/' + window.location.host + '/');
461      var isInternal = (href) => {
462          return filterRegex.test(href) || localhostRegex.test(href) || mailtoRegex.test(href);
463      }
464      // Inspect non-navigation links and adorn them if external
465     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)');
466      for (var i=0; i<links.length; i++) {
467        const link = links[i];
468        if (!isInternal(link.href)) {
469          // undo the damage that might have been done by quarto-nav.js in the case of
470          // links that we want to consider external
471          if (link.dataset.originalHref !== undefined) {
472            link.href = link.dataset.originalHref;
473          }
474        }
475      }
476    function tippyHover(el, contentFn, onTriggerFn, onUntriggerFn) {
477      const config = {
478        allowHTML: true,
479        maxWidth: 500,
480        delay: 100,
481        arrow: false,
482        appendTo: function(el) {
483            return el.parentElement;
484        },
485        interactive: true,
486        interactiveBorder: 10,
487        theme: 'quarto',
488        placement: 'bottom-start',
489      };
490      if (contentFn) {
491        config.content = contentFn;
492      }
493      if (onTriggerFn) {
494        config.onTrigger = onTriggerFn;
495      }
496      if (onUntriggerFn) {
497        config.onUntrigger = onUntriggerFn;
498      }
499      window.tippy(el, config); 
500    }
501    const noterefs = window.document.querySelectorAll('a[role="doc-noteref"]');
502    for (var i=0; i<noterefs.length; i++) {
503      const ref = noterefs[i];
504      tippyHover(ref, function() {
505        // use id or data attribute instead here
506        let href = ref.getAttribute('data-footnote-href') || ref.getAttribute('href');
507        try { href = new URL(href).hash; } catch {}
508        const id = href.replace(/^#\/?/, "");
509        const note = window.document.getElementById(id);
510        if (note) {
511          return note.innerHTML;
512        } else {
513          return "";
514        }
515      });
516    }
517    const xrefs = window.document.querySelectorAll('a.quarto-xref');
518    const processXRef = (id, note) => {
519      // Strip column container classes
520      const stripColumnClz = (el) => {
521        el.classList.remove("page-full", "page-columns");
522        if (el.children) {
523          for (const child of el.children) {
524            stripColumnClz(child);
525          }
526        }
527      }
528      stripColumnClz(note)
529      if (id === null || id.startsWith('sec-')) {
530        // Special case sections, only their first couple elements
531        const container = document.createElement("div");
532        if (note.children && note.children.length > 2) {
533          container.appendChild(note.children[0].cloneNode(true));
534          for (let i = 1; i < note.children.length; i++) {
535            const child = note.children[i];
536            if (child.tagName === "P" && child.innerText === "") {
537              continue;
538            } else {
539              container.appendChild(child.cloneNode(true));
540              break;
541            }
542          }
543          if (window.Quarto?.typesetMath) {
544            window.Quarto.typesetMath(container);
545          }
546          return container.innerHTML
547        } else {
548          if (window.Quarto?.typesetMath) {
549            window.Quarto.typesetMath(note);
550          }
551          return note.innerHTML;
552        }
553      } else {
554        // Remove any anchor links if they are present
555        const anchorLink = note.querySelector('a.anchorjs-link');
556        if (anchorLink) {
557          anchorLink.remove();
558        }
559        if (window.Quarto?.typesetMath) {
560          window.Quarto.typesetMath(note);
561        }
562        if (note.classList.contains("callout")) {
563          return note.outerHTML;
564        } else {
565          return note.innerHTML;
566        }
567      }
568    }
569    for (var i=0; i<xrefs.length; i++) {
570      const xref = xrefs[i];
571      tippyHover(xref, undefined, function(instance) {
572        instance.disable();
573        let url = xref.getAttribute('href');
574        let hash = undefined; 
575        if (url.startsWith('#')) {
576          hash = url;
577        } else {
578          try { hash = new URL(url).hash; } catch {}
579        }
580        if (hash) {
581          const id = hash.replace(/^#\/?/, "");
582          const note = window.document.getElementById(id);
583          if (note !== null) {
584            try {
585              const html = processXRef(id, note.cloneNode(true));
586              instance.setContent(html);
587            } finally {
588              instance.enable();
589              instance.show();
590            }
591          } else {
592            // See if we can fetch this
593            fetch(url.split('#')[0])
594            .then(res => res.text())
595            .then(html => {
596              const parser = new DOMParser();
597              const htmlDoc = parser.parseFromString(html, "text/html");
598              const note = htmlDoc.getElementById(id);
599              if (note !== null) {
600                const html = processXRef(id, note);
601                instance.setContent(html);
602              } 
603            }).finally(() => {
604              instance.enable();
605              instance.show();
606            });
607          }
608        } else {
609          // See if we can fetch a full url (with no hash to target)
610          // This is a special case and we should probably do some content thinning / targeting
611          fetch(url)
612          .then(res => res.text())
613          .then(html => {
614            const parser = new DOMParser();
615            const htmlDoc = parser.parseFromString(html, "text/html");
616            const note = htmlDoc.querySelector('main.content');
617            if (note !== null) {
618              // This should only happen for chapter cross references
619              // (since there is no id in the URL)
620              // remove the first header
621              if (note.children.length > 0 && note.children[0].tagName === "HEADER") {
622                note.children[0].remove();
623              }
624              const html = processXRef(null, note);
625              instance.setContent(html);
626            } 
627          }).finally(() => {
628            instance.enable();
629            instance.show();
630          });
631        }
632      }, function(instance) {
633      });
634    }
635        let selectedAnnoteEl;
636        const selectorForAnnotation = ( cell, annotation) => {
637          let cellAttr = 'data-code-cell="' + cell + '"';
638          let lineAttr = 'data-code-annotation="' +  annotation + '"';
639          const selector = 'span[' + cellAttr + '][' + lineAttr + ']';
640          return selector;
641        }
642        const selectCodeLines = (annoteEl) => {
643          const doc = window.document;
644          const targetCell = annoteEl.getAttribute("data-target-cell");
645          const targetAnnotation = annoteEl.getAttribute("data-target-annotation");
646          const annoteSpan = window.document.querySelector(selectorForAnnotation(targetCell, targetAnnotation));
647          const lines = annoteSpan.getAttribute("data-code-lines").split(",");
648          const lineIds = lines.map((line) => {
649            return targetCell + "-" + line;
650          })
651          let top = null;
652          let height = null;
653          let parent = null;
654          if (lineIds.length > 0) {
655              //compute the position of the single el (top and bottom and make a div)
656              const el = window.document.getElementById(lineIds[0]);
657              top = el.offsetTop;
658              height = el.offsetHeight;
659              parent = el.parentElement.parentElement;
660            if (lineIds.length > 1) {
661              const lastEl = window.document.getElementById(lineIds[lineIds.length - 1]);
662              const bottom = lastEl.offsetTop + lastEl.offsetHeight;
663              height = bottom - top;
664            }
665            if (top !== null && height !== null && parent !== null) {
666              // cook up a div (if necessary) and position it 
667              let div = window.document.getElementById("code-annotation-line-highlight");
668              if (div === null) {
669                div = window.document.createElement("div");
670                div.setAttribute("id", "code-annotation-line-highlight");
671                div.style.position = 'absolute';
672                parent.appendChild(div);
673              }
674              div.style.top = top - 2 + "px";
675              div.style.height = height + 4 + "px";
676              div.style.left = 0;
677              let gutterDiv = window.document.getElementById("code-annotation-line-highlight-gutter");
678              if (gutterDiv === null) {
679                gutterDiv = window.document.createElement("div");
680                gutterDiv.setAttribute("id", "code-annotation-line-highlight-gutter");
681                gutterDiv.style.position = 'absolute';
682                const codeCell = window.document.getElementById(targetCell);
683                const gutter = codeCell.querySelector('.code-annotation-gutter');
684                gutter.appendChild(gutterDiv);
685              }
686              gutterDiv.style.top = top - 2 + "px";
687              gutterDiv.style.height = height + 4 + "px";
688            }
689            selectedAnnoteEl = annoteEl;
690          }
691        };
692        const unselectCodeLines = () => {
693          const elementsIds = ["code-annotation-line-highlight", "code-annotation-line-highlight-gutter"];
694          elementsIds.forEach((elId) => {
695            const div = window.document.getElementById(elId);
696            if (div) {
697              div.remove();
698            }
699          });
700          selectedAnnoteEl = undefined;
701        };
702          // Handle positioning of the toggle
703      window.addEventListener(
704        "resize",
705        throttle(() => {
706          elRect = undefined;
707          if (selectedAnnoteEl) {
708            selectCodeLines(selectedAnnoteEl);
709          }
710        }, 10)
711      );
712      function throttle(fn, ms) {
713      let throttle = false;
714      let timer;
715        return (...args) => {
716          if(!throttle) { // first call gets through
717              fn.apply(this, args);
718              throttle = true;
719          } else { // all the others get throttled
720              if(timer) clearTimeout(timer); // cancel #2
721              timer = setTimeout(() => {
722                fn.apply(this, args);
723                timer = throttle = false;
724              }, ms);
725          }
726        };
727      }
728        // Attach click handler to the DT
729        const annoteDls = window.document.querySelectorAll('dt[data-target-cell]');
730        for (const annoteDlNode of annoteDls) {
731          annoteDlNode.addEventListener('click', (event) => {
732            const clickedEl = event.target;
733            if (clickedEl !== selectedAnnoteEl) {
734              unselectCodeLines();
735              const activeEl = window.document.querySelector('dt[data-target-cell].code-annotation-active');
736              if (activeEl) {
737                activeEl.classList.remove('code-annotation-active');
738              }
739              selectCodeLines(clickedEl);
740              clickedEl.classList.add('code-annotation-active');
741            } else {
742              // Unselect the line
743              unselectCodeLines();
744              clickedEl.classList.remove('code-annotation-active');
745            }
746          });
747        }
748    const findCites = (el) => {
749      const parentEl = el.parentElement;
750      if (parentEl) {
751        const cites = parentEl.dataset.cites;
752        if (cites) {
753          return {
754            el,
755            cites: cites.split(' ')
756          };
757        } else {
758          return findCites(el.parentElement)
759        }
760      } else {
761        return undefined;
762      }
763    };
764    var bibliorefs = window.document.querySelectorAll('a[role="doc-biblioref"]');
765    for (var i=0; i<bibliorefs.length; i++) {
766      const ref = bibliorefs[i];
767      const citeInfo = findCites(ref);
768      if (citeInfo) {
769        tippyHover(citeInfo.el, function() {
770          var popup = window.document.createElement('div');
771          citeInfo.cites.forEach(function(cite) {
772            var citeDiv = window.document.createElement('div');
773            citeDiv.classList.add('hanging-indent');
774            citeDiv.classList.add('csl-entry');
775            var biblioDiv = window.document.getElementById('ref-' + cite);
776            if (biblioDiv) {
777              citeDiv.innerHTML = biblioDiv.innerHTML;
778            }
779            popup.appendChild(citeDiv);
780          });
781          return popup.innerHTML;
782        });
783      }
784    }
785  });
786  </script>
786
787</div> <!-- /content -->
788<footer class="footer">
789  <div class="nav-footer">
790    <div class="nav-footer-left">
791<p>Copyright 2023, Jun Nguyen</p>
792</div>   
793    <div class="nav-footer-center">
794      &nbsp;
795    </div>
796    <div class="nav-footer-right">
797      &nbsp;
798    </div>
799  </div>
800</footer>
801
802
803
804
805</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.