<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Armando C. Santisbon</title>
    <description>The latest articles on DEV Community by Armando C. Santisbon (@santisbon).</description>
    <link>https://dev.to/santisbon</link>
    <image>
      <url>https://res.cloudinary.com/practicaldev/image/fetch/s--WIi5JtOj--/c_fill,f_auto,fl_progressive,h_90,q_auto,w_90/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/1014326/163a7759-cb0a-4190-9069-ea8b0b0c5ec2.png</url>
      <title>DEV Community: Armando C. Santisbon</title>
      <link>https://dev.to/santisbon</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/santisbon"/>
    <language>en</language>
    <item>
      <title>Cloud native homelab, Part 2: Kubernetes + Ceph</title>
      <dc:creator>Armando C. Santisbon</dc:creator>
      <pubDate>Wed, 25 Oct 2023 01:57:08 +0000</pubDate>
      <link>https://dev.to/santisbon/cloud-native-homelab-part-2-kubernetes-cluster-453b</link>
      <guid>https://dev.to/santisbon/cloud-native-homelab-part-2-kubernetes-cluster-453b</guid>
      <description>&lt;p&gt;In Part 1 of this series we went over the hardware you'll need to get started on your cloud native homelab, where hopefully I've convinced you to choose Raspberry Pi boards and a cooling solution.&lt;/p&gt;

&lt;p&gt;For the best performance we'll use SSDs for the boot partition as well as the storage cluster. This will give us a huge advantage over microSD cards in both speed and reliability.&lt;/p&gt;

&lt;p&gt;In this example we'll use: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;2 Raspberry Pi 4B boards. I used an 8GB model for the control plane node and a 4GB model for a worker node.&lt;/li&gt;
&lt;li&gt;2 SATA SSDs with USB adapters (ASMedia chipset).&lt;/li&gt;
&lt;li&gt;1 microSD card to flash the USB bootloader to the Pis.&lt;/li&gt;
&lt;li&gt;Cluster case with fans.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's what my homelab looks like. It also has a Raspberry Pi 2 that serves as a retro gaming console but for this post we'll be focusing on the Kubernetes cluster.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--A_N3D8Zm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ydobfr5o1ts4o7exr1p0.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A_N3D8Zm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ydobfr5o1ts4o7exr1p0.jpeg" alt="Image description" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZEsnlotA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pktuf0ksc70xp2jgqkt2.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZEsnlotA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pktuf0ksc70xp2jgqkt2.jpeg" alt="Image description" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our cluster will have a lightweight distribution of both Kubernetes and Ceph, a unified storage service with block, file, and object interfaces.&lt;/p&gt;

&lt;p&gt;I've documented how to set up a Raspberry Pi and SSD in an automated, cloud native way in my notes here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://santisbon.github.io/reference/rpi/"&gt;Raspberry Pi&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Follow those instructions to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set up your Pi to &lt;strong&gt;boot from SSD&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Get the OS image&lt;/strong&gt; (Ubuntu for Raspberry Pi).&lt;/li&gt;
&lt;li&gt;Following the instructions on the &lt;strong&gt;setup&lt;/strong&gt; section, &lt;strong&gt;flash the image&lt;/strong&gt; on the SSD.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verify&lt;/strong&gt; that the automatic setup worked correctly. Do not continue without first fixing any errors found.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Repeat the process for each Raspberry Pi you have. Once you're done you'll have your Pi devices with MicroK8s installed, all software updated, and relevant kernel modules added.&lt;/p&gt;

&lt;p&gt;Now it's time to configure our MicroK8s and MicroCeph cluster. I documented the process in my notes here: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://santisbon.github.io/reference/microk8s/"&gt;MicroK8s&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Follow those instructions to set up:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;MicroCeph cluster.&lt;/li&gt;
&lt;li&gt;MicroK8s cluster.&lt;/li&gt;
&lt;li&gt;Connect MicroK8s to the external MicroCeph cluster.&lt;/li&gt;
&lt;li&gt;(Optional) MicroK8s dashboard.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;🎉 You're done! 🍾&lt;/p&gt;

&lt;p&gt;Here's what a Ceph cluster looks like with 2 nodes and 3 (virtual) disks on each node/SSD:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mHMsSF-V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/86xao3ftbytir2myg61b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mHMsSF-V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/86xao3ftbytir2myg61b.png" alt="Cluster status" width="800" height="1033"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Come back soon for part 3 where we'll deploy some workloads to our cluster.&lt;/p&gt;

</description>
      <category>raspberrypi</category>
      <category>homelab</category>
      <category>kubernetes</category>
      <category>ceph</category>
    </item>
    <item>
      <title>Finding the right macOS `defaults` command</title>
      <dc:creator>Armando C. Santisbon</dc:creator>
      <pubDate>Sun, 01 Oct 2023 01:40:25 +0000</pubDate>
      <link>https://dev.to/santisbon/finding-the-right-macos-defaults-command-4186</link>
      <guid>https://dev.to/santisbon/finding-the-right-macos-defaults-command-4186</guid>
      <description>&lt;p&gt;&lt;a href="https://santisbon.github.io/reference/automated/"&gt;Automating the setup of a clean macOS install&lt;/a&gt; is a lot easier when you know which keys to edit via the &lt;code&gt;defaults&lt;/code&gt; command. Since there's no official listing of all the keys, there are places online that give you the most commonly used ones and try to stay up to date with the names of the keys in the latest release of macOS, with varying degrees of success. The best way is to grab the correct names directly from your Mac. &lt;/p&gt;

&lt;p&gt;Note: First, make sure your terminal has &lt;em&gt;Full Disk Access&lt;/em&gt; in &lt;em&gt;System Settings &amp;gt; Privacy and Security&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The format to edit your macOS preferences is&lt;br&gt;
&lt;code&gt;defaults write $DOMAIN $KEY -$TYPE $VALUE&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And you can list all the domains with&lt;br&gt;
&lt;code&gt;defaults domains | tr ', ' '\n'&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You can figure out the correct domain and key names by comparing the output of &lt;code&gt;defaults read&lt;/code&gt; &lt;em&gt;before&lt;/em&gt; and &lt;em&gt;after&lt;/em&gt; manually changing a setting in the UI. You can also specify a domain to narrow down the output but it's not required so don't worry if you're not sure which domain is affected by the setting you're interested in. Remember to kill any affected apps to apply the changes.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;defaults &lt;span class="nb"&gt;read &lt;/span&gt;com.apple.finder &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; before.txt
&lt;span class="c"&gt;# Change Finder Settings in the UI&lt;/span&gt;
&lt;span class="c"&gt;# to clear "Show warning before changing an extension" &lt;/span&gt;
defaults &lt;span class="nb"&gt;read &lt;/span&gt;com.apple.finder &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; after.txt
diff before.txt after.txt
&lt;span class="c"&gt;# &amp;lt;     FXEnableExtensionChangeWarning = 1;&lt;/span&gt;
&lt;span class="c"&gt;# ---&lt;/span&gt;
&lt;span class="c"&gt;# &amp;gt;     FXEnableExtensionChangeWarning = 0;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now check the type and you got a command you can add to any automation you wish.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;defaults read-type com.apple.finder FXEnableExtensionChangeWarning
&lt;span class="c"&gt;# Type is boolean&lt;/span&gt;
defaults write com.apple.finder FXEnableExtensionChangeWarning &lt;span class="nt"&gt;-bool&lt;/span&gt; &lt;span class="nb"&gt;false
&lt;/span&gt;killall Finder 2&amp;gt; /dev/null
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you can't find a key where you expected it, remove the domain from your query or check the global domain. This one affects Finder but it's in the global domain instead of &lt;code&gt;com.apple.finder&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;defaults &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="s2"&gt;"Apple Global Domain"&lt;/span&gt; AppleShowAllExtensions
&lt;span class="c"&gt;# 1&lt;/span&gt;
defaults read-type &lt;span class="s2"&gt;"Apple Global Domain"&lt;/span&gt; AppleShowAllExtensions
&lt;span class="c"&gt;# Type is boolean&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other commands to try:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;defaults &lt;span class="nb"&gt;help
&lt;/span&gt;defaults find &lt;span class="nv"&gt;$WORD&lt;/span&gt;
defaults &lt;span class="nb"&gt;read &lt;/span&gt;com.apple.dock | &lt;span class="nb"&gt;grep &lt;/span&gt;wvous &lt;span class="c"&gt;# Hot Corners&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Want an example of a setup script? Check out &lt;a href="https://github.com/santisbon/dotfiles/blob/main/macos-defaults.sh"&gt;mine&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>macos</category>
      <category>shell</category>
      <category>productivity</category>
      <category>terminal</category>
    </item>
    <item>
      <title>Cloud native homelab, Part 1: Hardware</title>
      <dc:creator>Armando C. Santisbon</dc:creator>
      <pubDate>Sun, 10 Sep 2023 03:29:43 +0000</pubDate>
      <link>https://dev.to/santisbon/build-your-homelab-as-a-private-cloud-part-1-2eb4</link>
      <guid>https://dev.to/santisbon/build-your-homelab-as-a-private-cloud-part-1-2eb4</guid>
      <description>&lt;p&gt;In this first installment of the series on building a cloud native homelab, we go over selecting your hardware. &lt;/p&gt;

