site

Unnamed repository; edit this file 'description' to name the repository.
git clone https://git.beauhilton.com/site.git
Log | Files | Refs

commit f75f832bdf8a7967f5935fbf53e844d8d8f94f86
parent ecad8a35ecc759c3d59bec4efd959a6c79f69464
Author: Beau <cbeauhilton@gmail.com>
Date:   Thu,  1 Dec 2022 14:42:34 -0600

small change to test build

Diffstat:
Atest/about/index.html | 81+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atest/atom.xml | 88+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atest/contact/index.html | 46++++++++++++++++++++++++++++++++++++++++++++++
Atest/index.html | 38++++++++++++++++++++++++++++++++++++++
Atest/now/index.html | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atest/posts/employee-wifi/index.html | 240+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atest/posts/geocheatcode/index.html | 243+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atest/posts/index.html | 119+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atest/posts/intake-2022-03-25/index.html | 98+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atest/posts/mime/index.html | 144+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atest/posts/mr-2021/index.html | 419+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atest/posts/ugbsd/index.html | 100+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atest/style.css | 296+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atest/wants/index.html | 90+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
14 files changed, 2073 insertions(+), 0 deletions(-)

diff --git a/test/about/index.html b/test/about/index.html @@ -0,0 +1,81 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <link rel="stylesheet" href="/style.css" type="text/css"> + <meta charset="utf-8"> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <link rel="stylesheet" type="text/css" href="/style.css"> + <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cstyle%3E %23m %7B opacity:0; %7D%0A@media (prefers-color-scheme: dark) %7B %23m %7B opacity:1; %7D %23e %7B opacity:0 %7D%0A%7D %3C/style%3E%3Ctext id='m' y='.9em' font-size='90'%3E🏕️%3C/text%3E%3Ctext id='e' y='.9em' font-size='90'%3E🌞%3C/text%3E%3C/svg%3E"> + <title></title> + </head> + <body> + <div id="page-wrapper"> + <div id="header" role="banner"> + <header class="banner"> + <div id="banner-text"> + <span class="banner-title"><a href="/">beauhilton</a></span> + </div> + </header> + <nav> + <a class="nav-active" href="/about">about</a> +<a href="/now">now</a> +<a href="/posts">posts</a> +<a href="https://notes.beauhilton.com">notes</a> +<a href="https://talks.beauhilton.com">talks</a> +<a href="https://git.beauhilton.com">git</a> +<a href="/contact">contact</a> +<a href="/feed.xml">rss</a> + </nav> + </div> + <main> + <h1> + about + </h1> + <p> + I’m a husband, father, physician, educator, and data scientist. + </p> + <h2> + husband and father + </h2> + <p> + These are the most important roles I play. If we meet, and you’re +interested, we can talk about it. + </p> + <h2> + physician + </h2> + <p> + Medical school at Cleveland Clinic Lerner College of Medicine of Case +Western Reserve University, Class of 2020. + </p> + <p> + Harrison Society member at Vanderbilt University, which includes +internal medicine residency (2020-2022) and research/fellowship in +hematology-oncology (2022-2026). + </p> + <h2> + educator + </h2> + <p> + Harvard Macy Institute faculty, 2018-present. Health Care Education +2.0. + </p> + <h2> + data scientist + </h2> + <p> + Machine learning and data science approaches to diagnosis and +prognosis of blood cancers; healthcare disparities in hospital medicine; +predictive modeling of hospital readmissions and length of stay. + </p> + <p> + <a href="https://scholar.google.com/citations?user=Ng5AgXAAAAAJ">Google +Scholar profile</a> + </p> + </main> + <div id="footnotes"></div> + <footer></footer> + </div> + </body> +</html> diff --git a/test/atom.xml b/test/atom.xml @@ -0,0 +1,87 @@ +<?xml version='1.0' encoding='UTF-8'?> +<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"> + <id>https://soupault.app/atom.xml</id> + <title>beauhilton</title> + <updated>2022-11-13T00:00:00+00:00</updated> + <author> + <name>beau hilton</name> + <email>beau@beauhilton.com</email> + </author> + <generator uri="https://soupault.app" version="4.3.1">soupault</generator> + <logo>🏕️</logo> + <subtitle>beau's website</subtitle> + <entry> + <id>https://soupault.app/posts/mime</id> + <title>fix MIME Types to unbreak RSS feeds served by OpenBSD’s +httpd(8)</title> + <updated>2022-11-13T00:00:00+00:00</updated> + <content type="html"> + I've been getting back into RSS lately. +Turns out, my own RSS feed was broken. + </content> + <link href="https://soupault.app/posts/mime" rel="alternate"/> + </entry> + + <entry> + <id>https://soupault.app/posts/ugbsd</id> + <title>Upgrading out-of-date OpenBSD installs</title> + <updated>2022-11-11T00:00:00+00:00</updated> + <content type="html"> + First of all, don't do how I do. +Upgrade your installs regularly. +OpenBSD makes it very easy. + </content> + <link href="https://soupault.app/posts/ugbsd" rel="alternate"/> + </entry> + + <entry> + <id>https://soupault.app/posts/geocheatcode</id> + <title>geocheatcode</title> + <updated>2022-04-22T00:00:00+00:00</updated> + <content type="html"> + Here is background and code +for a trick I use to get +Google to give me best-in-class guesses +for latitude and longitude, +despite goofy and/or downright bad location searches. + </content> + <link href="https://soupault.app/posts/geocheatcode" rel="alternate"/> + </entry> + + <entry> + <id>https://soupault.app/posts/intake-2022-03-25</id> + <title>intake</title> + <updated>2022-03-25T00:00:00+00:00</updated> + <content type="html"> + candidal esophagitis, achalasia, H Pylori PUD + </content> + <link href="https://soupault.app/posts/intake-2022-03-25" rel="alternate"/> + </entry> + + <entry> + <id>https://soupault.app/posts/employee-wifi</id> + <title>Set Up Enterprise Wifi on Arch Linux</title> + <updated>2021-09-17T00:00:00+00:00</updated> + <content type="html"> + Most big institutions have guest and employee wifi networks. +Guest wifi is usually fine, fast enough for the basics, +but far inferior to employee wifi. +On a custom-built OS, such as a fairly minimalist Linux distribution, +getting the employee wifi to work +can be a beast. + </content> + <link href="https://soupault.app/posts/employee-wifi" rel="alternate"/> + </entry> + + <entry> + <id>https://soupault.app/posts/mr-2021</id> + <title>Morning Report 08/23/2021</title> + <updated>2021-08-23T00:00:00+00:00</updated> + <content type="html"> + Diagnosis is... MDS/MPN/MF NOS. +i.e., who knows. + </content> + <link href="https://soupault.app/posts/mr-2021" rel="alternate"/> + </entry> + +</feed> +\ No newline at end of file diff --git a/test/contact/index.html b/test/contact/index.html @@ -0,0 +1,46 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <link rel="stylesheet" href="/style.css" type="text/css"> + <meta charset="utf-8"> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <link rel="stylesheet" type="text/css" href="/style.css"> + <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cstyle%3E %23m %7B opacity:0; %7D%0A@media (prefers-color-scheme: dark) %7B %23m %7B opacity:1; %7D %23e %7B opacity:0 %7D%0A%7D %3C/style%3E%3Ctext id='m' y='.9em' font-size='90'%3E🏕️%3C/text%3E%3Ctext id='e' y='.9em' font-size='90'%3E🌞%3C/text%3E%3C/svg%3E"> + <title></title> + </head> + <body> + <div id="page-wrapper"> + <div id="header" role="banner"> + <header class="banner"> + <div id="banner-text"> + <span class="banner-title"><a href="/">beauhilton</a></span> + </div> + </header> + <nav> + <a href="/about">about</a> +<a href="/now">now</a> +<a href="/posts">posts</a> +<a href="https://notes.beauhilton.com">notes</a> +<a href="https://talks.beauhilton.com">talks</a> +<a href="https://git.beauhilton.com">git</a> +<a class="nav-active" href="/contact">contact</a> +<a href="/feed.xml">rss</a> + </nav> + </div> + <main> + <p> + This is my social media account. + </p> + <p> + If you want to get in touch, email: <a href="mailto:beau@beauhilton.com">beau@beauhilton.com</a>. + </p> + <p> + I’ll respond within the week. + </p> + </main> + <div id="footnotes"></div> + <footer></footer> + </div> + </body> +</html> diff --git a/test/index.html b/test/index.html @@ -0,0 +1,38 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <link rel="stylesheet" href="/style.css" type="text/css"> + <meta charset="utf-8"> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <link rel="stylesheet" type="text/css" href="/style.css"> + <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cstyle%3E %23m %7B opacity:0; %7D%0A@media (prefers-color-scheme: dark) %7B %23m %7B opacity:1; %7D %23e %7B opacity:0 %7D%0A%7D %3C/style%3E%3Ctext id='m' y='.9em' font-size='90'%3E🏕️%3C/text%3E%3Ctext id='e' y='.9em' font-size='90'%3E🌞%3C/text%3E%3C/svg%3E"> + <title></title> + </head> + <body> + <div id="page-wrapper"> + <div id="header" role="banner"> + <header class="banner"> + <div id="banner-text"> + <span class="banner-title"><a href="/">beauhilton</a></span> + </div> + </header> + <nav> + <a href="/about">about</a> +<a href="/now">now</a> +<a href="/posts">posts</a> +<a href="https://notes.beauhilton.com">notes</a> +<a href="https://talks.beauhilton.com">talks</a> +<a href="https://git.beauhilton.com">git</a> +<a href="/contact">contact</a> +<a href="/feed.xml">rss</a> + </nav> + </div> + <main> + <br> + </main> + <div id="footnotes"></div> + <footer></footer> + </div> + </body> +</html> diff --git a/test/now/index.html b/test/now/index.html @@ -0,0 +1,71 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <link rel="stylesheet" href="/style.css" type="text/css"> + <meta charset="utf-8"> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <link rel="stylesheet" type="text/css" href="/style.css"> + <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cstyle%3E %23m %7B opacity:0; %7D%0A@media (prefers-color-scheme: dark) %7B %23m %7B opacity:1; %7D %23e %7B opacity:0 %7D%0A%7D %3C/style%3E%3Ctext id='m' y='.9em' font-size='90'%3E🏕️%3C/text%3E%3Ctext id='e' y='.9em' font-size='90'%3E🌞%3C/text%3E%3C/svg%3E"> + <title></title> + </head> + <body> + <div id="page-wrapper"> + <div id="header" role="banner"> + <header class="banner"> + <div id="banner-text"> + <span class="banner-title"><a href="/">beauhilton</a></span> + </div> + </header> + <nav> + <a href="/about">about</a> +<a class="nav-active" href="/now">now</a> +<a href="/posts">posts</a> +<a href="https://notes.beauhilton.com">notes</a> +<a href="https://talks.beauhilton.com">talks</a> +<a href="https://git.beauhilton.com">git</a> +<a href="/contact">contact</a> +<a href="/feed.xml">rss</a> + </nav> + </div> + <main> + <h1> + family + </h1> + <p> + Our oldest is 8, youngest is 2. Everyone remains well and +cantankerous. + </p> + <h1> + work + </h1> + <p> + I’m an internal medicine doctor at Vanderbilt University Medical +Center. + </p> + <p> + In July I’ll start cancer fellowship, here as well, as a member of +the <a href="https://medicine.vumc.org/harrison-society">Harrison +Society</a>. + </p> + <h1> + other + </h1> + <p> + Ted Hawkins’ song “<a href="https://youtu.be/jTO-zb6XTzg">Sorry +You’re Sick</a>” reminds me of the book <a href="https://en.wikipedia.org/wiki/One_Day_in_the_Life_of_Ivan_Denisovich"><em>One +Day in the Life of Ivan Denisovich</em></a> by Aleksandr Solzhenitsyn, +and the uncomfortable and sublime truth that all medicine is palliative +medicine. + </p> + <hr> + <p> + This <a href="https://nownownow.com/about">now page</a> was last +updated 2022-04-22. + </p> + </main> + <div id="footnotes"></div> + <footer></footer> + </div> + </body> +</html> diff --git a/test/posts/employee-wifi/index.html b/test/posts/employee-wifi/index.html @@ -0,0 +1,240 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <link rel="stylesheet" href="/style.css" type="text/css"> + <meta charset="utf-8"> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <link rel="stylesheet" type="text/css" href="/style.css"> + <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cstyle%3E %23m %7B opacity:0; %7D%0A@media (prefers-color-scheme: dark) %7B %23m %7B opacity:1; %7D %23e %7B opacity:0 %7D%0A%7D %3C/style%3E%3Ctext id='m' y='.9em' font-size='90'%3E🏕️%3C/text%3E%3Ctext id='e' y='.9em' font-size='90'%3E🌞%3C/text%3E%3C/svg%3E"> + <title></title> + </head> + <body> + <div id="page-wrapper"> + <div id="header" role="banner"> + <header class="banner"> + <div id="banner-text"> + <span class="banner-title"><a href="/">beauhilton</a></span> + </div> + </header> + <nav> + <a href="/about">about</a> +<a href="/now">now</a> +<a class="nav-active" href="/posts">posts</a> +<a href="https://notes.beauhilton.com">notes</a> +<a href="https://talks.beauhilton.com">talks</a> +<a href="https://git.beauhilton.com">git</a> +<a href="/contact">contact</a> +<a href="/feed.xml">rss</a> + </nav> + </div> + <main> + <h1> + Set Up Enterprise Wifi on Arch Linux + </h1> + <p> + <time id="post-date">2021-09-17</time> + </p> + <p id="post-excerpt"> + Most big institutions have guest and employee wifi networks. +Guest wifi is usually fine, fast enough for the basics, +but far inferior to employee wifi. +On a custom-built OS, such as a fairly minimalist Linux distribution, +getting the employee wifi to work +can be a beast. + </p> + <p> + This was a little tricky to get working but very worth it, so here’s +an outline, mostly for my own later benefit. + </p> + <p></p> + <p> + This post is specific to <a href="https://www.vumc.org">VUMC</a>, +with the VUMCEmployee network. + </p> + <p> + Similar steps should be applicable for other enterprise wifi users, +though this post will unquestionably be out of date before long, and the +intricacies of enterprise wifi are infinite. + </p> + <h2> + VUMCGuest is fine + </h2> + <p> + As with other public networks at large institutions, VUMCGuest is +just a little slow and finicky, and it’s annoying to have to +re-authenticate repeatedly to use all the HIPAA-compliant things. + </p> + <h2> + VUMCEmployee is better + </h2> + <p> + I’ll probably put a screenshot here at some point comparing speedtest +scores. VUMCEmployee gives over 100 Mbps down, and around 100 up. + </p> + <p> + It’s also more stable, and latency is around 10ms. + </p> + <p> + Most practical gain, other than faster everything: When I use +VUMCGuest, the keyboard shortcut I use to launch and automatically login +to Epic only works intermittently. On VUMCEmployee, it works reliably. +No more typing! It’s faster and, again, more reliable than tapping the +badge-readers at the VUMC workstations. + </p> + <h2> + Backend + </h2> + <p> + The personal networking stack of greatest beauty on Linux at this +point is: + </p> + <p> + <code>systemd-networkd</code> +<code>systemd-resolved</code> + +<code>iwd</code> + </p> + <p> + Disable and delete <code>NetworkManager</code> and other such +nonsense, if you are unwise like me and installed conflicting and +useless things. + </p> + <p> + If you’d like a GUI, <a href="https://github.com/J-Lentz/iwgtk">iwgtk</a> is nice, but the CLI +shipped with <code>iwd</code> (<code>iwctl</code>) is intuitive, +friendly, and well-documented. I keep the GUI version around for quickly +checking on things via a keyboard shortcut, but use the CLI for any +heavy lifting, which has thankfully become rare since landing on this +setup. + </p> + <h2> + Start with VUMCEmployeeSetup + </h2> + <p> + First, log on to the VUMCEmployeeSetup wifi. Then navigate to one of +my favorite websites, <a href="http://neverssl.com/">http://neverssl.com/</a>. This will force +the redirect to the VUMCEmployee enrollment page (I also use this site +for connecting to public wifi at airports, libraries, coffee shops, +etc.). Agree to the terms and conditions. Then click the “Show all +operating systems” link at the bottom, followed by the “Other Operating +Systems” tab that pops up at the bottom of the list. + </p> + <p> + The “Other Operating Systems” tab has three steps listed, which are +simply the pieces that the various installers put together for you. The +first two are downloads for certificates, and the third is a +template. + </p> + <p> + Finding this tab was the gold mine - initially I repackaged one of +the other Linux installers for Arch, because I thought that (since there +was an installer) the process must be complicated, and repackaging +things from Debian-based systems for Arch-based systems is easy enough. +The repackaged version of the installer was decent at first, but it +turns out that the manual process is easier and more reliable. I also +learned more about enterprise networks in the process, which was an +added bonus (I’m honestly not sure about the sarcasm:sincerity ratio in +the previous sentence). + </p> + <p> + Download the <code>PEM</code> files listed under Steps 1 (root +certificate) and 2 (client certificate). + </p> + <h2> + Make your own <code>iwd</code> profile + </h2> + <p> + Here’s where it goes: +<code>/var/lib/iwd/VUMCEmployee.8021x</code> + </p> + <p> + Below are the contents, sensitive info redacted, then we’ll go +through some of the key parts and one nicety. + </p> + <pre tabindex="0"><code class="language-toml"><span class="hl kwa">[IPv6]</span> +<span class="hl kwb">Enabled</span><span class="hl opt">=</span><span class="hl kwd">true</span> + +<span class="hl kwa">[Security]</span> +<span class="hl kwb">EAP-Method</span><span class="hl opt">=</span>PEAP +<span class="hl kwb">EAP-Identity</span><span class="hl opt">=</span>username +<span class="hl kwb">EAP-PEAP-CACert</span><span class="hl opt">=</span>embed<span class="hl opt">:</span>root_cert +<span class="hl kwb">EAP-PEAP-ServerDomainMask</span><span class="hl opt">=*</span>.radius.service.vumc.org +<span class="hl kwb">EAP-PEAP-Phase2-Method</span><span class="hl opt">=</span>MSCHAPV2 +<span class="hl kwb">EAP-PEAP-Phase2-Identity</span><span class="hl opt">=</span>username +<span class="hl kwb">EAP-PEAP-Phase2-Password</span><span class="hl opt">=</span>password + +<span class="hl kwa">[Settings]</span> +<span class="hl kwb">AutoConnect</span><span class="hl opt">=</span><span class="hl kwd">true</span> + +<span class="hl kwa">[@pem@root_cert]</span> +<span class="hl opt">-----</span>BEGIN CERTIFICATE<span class="hl opt">-----</span> +<span class="hl opt">*</span>lots of gobbledigook goes here<span class="hl opt">*</span> +<span class="hl opt">-----</span>END CERTIFICATE<span class="hl opt">-----</span> +</code></pre> + <p> + Most of these options are outlined in Step 3 from the +VUMCEmployeeSetup, cross-referenced against the Arch Wiki page on +<code>iwd</code>, subsection <a href="https://wiki.archlinux.org/title/Iwd#EAP-PEAP">Network +configuration</a>, and the <a href="https://iwd.wiki.kernel.org/networkconfigurationsettings"><code>iwd</code> +wiki proper</a>. + </p> + <p> + An easy-to-miss step: The <code>EAP-PEAP-Phase2-Method</code> +requirement for <code>MSCHAPV2</code> leads to another required install, +check the wiki for current instructions. + </p> + <p> + Put in your own username and password. + </p> + <p> + My favorite trick in this file is directly embedding the root +certificate in the line <code>EAP-PEAP-CACert=</code> with the syntax +<code>embed:root_cert</code> (any name is fine, doesn’t have to be +<code>root_cert</code>, it’s just a pointer). Then you add a definition +of <code>root_cert</code> in a <code>[@pem@root_cert]</code> section. +Insert the contents of the root certificate directly via copy-paste or +<code>cat</code>, etc. + </p> + <p> + Easiest method, as root: + </p> + <pre tabindex="0"><code class="language-shell">cat /home/beau/dl/root_cert.PEM &gt;&gt; /var/lib/iwd/VUMCEmployee.8021x +</code></pre> + <p> + With the direct embed method, you don’t need to point to the root +certificate file or keep it around at all. + </p> + <p> + Needless to say, <code>VUMCEmployee.8021x</code> is a sensitive file +and should be protected appropriately. However, this file or a version +of it is what the automated tools would have made anyway, so there’s no +special risk here - AND since you did it all yourself you know there was +no funny business coming from a black-box installer. + </p> + <h2> + The other certificate (Client) + </h2> + <p> + I can’t remember what I had to do with the client cert, probably +added using the Chrome/Firefox certificate managers. + </p> + <p> + I had to do this before when getting set up for VA remote access, the +Arch Wiki comes through again with an article on <a href="https://wiki.archlinux.org/title/Common_Access_Card">Common Access +Cards</a> that includes instructions on adding certs to browsers. + </p> + <p> + There’s a chance it’s not even needed? The <a href="https://iwd.wiki.kernel.org/networkconfigurationsettings">specification</a> +no longer supports adding a client cert field without a key, which I +don’t have, and do not, apparently, need (see the section “EAP-PEAP with +tunneled EAP-MSCHAPV2”). At any rate, this setup is working now and I +won’t futz with it further until something breaks. + </p> + <h2> + -&gt; ~~Profit~~ Prosper + </h2> + </main> + <div id="footnotes"></div> + <footer></footer> + </div> + </body> +</html> diff --git a/test/posts/geocheatcode/index.html b/test/posts/geocheatcode/index.html @@ -0,0 +1,243 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <link rel="stylesheet" href="/style.css" type="text/css"> + <meta charset="utf-8"> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <link rel="stylesheet" type="text/css" href="/style.css"> + <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cstyle%3E %23m %7B opacity:0; %7D%0A@media (prefers-color-scheme: dark) %7B %23m %7B opacity:1; %7D %23e %7B opacity:0 %7D%0A%7D %3C/style%3E%3Ctext id='m' y='.9em' font-size='90'%3E🏕️%3C/text%3E%3Ctext id='e' y='.9em' font-size='90'%3E🌞%3C/text%3E%3C/svg%3E"> + <title></title> + </head> + <body> + <div id="page-wrapper"> + <div id="header" role="banner"> + <header class="banner"> + <div id="banner-text"> + <span class="banner-title"><a href="/">beauhilton</a></span> + </div> + </header> + <nav> + <a href="/about">about</a> +<a href="/now">now</a> +<a class="nav-active" href="/posts">posts</a> +<a href="https://notes.beauhilton.com">notes</a> +<a href="https://talks.beauhilton.com">talks</a> +<a href="https://git.beauhilton.com">git</a> +<a href="/contact">contact</a> +<a href="/feed.xml">rss</a> + </nav> + </div> + <main> + <h1> + geocheatcode + </h1> + <p> + <time id="post-date">2022-04-22</time> + </p> + <p id="post-excerpt"> + Here is background and code +for a trick I use to get +Google to give me best-in-class guesses +for latitude and longitude, +despite goofy and/or downright bad location searches. + </p> + <h2> + Map all the things + </h2> + <p> + I love maps. + </p> + <p> + Several of my projects involve mapping things at scale. + </p> + <p> + When you want to map a few things, you type searches into Google Maps +and get addresses and/or latitudes and longitudes quickly and +reliably. + </p> + <p> + But what if you’d like to map 90,000 things whose locations you don’t +yet know? + </p> + <p> + <a href="https://developers.google.com/maps">Google</a> and <a href="https://www.openstreetmap.org/">OpenStreetMap</a>, as well as +others, provide mapping services you can call programmatically from your +software. You send in some query, such as “VUMC Internal Medicine,” and +they return information relevant to that query, such as street address +and latitude and longitude. Up to a certain number of queries per day or +hour, the services are free, and since my work is academic, rather than +real-time mapping for some for-profit app, I am happy to send in small +batches to stay under the limits in the free tier. + </p> + <p> + I’ve used these services to make large maps, and they work pretty +well. + </p> + <p> + <em>Pretty</em> well. + </p> + <h2> + But mapping is hard + </h2> + <p> + Problems with these services: + </p> + <ol type="1"> + <li> + they expected well-formed and reasonable queries + </li> + <li> + if they didn’t know the answer, the guesses were often wildly off, +or they would refuse to guess at all + </li> + </ol> + <p> + If I’m mapping 90,000 things, I’m going to write some code to go +through each of those 90,000 things and ask the mapping services to +kindly tell me what I want to know. Though I write sanitation code to +clean up the 90,000 things, I’m not going to quality check each of those +90,000 things. Sometimes things among the 90,000 things are kinda nuts +(misspelled, inclusive of extraneous data, oddly formatted), in +idiosyncratic ways that are impossible to completely cover, no matter +how much code I write to catch the weird cases. + </p> + <p> + I would like a solution that is fairly tolerant of weirdnesses, and +makes good guesses. + </p> + <h2> + Google is really good at search + </h2> + <p> + I noticed that when I manually typed things into the Google Maps +search bar, it forgave a myriad of sins and did a great job centering +the map on its best guess. When I copied and pasted some of the weird +things among the 90,000 into the Google Maps search bar (the same things +that made the official mapping services - including Google’s - go all +Poltergeist), <em>voila!</em>, the right answer appeared, success rates +nearing 100%. + </p> + <p> + I thought there must be a way to repeat this process with code, in a +scalable way. + </p> + <p> + Turns out there is, and it’s easy. + </p> + <h2> + <code>geocheatcode.py</code> + </h2> + <pre tabindex="0"><code class="language-python"> +<span class="hl kwa">from</span> requests_html <span class="hl kwa">import</span> HTMLSession + +session <span class="hl opt">=</span> <span class="hl kwd">HTMLSession</span><span class="hl opt">()</span> + + +<span class="hl kwa">def</span> <span class="hl kwd">google_lat_lon</span><span class="hl opt">(</span>query<span class="hl opt">:</span> <span class="hl kwb">str</span><span class="hl opt">):</span> + + url <span class="hl opt">=</span> <span class="hl sng">"https://www.google.com/maps/search/?api=1"</span> + params <span class="hl opt">= {}</span> + params<span class="hl opt">[</span><span class="hl sng">"query"</span><span class="hl opt">] =</span> query + + r <span class="hl opt">=</span> session<span class="hl opt">.</span><span class="hl kwd">get</span><span class="hl opt">(</span>url<span class="hl opt">,</span> params<span class="hl opt">=</span>params<span class="hl opt">)</span> + + reg <span class="hl opt">=</span> <span class="hl sng">"APP_INITIALIZATION_STATE=[[[{}]"</span> + res <span class="hl opt">=</span> r<span class="hl opt">.</span>html<span class="hl opt">.</span><span class="hl kwd">search</span><span class="hl opt">(</span>reg<span class="hl opt">)[</span><span class="hl num">0</span><span class="hl opt">]</span> + lat <span class="hl opt">=</span> res<span class="hl opt">.</span><span class="hl kwd">split</span><span class="hl opt">(</span><span class="hl sng">","</span><span class="hl opt">)[</span><span class="hl num">2</span><span class="hl opt">]</span> + lon <span class="hl opt">=</span> res<span class="hl opt">.</span><span class="hl kwd">split</span><span class="hl opt">(</span><span class="hl sng">","</span><span class="hl opt">)[</span><span class="hl num">1</span><span class="hl opt">]</span> + + <span class="hl kwa">return</span> lat<span class="hl opt">,</span> lon + + +extraneous <span class="hl opt">=</span> <span class="hl sng">""" something something</span> +<span class="hl sng"> the earth is banana shaped</span> +<span class="hl sng"> latitude and longitude </span> +<span class="hl sng"> wouldn't you like to know, maybe """</span> + +relevant <span class="hl opt">=</span> <span class="hl sng">""" Vanderbilt University Medical Center </span> +<span class="hl sng"> Internal Medicine """</span> + +query <span class="hl opt">=</span> extraneous <span class="hl opt">+</span> relevant + +lat<span class="hl opt">,</span> lon <span class="hl opt">=</span> <span class="hl kwd">google_lat_lon</span><span class="hl opt">(</span>query<span class="hl opt">)</span> + +<span class="hl kwa">print</span><span class="hl opt">(</span> + <span class="hl sng">"Hello. "</span> + <span class="hl sng">"My name is Google. "</span> + <span class="hl sng">"I am really good at guessing what you meant. "</span> + f<span class="hl sng">"Your query was '</span><span class="hl ipl">{query}</span><span class="hl sng">'. "</span> + <span class="hl sng">"Here are the coordinates you probably wanted. "</span> + f<span class="hl sng">"The latitude is</span> <span class="hl ipl">{lat}</span><span class="hl sng">, and the longitude is</span> <span class="hl ipl">{lon}</span><span class="hl sng">. "</span> + <span class="hl sng">"Don't believe me? "</span> + <span class="hl sng">"Here it is again, "</span> + <span class="hl sng">"in a format you can paste into the search bar:</span> <span class="hl esc">\n</span><span class="hl sng">"</span> + f<span class="hl sng">"</span><span class="hl ipl">{lat}</span><span class="hl sng">,</span> <span class="hl ipl">{lon}</span> <span class="hl sng"></span><span class="hl esc">\n</span><span class="hl sng">"</span> + <span class="hl sng">"Told ya. "</span> +<span class="hl opt">)</span> +</code></pre> + <p> + Despite having all that extra junk in the query, this returns the +right answer. Because Google is many things good and evil, but of these +one is certain: Google is <em>really</em> good at search. + </p> + <h2> + How does the code work? + </h2> + <p> + If you inspect the source HTML on the Google Maps website after you +search for something and it centers the map on its best guess, and you +scroll way on down (or Ctrl-F search for it) you’ll find +<code>APP_INITIALIZATION_STATE</code>, which contains latitude and +longitude for the place the map centered on. + </p> + <ul> + <li> + <a href="https://www.google.com/maps?q=something+whose+latitude+and+longitude+you+would+like+to+know,+maybe+VUMC+Internal+Medicine">example +search</a> + </li> + <li> + <a href="view-source:https://www.google.com/maps/search/something+whose+latitude+and+longitude+you+would+like+to+know,+maybe+VUMC+Internal+Medicine/">example +source</a> (you have to copy and paste this link into a new tab +manually, clicking won’t work) + </li> + </ul> + <p> + I use the lovely <a href="https://docs.python-requests.org/projects/requests-html/en/latest/"><code>requests-html</code></a> +Python library to send the query to Google, receive the response, and +search through the response for the part I want to extract. Then I use a +little standard Python to parse the extracted part and save the +important bits. + </p> + <h2> + With great power… + </h2> + <p> + Don’t go crazy with this. + </p> + <p> + The trick is good for leisurely automation of location retrieval when +you have squirrelly queries. + </p> + <p> + If you need real-time mapping of many things, you don’t want this +solution. Use the actual APIs, and work instead on formatting the +queries properly before sending them to Google/OSM. + </p> + <p> + Also, if you try to query too much/too quickly, Google will shut you +out after a little while. Put a few seconds of delay between each +request and run it overnight and/or in automated batches. + </p> + <h2> + Know a better way? + </h2> + <p> + I’d love to know. Drop me a line. + </p> + </main> + <div id="footnotes"></div> + <footer></footer> + </div> + </body> +</html> diff --git a/test/posts/index.html b/test/posts/index.html @@ -0,0 +1,119 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <link rel="stylesheet" href="/style.css" type="text/css"> + <meta charset="utf-8"> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <link rel="stylesheet" type="text/css" href="/style.css"> + <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cstyle%3E %23m %7B opacity:0; %7D%0A@media (prefers-color-scheme: dark) %7B %23m %7B opacity:1; %7D %23e %7B opacity:0 %7D%0A%7D %3C/style%3E%3Ctext id='m' y='.9em' font-size='90'%3E🏕️%3C/text%3E%3Ctext id='e' y='.9em' font-size='90'%3E🌞%3C/text%3E%3C/svg%3E"> + <title></title> + </head> + <body> + <div id="page-wrapper"> + <div id="header" role="banner"> + <header class="banner"> + <div id="banner-text"> + <span class="banner-title"><a href="/">beauhilton</a></span> + </div> + </header> + <nav> + <a href="/about">about</a> +<a href="/now">now</a> +<a class="nav-active" href="/posts">posts</a> +<a href="https://notes.beauhilton.com">notes</a> +<a href="https://talks.beauhilton.com">talks</a> +<a href="https://git.beauhilton.com">git</a> +<a href="/contact">contact</a> +<a href="/feed.xml">rss</a> + </nav> + </div> + <main> + <h1 id="title"> + Posts + </h1> + <p> + You can subscribe to the <a href="/atom.xml">Atom feed</a> to receive updates. + </p> + <div id="posts-index"> + <h2> + <a href="/posts/mime">fix MIME Types to unbreak RSS feeds served by OpenBSD’s +httpd(8)</a> + </h2> + <p> + <strong>Last update:</strong> 2022-11-13. + </p> + <p> + I've been getting back into RSS lately. +Turns out, my own RSS feed was broken. + </p> + <a href="/posts/mime">Read more</a> + <h2> + <a href="/posts/ugbsd">Upgrading out-of-date OpenBSD installs</a> + </h2> + <p> + <strong>Last update:</strong> 2022-11-11. + </p> + <p> + First of all, don't do how I do. +Upgrade your installs regularly. +OpenBSD makes it very easy. + </p> + <a href="/posts/ugbsd">Read more</a> + <h2> + <a href="/posts/geocheatcode">geocheatcode</a> + </h2> + <p> + <strong>Last update:</strong> 2022-04-22. + </p> + <p> + Here is background and code +for a trick I use to get +Google to give me best-in-class guesses +for latitude and longitude, +despite goofy and/or downright bad location searches. + </p> + <a href="/posts/geocheatcode">Read more</a> + <h2> + <a href="/posts/intake-2022-03-25">intake</a> + </h2> + <p> + <strong>Last update:</strong> 2022-03-25. + </p> + <p> + candidal esophagitis, achalasia, H Pylori PUD + </p> + <a href="/posts/intake-2022-03-25">Read more</a> + <h2> + <a href="/posts/employee-wifi">Set Up Enterprise Wifi on Arch Linux</a> + </h2> + <p> + <strong>Last update:</strong> 2021-09-17. + </p> + <p> + Most big institutions have guest and employee wifi networks. +Guest wifi is usually fine, fast enough for the basics, +but far inferior to employee wifi. +On a custom-built OS, such as a fairly minimalist Linux distribution, +getting the employee wifi to work +can be a beast. + </p> + <a href="/posts/employee-wifi">Read more</a> + <h2> + <a href="/posts/mr-2021">Morning Report 08/23/2021</a> + </h2> + <p> + <strong>Last update:</strong> 2021-08-23. + </p> + <p> + Diagnosis is... MDS/MPN/MF NOS. +i.e., who knows. + </p> + <a href="/posts/mr-2021">Read more</a> + </div> + </main> + <div id="footnotes"></div> + <footer></footer> + </div> + </body> +</html> diff --git a/test/posts/intake-2022-03-25/index.html b/test/posts/intake-2022-03-25/index.html @@ -0,0 +1,98 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <link rel="stylesheet" href="/style.css" type="text/css"> + <meta charset="utf-8"> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <link rel="stylesheet" type="text/css" href="/style.css"> + <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cstyle%3E %23m %7B opacity:0; %7D%0A@media (prefers-color-scheme: dark) %7B %23m %7B opacity:1; %7D %23e %7B opacity:0 %7D%0A%7D %3C/style%3E%3Ctext id='m' y='.9em' font-size='90'%3E🏕️%3C/text%3E%3Ctext id='e' y='.9em' font-size='90'%3E🌞%3C/text%3E%3C/svg%3E"> + <title></title> + </head> + <body> + <div id="page-wrapper"> + <div id="header" role="banner"> + <header class="banner"> + <div id="banner-text"> + <span class="banner-title"><a href="/">beauhilton</a></span> + </div> + </header> + <nav> + <a href="/about">about</a> +<a href="/now">now</a> +<a class="nav-active" href="/posts">posts</a> +<a href="https://notes.beauhilton.com">notes</a> +<a href="https://talks.beauhilton.com">talks</a> +<a href="https://git.beauhilton.com">git</a> +<a href="/contact">contact</a> +<a href="/feed.xml">rss</a> + </nav> + </div> + <main> + <h1> + intake + </h1> + <p> + <time id="post-date">2022-03-25</time> + </p> + <h2> + cc: trouble swallowing and weight loss + </h2> + <p> + 28M w few weeks of trouble swallowing (gets stuck “right here,” +points to mid-sternum), solid/liquids same, gradual over months-weeks, +some vomiting w/o specific timing. Sometimes has pain when not eating. +20lb weight loss over months. No skin lesions. ?thrush. + </p> + <h2> + PMHx/PSHx + </h2> + <p> + dx BPD, no other dx or procedures + </p> + <h2> + SHx + </h2> + <ul> + <li> + MSM w occasional use of protection, no PrEP + </li> + <li> + occ MJ use, no other substances + </li> + <li> + unemployed, lives w mom + </li> + <li> + no unusual hobbies or travel + </li> + </ul> + <h2> + PE + </h2> + <p> + HR 100, SBP 80 -&gt; 100 w 500mL LR, AF cachectic (temporal, +hypothenar wasting) +skin tenting diffuse abd tenderness + </p> + <h2> + w/u + </h2> + <p> + Hgb 10, MCV 88, WBC ~4, ANC 1500 BMP wnl Alb 3.4 HIV+, VL 15k, rest +of STI -ve + </p> + <p> + CXR wnl (AP and lateral) + </p> + <h2> + dx + </h2> + <p id="post-excerpt"> + candidal esophagitis, achalasia, H Pylori PUD + </p> + </main> + <div id="footnotes"></div> + <footer></footer> + </div> + </body> +</html> diff --git a/test/posts/mime/index.html b/test/posts/mime/index.html @@ -0,0 +1,144 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <link rel="stylesheet" href="/style.css" type="text/css"> + <meta charset="utf-8"> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <link rel="stylesheet" type="text/css" href="/style.css"> + <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cstyle%3E %23m %7B opacity:0; %7D%0A@media (prefers-color-scheme: dark) %7B %23m %7B opacity:1; %7D %23e %7B opacity:0 %7D%0A%7D %3C/style%3E%3Ctext id='m' y='.9em' font-size='90'%3E🏕️%3C/text%3E%3Ctext id='e' y='.9em' font-size='90'%3E🌞%3C/text%3E%3C/svg%3E"> + <title></title> + </head> + <body> + <div id="page-wrapper"> + <div id="header" role="banner"> + <header class="banner"> + <div id="banner-text"> + <span class="banner-title"><a href="/">beauhilton</a></span> + </div> + </header> + <nav> + <a href="/about">about</a> +<a href="/now">now</a> +<a class="nav-active" href="/posts">posts</a> +<a href="https://notes.beauhilton.com">notes</a> +<a href="https://talks.beauhilton.com">talks</a> +<a href="https://git.beauhilton.com">git</a> +<a href="/contact">contact</a> +<a href="/feed.xml">rss</a> + </nav> + </div> + <main> + <h1> + fix MIME Types to unbreak RSS feeds served by OpenBSD’s +httpd(8) + </h1> + <p> + <time id="post-date">2022-11-13</time> + </p> + <h2> + RSS is life - but mine was broken + </h2> + <p> + As of today (2022-11-13) my website lives on an OpenBSD server hosted +at <a href="https://vultr.com">vultr</a>. + </p> + <p> + It’s great, delightfully simple and low-resource, robust, extendable, +low-maintenance. + </p> + <p id="post-excerpt"> + I've been getting back into RSS lately. +Turns out, my own RSS feed was broken. + </p> + <p> + I knew it was janky, but would have had no idea how broken it was if +not for the great folks on the <a href="https://datasette.io">datasette</a> Discord, one of whom reached +out to let me know my RSS link wasn’t working. + </p> + <p> + This could not stand! + </p> + <p> + I’ve been meaning to fix my RSS feed anyway, and now I had a good +reason. + </p> + <h2> + fixing the file itself + </h2> + <p> + I ended up tearing out my previous RSS solution, <a href="https://romanzolotarev.com/rssg.html"><code>rssg</code></a>, which +is great but made some assumptions about my site’s layout that aren’t +true. I could have rewritten the script, but I’m lazy and a little +strapped for time, so I ended up replacing it with a hand-written RSS +file. + </p> + <p> + (The RSS spec is easy enough to write by hand, a little copy-paste +and replace to add a new article - at some point I’ll probably migrate +to <code>hugo</code> or similar and hand off the feed creation to a more +flexible script, but for now this works). + </p> + <p> + After I was certain the file format was fine and had the info I +wanted, I thought I was good. + </p> + <h2> + fixing the MIME Type + </h2> + <p> + The kind soul who reached out to let me know the RSS feed was +malformed reached out again to let me know he was now getting a MIME +Type error. + </p> + <p> + My feedreader of choice, <code>newsboat</code>, is very forgiving of +what it accepts, and didn’t throw any errors when I tested it. +<code>FreshRSS</code>, on the other hand, is more strict, and the feed +would fail even though the file itself was fine. + </p> + <p> + I looked into it, and found out that <code>httpd(8)</code> only +supports a handful of MIME Types by default, so my server was sending +out <code>application/octet-stream</code> (a generic type) instead of +the <code>rss+xml</code> type, and it was confusing the feedreader. + </p> + <h2> + add all the types + </h2> + <p> + Thank goodness, and as usual in OpenBSD, there’s a very easy way to +add all the relevant types one might need. + </p> + <p> + OpenBSD has an internal MIME declaration file you can link to from +within <code>httpd.conf(5)</code>. + </p> + <p> + Here’s the relevant bit, just chuck this on the end of the conf +file: + </p> + <pre tabindex="0"><code class="language-shell"> +types { + include "/usr/share/misc/mime.types" +} +</code></pre> + <p> + And reload <code>httpd(8)</code>. + </p> + <h2> + great success + </h2> + <p> + Much thanks to my new friend on the Datasette Discord, the fantastic +OpenBSD documentation, as always, and <a href="https://blog.lambda.cx/posts/openbsd-httpd-mime-types/">lambda.cx</a> +for writing a post almost identical to mine (except that his had nothing +to do with RSS - he was fixing PDF serving, which should now be fixed on +my site as well). + </p> + </main> + <div id="footnotes"></div> + <footer></footer> + </div> + </body> +</html> diff --git a/test/posts/mr-2021/index.html b/test/posts/mr-2021/index.html @@ -0,0 +1,419 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <link rel="stylesheet" href="/style.css" type="text/css"> + <meta charset="utf-8"> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <link rel="stylesheet" type="text/css" href="/style.css"> + <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cstyle%3E %23m %7B opacity:0; %7D%0A@media (prefers-color-scheme: dark) %7B %23m %7B opacity:1; %7D %23e %7B opacity:0 %7D%0A%7D %3C/style%3E%3Ctext id='m' y='.9em' font-size='90'%3E🏕️%3C/text%3E%3Ctext id='e' y='.9em' font-size='90'%3E🌞%3C/text%3E%3C/svg%3E"> + <title></title> + </head> + <body> + <div id="page-wrapper"> + <div id="header" role="banner"> + <header class="banner"> + <div id="banner-text"> + <span class="banner-title"><a href="/">beauhilton</a></span> + </div> + </header> + <nav> + <a href="/about">about</a> +<a href="/now">now</a> +<a class="nav-active" href="/posts">posts</a> +<a href="https://notes.beauhilton.com">notes</a> +<a href="https://talks.beauhilton.com">talks</a> +<a href="https://git.beauhilton.com">git</a> +<a href="/contact">contact</a> +<a href="/feed.xml">rss</a> + </nav> + </div> + <main> + <h1> + Morning Report 08/23/2021 + </h1> + <p> + <time id="post-date">2021-08-23</time> + </p> + <p> + Details modified, generalized, and otherwise fudged to be +HIPAA-compliant. + </p> + <h2> + HPI + </h2> + <p> + 72F with chest pain, abdominal pain, and constipation. + </p> + <p> + 2-3mo weight loss, night sweats. + </p> + <p> + 2-3wk +perineal ?cyst, initially ttp and hurt to walk, but now +nontender. + </p> + <p> + ~1wk constipation, BRB on TP. + </p> + <p> + +crampy LLQ pain 8/10, x3-4 days, improves with positioning (supine +with head raised somewhat, 3-4 pillows). + </p> + <p> + +LUQ and left-sided chest pain x1-2 days, radiates to L arm, not +related to exertion, lasts a few minutes. + </p> + <h2> + OP Meds + </h2> + <ul> + <li> + duloxetine 60mg + </li> + <li> + ASA 81mg + </li> + <li> + melatonin 6mg + </li> + <li> + no notable allergies + </li> + </ul> + <h2> + PMSHx + </h2> + <ul> + <li> + TVH-BSO for fibroids and endometriosis (~20y ago) + </li> + <li> + hemorrhoids (no surgeries) + </li> + <li> + s/p Moderna COVID vaccine (~4wk ago) + </li> + <li> + UTD on mammograms, colonoscopies, no deviations from regular +schedule + </li> + </ul> + <h2> + SHx + </h2> + <ul> + <li> + monogamous x45y, G2P2 sons, 6yo grandson, all healthy + </li> + <li> + never smoker + </li> + <li> + social EtOH, none this year + </li> + <li> + no non-Rx medicines + </li> + <li> + previously secretary + </li> + <li> + likes to DIY: painting, home crafts, gardening + </li> + </ul> + <h2> + FHx + </h2> + <ul> + <li> + M GM: uterine cancer (~40yo) + </li> + <li> + P GF: lung ca, unknown type (~70yo) + </li> + </ul> + <h2> + PE + </h2> + <ul> + <li> + VS: wnl + </li> + <li> + GEN: NAD + </li> + <li> + HEENT: no LAD + </li> + <li> + PULM: fine + </li> + <li> + CV: fine + </li> + <li> + ABD: NTND, +splenomegaly + </li> + <li> + GYN: 0.5cm lesion R side of anterior perineum, NT, freely +mobile + </li> + <li> + NEURO: fine + </li> + </ul> + <h2> + Labs + </h2> + <ul> + <li> + Hgb 12.7 + </li> + <li> + WBC 58.3 + <ul> + <li> + 0 blasts + </li> + <li> + 0 atypical lymphs + </li> + <li> + <ul> + <li> + slight L shift + </li> + </ul> + </li> + </ul> + </li> + <li> + Plt 490 + </li> + <li> + BMP grossly wnl (gluc 202, <a href="https://www.ashclinicalnews.org/viewpoints/editors-corner/illegitimi-epic-non-carborundum-dont-let-epic-bastards-grind/">Cr +fine</a>) + </li> + <li> + LFTs fine + </li> + <li> + Trop &lt;0.01 + </li> + <li> + urate 10.4 + </li> + <li> + phos 5.0 + </li> + <li> + LDH 330 + </li> + <li> + fibrinogen 355 + </li> + </ul> + <h2> + Other studies + </h2> + <ul> + <li> + EKG wnl + </li> + <li> + CT-PE -ve + </li> + <li> + CT a/p wwo + <ul> + <li> + +10x7cm pelvic mass (central/R adnexum, exerting mass effect on +sigmoid colon) + </li> + <li> + spleen ~20cm largest dimension w ?infarcts x2, + </li> + <li> + L internal iliac vein filling defects c/w nonocclusive DVT + </li> + </ul> + </li> + <li> + PET/CT + <ul> + <li> + splenomegaly with diffusely increased uptake, diffuse FDG uptake of +axial and appendicular skeleton, mild uptake of abdominal pelvic lymph +nodes, and minimal to mild uptake in the pelvic mass. + </li> + </ul> + </li> + </ul> + <h2> + Further notes on hospital course + </h2> + <ul> + <li> + CEA 1.7 (wnl), CA-125 52 (-) + </li> + <li> + urate 9.5 5d later w IVF, given rasburicase 3mg x1 -&gt; urate +3.8 + </li> + <li> + phos similarly without movement, sevelamer eventually helpful + </li> + <li> + pelvic mass bx: smooth muscle + </li> + <li> + BMBx: hypercellular &gt;90%, no blasts, +trilineage atypica &gt; +myeloid, MF-1 fibrosis. + </li> + <li> + JAK2 -ve, BCR/ABL -ve + </li> + <li> + NGS + <ul> + <li> + BRAF 5% (MGUS, MM, hairy cell, hystiocytic/dendritic cell, solid +tumors, therapy-related myeloid neoplasms) + </li> + <li> + KRAS 39% (MDS, AML, MDS/MPN inc CMML and JMML) + </li> + <li> + BCOR 49% (?, possibly germline since allele fraction ~50%) + </li> + <li> + BCORL1 48% (ditto) + </li> + <li> + EZH2 93% (?, likely germline w loss of heterozygosity) + </li> + </ul> + </li> + </ul> + <h2> + And then… + </h2> + <p id="post-excerpt"> + Diagnosis is... MDS/MPN/MF NOS. +i.e., who knows. + </p> + <p> + Started on hydroxyurea and decitabine, c/b recurrent bacteremia, so +currently tx on hold. + </p> + <hr> + <h2> + TLS + </h2> + <p> + The big idea, and a few finer points. + </p> + <p> + <a href="https://jamanetwork.com/journals/jamaoncology/fullarticle/2680750">![TLS](https://cdn.jamanetwork.com/ama/content_public/journal/oncology/937239/cpg180002fa.png?Expires=1632594426&amp;Signature=y4M-w5gXSYJCAVMqGVEyfaPaqZocE9nGaWFnmr7GY7vuiD35l7dL-yJLWn4l3huTo4yBhri1nM0KjQ4dZBBjEYH5tPmKExEJ0D6V~WNou9Av-OEwhyQh79y9feHp790YWY6hTKRJJge958meDu~OmNl8Sl0Wn1N4buZZgVNMRdRds9fKbaDr4DhEdCbMgFbbLSeW9h8KIOm49Gog8FREQNntRaN1jILZgKPBTr9sUNv2BUiapZaLPO4teIf33LkJXcStx6o1VVsZJoP-G-sfMKG3ql1O~23E6LFJeirnMt5MYQdfk-LZlieuSw16HzqTXr-jBtOicDtyFzDJ9VcQ~g__&amp;Key-Pair-Id=APKAIE5G5CRDK6RD3PGA +=500x500 ‘JAMA Oncology 2018, TLS Review’)</a> + </p> + <h3> + Cairo-Bishop classification system + </h3> + <p> + (Most of the following derived from <a href="https://www.asn-online.org/education/distancelearning/curricula/onco/Chapter4.pdf">Chapter +4</a> of the American Society of Nephrology online <a href="https://www.asn-online.org/education/distancelearning/curricula/onco/">Onco-Nephrology +curriculum</a>, which is good and great.) + </p> + <h3> + Laboratory TLS + </h3> + <p> + Definition: Chemotherapy plus the two or more of the following within +3d before or 7d after initiation (so doesn’t account for the spontaneous +TLS seen in our patient). + </p> + <p> + | Metabolite/Electrolyte | Criterion | | :———————– | +:––––––––––––––––––––: | | Uric Acid | &gt;=8 mg/dL or 25% increase from +baseline | | Potassium | &gt;=6mEq/L or 25% increase from baseline | | +Phosphorus | &gt;=4.5mg/dL or 25% increase from baseline | | Calcium | +25% <em>decrease</em> from baseline | + </p> + <p> + The “25% increase/decrease” part is contested, as it may not be +clinically meaningful if the value stays within the normal range. + </p> + <h3> + Clinical TLS + </h3> + <p> + | Laboratory TLS and one or more of | | :–––––––––––––––– | | +creatinine &gt;= 1.5 ULN (Note: just use AKI criteria) | | cardiac +arrhythmia or sudden death | | seizure | + </p> + <ul> + <li> + risk assessment + </li> + </ul> + <h3> + Treating TLS + </h3> + <p> + IVF, electrolytes, rasburicase. + </p> + <p> + Rasburicase is the subject of a recent “Things We Do for No +Reason.” + </p> + <p> + <a href="https://www.journalofhospitalmedicine.com/jhospmed/article/241443/hospital-medicine/things-we-do-no-reasontm-rasburicase-adult-patients-tumor">Pay-walled +article</a>, <a href="https://cdn.mdedge.com/files/s3fs-public/JHM01607424.PDF">PDF made +available by the authors</a> + </p> + <p> + TL;DR: the evidence is thin, but could be reasonable to + </p> + <ul> + <li> + ppx w IVF and allopurinol for low-med risk, + </li> + <li> + use single 3mg dose rasburicase as ppx in high-risk disease (don’t +use weight-based dosing), + </li> + <li> + tx active TLS (laboratory or clinical) with aggressive fluid +resuscitation and electrolyte mgmt, possibly single 3mg dose. + </li> + </ul> + <p> + Hard outcomes in support of rasburicase are generally lacking, e.g. +consistently reducing renal injury, renal failure, length of stay. + </p> + <p> + It also seems like the classification criteria need revamping, with a +larger N. It’s been a while. However, like redefining fever, it’s +difficult to get a clean slate, because we act on the established +criteria so aggressively. + </p> + <hr> + <h2> + MDS/MPN overlap syndromes + </h2> + <p> + Not much to say here, except that the dx is not always clear-cut, +even with BMBx and NGS data, so the clinical picture matters, and +sometimes we have to shoot in the dark. + </p> + <hr> + <p> + Last updated: 2021-08-22 + </p> + </main> + <div id="footnotes"></div> + <footer></footer> + </div> + </body> +</html> diff --git a/test/posts/ugbsd/index.html b/test/posts/ugbsd/index.html @@ -0,0 +1,100 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <link rel="stylesheet" href="/style.css" type="text/css"> + <meta charset="utf-8"> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <link rel="stylesheet" type="text/css" href="/style.css"> + <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cstyle%3E %23m %7B opacity:0; %7D%0A@media (prefers-color-scheme: dark) %7B %23m %7B opacity:1; %7D %23e %7B opacity:0 %7D%0A%7D %3C/style%3E%3Ctext id='m' y='.9em' font-size='90'%3E🏕️%3C/text%3E%3Ctext id='e' y='.9em' font-size='90'%3E🌞%3C/text%3E%3C/svg%3E"> + <title></title> + </head> + <body> + <div id="page-wrapper"> + <div id="header" role="banner"> + <header class="banner"> + <div id="banner-text"> + <span class="banner-title"><a href="/">beauhilton</a></span> + </div> + </header> + <nav> + <a href="/about">about</a> +<a href="/now">now</a> +<a class="nav-active" href="/posts">posts</a> +<a href="https://notes.beauhilton.com">notes</a> +<a href="https://talks.beauhilton.com">talks</a> +<a href="https://git.beauhilton.com">git</a> +<a href="/contact">contact</a> +<a href="/feed.xml">rss</a> + </nav> + </div> + <main> + <h1> + Upgrading out-of-date OpenBSD installs + </h1> + <p> + <time id="post-date">2022-11-11</time> + </p> + <p id="post-excerpt"> + First of all, don't do how I do. +Upgrade your installs regularly. +OpenBSD makes it very easy. + </p> + <p> + But, if you do happen to get behind… + </p> + <p> + <code>sysupgrade</code> is very likely to fail. + </p> + <h2> + What happens when you try to upgrade a very old install? + </h2> + <p> + Lots of 404 errors. + </p> + <p> + The <code>sysupgrade</code> utility tries to grab the next version of +the OS from one of the many mirrors (the specific one your system will +use is in <code>/etc/installurl</code>.) + </p> + <p> + The default mirrors only keep the last 2 or 3 versions around, so +when <code>sysupgrade</code> constructs the url and tries to hit it for +downloads, it will fail. + </p> + <h2> + Where to get old versions? + </h2> + <p> + There are a couple of mirrors that keep almost all the old versions +around. + </p> + <p> + <a href="https://mirror.yandex.ru/pub/OpenBSD/">https://mirror.yandex.ru/pub/OpenBSD/</a> +has files going back to OpenBSD 2.x - they seem like the most serious +archivists, at least of the mirrors I looked at. + </p> + <p> + <a href="https://mirror.sjtu.edu.cn/OpenBSD/">https://mirror.sjtu.edu.cn/OpenBSD/</a> +has files going back to 6.5 as of this writing (2022-11-11), also not +too shabby. + </p> + <p> + Do a little <code>vi /etc/installurl</code> and change the link to +one of the above, depending on how delinquent you’ve been. + </p> + <p> + That should allow you to do serial <code>sysupgrade</code> commands +until you catch up. + </p> + <p> + When you get close to the current version, consider switching back to +a closer mirror, both for faster installs and to be kind to the folks +who just saved your bacon. + </p> + </main> + <div id="footnotes"></div> + <footer></footer> + </div> + </body> +</html> diff --git a/test/style.css b/test/style.css @@ -0,0 +1,296 @@ +/** Variables **/ + +:root +{ + --Canvas-bg: #201b1b; + --Canvas-color: #fff; + --Pre-bg: #151515; + --Pre-color: #fff; + --Pre-border: #222; + --Main-color: #f2f2f2; + --Code-color: #2adba4; + --Accent1-color: #2adba4; /* green */ + --Accent2-color: #368aeb; /* blue */ + --Highlight-num: #43a60d; + --Highlight-esc: #dfad06; + --Highlight-str: #f77f1d; + --Highlight-pps: #458759; + --Highlight-slc: #a0a0a0; + --Highlight-com: #a0a0a0; + --Highlight-ppc: #94e39; + --Highlight-opt: #ffffff; + --Highlight-ipl: #4dc987; + --Highlight-lin: #555555; + --Highlight-kwa: #d9396a; + --Highlight-kwb: #8655e7; + --Highlight-kwc: #ffffff; + --Highlight-kwd: #00a48f; +} + +img { + display: inline-block; + max-width: 100%; +} + +pre, code, sample { + white-space: pre-wrap; + hyphens: none; +} + +table { + max-width: 100%; +} + +html { + font-size: 70.5%; +} + +body { + line-height: 1.5; + font-size: 1.6rem; + max-width: 38em; + margin: auto; + padding: 13px; +} + +/* Structural blocks */ + +#page-wrapper +{ + max-width: 88rem; + + padding: 1rem 2rem 2rem; + + margin-left: auto; + margin-right: auto; +} + + +/* Visual styles */ + +html +{ + background: var(--Canvas-bg); + color: var(--Canvas-color); +} + +header +{ + text-align: center; +} + +::selection +{ + background: var(--Selection-bg); + color: var(--Selection-color); +} + +/* shared gradient border */ +nav, footer +{ + border-width: 0; + border-style: solid; + border-color: var(--Accent1-color); + border-image: linear-gradient(to right, var(--Accent1-color), var(--Accent2-color)) 2; +} + +nav +{ + font-size: 1.8rem; + border-bottom-width: 2px; + padding-top: 0.5rem; + padding-bottom: 0.5rem; + word-spacing: 5px; + text-align: center; +} + +main +{ + color: var(--Main-color); + text-rendering: optimizeLegibility; +} + +footer +{ + text-align: center; + padding-top: 1rem; + margin-top: 1rem; + border-top-width: 2px; +} + +div#banner-text +{ + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.banner +{ + display: flex; + flex-direction: row; + gap: 1rem; + justify-content: center; + align-items: center; + line-height: 1; +} + +.banner-title +{ + margin: 0; + font-size: 3.6rem; + font-weight: 200; + letter-spacing: 0.425em; + /* letter-spacing is applied even to the last letter, + so for proper centering, we have to remove it ourselves, sadly */ + margin-right: -0.425em; +} + +.banner-title a +{ + text-decoration:none; + color: var(--Main-color); +} + +.banner-title a:hover +{ + text-decoration:none; + color: var(--Accent1-color); +} + +a { + color: var(--Accent2-color); +} + +a:hover, a:focus +{ + text-decoration: underline; + color: var(--Accent1-color); +} + +a.nav-active { + color: var(--Accent1-color); + font-weight: 200; +} + +nav a { text-decoration: none; } + +a.here { text-decoration: none; } + +hr +{ + border: 0 none; + color: var(--Accent2-color); + background-color: currentColor; + height: 2px; +} + +hr.footnotes { width: 40%; } + +a.footnote +{ + text-decoration: none; + margin-right: 0.4rem; +} + +ul.toc { list-style: none; } + +h5 { font-size: 1.6rem; } +h6 { font-size: 1.4rem; } + +code, kbd, samp +{ + color: var(--Code-color); +} + + +/** Typography */ + +@supports (hyphens: auto) +{ + main + { + text-align: justify; + hyphens: auto; + } +} + +body +{ + font-family: system-ui, sans-serif; + font-weight: 200; +} + +table, th, td +{ + border: 1px solid var(--Accent1-color); + border-collapse: collapse; +} + +th, td +{ + padding: 0.5em; + hyphens: none; + text-align: left; +} + +.centered { text-align: center; } + +/* Style definition file generated by highlight 3.52, http://www.andre-simon.de/ */ +/* highlight theme: Kwrite Editor */ +body.hl { background-color: #e0eaee; } +pre.hl { color: #000000; background-color:#e0eaee; font-size: 10pt; font-family: monospace; } +.hl.num { color: var(--Highlight-num); } +.hl.esc { color: var(--Highlight-esc); } +.hl.str { color: var(--Highlight-str); } +.hl.pps { color: var(--Highlight-pps); } +.hl.slc { color: var(--Highlight-slc); font-style: italic; } +.hl.com { color: var(--Highlight-com); font-style: italic; } +.hl.ppc { color: var(--Highlight-ppc); } +.hl.opt { color: var(--Highlight-opt); } +.hl.ipl { color: var(--Highlight-ipl); } +.hl.lin { color: var(--Highlight-lin); } +.hl.kwa { color: var(--Highlight-kwa); font-weight: bold; } +.hl.kwb { color: var(--Highlight-kwb); } +.hl.kwc { color: var(--Highlight-kwc); font-weight: bold; } +.hl.kwd { color: var(--Highlight-kwd); } + +pre +{ + box-sizing: border-box; + overflow: auto; + padding: 2rem; + margin-left: -2rem; + margin-right: -2rem; + border: 1px solid var(--Pre-border); + background: var(--Pre-bg); + color: var(--Pre-color); +} + +pre code +{ + color: inherit; +} + +@media screen and (max-width: 34em) +{ + .banner, .banner-title + { + display: block; + text-align: center; + margin: auto; + } + .banner + { + margin-bottom: 2rem; + } +} + +@media screen and (max-width: 28em) +{ + .banner-title + { + font-size: 3.2rem; + } +} diff --git a/test/wants/index.html b/test/wants/index.html @@ -0,0 +1,90 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <link rel="stylesheet" href="/style.css" type="text/css"> + <meta charset="utf-8"> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <link rel="stylesheet" type="text/css" href="/style.css"> + <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cstyle%3E %23m %7B opacity:0; %7D%0A@media (prefers-color-scheme: dark) %7B %23m %7B opacity:1; %7D %23e %7B opacity:0 %7D%0A%7D %3C/style%3E%3Ctext id='m' y='.9em' font-size='90'%3E🏕️%3C/text%3E%3Ctext id='e' y='.9em' font-size='90'%3E🌞%3C/text%3E%3C/svg%3E"> + <title></title> + </head> + <body> + <div id="page-wrapper"> + <div id="header" role="banner"> + <header class="banner"> + <div id="banner-text"> + <span class="banner-title"><a href="/">beauhilton</a></span> + </div> + </header> + <nav> + <a href="/about">about</a> +<a href="/now">now</a> +<a href="/posts">posts</a> +<a href="https://notes.beauhilton.com">notes</a> +<a href="https://talks.beauhilton.com">talks</a> +<a href="https://git.beauhilton.com">git</a> +<a href="/contact">contact</a> +<a href="/feed.xml">rss</a> + </nav> + </div> + <main> + <h1> + Wishlist + </h1> + <p> + While there are always <a href="https://rosewhitemusic.com/piano/writings/ten-thousand-things/#:~:text=%E2%80%9CThe%20Ten%20Thousand%20Things%E2%80%9D%20is,The%20One%20produced%20the%20two.">ten +thousand material things</a> I want, some of which are in the Amazon +Wishlist below, I’m more into digital capability these days. + </p> + <p> + Probably digital, use-anywhere gift cards are the way to go. E.g. +Visa or MasterCard. + </p> + <h2> + beau@beauhilton.com + </h2> + <p> + I recently found <a href="https://www.fastmail.com/">fastmail</a>, +which is a delightful mail service. I’m trying to be less reliant on +Google, and using an independent email client is a big part of that. +They charge money because they’re <em>not</em> doing all the stuff +Google does to keep their products free, namely, using your info for ad +targeting. + </p> + <p> + It’s $5 a month. I got a few months for free, and really like it. In +addition to not selling your data, they have a good facility for having +your own email extension (provided you own your domain), so I got +<code>beau@beauhilton.com</code>. Any money toward supporting their +service and keeping my cool new email address going would be much +appreciated. + </p> + <h2> + beauhilton.com + </h2> + <p> + I use <a href="https://www.vultr.com/">Vultr</a> to host my server, +which in turn hosts this website. It’s also $5 a month, which is a great +deal for a server that I fully manage and is plenty powerful for a +simple website. + </p> + <p> + Happy to receive any funds to support this going forward. + </p> + <h2> + Amazon + </h2> + <p> + And finally: + </p> + <p> + <a href="https://www.amazon.com/hz/wishlist/ls/3AKNW7PDL7STX?ref_=wl_share">Amazon +Wishlist</a> + </p> + </main> + <div id="footnotes"></div> + <footer></footer> + </div> + </body> +</html>