&lt;p&gt;The emphasis here is on cost optimization so we're &lt;strong&gt;not&lt;/strong&gt; getting a &lt;a href="https://turingpi.com/product/turing-pi-2/"&gt;cluster board&lt;/a&gt;, a bunch of compute modules (&lt;a href="https://www.raspberrypi.com/products/compute-module-4/?variant=raspberry-pi-cm4001000"&gt;general purpose&lt;/a&gt; or &lt;a href="https://store.nvidia.com/en-us/jetson/store/?page=1&amp;amp;limit=9"&gt;machine learning&lt;/a&gt;), servers, a rack mount, or anything like that. We'll start out with one or two single-board computers (SBCs) that we can set up easily without a big capital expense. This will allow us to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deploy new nodes to our homelab in an automated fashion, just like on a public cloud with &lt;a href="https://cloud-init.io"&gt;cloud-init&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Set up a &lt;a href="https://kubernetes.io"&gt;Kubernetes&lt;/a&gt; cluster and deploy workloads to it using cloud native technologies for container orchestration, storage, and more.&lt;/li&gt;
&lt;li&gt;Interact with the real world through sensors, cameras, motors, and other hardware if we choose to.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The most popular SBC is Raspberry Pi but finding one during a shortage may be hard. Fortunately at the time of this writing the shortage is over and you can now easily find one at a reasonable price. There are cheaper options, though, and you might be tempted to buy something like the Orange Pi. Let's go over the differences to show exactly what you're getting with each.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;TL;DR Get the Raspberry Pi if you want a cloud native homelab&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gU1esoW1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k1mer6vmt81awg37l856.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gU1esoW1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k1mer6vmt81awg37l856.png" alt="Image description" width="800" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;

&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Raspberry Pi 4B&lt;/th&gt;
&lt;th&gt;Orange Pi 3B&lt;/th&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Origin&lt;/td&gt;
&lt;td&gt;United Kingdom&lt;/td&gt;
&lt;td&gt;China&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;RAM&lt;/td&gt;
&lt;td&gt;8GB LPDDR4-3200 SDRAM&lt;/td&gt;
&lt;td&gt;8GB LPDDR4/4x&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;Micro-SD card slot&lt;/td&gt;
&lt;td&gt;Micro SD slot.&lt;br&gt; 
Supports an eMMC module: 16GB - 256GB.&lt;br&gt; 
SPI Flash: 16MB/32MB.&lt;br&gt; 
M.2 M-KEY slot for SATA3 or PCIe 2.0 NVMe SSD.&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Price (USD)&lt;/td&gt;
&lt;td&gt;$75 + shipping&lt;/td&gt;
&lt;td&gt;$45 + shipping&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;OS&lt;/td&gt;
&lt;td&gt;Raspberry Pi OS, Ubuntu, RetroPie, Recalbox, OctoPi, Home Assistant, others&lt;/td&gt;
&lt;td&gt;Orange Pi OS [1], Ubuntu, Debian, Android, others&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Official images from Ubuntu and Debian?&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No. Custom Ubuntu and Debian images provided by Orange Pi.&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;cloud-init included?&lt;/td&gt;
&lt;td&gt;Yes (at least on Ubuntu)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Default Ubuntu package repo&lt;/td&gt;
&lt;td&gt;ubuntu.com&lt;/td&gt;
&lt;td&gt;huaweicloud.com&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Linux kernel release [4]&lt;/td&gt;
&lt;td&gt;5.15.0-1037-raspi (kernel extra modules available)&lt;/td&gt;
&lt;td&gt;5.10.160-rockchip-rk356x (kernel extra modules not available)&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;CPU&lt;/td&gt;
&lt;td&gt;Broadcom BCM2711 Quad core Cortex-A72 (ARM v8) 64-bit SoC 1.8GHz&lt;/td&gt;
&lt;td&gt;Rockchip RK3566 Quad-core Cortex-A55 (ARM v8) 64-bit SoC 1.8GHz&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Graphics Processing Unit (GPU)&lt;/td&gt;
&lt;td&gt;Integrated&lt;/td&gt;
&lt;td&gt;ARM Mali G52 2EE (Bitfrost) [2]&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Neural Processing Unit (NPU)&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;Rockchip NPU AI accelerator with 0.8Tops@INT8 performance.&lt;br&gt; 
RKNN model type supports conversion of Caffe / TensorFlow / TFLite / ONNX / PyTorch / Keras / Darknet models&lt;/td&gt;
&lt;/tr&gt;


&lt;tr&gt;
&lt;td&gt;Vision Processing Unit (VPU)&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Graphics &amp;amp; Video&lt;/td&gt;
&lt;td&gt;OpenGL ES 3.1, Vulkan 1.0.&lt;br&gt; 
H.265 (4K 60fps decode).&lt;br&gt; 
H.264 (1080p 60fps decode, 1080p 30fps encode).&lt;/td&gt;
&lt;td&gt;GPU&lt;br&gt;
OpenGL ES 3.2/2.0/1.1, Vulkan 1.1, OpenCL 2.0.&lt;br&gt; 
Embedded high performance 2D acceleration hardware.&lt;br&gt;&lt;br&gt;
VPU&lt;br&gt;
H.265/H.264/VP9 (4K 60fps decode).&lt;br&gt; 
H.265 (1080p 100fps encode).&lt;br&gt; 
H.264 (1080p 60fps encode).
&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Ethernet&lt;/td&gt;
&lt;td&gt;Gigabit&lt;/td&gt;
&lt;td&gt;Gigabit&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Wireless&lt;/td&gt;
&lt;td&gt;Wi-Fi 5 (802.11ac)&lt;br&gt; 
Bluetooth 5.0, BLE&lt;/td&gt;
&lt;td&gt;Wi-Fi 5 (802.11ac)&lt;br&gt; 
Bluetooth 5.0, BLE&lt;br&gt;
Wired antenna (not shown). Useful when building into a metal housing.&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;USB&lt;/td&gt;
&lt;td&gt;2 USB 3.0 ports&lt;br&gt; 
2 USB 2.0 ports&lt;/td&gt;
&lt;td&gt;1 USB 3.0 HOST&lt;br&gt; 
2 USB 2.0 HOST&lt;br&gt; 
1 USB 2.0 Device or HOST mode&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;General Purpose Input/Output (GPIO)&lt;/td&gt;
&lt;td&gt;40 pin GPIO header&lt;/td&gt;
&lt;td&gt;40 pin header supporting interface types: GPIO, UART, I2C, SPI, PWM&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Video output&lt;/td&gt;
&lt;td&gt;2 × micro-HDMI up to 4K 60fps.&lt;br&gt; 
1 × 2-lane MIPI DSI display port.&lt;/td&gt;
&lt;td&gt;1 × HDMI TX 2.0 up to 4K 60fps.&lt;br&gt; 
1 × 2-lane MIPI DSI display port.&lt;br&gt;
eDP1.3&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Camera&lt;/td&gt;
&lt;td&gt;1 × 2-lane MIPI CSI camera port&lt;/td&gt;
&lt;td&gt;1 × 2-lane MIPI CSI camera port&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Audio&lt;/td&gt;
&lt;td&gt;4-pole stereo audio and composite video port&lt;/td&gt;
&lt;td&gt;3.5mm headphone jack audio in/out&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Power&lt;/td&gt;
&lt;td&gt;5V DC via USB-C (minimum 3A) [3].&lt;br&gt;
5V DC via GPIO header (minimum 3A) [3]&lt;br&gt; 
Power over Ethernet (PoE) enabled (requires separate PoE HAT).&lt;/td&gt;
&lt;td&gt;5V DC via USB-C (3A)&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Button&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;1 MaskROM key&lt;br&gt; 
1 RESET key&lt;br&gt; 
1 POWER key&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Fan&lt;/td&gt;
&lt;td&gt;Use the GPIO pins (3.3V or 5V) 2.54mm pin pitch&lt;/td&gt;
&lt;td&gt;2-Pin 1.25mm pin pitch 5V fan connector&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Real-time clock (RTC)&lt;/td&gt;
&lt;td&gt;Use the GPIO pins (3.3V) 2.54mm pin pitch&lt;/td&gt;
&lt;td&gt;2-Pin 1.25mm pin pitch battery backup connector&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Dimensions&lt;/td&gt;
&lt;td&gt;85mm x 56mm x 11mm&lt;br&gt; 
46g&lt;/td&gt;
&lt;td&gt;85mm x 56mm x 17mm&lt;br&gt; 
49g&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;&lt;/div&gt;

&lt;h6&gt;
  
  
  [1] Orange Pi OS doesn't support the GPU, NPU, or VPU. But Debian, Ubuntu, and Android support them.
&lt;/h6&gt;

&lt;h6&gt;
  
  
  [2] &lt;a href="https://developer.arm.com/Processors/Mali-G52"&gt;arm.com&lt;/a&gt;, &lt;a href="https://github.com/rockchip-linux/rknpu2"&gt;Rockchip GitHub&lt;/a&gt;
&lt;/h6&gt;

&lt;h6&gt;
  
  
  [3] A good quality 2.5A power supply can be used if downstream USB peripherals consume less than 500mA in total.
&lt;/h6&gt;

&lt;h6&gt;
  
  
  [4] Linux kernel extra modules &lt;code&gt;nvme_fabrics&lt;/code&gt; and &lt;code&gt;nvme_tcp&lt;/code&gt; are required for cloud native storage like OpenEBS.
&lt;/h6&gt;

&lt;ul&gt;
&lt;li&gt;You'll also need a 5V 3A power supply for each board if you're not setting them up with Power over Ethernet (PoE). &lt;/li&gt;
&lt;li&gt;You &lt;em&gt;don't&lt;/em&gt; need a mouse and keyboard for the boards because you'll manage them over &lt;a href="https://www.ssh.com/academy/ssh"&gt;SSH&lt;/a&gt; from your laptop. Even if you installed a graphical desktop, you could still access it remotely with a VNC viewer.&lt;/li&gt;
&lt;li&gt;If you're not setting them up with Wi-Fi, you'll need an ethernet cable (CAT 5e or better) for each board.&lt;/li&gt;
&lt;li&gt;For many applications you can use the Pi by itself without heat sinks or a fan and monitor the temperature in millidegree Celsius with &lt;code&gt;cat /sys/class/thermal/thermal_zone*/temp&lt;/code&gt;. But we're going to be running some resource-intensive software like Kubernetes. For our cloud native homelab I recommend getting heat sinks, a fan, and a case to house everything from the start. The &lt;a href="https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#frequency-management-and-thermal-control"&gt;Raspberry Pi ARM cores and GPU will start throttling&lt;/a&gt; when they reach around 80°C.&lt;/li&gt;
&lt;li&gt;Speaking of cases, I recommend getting a cluster case. It's way cheaper than a cluster board and it houses your Pis in a stackable way so it's great for expanding your homelab in the future. &lt;a href="https://thepihut.com/products/cluster-case-for-raspberry-pi"&gt;This one&lt;/a&gt; from the UK is particularly nice and made with Perspex (a high-quality acrylic) but there are other options on Amazon with faster shipping.&lt;/li&gt;
&lt;li&gt;For storing large amounts of data you'll need external storage like an SSD drive. I recommend a SATA SSD although if you already have an NVMe SSD you can use that as well, just know that your board won't take full advantage of its speeds. &lt;a href="https://thepihut.com/products/wd-green-240gb-2-5-ssd"&gt;This one&lt;/a&gt; is a great option along with &lt;a href="https://thepihut.com/products/ssd-to-usb-3-0-cable-for-raspberry-pi"&gt;this cable&lt;/a&gt;. Just make sure the cable/adapter has an ASMedia chipset.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With Raspberry Pi it's easy to automate the setup with cloud-init. You're also able to have cloud native replicated storage with OpenEBS thanks to the extra kernel modules for NVMe over Fabrics. If you want your homelab to be cloud native, Raspberry Pi is the way to go.&lt;/p&gt;

&lt;p&gt;For Orange Pi, cloud-init is not included. On top of that, the images provided by Orange Pi can't be mounted on macOS so you can't inject the &lt;code&gt;user-data&lt;/code&gt; anyway (and you have to use the images they provide, others won't work). That means you'll have to set it up manually. There's also the issue of not being able to use cloud native storage due to a lack of extra modules for that kernel release. Having said that, Orange Pi's AI capabilities might be a good addition to your homelab if you need a low-cost AI-accelerated IoT device and don't need any cloud native features like an automated setup or replicated storage.&lt;/p&gt;

&lt;p&gt;If you have a 32-bit SBC like the Raspberry Pi 2, keep in mind that it can't run some Kubernetes distributions like MicroK8s so whatever SBCs you choose make sure they're 64-bit. If you have a Pi 2 it's great as a dedicated retro gaming console with &lt;a href="https://www.recalbox.com"&gt;Recalbox&lt;/a&gt;.  &lt;/p&gt;

&lt;p&gt;In the next part of this series, we'll set up our nodes as a Kubernetes cluster.&lt;/p&gt;

</description>
      <category>raspberrypi</category>
      <category>orangepi</category>
      <category>homelab</category>
      <category>kubernetes</category>
    </item>
    <item>
      <title>A Mastodon bot to find EV charging stations</title>
      <dc:creator>Armando C. Santisbon</dc:creator>
      <pubDate>Thu, 31 Aug 2023 21:38:05 +0000</pubDate>
      <link>https://dev.to/santisbon/a-mastodon-bot-for-ev-charging-stations-4j46</link>
      <guid>https://dev.to/santisbon/a-mastodon-bot-for-ev-charging-stations-4j46</guid>
      <description>&lt;p&gt;I have a new addition to my homelab. I wanted to do a project that was fun to build but also let me apply a few different technical concepts. Read along if you're interested in any of the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Homelabs based on Raspberry Pi.&lt;/li&gt;
&lt;li&gt;Mastodon and the wider Fediverse.&lt;/li&gt;
&lt;li&gt;Civic tech.&lt;/li&gt;
&lt;li&gt;Electric vehicles.&lt;/li&gt;
&lt;li&gt;Loosely-coupled microservices.&lt;/li&gt;
&lt;li&gt;Message brokers with long-running producers and consumers.&lt;/li&gt;
&lt;li&gt;Caching.&lt;/li&gt;
&lt;li&gt;Container orchestration.&lt;/li&gt;
&lt;li&gt;Secrets management.&lt;/li&gt;
&lt;li&gt;Handling server-sent events from a streaming API.&lt;/li&gt;
&lt;li&gt;Consuming REST APIs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal was simple: a bot that, whenever you mention it with a location, will reply with a list of nearby EV charging stations. It must also display the type of connectors available and link to the location of each station using Apple or Google Maps, depending on the user's device.&lt;/p&gt;

&lt;p&gt;Once you've &lt;a href="https://santisbon.github.io/reference/rpi/"&gt;set up your Raspberry Pi&lt;/a&gt; and &lt;a href="https://santisbon.github.io/reference/k8s/#microk8s"&gt;lightweight Kubernetes distribution&lt;/a&gt;, it's time to think about our architecture.&lt;/p&gt;

&lt;p&gt;Our solution has: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;em&gt;watcher&lt;/em&gt; that keeps track of Mastodon notifications for mentions of our bot account and prepares a request for the task to be done.&lt;/li&gt;
&lt;li&gt;A &lt;em&gt;worker&lt;/em&gt; that fulfills the task of putting together the response and sending it to the user.&lt;/li&gt;
&lt;li&gt;A message broker that the watcher and the worker will use to communicate with each other.&lt;/li&gt;
&lt;li&gt;A cache to store the responses from the external service that helps us translate user requests into a geographic location.&lt;/li&gt;
&lt;li&gt;A Mastodon instance hosting our bot account and offering a streaming API with notifications and a web API for posting.&lt;/li&gt;
&lt;li&gt;A third-party API with a geocoding service.&lt;/li&gt;
&lt;li&gt;A third-party API with charging station locations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's the high-level architecture&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zFFfRLRl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yir6isbvvrykw3in1i93.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zFFfRLRl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yir6isbvvrykw3in1i93.png" alt="Image description" width="800" height="564"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We'll take advantage of Docker container images to package our two microservices (watcher and worker) and their dependencies. We'll also use Kubernetes for container orchestration. &lt;/p&gt;

&lt;p&gt;Each microservice consists of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;App container.&lt;/li&gt;
&lt;li&gt;Configuration and secrets.&lt;/li&gt;
&lt;li&gt;Horizontal autoscaling to meet an increase in demand.&lt;/li&gt;
&lt;li&gt;Init container to delay the creation of the app container until the message broker is available.&lt;/li&gt;
&lt;li&gt;In the case of the worker, a cache to avoid unnecessary calls to the geocoding API as required by its terms of service.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dive into the instructions, code, a detailed diagram of the Kubernetes objects, and documentation here:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/santisbon"&gt;
        santisbon
      &lt;/a&gt; / &lt;a href="https://github.com/santisbon/evstations"&gt;
        evstations
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Mastodon bot to get electric vehicle charging stations.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1 id="user-content-ev-stations"&gt;&lt;a class="heading-link" href="https://github.com/santisbon/evstations#ev-stations"&gt;EV Stations&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;🧪 Experimental&lt;/p&gt;
&lt;p&gt;&lt;a href="https://botsin.space/@ev" rel="nofollow"&gt;@ev@botsin.space&lt;/a&gt; is a Mastodon bot to get electric vehicle (EV) charging stations near a location in the &lt;strong&gt;United States&lt;/strong&gt; or &lt;strong&gt;Canada&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id="user-content-highlights"&gt;&lt;a class="heading-link" href="https://github.com/santisbon/evstations#highlights"&gt;Highlights&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Mention it with just a requested location and it will reply with some charging stations near it.&lt;/li&gt;
&lt;li&gt;The links provided in the results (even though they point to Apple Maps) will automatically open either Apple or Google Maps depending on your device.&lt;/li&gt;
&lt;li&gt;If the response doesn't fit in one post due to Mastodon's character limit it will be split into a couple of posts.&lt;/li&gt;
&lt;li&gt;The response includes symbols for the available connector types at each station
&lt;ul&gt;
&lt;li&gt;Ⓣ Tesla aka North American Charging Standard (NACS)&lt;/li&gt;
&lt;li&gt;Ⓙ J1772&lt;/li&gt;
&lt;li&gt;ⒸⒸⓈ Combined Charging System (CCS) aka J1772 Combo&lt;/li&gt;
&lt;li&gt;Ⓝ⑭-㊿ NEMA 14-50&lt;/li&gt;
&lt;li&gt;Ⓝ⑤-⑮ NEMA 5-15&lt;/li&gt;
&lt;li&gt;Ⓝ⑤-⑳ NEMA 5-20&lt;/li&gt;
&lt;li&gt;ⒸⒽⒶ CHAdeMO&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="user-content-usage"&gt;&lt;a class="heading-link" href="https://github.com/santisbon/evstations#usage"&gt;Usage&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Post this from your Fediverse account:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;@ev@botsin.space&lt;/code&gt; Brickell, Miami&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Query examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;60601&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Wrigley Field&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chinatown, chicago&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;financial&lt;/code&gt;…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/santisbon/evstations"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


</description>
      <category>civictech</category>
      <category>kubernetes</category>
      <category>raspberrypi</category>
      <category>python</category>
    </item>
    <item>
      <title>Monitor internet speeds with Raspberry Pi</title>
      <dc:creator>Armando C. Santisbon</dc:creator>
      <pubDate>Sun, 13 Aug 2023 20:55:13 +0000</pubDate>
      <link>https://dev.to/santisbon/monitor-internet-speeds-with-raspberry-pi-3k59</link>
      <guid>https://dev.to/santisbon/monitor-internet-speeds-with-raspberry-pi-3k59</guid>
      <description>&lt;p&gt;A great addition to any homelab is being able to track your internet speeds over time and have a nice dashboard to visualize the data for download/upload speeds, latency, and jitter.&lt;/p&gt;

&lt;p&gt;We'll use the speedtest.net API for the test itself, a time series database to store our test results, and a dashboard to visualize them from other machines on the network.&lt;/p&gt;

&lt;p&gt;To make the deployment easier we'll take advantage of Docker containers to package our apps, Kubernetes for orchestration, and Helm to deploy everything. &lt;/p&gt;

&lt;p&gt;You'll need a Raspberry Pi or some other low-cost, low-energy consumption computer you'd like to leave on to do the speed monitoring. You won't need a graphical desktop on it since you can &lt;code&gt;ssh&lt;/code&gt; into it to carry out all tasks.&lt;/p&gt;

&lt;p&gt;Let's get started! All the details are here:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/santisbon"&gt;
        santisbon
      &lt;/a&gt; / &lt;a href="https://github.com/santisbon/speedtest"&gt;
        speedtest
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Keep track of your internet connection speeds over time with a Raspberry Pi.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1 id="user-content-internet-speed-monitor"&gt;&lt;a class="heading-link" href="https://github.com/santisbon/speedtest#internet-speed-monitor"&gt;Internet Speed Monitor&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Keep track of your internet connection speeds over time with a Raspberry Pi.&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/7a0aece2d50af00a816665fd5fffe89ae9e0dea18aecd49abcbe28f0d8995bd4/68747470733a2f2f692e696d6775722e636f6d2f786a70387453672e706e67"&gt;&lt;img src="https://camo.githubusercontent.com/7a0aece2d50af00a816665fd5fffe89ae9e0dea18aecd49abcbe28f0d8995bd4/68747470733a2f2f692e696d6775722e636f6d2f786a70387453672e706e67" alt="Dashboard"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This Helm chart deploys:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;InfluxDB 2.x database for time series data.&lt;/li&gt;
&lt;li&gt;Grafana dashboard.&lt;/li&gt;
&lt;li&gt;Python app to run the speed test on a schedule.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
    &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/2bd5c0df120f2550a2a783238991e8ff795df08b2996d9321b4e628be9d4bb3a/68747470733a2f2f692e696d6775722e636f6d2f3153714344755a2e706e67"&gt;&lt;img src="https://camo.githubusercontent.com/2bd5c0df120f2550a2a783238991e8ff795df08b2996d9321b4e628be9d4bb3a/68747470733a2f2f692e696d6775722e636f6d2f3153714344755a2e706e67" width="80%"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;h2 id="user-content-prerequisites"&gt;&lt;a class="heading-link" href="https://github.com/santisbon/speedtest#prerequisites"&gt;Prerequisites&lt;/a&gt;&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://santisbon.github.io/reference/rpi/" rel="nofollow"&gt;Set up&lt;/a&gt; your Raspberry Pi.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://santisbon.github.io/reference/k8s/#microk8s" rel="nofollow"&gt;Install and configure MicroK8s&lt;/a&gt; (or another lightweight Kubernetes distribution with DNS and Helm addons) on your Pi.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Note: MicroK8s by default uses &lt;code&gt;Dqlite&lt;/code&gt; as its storage backend instead of &lt;code&gt;etcd&lt;/code&gt;. Further securing of &lt;code&gt;Secret&lt;/code&gt; objects with &lt;a href="https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/" rel="nofollow"&gt;encryption at rest&lt;/a&gt; for either storage backend is outside the scope of this project.&lt;/p&gt;

&lt;h2 id="user-content-install"&gt;&lt;a class="heading-link" href="https://github.com/santisbon/speedtest#install"&gt;Install&lt;/a&gt;&lt;/h2&gt;


&lt;ol&gt;
&lt;li&gt;

&lt;p&gt;Prepare your Raspberry Pi's local storage for both the database and dashboard&lt;/p&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; On your Pi&lt;/span&gt;
sudo mkdir -p /var/lib/influxdb2
sudo mkdir -p /etc/influxdb2
sudo mkdir -p /var/lib/grafana&lt;/pre&gt;

&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If installing from the repository&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; On your Pi&lt;/span&gt;
helm repo add santisbon https://santisbon.github.io/charts/
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; or &lt;/span&gt;
helm repo update
CHART=&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;santisbon/speedtest&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Or if…&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/santisbon/speedtest"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



</description>
      <category>raspberrypi</category>
      <category>kubernetes</category>
      <category>python</category>
      <category>homelab</category>
    </item>
    <item>
      <title>Homelab or cloud? Where should your apps and data go?</title>
      <dc:creator>Armando C. Santisbon</dc:creator>
      <pubDate>Fri, 11 Aug 2023 06:54:59 +0000</pubDate>
      <link>https://dev.to/santisbon/homelab-or-cloud-where-should-your-apps-and-data-go-588f</link>
      <guid>https://dev.to/santisbon/homelab-or-cloud-where-should-your-apps-and-data-go-588f</guid>
      <description>&lt;p&gt;You may have a lot of personal digital assets: web applications, a blog, productivity and collaboration software, email, calendars, photos, video, documents, music, social networking bots or servers, monitoring and security tools, game servers, content management systems, home automation software. All of these have to live somewhere and sometimes it's not easy to decide what the best place is for each.&lt;/p&gt;

&lt;p&gt;The suitability of your homelab for a particular workload will, of course, depend in part on how sophisticated your homelab is. But there are a few rules of thumb that can help you decide.&lt;/p&gt;

&lt;p&gt;Your workload may be well suited for the public &lt;strong&gt;cloud&lt;/strong&gt; if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It has extremely high durability and availability requirements e.g. storage with 99.999999999% durability and 99.99% availability of objects over a given year.&lt;/li&gt;
&lt;li&gt;It exposes services to the outside world and demand is unpredictable so elasticity is important.&lt;/li&gt;
&lt;li&gt;It needs specialized hardware like GPU-based instances or FPGAs.&lt;/li&gt;
&lt;li&gt;You want someone else to take care of administrative overhead, power, cooling, physical security, and other undifferentiated heavy lifting.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your workload may be best on your &lt;strong&gt;homelab&lt;/strong&gt; if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It only provides services to your home network and doesn't need to expose services to the outside.&lt;/li&gt;
&lt;li&gt;Its demand is predictable.&lt;/li&gt;
&lt;li&gt;In the event that your house burns down or is flooded, the loss of apps and data is not your biggest concern.&lt;/li&gt;
&lt;li&gt;It doesn't need specialized hardware.&lt;/li&gt;
&lt;li&gt;You want local control of your data and the infrastructure that hosts it.&lt;/li&gt;
&lt;li&gt;You want to learn more about clusters, networking, containers, or orchestration with a hands-on approach.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some apps that are great for a homelab include a network-wide ad blocker like &lt;a href="https://dev.to/santisbon/block-ads-on-your-whole-network-2gmd"&gt;Pi-hole&lt;/a&gt;, a &lt;a href="https://github.com/santisbon/mastodonbot"&gt;Mastodon bot&lt;/a&gt;, an &lt;a href="https://dev.to/santisbon/monitor-internet-speeds-with-raspberry-pi-3k59"&gt;internet speed monitor&lt;/a&gt;, open source home automation like &lt;a href="https://www.home-assistant.io"&gt;Home Assistant&lt;/a&gt;, a media server like &lt;a href="https://www.plex.tv/media-server-downloads/"&gt;Plex&lt;/a&gt;, a private cloud for your family like &lt;a href="https://nextcloud.com/athome/"&gt;Nextcloud&lt;/a&gt;, and pet projects/experiments for learning new technologies.&lt;/p&gt;

</description>
      <category>homelab</category>
      <category>cloud</category>
      <category>comparisons</category>
      <category>infrastructure</category>
    </item>
    <item>
      <title>Set up a new dev machine</title>
      <dc:creator>Armando C. Santisbon</dc:creator>
      <pubDate>Wed, 09 Aug 2023 20:01:28 +0000</pubDate>
      <link>https://dev.to/santisbon/set-up-a-new-dev-machine-j09</link>
      <guid>https://dev.to/santisbon/set-up-a-new-dev-machine-j09</guid>
      <description>&lt;p&gt;I keep my notes on setting up a new development machine as a MkDocs site on Github Pages. You can find all the material here:&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;a href="https://santisbon.github.io/reference/" rel="noopener noreferrer"&gt;
      santisbon.github.io
    &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>tutorial</category>
      <category>development</category>
      <category>productivity</category>
    </item>
    <item>
      <title>The Sleeping Beauty Problem</title>
      <dc:creator>Armando C. Santisbon</dc:creator>
      <pubDate>Mon, 17 Jul 2023 17:20:12 +0000</pubDate>
      <link>https://dev.to/santisbon/the-sleeping-beauty-problem-3a9m</link>
      <guid>https://dev.to/santisbon/the-sleeping-beauty-problem-3a9m</guid>
      <description>&lt;p&gt;Sleeping Beauty agrees to be the subject of an experiment and is informed of the procedure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On Sunday night, she will be put to sleep.&lt;/li&gt;
&lt;li&gt;Then, a fair coin will be flipped.&lt;/li&gt;
&lt;li&gt;If it comes up Heads, she will be awakened on Monday and put back to sleep.&lt;/li&gt;
&lt;li&gt;If it comes up Tails, she will also be awakened on Monday and put back to sleep, but then she'll be awakened on Tuesday as well and put back to sleep.&lt;/li&gt;
&lt;li&gt;Each time that she is put back to sleep she will forget that she was ever awakened. &lt;/li&gt;
&lt;li&gt;Any time she's awake, she will be told no information but she'll be asked one question: &lt;strong&gt;What do you believe is the probability that the coin came up heads?&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5-KAtFlF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2kjuxhi134mnyly8gkr4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5-KAtFlF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2kjuxhi134mnyly8gkr4.png" alt="Experiment" width="800" height="520"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Image credit: &lt;a href="https://www.youtube.com/@veritasium"&gt;Veritasium&lt;/a&gt;
&lt;/h6&gt;

&lt;p&gt;How should she answer?&lt;/p&gt;

&lt;p&gt;You might be tempted to say 

&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;50%50\%&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;50%&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 because that's the probability of a fair coin coming up Heads, but you would be mistaken. The correct answer is 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;1/31/3&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;1/3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
. To understand why, we need to realize that the question that is &lt;em&gt;really&lt;/em&gt; being asked is this: What is the probability that the coin came up Heads given that you've been awakened?&lt;/p&gt;

&lt;p&gt;This is a case where we need to incorporate observed data into our prior odds to come up with new odds that account for the new data. To do that, we need to calculate the probability of an event happening given that another event has already happened. We can use Bayes' Theorem for this.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ℹ️ &lt;strong&gt;Bayes' Theorem&lt;/strong&gt;&lt;br&gt;

&lt;/p&gt;
&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;P(A∣B)=P(B∣A)P(A)P(B)P(A|B)={P(B|A)P(A) \over P(B)}&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;A&lt;/span&gt;&lt;span class="mord"&gt;∣&lt;/span&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="mord"&gt;∣&lt;/span&gt;&lt;span class="mord mathnormal"&gt;A&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;A&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;/blockquote&gt;

&lt;p&gt;But wait, where did that come from?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 It can be derived from the conditional probability that tells us in how many cases do both events 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;AA&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 and 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;BB&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 happen out of the cases where 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;BB&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 happens:&lt;/p&gt;

&lt;p&gt;
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;P(A∣B)=P(A∩B)P(B)P(A|B)={P(A \cap B) \over P(B)}&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;A&lt;/span&gt;&lt;span class="mord"&gt;∣&lt;/span&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;P&lt;/span&gt;&lt;span class="mopen mtight"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;B&lt;/span&gt;&lt;span class="mclose mtight"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;P&lt;/span&gt;&lt;span class="mopen mtight"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;A&lt;/span&gt;&lt;span class="mbin mtight"&gt;∩&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;B&lt;/span&gt;&lt;span class="mclose mtight"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
&lt;/p&gt;

&lt;p&gt;Similarly, 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;P(B∣A)=P(A∩B)P(A)P(B|A)={P(A \cap B) \over P(A)}&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="mord"&gt;∣&lt;/span&gt;&lt;span class="mord mathnormal"&gt;A&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;P&lt;/span&gt;&lt;span class="mopen mtight"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;A&lt;/span&gt;&lt;span class="mclose mtight"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;P&lt;/span&gt;&lt;span class="mopen mtight"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;A&lt;/span&gt;&lt;span class="mbin mtight"&gt;∩&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;B&lt;/span&gt;&lt;span class="mclose mtight"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
&lt;/p&gt;

&lt;p&gt;which means&lt;/p&gt;

&lt;p&gt;
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;P(A∩B)=P(B∣A)P(A)P(A \cap B)=P(B|A)P(A)&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;A&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;∩&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="mord"&gt;∣&lt;/span&gt;&lt;span class="mord mathnormal"&gt;A&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;A&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
&lt;/p&gt;

&lt;p&gt;and substituting in the expression for conditional probability yields Bayes' Theorem:&lt;br&gt;

&lt;/p&gt;
&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;P(A∣B)=P(B∣A)P(A)P(B)P(A|B)={P(B|A)P(A) \over P(B)}&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;A&lt;/span&gt;&lt;span class="mord"&gt;∣&lt;/span&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="mord"&gt;∣&lt;/span&gt;&lt;span class="mord mathnormal"&gt;A&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;A&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;

&lt;/blockquote&gt;

&lt;p&gt;Now that we understand where Bayes' Theorem comes from, there's another way to look at it: As a way to understand two competing hypotheses 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;H1H_1&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 and 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;H2H_2&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
. We start by having some prior belief about the odds of those two. After observing some data, what are the &lt;strong&gt;new&lt;/strong&gt; odds of the two hypotheses given the new data? In other words, how do we update our belief based on new evidence?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ℹ️ &lt;br&gt;
Let's start by specifying what we mean by &lt;em&gt;odds&lt;/em&gt;. We mean how large is one probability relative to the other. Let's put it as a ratio. For example, if prior to seeing any data one hypothesis has 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;3/43/4&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;3/4&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 probability of being true and the other has 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;1/41/4&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;1/4&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;P(H1)P(H2)=3/41/4=31\frac {P(H_1)} {P(H_2)}=\frac {3/4} {1/4}=\frac 3 1&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1/4&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;3/4&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;Meaning the odds of 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;H1H_1&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 to 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;H2H_2&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 are 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;33&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 to 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;11&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So how do we incorporate the new data 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;DD&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 into our belief? &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 By calculating the new probability of each hypothesis given the new data.&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;P(H1∣D)P(H2∣D)=P(H1∩D)P(D)P(H2∩D)P(D)=P(H1∩D)P(H2∩D)\frac {P(H_1|D)} {P(H_2|D)}=\frac {\frac {P(H_1 \cap D)} {P(D)}} {\frac {P(H_2 \cap D)} {P(D)}}=\frac {P(H_1 \cap D)} {P(H_2 \cap D)}&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;∣&lt;/span&gt;&lt;span class="mord mathnormal"&gt;D&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;∣&lt;/span&gt;&lt;span class="mord mathnormal"&gt;D&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;P&lt;/span&gt;&lt;span class="mopen mtight"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;D&lt;/span&gt;&lt;span class="mclose mtight"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;P&lt;/span&gt;&lt;span class="mopen mtight"&gt;(&lt;/span&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size3 size1 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mbin mtight"&gt;∩&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;D&lt;/span&gt;&lt;span class="mclose mtight"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;P&lt;/span&gt;&lt;span class="mopen mtight"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;D&lt;/span&gt;&lt;span class="mclose mtight"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;P&lt;/span&gt;&lt;span class="mopen mtight"&gt;(&lt;/span&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size3 size1 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mbin mtight"&gt;∩&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;D&lt;/span&gt;&lt;span class="mclose mtight"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;∩&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;D&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;∩&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;D&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;Now we'll use a mathematical trick of multiplying and dividing &lt;strong&gt;by the same number&lt;/strong&gt; to get the same value but expressed in terms of the &lt;strong&gt;probability of seeing the observed data given each hypothesis&lt;/strong&gt;.&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;=P(H1∩D)P(H2∩D)⋅P(H2)P(H1)⋅P(H1)P(H2)=\frac {P(H_1 \cap D)} {P(H_2 \cap D)} \cdot \frac {P(H_2)} {P(H_1)} \cdot \frac {P(H_1)} {P(H_2)}&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;∩&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;D&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;∩&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;D&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;⋅&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;⋅&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;=P(H1∩D)P(H1)P(H2∩D)P(H2)⋅P(H1)P(H2)=\frac {\frac {P(H_1 \cap D)} {P(H_1)}} {\frac {P(H_2 \cap D)} {P(H_2)}} \cdot \frac {P(H_1)} {P(H_2)}&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;P&lt;/span&gt;&lt;span class="mopen mtight"&gt;(&lt;/span&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size3 size1 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose mtight"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;P&lt;/span&gt;&lt;span class="mopen mtight"&gt;(&lt;/span&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size3 size1 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mbin mtight"&gt;∩&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;D&lt;/span&gt;&lt;span class="mclose mtight"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;P&lt;/span&gt;&lt;span class="mopen mtight"&gt;(&lt;/span&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size3 size1 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose mtight"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;P&lt;/span&gt;&lt;span class="mopen mtight"&gt;(&lt;/span&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size3 size1 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mbin mtight"&gt;∩&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;D&lt;/span&gt;&lt;span class="mclose mtight"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;⋅&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;So,&lt;br&gt;

&lt;/p&gt;
&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;P(H1∣D)P(H2∣D)=P(D∣H1)P(D∣H2)⋅P(H1)P(H2)\frac {P(H_1|D)} {P(H_2|D)}=\frac {P(D|H_1)} {P(D|H_2)} \cdot \frac {P(H_1)} {P(H_2)}&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;∣&lt;/span&gt;&lt;span class="mord mathnormal"&gt;D&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;∣&lt;/span&gt;&lt;span class="mord mathnormal"&gt;D&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;D&lt;/span&gt;&lt;span class="mord"&gt;∣&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;D&lt;/span&gt;&lt;span class="mord"&gt;∣&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;⋅&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;And so we have that as a ratio, the posterior odds equal the prior odds times the probabilities of generating the new data.&lt;/p&gt;


&lt;/blockquote&gt;

&lt;p&gt;Now let's apply this to our Sleeping Beauty problem. Let&lt;br&gt;

&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;H1=H_1=&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
&lt;em&gt;The coin came up Heads&lt;/em&gt;&lt;br&gt;

&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;H2=H_2=&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
&lt;em&gt;The coin came up Tails&lt;/em&gt;&lt;br&gt;

&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;D=D=&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;D&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
&lt;em&gt;You've been woken up&lt;/em&gt;&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;P(H1∣D)P(H2∣D)=1/32/3⋅1/21/2=3/6=1/2\frac {P(H_1|D)} {P(H_2|D)}=\frac {1/3} {2/3} \cdot \frac {1/2} {1/2}=3/6=1/2&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;∣&lt;/span&gt;&lt;span class="mord mathnormal"&gt;D&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;∣&lt;/span&gt;&lt;span class="mord mathnormal"&gt;D&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;2/3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1/3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;⋅&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1/2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1/2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;3/6&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;1/2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;Meaning 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;H2H_2&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 is twice as likely as 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;H1H_1&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 given the new data. If you want to convert that to probabilities: &lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;P(H1)=11+2=1/3P(H_1)=\frac 1 {1+2}=1/3&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;1/3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;P(H2)=21+2=2/3P(H_2)=\frac 2 {1+2}=2/3&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;2/3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;Therefore Sleeping Beauty should answer that the coin came up Tails as the probabilities are 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;1/31/3&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;1/3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 for Heads and 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;2/32/3&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;2/3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 for Tails.&lt;/p&gt;




&lt;p&gt;We can give another explanation that is more informal but more intuitive. Imagine she's still woken up once if it's Heads, but on 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;100100&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;100&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 consecutive days if it's Tails. She's awake. She has no idea which of those 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;101101&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;101&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 scenarios she's in, but effectively she's being asked if she thinks she's in the 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;11&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 scenario where it was Heads or in one of the 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;100100&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;100&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 scenarios where it was Tails. The answer should be clear.&lt;/p&gt;

</description>
      <category>math</category>
      <category>probability</category>
      <category>statistics</category>
    </item>
    <item>
      <title>Document your project with MkDocs and GitHub Pages</title>
      <dc:creator>Armando C. Santisbon</dc:creator>
      <pubDate>Fri, 17 Mar 2023 22:13:38 +0000</pubDate>
      <link>https://dev.to/santisbon/document-your-project-with-mkdocs-and-github-pages-1fbf</link>
      <guid>https://dev.to/santisbon/document-your-project-with-mkdocs-and-github-pages-1fbf</guid>
      <description>&lt;p&gt;Most project documentation starts with a single README.md file. But for medium and large projects this quickly becomes a really long and hard to manage file. Searching for the content you want, navigation, and styling become a mess.&lt;/p&gt;

&lt;p&gt;Enter &lt;a href="https://www.mkdocs.org"&gt;MkDocs&lt;/a&gt;. It can generate a static site that can be hosted on any web server. We'll set it up on GitHub Pages with a configuration that not only makes it look great but allows rich content like math expressions and simplifies deployment.&lt;/p&gt;

&lt;p&gt;First install the needed software and create the file structure we'll use.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;mkdocs python-markdown-math mkdocs-material
mkdocs new &lt;span class="o"&gt;[&lt;/span&gt;dir-name]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create this default layout&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mkdocs.yml    &lt;span class="c"&gt;# The configuration file.&lt;/span&gt;
docs/
    index.md  &lt;span class="c"&gt;# The documentation homepage.&lt;/span&gt;
    ...       &lt;span class="c"&gt;# Other markdown pages, images and other files.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub Pages gives you the option to host your static site on any branch in either the root of your project or in a /docs folder so we'll modify the default layout to make our lives easier. Rename &lt;code&gt;/docs&lt;/code&gt; to &lt;code&gt;/src/&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mv&lt;/span&gt; ./docs/ ./src/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and move the whole dir with &lt;code&gt;mkdocs.yaml&lt;/code&gt; and &lt;code&gt;/src/&lt;/code&gt; to your project's directory.&lt;/p&gt;

&lt;p&gt;Now edit your &lt;code&gt;mkdocs.yml&lt;/code&gt; file to look like this. Replace the placeholders with your GitHub username and repo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;site_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;My Site&lt;/span&gt;
&lt;span class="na"&gt;site_url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://&amp;lt;user&amp;gt;.github.io/&amp;lt;repo&amp;gt;/&lt;/span&gt;
&lt;span class="na"&gt;repo_url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://github.com/&amp;lt;user&amp;gt;/&amp;lt;repo&amp;gt;&lt;/span&gt;
&lt;span class="na"&gt;nav&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Home&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;index.md'&lt;/span&gt;
&lt;span class="na"&gt;markdown_extensions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;toc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;permalink&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#"&lt;/span&gt;
&lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;material&lt;/span&gt;
  &lt;span class="na"&gt;features&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;navigation.expand&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;navigation.top&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;content.code.copy&lt;/span&gt;
  &lt;span class="na"&gt;palette&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Palette toggle for light mode&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;media&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;(prefers-color-scheme:&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;light)"&lt;/span&gt;
      &lt;span class="na"&gt;scheme&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt;
      &lt;span class="na"&gt;toggle&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;icon&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;material/brightness-5&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Switch to dark mode&lt;/span&gt;
    &lt;span class="c1"&gt;# Palette toggle for dark mode&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;media&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;(prefers-color-scheme:&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;dark)"&lt;/span&gt;
      &lt;span class="na"&gt;scheme&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;slate&lt;/span&gt;
      &lt;span class="na"&gt;toggle&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;icon&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;material/brightness-3&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Switch to light mode&lt;/span&gt;
&lt;span class="na"&gt;extra_javascript&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS-MML_HTMLorMML&lt;/span&gt;
&lt;span class="na"&gt;markdown_extensions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mdx_math&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;admonition&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;sane_lists&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;pymdownx.highlight&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;auto_title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;pymdownx.superfences&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;pymdownx.keys&lt;/span&gt;
&lt;span class="na"&gt;docs_dir&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;src&lt;/span&gt;
&lt;span class="na"&gt;edit_uri&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;edit/main/src/&lt;/span&gt;
&lt;span class="na"&gt;site_dir&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice we set &lt;code&gt;docs_dir: src&lt;/code&gt; to hold our .md files and &lt;strong&gt;&lt;code&gt;site_dir: docs&lt;/code&gt; to automatically place the generated site in the folder that GitHub uses to serve our GitHub Pages site&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We're also using the Material theme which is clean, elegant, and has great customization options.&lt;/p&gt;

&lt;p&gt;
  A few &lt;a href="https://python-markdown.github.io/extensions/"&gt;extensions&lt;/a&gt; we added
  &lt;h3&gt;
  
  
  &lt;a href="https://python-markdown.github.io/extensions/admonition/"&gt;Admonition&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Pencil: &lt;code&gt;attention&lt;/code&gt;, &lt;code&gt;caution&lt;/code&gt;, &lt;code&gt;error&lt;/code&gt;, &lt;code&gt;hint&lt;/code&gt;, &lt;code&gt;important&lt;/code&gt;,&lt;code&gt;note&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Fire: &lt;code&gt;tip&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Exclamation mark: &lt;code&gt;warning&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Lightning bolt: &lt;code&gt;danger&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The text must be indented.&lt;br&gt;
&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;!!! attention
    Text goes here.
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IlO6vlF0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cteogs6ch3m6tkr8czd7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IlO6vlF0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cteogs6ch3m6tkr8czd7.png" alt="Admonition" width="800" height="476"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://facelessuser.github.io/pymdown-extensions/extensions/keys/#extendingmodifying-key-map-index"&gt;Keys&lt;/a&gt;
&lt;/h3&gt;



&lt;pre&gt;&lt;code&gt;++command+shift+n++
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1HifPZVu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x67u1jbv5z96s0xabo6s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1HifPZVu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x67u1jbv5z96s0xabo6s.png" alt="Keys" width="430" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  MathJax
&lt;/h3&gt;



&lt;pre&gt;&lt;code&gt;When \(a \ne 0\), there are two solutions to \(ax^2 + bx + c = 0\) and they are
$$x = {-b \pm \sqrt{b^2-4ac} \over 2a}$$
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SXleLIWx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lkymirvdd46zwr1vevud.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SXleLIWx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lkymirvdd46zwr1vevud.png" alt="Math" width="800" height="115"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;br&gt;
&lt;/p&gt;



&lt;p&gt;Now generate the site. You can use the live-reloading site during development and when you're ready to deploy, build the production site.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;mkdocs serve&lt;/code&gt; - Start the live-reloading docs server.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mkdocs build&lt;/code&gt; - Build the documentation site.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Almost ready!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enable &lt;a href="https://docs.github.com/en/pages/quickstart"&gt;GitHub Pages&lt;/a&gt; for your project. Make sure you set it to use the &lt;code&gt;main&lt;/code&gt; branch and the &lt;code&gt;/docs&lt;/code&gt; folder.&lt;/li&gt;
&lt;li&gt;Commit your changes and push them to GitHub. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This will kick off a GitHub Action to serve your site. After about a minute it will be available at &lt;code&gt;username.github.io/repo&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Go ahead and create stunning technical documentation for your project!&lt;/p&gt;

</description>
      <category>github</category>
      <category>documentation</category>
      <category>mkdocs</category>
    </item>
    <item>
      <title>Block ads with Pi-hole and Kubernetes</title>
      <dc:creator>Armando C. Santisbon</dc:creator>
      <pubDate>Tue, 14 Mar 2023 21:49:35 +0000</pubDate>
      <link>https://dev.to/santisbon/block-ads-on-your-whole-network-2gmd</link>
      <guid>https://dev.to/santisbon/block-ads-on-your-whole-network-2gmd</guid>
      <description>&lt;p&gt;While there are browser extensions and apps you can use to block ads on your desktop and mobile, they require installing them individually on each of your devices. And that's assuming there's an app available for the device and OS in question. &lt;/p&gt;

&lt;p&gt;Wouldn't it be better to also block ads at the router level? All those smart TVs, set-top boxes, game consoles, VR headsets, smart speakers, smart thermostats, robot vacuums, security cameras, doorbells, and other IoT devices love chatting with metrics/ad services. Let's put a stop to that by deploying a DNS server that will block requests to known ad servers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.raspberrypi.com/products/raspberry-pi-4-model-b/"&gt;Raspberry Pi&lt;/a&gt; is a tiny computer you can use as a desktop, smart home hub, robot brains, media center, and more. If you have been thinking about setting up a homelab, a Raspberry Pi is a great place to start at an extremely low cost. They are in high demand but &lt;a href="https://rpilocator.com"&gt;this site&lt;/a&gt; can help you find one.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://microk8s.io"&gt;MicroK8s&lt;/a&gt; is a lightweight distribution of Kubernetes (K8s) for container orchestration. We'll also use &lt;a href="https://helm.sh"&gt;Helm&lt;/a&gt;, a package manager for K8s, for easy deployment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.pi-hole.net"&gt;Pi-hole&lt;/a&gt; is a DNS sinkhole that protects your devices from unwanted content, without installing any client-side software. It's installed in one place and blocks ads for your entire home network. &lt;/p&gt;

&lt;p&gt;When you're done you'll have an admin interface for all your K8s workloads:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--j1q-t3GC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/Gb4C6py.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--j1q-t3GC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/Gb4C6py.jpg" alt="k8s" width="800" height="230"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And another for your Pi-hole stats:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hYcS1A7s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/0EDMcjL.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hYcS1A7s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/0EDMcjL.jpg" alt="pi-hole" width="800" height="815"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's get started! All the details are here:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/santisbon"&gt;
        santisbon
      &lt;/a&gt; / &lt;a href="https://github.com/santisbon/pi-hole-k8s"&gt;
        pi-hole-k8s
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Deploy Pi-hole to a Kubernetes cluster on a Raspberry Pi.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1 id="user-content-network-wide-ad-blocking-with-pi-hole-kubernetes-and-raspberry-pi"&gt;&lt;a class="heading-link" href="https://github.com/santisbon/pi-hole-k8s#network-wide-ad-blocking-with-pi-hole-kubernetes-and-raspberry-pi"&gt;Network-wide ad blocking with Pi-hole, Kubernetes, and Raspberry Pi&lt;/a&gt;&lt;/h1&gt;
&lt;h2 id="user-content-prerequisites"&gt;&lt;a class="heading-link" href="https://github.com/santisbon/pi-hole-k8s#prerequisites"&gt;Prerequisites&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://santisbon.github.io/reference/rpi/" rel="nofollow"&gt;Set up&lt;/a&gt; your Raspberry Pi with a static IP.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://santisbon.github.io/reference/k8s/#microk8s" rel="nofollow"&gt;Install and configure MicroK8s&lt;/a&gt; (or any other lightweight Kubernetes distribution) on your Pi.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="user-content-install"&gt;&lt;a class="heading-link" href="https://github.com/santisbon/pi-hole-k8s#install"&gt;Install&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Prepare your Pi's storage
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; On your Pi&lt;/span&gt;
sudo mkdir -p /etc/pihole
sudo mkdir -p /etc/dnsmasq.d&lt;/pre&gt;

&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;If installing from source, grab the code
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; On your Pi&lt;/span&gt;
CHART=&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;./piholechart&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;
git clone https://github.com/santisbon/pi-hole-k8s.git &lt;span class="pl-k"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="pl-c1"&gt;cd&lt;/span&gt; pi-hole-k8s
nano &lt;span class="pl-smi"&gt;$CHART&lt;/span&gt;/values.yaml
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; edit the values&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
Or if installing from the repository
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; On your Pi&lt;/span&gt;
helm repo add santisbon https://santisbon.github.io/charts/
CHART=&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;santisbon/pihole&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;Install the Helm chart which will &lt;a href="https://helm.sh/docs/intro/using_helm" rel="nofollow"&gt;enforce the installation order&lt;/a&gt;. Replace parameters with a secure password and the static IP of your Pi if you didn't do it through the &lt;code&gt;values.yaml&lt;/code&gt; file. If using MicroK8s type the commands as &lt;code&gt;microk8s helm&lt;/code&gt; and &lt;code&gt;microk8s kubectl&lt;/code&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; On your Pi&lt;/span&gt;
RELEASE=pihole
NAMESPACE=pihole-n
helm install &lt;/pre&gt;…
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/santisbon/pi-hole-k8s"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


</description>
      <category>raspberrypi</category>
      <category>kubernetes</category>
      <category>pihole</category>
      <category>homelab</category>
    </item>
    <item>
      <title>Service Worker lifecycle</title>
      <dc:creator>Armando C. Santisbon</dc:creator>
      <pubDate>Sun, 05 Mar 2023 22:13:04 +0000</pubDate>
      <link>https://dev.to/santisbon/service-worker-lifecycle-32op</link>
      <guid>https://dev.to/santisbon/service-worker-lifecycle-32op</guid>
      <description>&lt;p&gt;Getting started with Progressive Web Apps (PWAs)? Here's a succinct explanation of the &lt;a href="https://web.dev/learn/pwa/service-workers/"&gt;service worker&lt;/a&gt; (SW) lifecycle and update process.&lt;/p&gt;

&lt;h2&gt;
  
  
  SW lifecycle:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The SW is registered with&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;serviceWorker&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;serviceWorker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/serviceworker.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The browser attempts to download and parse the SW file as JavaScript.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If it succeeds the install event is fired (it only fires once). The SW is now installed but not yet in control of its clients like the PWA.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;By default, the SW will not take control until the next time you navigate to the page by reloading it or re-opening the PWA.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LErL6c2f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://sketchviz.com/%40santisbon/e09914c18e60eb9a76e31a9a37eb22cc/c0189157aacc7f6d16ce1c7684d1dafbbfad8510.sketchy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LErL6c2f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://sketchviz.com/%40santisbon/e09914c18e60eb9a76e31a9a37eb22cc/c0189157aacc7f6d16ce1c7684d1dafbbfad8510.sketchy.png" alt="SW Lifecycle" width="209" height="479"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Updating a SW
&lt;/h2&gt;

&lt;p&gt;You can find all the details &lt;a href="https://developer.chrome.com/docs/workbox/service-worker-lifecycle/#handling-service-worker-updates"&gt;here&lt;/a&gt; and can be summarized like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Browser detects that the SW currently controlling the client and the new (from the server) version of the same file are byte-different.&lt;/li&gt;
&lt;li&gt;After the new SW is installed it will wait to activate until the old SW no longer controls any clients. This way only 1 version of the SW runs at a time. Refreshing the page or reopening the PWA won't make the new SW take control.&lt;/li&gt;
&lt;li&gt;The user closes or navigates away from all tabs and windows using the curernt SW and then navigates back. The new SW takes control.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--84Oy3l_m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://sketchviz.com/%40santisbon/2d2264a2a938d6ccaf5a3b95de0a34fe/f31c80d4f992fca95bfa00f44bf53ff9fcf7378a.sketchy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--84Oy3l_m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://sketchviz.com/%40santisbon/2d2264a2a938d6ccaf5a3b95de0a34fe/f31c80d4f992fca95bfa00f44bf53ff9fcf7378a.sketchy.png" alt="SW Update" width="346" height="295"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>pwa</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Serving a React Router app through CloudFront</title>
      <dc:creator>Armando C. Santisbon</dc:creator>
      <pubDate>Fri, 03 Mar 2023 05:44:12 +0000</pubDate>
      <link>https://dev.to/santisbon/serving-a-react-router-app-through-cloudfront-1h28</link>
      <guid>https://dev.to/santisbon/serving-a-react-router-app-through-cloudfront-1h28</guid>
      <description>&lt;p&gt;Single Page Apps (SPAs) are great. They can be hosted as a static site on object storage like an S3 bucket and served through a CDN like CloudFront to cache the content close to your users wherever they are in the world. All without having to manage server infrastructure.&lt;/p&gt;

&lt;p&gt;There are however, things to keep in mind to make this setup work. The different frameworks these apps are built on have their own way of dealing with URLs. For example, React Router can intercept the request and handle it instead of sending it to the server. &lt;/p&gt;

&lt;p&gt;This client-side routing means that React Router knows how to handle a request for &lt;code&gt;www.example.com/products/12&lt;/code&gt; while clearly there's no such resource as &lt;code&gt;&amp;lt;bucket-name&amp;gt;/products/12&lt;/code&gt; on the server. This all works fine as long as navigation happens within your app where React can intercept those requests. The only request the server should be handling is for &lt;code&gt;www.example.com&lt;/code&gt; or any other resource that actually lives on the server.&lt;/p&gt;

&lt;p&gt;But what happens when you type  &lt;code&gt;www.example.com/products/12&lt;/code&gt; in your browser's address bar and hit enter? That request is going to the server where it will make no sense because there's no resource by that URI. You might get something like this in your browser's console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Refused to apply style from 'https://www.example.com/assets/index-12345abc.css' because its MIME type ('text/html') is not a supported stylesheet MIME type, and strict MIME checking is enabled.
Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This and other errors have the same underlying cause: the resource your browser asked for is just not there. Depending on your setup, the server might be replying with the default document or something else.&lt;/p&gt;

&lt;p&gt;We need to run some code at the edge locations that can intercept the request, rewrite the URI, and hand it over to CloudFront for further processing. If the requested resource is something the client should handle, set the URI to &lt;code&gt;/&lt;/code&gt; so the server will respond as expected and let the client figure out how to handle the request. If the requested URI is for a server resource like &lt;code&gt;/img/cat.jpg&lt;/code&gt; then don't change it. Fortunately, CloudFront Functions let us do precisely that. You write them in Javascript, with &lt;a href="https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/functions-javascript-runtime-features.html"&gt;some restrictions&lt;/a&gt;. Here [1] is an example showing you how to create and test a function that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;paths&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;assets&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;img&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;robots.txt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app.webmanifest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;isServerPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isServerPath&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, &lt;code&gt;assets/&lt;/code&gt; is the folder where your bundler e.g. Vite places your app's Javascript and CSS files for production.&lt;/p&gt;

&lt;p&gt;Once you have your CloudFront function working, it's time to associate it with your CloudFront distribution. This [2] will show you how to deploy your SPA as a secure static site with a CloudFront function handling requests as needed by React Router.&lt;/p&gt;

&lt;p&gt;[1] &lt;a href="https://github.com/santisbon/amazon-cloudfront-functions/tree/main/url-rewrite-single-page-apps"&gt;https://github.com/santisbon/amazon-cloudfront-functions/tree/main/url-rewrite-single-page-apps&lt;/a&gt;&lt;br&gt;&lt;br&gt;
[2] &lt;a href="https://github.com/santisbon/static-site"&gt;https://github.com/santisbon/static-site&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>cloudfront</category>
      <category>aws</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
