<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Blake Sanie’s Blog: Newsletter]]></title><description><![CDATA[Curiosity beyond my mental capacity.]]></description><link>https://blakesanie.substack.com/s/blake-sanies-newsletter</link><image><url>https://substackcdn.com/image/fetch/$s_!9uuB!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6e7b96ad-c18a-478a-b8f4-beb5d6fdf35c_1280x1280.png</url><title>Blake Sanie’s Blog: Newsletter</title><link>https://blakesanie.substack.com/s/blake-sanies-newsletter</link></image><generator>Substack</generator><lastBuildDate>Mon, 20 Apr 2026 06:24:37 GMT</lastBuildDate><atom:link href="https://blakesanie.substack.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Blake Sanie]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[blakesanie@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[blakesanie@substack.com]]></itunes:email><itunes:name><![CDATA[Blake Sanie]]></itunes:name></itunes:owner><itunes:author><![CDATA[Blake Sanie]]></itunes:author><googleplay:owner><![CDATA[blakesanie@substack.com]]></googleplay:owner><googleplay:email><![CDATA[blakesanie@substack.com]]></googleplay:email><googleplay:author><![CDATA[Blake Sanie]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Aerodynamics, Acuity, and Adaptation: Reflections from Lake Placid]]></title><description><![CDATA[One foot in front of the other, one puddle at a time]]></description><link>https://blakesanie.substack.com/p/aerodynamics-acuity-and-adaptation</link><guid isPermaLink="false">https://blakesanie.substack.com/p/aerodynamics-acuity-and-adaptation</guid><dc:creator><![CDATA[Blake Sanie]]></dc:creator><pubDate>Thu, 01 Jan 2026 05:01:31 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/9e801234-d50c-4e88-8cc7-3e47b077a818_3024x1588.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Looking back on 2025, the memory of one long day in Lake Placid soars above the rest.</p><p>Ironman wasn&#8217;t some gradual escalation of my athletic interests; it was the end-goal from the start. I didn&#8217;t get into this sport to dabble in 5Ks or half-marathons; <strong>I wanted to become an Ironman</strong>. That singular ambition is what re-introduced consistent lifting near the end of college, motivated me to log my first legitimate running miles during grad school, and<a href="https://substack.com/@blakesanie/note/p-153539654?r=eveir&amp;utm_source=notes-share-action&amp;utm_medium=web"> </a><strong><a href="https://substack.com/@blakesanie/note/p-153539654?r=eveir&amp;utm_source=notes-share-action&amp;utm_medium=web">powered me through a successful 70.3 last year</a></strong>. I knew the momentum wouldn&#8217;t stay forever, and if I were going to finish an Ironman in my lifetime, now was my best shot.</p><p><strong><a href="https://www.ironman.com/races/im-lake-placid">Ironman Lake Placid</a></strong> caught my eye. I knew its reputation&#8212;the unforgiving two-lap bike course dominated by grueling<a href="https://visitadirondacks.com/"> </a><strong><a href="https://visitadirondacks.com/">Adirondack climbs</a></strong> and the deceptively hilly run. Something out of the ordinary, for an Illinois resident. I knew that if I conquered such a notoriously difficult course, I&#8217;d earn that finisher status absolutely. And so, the chase was on. Little did I know how severely I misjudged the feat.</p><p>A 140.6 mile triathlon, on initial impression, seems physically intimidating. Though physically <em>demanding</em> indeed, it became clear that Ironman is not a physical challenge; it is the ultimate masterclass in troubleshooting, resourcefulness, and risk management.</p><h3><strong>Training Without a Manual</strong></h3><p>My first exercise in critical judgement came where most of the hours were spent: training in the Chicago winter. Controversially, I rejected the idea of a training plan - my mission was to train as much as I could while granting myself rest or a step back when my body asked for it. No metric tracking or schedules necessary. With this, I skipped the overthinking behind metric tracking and scheduled sessions, in exchange for a deceptively fine line between productive training and burnout. To add insult to injury, Chicago only saw daylight during work hours, and no number of layers could make outdoor activity bearable (or safe, in some instances).</p><p>I had to gamify my approach. If training wasn&#8217;t fun, or felt like a chore, I knew I wouldn&#8217;t march towards my goal. Mental discipline alone has a surmountable growth impact, but has its limits, realistically speaking.</p><p>I redesigned my environment. Inside and on the saddle,<a href="https://www.zwift.com/"> </a><strong><a href="https://www.zwift.com/">Zwift</a> </strong>is the name of the game; I tackled side quests such as<a href="https://substack.com/home/post/p-158517051"> </a><strong><a href="https://substack.com/home/post/p-158517051">beating my century PR</a></strong>, completing the <strong><a href="https://zwiftinsider.com/route/the-uber-pretzel/">&#220;ber Pretzel</a></strong> route, and climbing<a href="https://en.wikipedia.org/wiki/Mont_Ventoux"> </a><strong><a href="https://en.wikipedia.org/wiki/Mont_Ventoux">Mont Ventoux</a></strong> as if I were a world tour rider.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!cLsZ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F320156d2-356b-4bcc-b48e-b92ef989832c_1440x871.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!cLsZ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F320156d2-356b-4bcc-b48e-b92ef989832c_1440x871.jpeg 424w, https://substackcdn.com/image/fetch/$s_!cLsZ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F320156d2-356b-4bcc-b48e-b92ef989832c_1440x871.jpeg 848w, https://substackcdn.com/image/fetch/$s_!cLsZ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F320156d2-356b-4bcc-b48e-b92ef989832c_1440x871.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!cLsZ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F320156d2-356b-4bcc-b48e-b92ef989832c_1440x871.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!cLsZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F320156d2-356b-4bcc-b48e-b92ef989832c_1440x871.jpeg" width="532" height="321.7861111111111" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/320156d2-356b-4bcc-b48e-b92ef989832c_1440x871.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:871,&quot;width&quot;:1440,&quot;resizeWidth&quot;:532,&quot;bytes&quot;:249107,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blakesanie.substack.com/i/177315476?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F320156d2-356b-4bcc-b48e-b92ef989832c_1440x871.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!cLsZ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F320156d2-356b-4bcc-b48e-b92ef989832c_1440x871.jpeg 424w, https://substackcdn.com/image/fetch/$s_!cLsZ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F320156d2-356b-4bcc-b48e-b92ef989832c_1440x871.jpeg 848w, https://substackcdn.com/image/fetch/$s_!cLsZ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F320156d2-356b-4bcc-b48e-b92ef989832c_1440x871.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!cLsZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F320156d2-356b-4bcc-b48e-b92ef989832c_1440x871.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Finally completed the &#220;ber Pretzel in slightly under six hours.</figcaption></figure></div><p>Shoes laced, I leapt from<a href="https://www.strava.com/activities/14437403786"> </a><strong><a href="https://www.strava.com/activities/14437403786">downtown Chicago to the end of each CTA &#8216;L&#8217; Line</a></strong>, collecting them like trading cards.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!R1rS!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3433d0a-4fbd-4942-bcc7-f5574230bcde_3072x4080.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!R1rS!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3433d0a-4fbd-4942-bcc7-f5574230bcde_3072x4080.jpeg 424w, https://substackcdn.com/image/fetch/$s_!R1rS!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3433d0a-4fbd-4942-bcc7-f5574230bcde_3072x4080.jpeg 848w, https://substackcdn.com/image/fetch/$s_!R1rS!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3433d0a-4fbd-4942-bcc7-f5574230bcde_3072x4080.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!R1rS!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3433d0a-4fbd-4942-bcc7-f5574230bcde_3072x4080.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!R1rS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3433d0a-4fbd-4942-bcc7-f5574230bcde_3072x4080.jpeg" width="326" height="433.02472527472526" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d3433d0a-4fbd-4942-bcc7-f5574230bcde_3072x4080.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1934,&quot;width&quot;:1456,&quot;resizeWidth&quot;:326,&quot;bytes&quot;:8079470,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blakesanie.substack.com/i/177315476?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3433d0a-4fbd-4942-bcc7-f5574230bcde_3072x4080.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!R1rS!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3433d0a-4fbd-4942-bcc7-f5574230bcde_3072x4080.jpeg 424w, https://substackcdn.com/image/fetch/$s_!R1rS!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3433d0a-4fbd-4942-bcc7-f5574230bcde_3072x4080.jpeg 848w, https://substackcdn.com/image/fetch/$s_!R1rS!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3433d0a-4fbd-4942-bcc7-f5574230bcde_3072x4080.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!R1rS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3433d0a-4fbd-4942-bcc7-f5574230bcde_3072x4080.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">CTA Yellow Line Run, 14+ miles from Clark &amp; Lake to Dempster-Skokie.</figcaption></figure></div><p>On Christmas eve, I <strong><a href="https://blakesanie.substack.com/p/stravart-a-christmas-tree-in-chicago">painted a city-scale Christmas tree</a></strong> with only footsteps. I will never forget when <strong><a href="https://citychallenge.chipotle.com/">Chipotle released its Strava segment</a></strong> - For 15 miles, my friends and I shuttled across the same 4-block sidewalk in the name of free burrito bowls.</p><p>Once it got warmer, my stravart adventures continued with a <strong><a href="https://www.strava.com/activities/14378148825">30-mile Millennium Falcom on May the Fourth</a></strong>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!G9x1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b425b60-ced3-43bc-8189-68863bd7ebd9_1107x1049.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!G9x1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b425b60-ced3-43bc-8189-68863bd7ebd9_1107x1049.png 424w, https://substackcdn.com/image/fetch/$s_!G9x1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b425b60-ced3-43bc-8189-68863bd7ebd9_1107x1049.png 848w, https://substackcdn.com/image/fetch/$s_!G9x1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b425b60-ced3-43bc-8189-68863bd7ebd9_1107x1049.png 1272w, https://substackcdn.com/image/fetch/$s_!G9x1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b425b60-ced3-43bc-8189-68863bd7ebd9_1107x1049.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!G9x1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b425b60-ced3-43bc-8189-68863bd7ebd9_1107x1049.png" width="458" height="434.003613369467" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2b425b60-ced3-43bc-8189-68863bd7ebd9_1107x1049.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1049,&quot;width&quot;:1107,&quot;resizeWidth&quot;:458,&quot;bytes&quot;:1150235,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blakesanie.substack.com/i/177315476?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b425b60-ced3-43bc-8189-68863bd7ebd9_1107x1049.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!G9x1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b425b60-ced3-43bc-8189-68863bd7ebd9_1107x1049.png 424w, https://substackcdn.com/image/fetch/$s_!G9x1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b425b60-ced3-43bc-8189-68863bd7ebd9_1107x1049.png 848w, https://substackcdn.com/image/fetch/$s_!G9x1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b425b60-ced3-43bc-8189-68863bd7ebd9_1107x1049.png 1272w, https://substackcdn.com/image/fetch/$s_!G9x1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b425b60-ced3-43bc-8189-68863bd7ebd9_1107x1049.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">The end-result of precise planning, scouting, and fandom.</figcaption></figure></div><p>To seal my confidence, I claimed victory on milestone sessions -<a href="https://www.strava.com/activities/14855280087"> </a><strong><a href="https://www.strava.com/activities/14855280087">5 loops around Wisconsin&#8217;s Lake Geneva</a></strong> for 130 miles and 8k ft elevation gain, <strong><a href="https://www.strava.com/activities/14883583940">20 miles on Chicago&#8217;s lakefront</a></strong> in the unrelenting summer humidity, and an <strong><a href="https://www.strava.com/activities/15005499169">uninterrupted swim from Ohio Street Beach to North Avenue (and back)</a></strong>. Now, I just had to string them in sequence - nothing complicated.</p><h3><strong>A Very Adirondack Welcome</strong></h3><p>No course overview pamphlet could have lightened my feeling of intimidation when first driving into Lake Placid. With mountains in every direction, I finally understood the physical demands set before me. In a way, this shock only drove further anticipation; I could already visualize myself running across the iconic red carpet.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!BJIp!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca9f84b5-2897-462e-8192-fac278a7494c_3024x2548.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!BJIp!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca9f84b5-2897-462e-8192-fac278a7494c_3024x2548.heic 424w, https://substackcdn.com/image/fetch/$s_!BJIp!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca9f84b5-2897-462e-8192-fac278a7494c_3024x2548.heic 848w, https://substackcdn.com/image/fetch/$s_!BJIp!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca9f84b5-2897-462e-8192-fac278a7494c_3024x2548.heic 1272w, https://substackcdn.com/image/fetch/$s_!BJIp!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca9f84b5-2897-462e-8192-fac278a7494c_3024x2548.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!BJIp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca9f84b5-2897-462e-8192-fac278a7494c_3024x2548.heic" width="502" height="423.0453296703297" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ca9f84b5-2897-462e-8192-fac278a7494c_3024x2548.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1227,&quot;width&quot;:1456,&quot;resizeWidth&quot;:502,&quot;bytes&quot;:1582990,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blakesanie.substack.com/i/177315476?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca9f84b5-2897-462e-8192-fac278a7494c_3024x2548.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!BJIp!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca9f84b5-2897-462e-8192-fac278a7494c_3024x2548.heic 424w, https://substackcdn.com/image/fetch/$s_!BJIp!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca9f84b5-2897-462e-8192-fac278a7494c_3024x2548.heic 848w, https://substackcdn.com/image/fetch/$s_!BJIp!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca9f84b5-2897-462e-8192-fac278a7494c_3024x2548.heic 1272w, https://substackcdn.com/image/fetch/$s_!BJIp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca9f84b5-2897-462e-8192-fac278a7494c_3024x2548.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Driving into town, we cyclist struggle was right before our eyes.</figcaption></figure></div><p>Preparing for the worst, I did not pack lightly. Bags of carb-heavy foods, electrolytes, spare bike components and tools, clothing options for rain or shine. Beyond basic Lake Placid tourism and a shakeout swim and ride, nothing sounded better than some cabin fever: guaranteed safety from injury and unforeseen bike mechanicals.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!UQcc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ac0261b-9539-4462-a541-9c51e00527d8_3024x2634.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!UQcc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ac0261b-9539-4462-a541-9c51e00527d8_3024x2634.heic 424w, https://substackcdn.com/image/fetch/$s_!UQcc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ac0261b-9539-4462-a541-9c51e00527d8_3024x2634.heic 848w, https://substackcdn.com/image/fetch/$s_!UQcc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ac0261b-9539-4462-a541-9c51e00527d8_3024x2634.heic 1272w, https://substackcdn.com/image/fetch/$s_!UQcc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ac0261b-9539-4462-a541-9c51e00527d8_3024x2634.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!UQcc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ac0261b-9539-4462-a541-9c51e00527d8_3024x2634.heic" width="465" height="404.9587912087912" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0ac0261b-9539-4462-a541-9c51e00527d8_3024x2634.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1268,&quot;width&quot;:1456,&quot;resizeWidth&quot;:465,&quot;bytes&quot;:1408304,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blakesanie.substack.com/i/177315476?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ac0261b-9539-4462-a541-9c51e00527d8_3024x2634.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!UQcc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ac0261b-9539-4462-a541-9c51e00527d8_3024x2634.heic 424w, https://substackcdn.com/image/fetch/$s_!UQcc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ac0261b-9539-4462-a541-9c51e00527d8_3024x2634.heic 848w, https://substackcdn.com/image/fetch/$s_!UQcc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ac0261b-9539-4462-a541-9c51e00527d8_3024x2634.heic 1272w, https://substackcdn.com/image/fetch/$s_!UQcc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ac0261b-9539-4462-a541-9c51e00527d8_3024x2634.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Safe bike transport outside our accommodation&#8217;s gravel roads.</figcaption></figure></div><p>From chatting with training partners, I learned of the high-speed descent into Keene, and the three major climbs back into town. Hence, driving the bike course for prior reconnaissance was a non-negotiable. Halfway around the loop, the sun had gone, but it was only lunch time. Ominous clouds made their Adirondack welcome, too. I had goosebumps.</p><h3><strong>Come Rain or Come Shine</strong></h3><p>When you picture yourself powering through all 140.6 miles of your first ironman Ironman, weather doesn&#8217;t usually come to mind - and never, ever, torrential downpour. Yet, there was no going back, and the rain didn&#8217;t phase me. The amount of work and sacrifice culminating to that weekend would be rewarded one way or another. If they cancelled the race, I&#8217;d drive back to Chicago and dominate my own (although less hilly) 140.6 mile course.</p><p>Luckily, Ironman shared the same go-big or go-big mentality. At the briefing, they reassured us that the race would go on as planned. Specifically, they stressed our own responsibility to use common sense to abandon the bike or run to seek shelter, if the circumstance presents itself. I thought to myself: do I need to knock on someone&#8217;s door asking for rain cover, and maybe for a bite, like it&#8217;s Halloween?</p><p>With less than 24 hours until race day, I checked my bike and gear bags in at the Ironman Village. I included multiple pairs of socks, gloves, a gilet, rain jacket, and towels. A solo cup fixed around the bag&#8217;s opening protected from overnight rain. I was prepared for any predicament of possibility. Back at the cabin and one dose of Benadryl later, I was fast asleep going into race morning.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!v3di!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb239b31-dfd4-42a8-8aaf-71dd0aef04ab_3024x2143.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!v3di!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb239b31-dfd4-42a8-8aaf-71dd0aef04ab_3024x2143.heic 424w, https://substackcdn.com/image/fetch/$s_!v3di!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb239b31-dfd4-42a8-8aaf-71dd0aef04ab_3024x2143.heic 848w, https://substackcdn.com/image/fetch/$s_!v3di!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb239b31-dfd4-42a8-8aaf-71dd0aef04ab_3024x2143.heic 1272w, https://substackcdn.com/image/fetch/$s_!v3di!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb239b31-dfd4-42a8-8aaf-71dd0aef04ab_3024x2143.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!v3di!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb239b31-dfd4-42a8-8aaf-71dd0aef04ab_3024x2143.heic" width="452" height="320.3736263736264" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/db239b31-dfd4-42a8-8aaf-71dd0aef04ab_3024x2143.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1032,&quot;width&quot;:1456,&quot;resizeWidth&quot;:452,&quot;bytes&quot;:2412633,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blakesanie.substack.com/i/177315476?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb239b31-dfd4-42a8-8aaf-71dd0aef04ab_3024x2143.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!v3di!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb239b31-dfd4-42a8-8aaf-71dd0aef04ab_3024x2143.heic 424w, https://substackcdn.com/image/fetch/$s_!v3di!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb239b31-dfd4-42a8-8aaf-71dd0aef04ab_3024x2143.heic 848w, https://substackcdn.com/image/fetch/$s_!v3di!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb239b31-dfd4-42a8-8aaf-71dd0aef04ab_3024x2143.heic 1272w, https://substackcdn.com/image/fetch/$s_!v3di!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb239b31-dfd4-42a8-8aaf-71dd0aef04ab_3024x2143.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Before going to bed, I collected inventory for the breakfast of champions.</figcaption></figure></div><p>Very early the next morning, we calmly and safely drove to Ironman Village. I had to make this idle time count, which meant shoveling spoonfuls of cereal right out of the box, and getting ahead on caffeine and electrolytes. I ignited my engine.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!tIy_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe82a3f37-936a-41ae-800d-d71b52662cf6_4032x3024.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!tIy_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe82a3f37-936a-41ae-800d-d71b52662cf6_4032x3024.heic 424w, https://substackcdn.com/image/fetch/$s_!tIy_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe82a3f37-936a-41ae-800d-d71b52662cf6_4032x3024.heic 848w, https://substackcdn.com/image/fetch/$s_!tIy_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe82a3f37-936a-41ae-800d-d71b52662cf6_4032x3024.heic 1272w, https://substackcdn.com/image/fetch/$s_!tIy_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe82a3f37-936a-41ae-800d-d71b52662cf6_4032x3024.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!tIy_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe82a3f37-936a-41ae-800d-d71b52662cf6_4032x3024.heic" width="484" height="363" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e82a3f37-936a-41ae-800d-d71b52662cf6_4032x3024.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1092,&quot;width&quot;:1456,&quot;resizeWidth&quot;:484,&quot;bytes&quot;:2174559,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blakesanie.substack.com/i/177315476?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe82a3f37-936a-41ae-800d-d71b52662cf6_4032x3024.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!tIy_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe82a3f37-936a-41ae-800d-d71b52662cf6_4032x3024.heic 424w, https://substackcdn.com/image/fetch/$s_!tIy_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe82a3f37-936a-41ae-800d-d71b52662cf6_4032x3024.heic 848w, https://substackcdn.com/image/fetch/$s_!tIy_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe82a3f37-936a-41ae-800d-d71b52662cf6_4032x3024.heic 1272w, https://substackcdn.com/image/fetch/$s_!tIy_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe82a3f37-936a-41ae-800d-d71b52662cf6_4032x3024.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">The dark, cold, dew-covered transition zone at 5am.</figcaption></figure></div><h3><strong>Shattering the Calm of Mirror Lake</strong></h3><p>Nervously standing in the neoprene crowd, waiting to dive from the shore is an experience inseparable from triathlon. Half an hour flashes into thirty seconds - then we&#8217;re exhaling underwater, pulling on legs and shoulders while searching for a steady state. The clock started whether I was ready for it or not.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!SWwm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a0e353e-95d7-4aa0-be34-426d46059a85.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!SWwm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a0e353e-95d7-4aa0-be34-426d46059a85.heic 424w, https://substackcdn.com/image/fetch/$s_!SWwm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a0e353e-95d7-4aa0-be34-426d46059a85.heic 848w, https://substackcdn.com/image/fetch/$s_!SWwm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a0e353e-95d7-4aa0-be34-426d46059a85.heic 1272w, https://substackcdn.com/image/fetch/$s_!SWwm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a0e353e-95d7-4aa0-be34-426d46059a85.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!SWwm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a0e353e-95d7-4aa0-be34-426d46059a85.heic" width="516" height="372.11538461538464" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3a0e353e-95d7-4aa0-be34-426d46059a85.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1050,&quot;width&quot;:1456,&quot;resizeWidth&quot;:516,&quot;bytes&quot;:1487385,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blakesanie.substack.com/i/177315476?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a0e353e-95d7-4aa0-be34-426d46059a85.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!SWwm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a0e353e-95d7-4aa0-be34-426d46059a85.heic 424w, https://substackcdn.com/image/fetch/$s_!SWwm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a0e353e-95d7-4aa0-be34-426d46059a85.heic 848w, https://substackcdn.com/image/fetch/$s_!SWwm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a0e353e-95d7-4aa0-be34-426d46059a85.heic 1272w, https://substackcdn.com/image/fetch/$s_!SWwm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a0e353e-95d7-4aa0-be34-426d46059a85.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Athletes waiting to begin the swim, hard rain impending within the hour.</figcaption></figure></div><p>The circumstances of Lake Placid&#8217;s swim are uniquely advantaged, compared to other Ironman courses in North America; a light-up cable lays a few feet below the swim line. This enables swimmers to move straighter, like in a pool, despite the unboundedness of open-water. I quickly realized the guiding light&#8217;s utility was too good to be true. The light was chained between the barrier buoys themselves; swimming over the line would&#8217;ve brought repeated head-on collisions.</p><p>Nonetheless, it appeared other athletes quite favored this course feature. I let aggression accumulate near the tightest line, giving myself some space. Greediness had no place this early. Gaining 30 seconds was not worth any larger-scale risk of course completion.</p><p>Also unique to Ironman Lake Placid is the &#8220;Australian Exit&#8221;, where the first and second swim laps were joined by a brief beach exit. From watching every course overview on Youtube, I received the common advice of kicking hard in the last 100 meters before the beach; this promotes blood circulation back to the head and reduces dizziness once suddenly standing upright. The advice only went so far for me. Feeling directionally disoriented and seeing through foggy goggles, I aimed to cut my losses and reenter the water as quickly as possible. I ran straight past the walking athletes and skipped the hydration table.</p><p>Back in the freestyle rhythm, I finished my second lap, and made my way to the transition zone. With no swimming background and lowest training priority (versus cycling and running), peeling my wetsuit took much weight off my shoulders.</p><h3><strong>Riders of the Storm</strong></h3><p>Cycling is such a joy, genuinely, but my enthusiasm was tested.</p><p>Within the first ten minutes out of transition, I saw a face of devastation with a snapped chain (it happens). Then came the<a href="https://www.strava.com/activities/15182169920"> </a><strong><a href="https://www.strava.com/activities/15182169920">mind-numbing 50 mph descent into Keene</a></strong>. Straight down, soaked roads, limited knowledge of the turns ahead. Almost every rider hugged their brakes in the right lane all the way down.</p><p>Logging almost six thousand miles in 2025 before July, my handling confidence earned its rank. I shot straight down, with the left lane clear, with vigilance dialed to 100. Gravity alone wasn&#8217;t capable of the speeds I chased; leaning forward into a compact tuck, slicing through five miles of air in eight minutes. Racing in the time trail position can be vulnerable, forfeiting the robustness of the hoods and drops. I built a physiological adaptation over thousands of miles, but there&#8217;s one factor I didn&#8217;t foresee: the hard rain absolutely pierced supinated forearms. Even my lips received hard impact from the sideways onslaught&#8211; an area generally protected by the helmet and glasses.</p><p>In my ultimate race preparation, I packed two pairs of extra socks in my<a href="https://www.ironman.com/news/beginners-guide-special-needs-bag"> </a><strong><a href="https://www.ironman.com/news/beginners-guide-special-needs-bag">special-needs bag</a></strong>. However, completely soaked and knowing new socks would drench in a matter of minutes, I ditched the backup gear. In fact, unable to get any more wet, I felt completely unworried, as if I were dry. Pedaling up the next hill was the only objective worthy of attention.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6duY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26f4f6f6-8a2d-49ff-8c5b-c8d5b31aa55a_1513x2158.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6duY!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26f4f6f6-8a2d-49ff-8c5b-c8d5b31aa55a_1513x2158.jpeg 424w, https://substackcdn.com/image/fetch/$s_!6duY!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26f4f6f6-8a2d-49ff-8c5b-c8d5b31aa55a_1513x2158.jpeg 848w, https://substackcdn.com/image/fetch/$s_!6duY!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26f4f6f6-8a2d-49ff-8c5b-c8d5b31aa55a_1513x2158.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!6duY!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26f4f6f6-8a2d-49ff-8c5b-c8d5b31aa55a_1513x2158.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6duY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26f4f6f6-8a2d-49ff-8c5b-c8d5b31aa55a_1513x2158.jpeg" width="427" height="609.1201923076923" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/26f4f6f6-8a2d-49ff-8c5b-c8d5b31aa55a_1513x2158.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:2077,&quot;width&quot;:1456,&quot;resizeWidth&quot;:427,&quot;bytes&quot;:1051095,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blakesanie.substack.com/i/177315476?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e7f9f0b-8adb-44ba-b9a3-83a8c6bc9f23_1513x2158.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!6duY!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26f4f6f6-8a2d-49ff-8c5b-c8d5b31aa55a_1513x2158.jpeg 424w, https://substackcdn.com/image/fetch/$s_!6duY!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26f4f6f6-8a2d-49ff-8c5b-c8d5b31aa55a_1513x2158.jpeg 848w, https://substackcdn.com/image/fetch/$s_!6duY!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26f4f6f6-8a2d-49ff-8c5b-c8d5b31aa55a_1513x2158.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!6duY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26f4f6f6-8a2d-49ff-8c5b-c8d5b31aa55a_1513x2158.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Back in town, starting my second lap. While the course&#8217;s northern end was pouring hard, downtown remained moderately tame.</figcaption></figure></div><p>Like the physical effects of caffeinated gels, I found humor to be a necessary endurance tactic. I rejoiced upon meeting a 19 year old Coast Guard Academy student, asking him how he Zwifted at 5 o&#8217;clock in his dorm without disturbing his roommate. Next was leap-frogging with the most fit 50 year old woman I&#8217;ve ever met, joking how we&#8217;d pass the other soon enough. Once back in transition, I nudged the gentleman lacing his shoes next to me: &#8220;The race is over, right?&#8221;</p><p>Awkward timing, on my part. Right then, the first pro crossed the line. The marathon run was suddenly real, and more daunting than ever before.</p><h3><strong>Marathon Mountain Trek</strong></h3><p>The red carpet was in sight. There was no turning back now. Following the bike, I found myself in a state I had never explicitly simulated during training; I held no confident guess if my marathon pace would hold for 26.2 miles.</p><p>I ran a steady and confident seven miles. Then, everything changed. I lost all appetite. One can only consume so many gels. There was a runner holding his calf for dear life, laying on the shoulder. Another ambulance was moving down the out-and-back. Some runners on their second lap clearly lacked proper form due to neuromuscular fatigue (the &#8220;Ironman Shuffle&#8221;). I was determined to not meet the same fate.</p><p>I dialed into some sort of survival mode, working to maximize odds of course completion. I varied my feed across all available options, including bars, bananas, among other snacks. I executed a data-driven energy efficiency test&#8211; climbing hills with a jog, shuffle, or plain walk, while observing the resulting time and heart rate. With some mental math, I found it most optimal to simply speed walk the uphills. Not glamorous, but a scientifically justified means of making steady, low-risk progress.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!a-X6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f6efcb0-70e9-4c3b-9aaa-74a60aa7212f_3032x3767.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!a-X6!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f6efcb0-70e9-4c3b-9aaa-74a60aa7212f_3032x3767.jpeg 424w, https://substackcdn.com/image/fetch/$s_!a-X6!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f6efcb0-70e9-4c3b-9aaa-74a60aa7212f_3032x3767.jpeg 848w, https://substackcdn.com/image/fetch/$s_!a-X6!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f6efcb0-70e9-4c3b-9aaa-74a60aa7212f_3032x3767.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!a-X6!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f6efcb0-70e9-4c3b-9aaa-74a60aa7212f_3032x3767.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!a-X6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f6efcb0-70e9-4c3b-9aaa-74a60aa7212f_3032x3767.jpeg" width="462" height="573.9953825857519" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8f6efcb0-70e9-4c3b-9aaa-74a60aa7212f_3032x3767.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:3767,&quot;width&quot;:3032,&quot;resizeWidth&quot;:462,&quot;bytes&quot;:3302604,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blakesanie.substack.com/i/177315476?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa50e5966-75e3-4f9a-9e24-305337097f7f_3713x4804.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!a-X6!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f6efcb0-70e9-4c3b-9aaa-74a60aa7212f_3032x3767.jpeg 424w, https://substackcdn.com/image/fetch/$s_!a-X6!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f6efcb0-70e9-4c3b-9aaa-74a60aa7212f_3032x3767.jpeg 848w, https://substackcdn.com/image/fetch/$s_!a-X6!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f6efcb0-70e9-4c3b-9aaa-74a60aa7212f_3032x3767.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!a-X6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f6efcb0-70e9-4c3b-9aaa-74a60aa7212f_3032x3767.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">On each descent, chopping my feet was crucial to capitalize on momentum while maintaining control.</figcaption></figure></div><p>About to complete the first lap, I remember spotting the <strong><a href="https://en.wikipedia.org/wiki/Lake_Placid_Olympic_Ski_Jumping_Complex">ski-jump center</a></strong> seemingly many miles away. I turned to the runner beside me: &#8220;My goodness, we need to go back over there?&#8221; Pushing through the second lap was a true manifestation of placing one foot in front of the other, at all costs, mind over matter.</p><p>One quarter mile from the finish, I found a surge of energy. The hours of counting aid stations had almost passed. I was going to become an Ironman.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!oX6X!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21168c28-40f2-4c0e-b95e-21766fde239b_1997x2542.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!oX6X!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21168c28-40f2-4c0e-b95e-21766fde239b_1997x2542.heic 424w, https://substackcdn.com/image/fetch/$s_!oX6X!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21168c28-40f2-4c0e-b95e-21766fde239b_1997x2542.heic 848w, https://substackcdn.com/image/fetch/$s_!oX6X!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21168c28-40f2-4c0e-b95e-21766fde239b_1997x2542.heic 1272w, https://substackcdn.com/image/fetch/$s_!oX6X!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21168c28-40f2-4c0e-b95e-21766fde239b_1997x2542.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!oX6X!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21168c28-40f2-4c0e-b95e-21766fde239b_1997x2542.heic" width="370" height="470.885989010989" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/21168c28-40f2-4c0e-b95e-21766fde239b_1997x2542.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1853,&quot;width&quot;:1456,&quot;resizeWidth&quot;:370,&quot;bytes&quot;:921720,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blakesanie.substack.com/i/177315476?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21168c28-40f2-4c0e-b95e-21766fde239b_1997x2542.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!oX6X!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21168c28-40f2-4c0e-b95e-21766fde239b_1997x2542.heic 424w, https://substackcdn.com/image/fetch/$s_!oX6X!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21168c28-40f2-4c0e-b95e-21766fde239b_1997x2542.heic 848w, https://substackcdn.com/image/fetch/$s_!oX6X!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21168c28-40f2-4c0e-b95e-21766fde239b_1997x2542.heic 1272w, https://substackcdn.com/image/fetch/$s_!oX6X!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21168c28-40f2-4c0e-b95e-21766fde239b_1997x2542.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Stepping foot on the Ironman red carpet.</figcaption></figure></div><h3><strong>The Chimes of Triumph</strong></h3><p>I rang the bell hard with my right hand. It rang louder than any thunder clap. Following a straight path, I held myself together for a few final steps down the red carpet. I smiled at hearing my name, threw a fist pump in the air, and experienced a rush of pure fulfillment over my journey to this very moment.</p><div class="native-video-embed" data-component-name="VideoPlaceholder" data-attrs="{&quot;mediaUploadId&quot;:&quot;03c8f00a-60f3-4454-88c2-2e4da5328714&quot;,&quot;duration&quot;:null}"></div><p>In eagerness to rendezvous with my support crew, I quickly grabbed two slices of pizza and a donut, and left the athlete area within a minute. Then, we celebrated together.</p><p>They say Ironman is an individual sport, but standing here today, I know that&#8217;s a myth. It starts with those who help to embrace early mornings and often late nights. Others evolve into dear friends who engage in ridiculous workouts to keep it necessarily light and fun. Above all else, there are those who build an environment that drives growth for its own sake, without demanding anything in return. Sharing only two legs, my community ascended every climb alongside me.</p><h3><strong>Iron-Willed</strong></h3><p>From the other side, Ironman lends itself into nearly every journey faced in normal life. Any goal (and ounce of adversity alike) rooted in possibility is within reach. Once the mind finds willingness, obstacles become milestones. Most importantly, once the boxes seem finally crossed, more appear - new paths and opportunities once undiscovered.</p><p>Besides an athlete, I&#8217;m an avid engineer and academic who wishes to apply inventiveness towards my passions. Even more simply, I&#8217;m a man who wishes to show up for his friends and family, and bring the best version of himself to work every day.</p><p>Challenges will come, dreams will grow, but my doubt is gone. I have the tenacity. I have the fortitude. I have the proof. I am an Ironman.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!gSAP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff5592623-fad1-4f73-86ba-4ee4410a9a56_3024x4032.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!gSAP!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff5592623-fad1-4f73-86ba-4ee4410a9a56_3024x4032.jpeg 424w, https://substackcdn.com/image/fetch/$s_!gSAP!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff5592623-fad1-4f73-86ba-4ee4410a9a56_3024x4032.jpeg 848w, https://substackcdn.com/image/fetch/$s_!gSAP!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff5592623-fad1-4f73-86ba-4ee4410a9a56_3024x4032.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!gSAP!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff5592623-fad1-4f73-86ba-4ee4410a9a56_3024x4032.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!gSAP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff5592623-fad1-4f73-86ba-4ee4410a9a56_3024x4032.jpeg" width="1456" height="1941" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f5592623-fad1-4f73-86ba-4ee4410a9a56_3024x4032.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1941,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:12171390,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blakesanie.substack.com/i/177315476?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff5592623-fad1-4f73-86ba-4ee4410a9a56_3024x4032.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!gSAP!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff5592623-fad1-4f73-86ba-4ee4410a9a56_3024x4032.jpeg 424w, https://substackcdn.com/image/fetch/$s_!gSAP!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff5592623-fad1-4f73-86ba-4ee4410a9a56_3024x4032.jpeg 848w, https://substackcdn.com/image/fetch/$s_!gSAP!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff5592623-fad1-4f73-86ba-4ee4410a9a56_3024x4032.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!gSAP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff5592623-fad1-4f73-86ba-4ee4410a9a56_3024x4032.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blakesanie.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Blake Sanie&#8217;s Blog! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[A Comprehensive Guide to the Zwift Century]]></title><description><![CDATA[100 miles from the comfort of your own home! Oh, fun!]]></description><link>https://blakesanie.substack.com/p/a-comprehensive-guide-to-the-zwift</link><guid isPermaLink="false">https://blakesanie.substack.com/p/a-comprehensive-guide-to-the-zwift</guid><dc:creator><![CDATA[Blake Sanie]]></dc:creator><pubDate>Tue, 18 Mar 2025 00:52:17 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!1hi6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e142367-8b60-49f9-b16f-f5ec520c0398_4032x3024.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1hi6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e142367-8b60-49f9-b16f-f5ec520c0398_4032x3024.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1hi6!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e142367-8b60-49f9-b16f-f5ec520c0398_4032x3024.jpeg 424w, https://substackcdn.com/image/fetch/$s_!1hi6!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e142367-8b60-49f9-b16f-f5ec520c0398_4032x3024.jpeg 848w, https://substackcdn.com/image/fetch/$s_!1hi6!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e142367-8b60-49f9-b16f-f5ec520c0398_4032x3024.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!1hi6!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e142367-8b60-49f9-b16f-f5ec520c0398_4032x3024.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1hi6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e142367-8b60-49f9-b16f-f5ec520c0398_4032x3024.jpeg" width="1456" height="1092" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4e142367-8b60-49f9-b16f-f5ec520c0398_4032x3024.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1092,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:3789318,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blakesanie.substack.com/i/158517051?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e142367-8b60-49f9-b16f-f5ec520c0398_4032x3024.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!1hi6!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e142367-8b60-49f9-b16f-f5ec520c0398_4032x3024.jpeg 424w, https://substackcdn.com/image/fetch/$s_!1hi6!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e142367-8b60-49f9-b16f-f5ec520c0398_4032x3024.jpeg 848w, https://substackcdn.com/image/fetch/$s_!1hi6!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e142367-8b60-49f9-b16f-f5ec520c0398_4032x3024.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!1hi6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e142367-8b60-49f9-b16f-f5ec520c0398_4032x3024.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Where it all began, before many reiterations</figcaption></figure></div><h2>What is Zwift?</h2><p><strong><a href="https://www.zwift.com/invite/zw5HB3LbqJ">Zwift</a></strong> is an immersive, virtual cycling platform that combines gaming elements with structured training and free-ride experiences. Through the use of a smart trainer, power meter, or speed sensor, riders can interact with dynamic digital environments while receiving real-time feedback on their performance metrics. This platform enables cyclists to train, race, and complete endurance challenges in a controlled indoor environment. To add, one&#8217;s location and time of year may designate platforms like Zwift as the only semi-desirable cycling experience, anyway. </p><h2>What is a Zwift Century?</h2><p>A Zwift century refers to the completion of a 100-mile (160.9 km) ride on the Zwift platform. This feat, while traditionally a respected endurance milestone in outdoor cycling, becomes particularly grueling in the indoor realm due to environmental and psychological factors. Unlike outdoor centuries, where variables such as wind resistance, terrain variation, and coasting provide natural and necessary variation, the continuous nature of an indoor ride amplifies the physiological and mental demands.</p><h2>Motivating the a Zwift Century</h2><h3>Training for Long-Distance Events</h3><p>Athletes preparing for ultra-endurance events, such as Ironman triathlons, can leverage a Zwift century as a controlled long-duration training session. By maintaining consistent power zones, fine-tuning nutrition strategies, and simulating race conditions, cyclists can develop the necessary physiological adaptations and psychological determination for prolonged efforts.</p><h3>Map Exploration and Achievement Completion</h3><p>Zwift&#8217;s digital worlds feature numerous routes and challenges. Riding a century within the platform presents an opportunity to maximize route coverage, unlock in-game achievements, and progress toward long-term goals such as earning the coveted <strong><a href="https://zwiftinsider.com/tron-bike/">Tron bike</a></strong>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!9sQQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05054622-6d94-4b01-b4a5-cb4a64e71807_1024x682.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!9sQQ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05054622-6d94-4b01-b4a5-cb4a64e71807_1024x682.jpeg 424w, https://substackcdn.com/image/fetch/$s_!9sQQ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05054622-6d94-4b01-b4a5-cb4a64e71807_1024x682.jpeg 848w, https://substackcdn.com/image/fetch/$s_!9sQQ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05054622-6d94-4b01-b4a5-cb4a64e71807_1024x682.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!9sQQ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05054622-6d94-4b01-b4a5-cb4a64e71807_1024x682.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!9sQQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05054622-6d94-4b01-b4a5-cb4a64e71807_1024x682.jpeg" width="1024" height="682" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/05054622-6d94-4b01-b4a5-cb4a64e71807_1024x682.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:682,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Watopia Map Poster: Download or Purchase | Zwift Insider&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Watopia Map Poster: Download or Purchase | Zwift Insider" title="Watopia Map Poster: Download or Purchase | Zwift Insider" srcset="https://substackcdn.com/image/fetch/$s_!9sQQ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05054622-6d94-4b01-b4a5-cb4a64e71807_1024x682.jpeg 424w, https://substackcdn.com/image/fetch/$s_!9sQQ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05054622-6d94-4b01-b4a5-cb4a64e71807_1024x682.jpeg 848w, https://substackcdn.com/image/fetch/$s_!9sQQ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05054622-6d94-4b01-b4a5-cb4a64e71807_1024x682.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!9sQQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05054622-6d94-4b01-b4a5-cb4a64e71807_1024x682.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Watopia - Zwift&#8217;s base map</figcaption></figure></div><h2>My Journey: From Novice to Completionist</h2><p>Prior to writing this post, I&#8217;ve completed four Zwift centuries, each with a distinct goal:</p><ol><li><p><strong><a href="https://www.strava.com/activities/13390573740">Initial Attempt</a>:</strong> A straightforward ride with a constant, unvaried power output and minimal optimization.</p></li><li><p><strong><a href="https://www.strava.com/activities/13441260013">Performance-Oriented Century</a>:</strong> A competitive time-trial effort incorporating intriguing power intervals, route selection, bike aerodynamics.</p></li><li><p><strong><a href="https://www.strava.com/activities/13626177015">PR Chasing</a>:</strong> Just like before, but with a higher power output goal and more specific bike choice, culminating in a new Personal Best.</p></li><li><p><strong><a href="https://www.strava.com/activities/13680611144">Completionist Effort</a>:</strong> A comprehensive route-based strategy aimed at maximizing map coverage and achievements. This was also my first time completing the <strong><a href="https://zwiftinsider.com/route/the-uber-pretzel/">The &#220;ber Pretzel</a>!</strong></p></li></ol><h3>The Paincave: Optimizing the Indoor Environment</h3><p>Unlike outdoor rides, a Zwift century is most efficiently achieved through a self-sufficient setup. Key considerations include:</p><ul><li><p><strong>Unbroken Effort:</strong> Plan for a continuous ride without dismounts or extended breaks. More practically, be careful of unnecessarily long breaks that begin dissolving your interest in the feat, making the century&#8217;s remainder even more grueling. Full honesty - only my Personal Best effort saw continuous pedal strokes.</p></li><li><p><strong>Nutrition and Hydration:</strong> Ensure a desktop or tray fully stocked with carbohydrates, electrolytes, and sufficient water. I personally recruited every water bottle I owned and bought half the banana supply at Trader Joes.</p></li><li><p><strong>Temperature Regulation:</strong> A large, high-powered fan is essential to compensate for the lack of wind cooling. Your house, your rules - so no jersey necessary!</p></li><li><p><strong>Ergonomics:</strong> Utilize aero bars or other means of comfortable positioning. In my case, a standing desk raised to the right height allowed my wrists rest naturally, while my elbows rest on the handlebars.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!IaRh!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feea311e3-e901-4acb-b51e-0279f74c7bf5_3024x4032.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!IaRh!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feea311e3-e901-4acb-b51e-0279f74c7bf5_3024x4032.jpeg 424w, https://substackcdn.com/image/fetch/$s_!IaRh!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feea311e3-e901-4acb-b51e-0279f74c7bf5_3024x4032.jpeg 848w, https://substackcdn.com/image/fetch/$s_!IaRh!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feea311e3-e901-4acb-b51e-0279f74c7bf5_3024x4032.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!IaRh!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feea311e3-e901-4acb-b51e-0279f74c7bf5_3024x4032.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!IaRh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feea311e3-e901-4acb-b51e-0279f74c7bf5_3024x4032.jpeg" width="386" height="514.5782967032967" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/eea311e3-e901-4acb-b51e-0279f74c7bf5_3024x4032.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1941,&quot;width&quot;:1456,&quot;resizeWidth&quot;:386,&quot;bytes&quot;:3883505,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blakesanie.substack.com/i/158517051?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feea311e3-e901-4acb-b51e-0279f74c7bf5_3024x4032.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!IaRh!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feea311e3-e901-4acb-b51e-0279f74c7bf5_3024x4032.jpeg 424w, https://substackcdn.com/image/fetch/$s_!IaRh!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feea311e3-e901-4acb-b51e-0279f74c7bf5_3024x4032.jpeg 848w, https://substackcdn.com/image/fetch/$s_!IaRh!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feea311e3-e901-4acb-b51e-0279f74c7bf5_3024x4032.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!IaRh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feea311e3-e901-4acb-b51e-0279f74c7bf5_3024x4032.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Mid-Zwift-Century with bananas, energy bars, caffeine, electrolytes, and water in ample (but necessary) supply</figcaption></figure></div><h3>Workout Design: Structuring the Effort</h3><p>Three primary strategies can be employed:</p><ol><li><p><strong>Unstructured Ride:</strong> No predefined intervals, allowing for a natural feel of course gradients.</p></li><li><p><strong>Steady-State <a href="https://zwiftinsider.com/erg-mode-in-zwift/">ERG Mode</a>:</strong> Maintains a consistent power output to optimize endurance pacing.</p></li><li><p><strong>Dynamic Workouts:</strong> Alternating intensities to prevent monotony and stimulate varied physiological adaptations.</p></li></ol><p>Initially, I employed a monotonous Zone 2 steady-state approach, but later introduced structured variations. These intervals alternated between upper and lower Zone 2 power ranges to maintain engagement while maintaining an appropriate intensity for my goals.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!2URS!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82dc812c-33b5-43be-b863-2adcbfd08752_1440x871.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2URS!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82dc812c-33b5-43be-b863-2adcbfd08752_1440x871.jpeg 424w, https://substackcdn.com/image/fetch/$s_!2URS!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82dc812c-33b5-43be-b863-2adcbfd08752_1440x871.jpeg 848w, https://substackcdn.com/image/fetch/$s_!2URS!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82dc812c-33b5-43be-b863-2adcbfd08752_1440x871.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!2URS!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82dc812c-33b5-43be-b863-2adcbfd08752_1440x871.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2URS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82dc812c-33b5-43be-b863-2adcbfd08752_1440x871.jpeg" width="1440" height="871" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/82dc812c-33b5-43be-b863-2adcbfd08752_1440x871.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:871,&quot;width&quot;:1440,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Image&quot;,&quot;title&quot;:&quot;Image&quot;,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Image" title="Image" srcset="https://substackcdn.com/image/fetch/$s_!2URS!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82dc812c-33b5-43be-b863-2adcbfd08752_1440x871.jpeg 424w, https://substackcdn.com/image/fetch/$s_!2URS!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82dc812c-33b5-43be-b863-2adcbfd08752_1440x871.jpeg 848w, https://substackcdn.com/image/fetch/$s_!2URS!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82dc812c-33b5-43be-b863-2adcbfd08752_1440x871.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!2URS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82dc812c-33b5-43be-b863-2adcbfd08752_1440x871.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">A glimpse into my programmed power intervals, set to repeat for 5 hours</figcaption></figure></div><h3>Navigating the Zwift World</h3><h4>Route Selection</h4><p>My first attempt involved subjective course selection, such as the relatively flat <strong><a href="https://zwiftinsider.com/route/big-flat-8/">Big Flat 8</a></strong><a href="https://zwiftinsider.com/route/big-flat-8/"> </a>route. Later on, deeper analysis revealed <strong><a href="https://zwiftinsider.com/route/tempus-fugit/">Tempus Fugit</a></strong> as the optimal choice for a truly flat effort, necessitating approximately ten laps for a complete century. However, elevation can add significance in its own right&#8212;choosing a hillier route may contribute to additional long-term goals, such as progressing toward the Zwift Tron bike (unlocked at 50,000m all-time elevation gain ) or completing an <strong><a href="https://everesting.com/">Everesting</a></strong> (8,848m vertical gain in a single ride).</p><h4>Equipment Optimization</h4><p>Bike and wheel choice yield non-negligible performance impact in Zwift:</p><ul><li><p><strong>Standard or Flat Routes:</strong> Aero road frames with deep-section wheels provide a collectively preferred balance between weight and aerodynamic design.</p></li><li><p><strong>Climbing Routes:</strong> Lightweight frames and wheels optimize weight-to-power ratio, with gravity now much harder to overcome than air resistance.</p></li><li><p><strong>TT Bikes:</strong> Provide superior aerodynamics alongside slight weight increase, compared to aero road bikes. However, <em>equipping a TT bike will disable in-world drafting benefits</em>, ensuring independent pacing unaffected by group dynamics.</p></li></ul><p>Zwift Insider removed all the fuss from finding the most effective frameset and wheels for my given <strong><a href="https://zwiftinsider.com/points-levels-unlocks/">Zwift XP</a></strong> is made effortless. &#8220;<strong><a href="https://zwiftinsider.com/fastest-bikes-at-each-level/">Fastest Bike Frames and Wheels at Each Zwift Level</a></strong>&#8221; is a must read!</p><p>For an uncontested century attempt, a TT bike minimizes external variables, providing a pure test of sustained power.</p><h4>Solo Ride versus Meetup</h4><p>Meetup events in Zwift allow group rides with a "Keep Everyone Together" option, artificially synchronizing participants&#8217; speeds. While beneficial for social riding, this mechanism distorts pacing metrics and drafting effects. Thus, for accurate century performance benchmarking, a solo ride is preferred.</p><h3>Handling Boredom: Strategies for Mental Endurance</h3><p>Unlike outdoor riding, indoor efforts lack immersive environmental stimuli, necessitating proactive engagement strategies:</p><ul><li><p><strong>Media Consumption:</strong> Preload a YouTube playlist, stream a show, or participate in a shared Spotify Jam session.</p></li><li><p><strong>Multitasking Awareness:</strong> While passive media consumption is effective, activities requiring hand coordination can interfere with power stability.</p></li><li><p><strong>Social Interaction:</strong> Engaging in voice or text chats with friends can provide distraction without significantly affecting effort. With some coordination, you can find your friends on Watopia&#8217;s roads without an official Zwift meetup!</p></li><li><p><strong>Adaptive Entertainment Plan:</strong> Expect diminishing engagement levels&#8212;prepare multiple forms of entertainment to sustain interest throughout the ride.</p></li></ul><p><em>If you prefer to look straight ahead instead of listening to music, podcasts, or watching TV, you were born for Ironman.</em></p><h2>Conclusion</h2><p>A Zwift century is a demanding yet rewarding endurance challenge that combines physical performance, mental resilience, and strategic optimization. By refining route selection, workout structure, equipment choices, and entertainment strategies, cyclists can maximize efficiency and engagement, making the virtual century an invaluable component of long-distance training. Whether targeting personal bests, exploring virtual landscapes, or testing mental fortitude, the Zwift century offers a unique endurance experience amidst nonstop snow outside.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blakesanie.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Blake Sanie&#8217;s Blog! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Triathlon & the Prisoner's Dilemma]]></title><description><![CDATA[Game Theory at the core of sports. Mathletes, rejoice.]]></description><link>https://blakesanie.substack.com/p/triathlon-and-the-prisoners-dilemma</link><guid isPermaLink="false">https://blakesanie.substack.com/p/triathlon-and-the-prisoners-dilemma</guid><dc:creator><![CDATA[Blake Sanie]]></dc:creator><pubDate>Sun, 16 Feb 2025 18:01:35 GMT</pubDate><enclosure url="https://images.unsplash.com/photo-1533547477463-bcffb9ef386d?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw5fHx0cmlhdGhsb24lMjBydW58ZW58MHx8fHwxNzM2OTgzMDQ3fDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Background &amp; Motivation</h2><p>Triathlon is a multidimensional competition involving swimming, cycling, and running. While the physical demands of these events are widely recognized, their strategic depth is often underestimated. In fact, triathlons can be viewed as a highly intricate game where each participant&#8217;s decisions not only affect their own performance but also influence the outcomes for others. This interconnected decision-making process is where <em><strong>Game Theory</strong></em> applies. By analyzing concepts like cooperation, competition, and equilibrium strategies, Game Theory highlights smart decision-making as a deciding factor on race day.</p><h3>Defining Fundamental Game Components</h3><ul><li><p><strong>Environment</strong>: A direct competition, with athlete&#8217;s racing head-to-head for ranking. (<em>In the real world, racers aim to finish for pure enjoyment or accomplishment - truly inspiring, though less game-theoretic).</em></p></li><li><p><strong>Players</strong>: You and your direct competitors in the race. Note that Game Theory assumes <em>rational</em> agents - each expected to act in their own best interest.</p></li><li><p><strong>High-Level Strategies</strong>:</p><ul><li><p>Pacing (conserve energy vs. exert effort early).</p></li><li><p>Cooperation (draft vs. break away).</p></li><li><p>Transition speed (fast vs. steady).</p></li><li><p>Nutrition (aggressive early fueling vs. conservative).</p></li></ul></li><li><p><strong>Payoffs</strong>: Finish time, ranking, or energy conserved. <em>(Is the ability to walk of priority, post-finish)?</em></p></li></ul><h3><strong>Sequential Game Structure</strong></h3><p>A triathlon can be modeled as a <strong>Multi-Stage Sequential Game</strong>, where actions in earlier stages (swim, bike) impact outcomes in later stages (run). Decisions are influenced by:</p><ol><li><p>Personal fatigue, expectation of future resources (nutrition), and estimated standing.</p></li><li><p>Observed competitor fatigue, composure, strategies, and standing.</p></li></ol><p>I&#8217;ll save the leg-by-leg strategy deep-dive for a later day, as I recognize one principle to carry most of the strategizing brain power.</p><h2>The Prisoner&#8217;s Dilemma</h2><p>A cornerstone principle of Game Theory. A simple paradox of best-interest on paper, fueling fearless judgement on the course.</p><p>In a classic <em><strong><a href="https://en.wikipedia.org/wiki/Prisoner%27s_dilemma">The Prisoner&#8217;s Dilemma</a> </strong></em>variant, two accomplices are imprisoned on suspicion of a crime. When interrogated separately, each prisoner may remain quiet, or admit to the crime. As a defining characteristic, each prisoner&#8217;s sentence depends on both interrogations. All potential outcomes are enumerated below:</p><ul><li><p>Both stay quiet: each receives a short sentence.</p></li><li><p>Both admit the crime: each receives a long sentence.</p></li><li><p>One stays quiet, the other admits: the former is released, while the latter receives the longest sentence.</p></li></ul><p>Thus, a delicate balance between capitalizing on opportunity, taming greed, and above all, knowing the enemy.</p><p>Below are these outcomes represented as a payoff matrix captured as (your payoff, accomplice&#8217;s payoff):</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\begin{array}{c|c|c}\n    &amp; \\text{Accomplice quiet} &amp; \\text{Accomplice admits} \\\\ \\hline\n    \\text{Stay quiet} &amp; (-1, -1) &amp; (-5, 0) \\\\ \n    \\text{Admit} &amp; (0, -5) &amp; (-3, -3)\n\\end{array}&quot;,&quot;id&quot;:&quot;VIKKMSWJAP&quot;}" data-component-name="LatexBlockToDOM"></div><p>In a general triathlon context, competitors may achieve (mutual) benefit by cooperating, or even stronger (individual) benefits when attacking alone.</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\begin{array}{c|c|c}\n    &amp; \\text{Opponent cooperates} &amp; \\text{Opponent attacks} \\\\ \\hline\n    \\text{Cooperate} &amp; (+1, +1) &amp; (0, +5) \\\\ \n    \\text{Attack} &amp; (+5, 0) &amp; (0, 0)\n\\end{array}&quot;,&quot;id&quot;:&quot;CECUZRWIXL&quot;}" data-component-name="LatexBlockToDOM"></div><p>Now, to analyze specific strategic points and their foundation in this notion.</p><h2>Key Tactics, Intuition, &amp; Dilemmas</h2><h4>Swim Contact &amp; Aggression</h4><p>Who knew open water swimming was a contact sport? Freestyle strokes to the head, grabbing on the shoulders, kicks to the face - these are to be expected. Naturally, the race starts swimmingly if no competitor pursues contact. However, an advantage arises when you tug a swimmer, gaining ground. If everyone employed that strategy, though, all end up fatigued, potentially injured, and no faster than if no contact were made.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://images.unsplash.com/photo-1633114069176-8632494e6f4f?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw3fHx0cmlhdGhsb24lMjBzd2ltfGVufDB8fHx8MTczNjk4MjkxNXww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://images.unsplash.com/photo-1633114069176-8632494e6f4f?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw3fHx0cmlhdGhsb24lMjBzd2ltfGVufDB8fHx8MTczNjk4MjkxNXww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 424w, https://images.unsplash.com/photo-1633114069176-8632494e6f4f?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw3fHx0cmlhdGhsb24lMjBzd2ltfGVufDB8fHx8MTczNjk4MjkxNXww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 848w, https://images.unsplash.com/photo-1633114069176-8632494e6f4f?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw3fHx0cmlhdGhsb24lMjBzd2ltfGVufDB8fHx8MTczNjk4MjkxNXww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1272w, https://images.unsplash.com/photo-1633114069176-8632494e6f4f?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw3fHx0cmlhdGhsb24lMjBzd2ltfGVufDB8fHx8MTczNjk4MjkxNXww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1456w" sizes="100vw"><img src="https://images.unsplash.com/photo-1633114069176-8632494e6f4f?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw3fHx0cmlhdGhsb24lMjBzd2ltfGVufDB8fHx8MTczNjk4MjkxNXww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080" width="446" height="297.27956600361665" data-attrs="{&quot;src&quot;:&quot;https://images.unsplash.com/photo-1633114069176-8632494e6f4f?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw3fHx0cmlhdGhsb24lMjBzd2ltfGVufDB8fHx8MTczNjk4MjkxNXww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1843,&quot;width&quot;:2765,&quot;resizeWidth&quot;:446,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;a group of people swimming in the ocean&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="a group of people swimming in the ocean" title="a group of people swimming in the ocean" srcset="https://images.unsplash.com/photo-1633114069176-8632494e6f4f?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw3fHx0cmlhdGhsb24lMjBzd2ltfGVufDB8fHx8MTczNjk4MjkxNXww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 424w, https://images.unsplash.com/photo-1633114069176-8632494e6f4f?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw3fHx0cmlhdGhsb24lMjBzd2ltfGVufDB8fHx8MTczNjk4MjkxNXww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 848w, https://images.unsplash.com/photo-1633114069176-8632494e6f4f?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw3fHx0cmlhdGhsb24lMjBzd2ltfGVufDB8fHx8MTczNjk4MjkxNXww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1272w, https://images.unsplash.com/photo-1633114069176-8632494e6f4f?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw3fHx0cmlhdGhsb24lMjBzd2ltfGVufDB8fHx8MTczNjk4MjkxNXww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Photo by <a href="true">Mario La Pergola</a> on <a href="https://unsplash.com">Unsplash</a></figcaption></figure></div><h4>Open Water Navigation &amp; Corner Cutting</h4><p>If you can&#8217;t swim faster, swim a shorter distance. Turn buoys are highly contested for this reason. Take a chance on fully minimizing point-to-point distance, and get ready to risk a kick to the goggles. Keep your distance, and earn an unimpressive split. Most prominently, go against the broader decision of those surrounding you, and get run over by a stampede.</p><h4>Drafting (To the Extent Permitted)</h4><p>The quintessential example of cooperation versus lone onset. Drafting allows a cluster of cyclists to resist the effects of drag. This way, they can save energy for critical moments, such as a breakaway. If drafting the whole race, energy is conserved for the run, but no competitive gain is made in the bike leg. On the other hand, if every cyclist pursued their own breakaway (<em>could you even call it that?</em>), the field remains in uniform standing with exhaustion inflicted across the board. In the worst case, preferencing a draft but cycling alongside breakaway-focused competitors leaves you not only exhausted, but behind in standing. These considerations only become more crucial in sprint-focused races, such as criteriums.</p><p><em>Drafting has a non-negligible effect even outside of rule-defined drafting zones. Know your advantage, but play by the rules.</em></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://images.unsplash.com/photo-1517649763962-0c623066013b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw0fHxiaWtlJTIwZ3JvdXB8ZW58MHx8fHwxNzM2OTgyOTk2fDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://images.unsplash.com/photo-1517649763962-0c623066013b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw0fHxiaWtlJTIwZ3JvdXB8ZW58MHx8fHwxNzM2OTgyOTk2fDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 424w, https://images.unsplash.com/photo-1517649763962-0c623066013b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw0fHxiaWtlJTIwZ3JvdXB8ZW58MHx8fHwxNzM2OTgyOTk2fDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 848w, https://images.unsplash.com/photo-1517649763962-0c623066013b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw0fHxiaWtlJTIwZ3JvdXB8ZW58MHx8fHwxNzM2OTgyOTk2fDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1272w, https://images.unsplash.com/photo-1517649763962-0c623066013b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw0fHxiaWtlJTIwZ3JvdXB8ZW58MHx8fHwxNzM2OTgyOTk2fDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1456w" sizes="100vw"><img src="https://images.unsplash.com/photo-1517649763962-0c623066013b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw0fHxiaWtlJTIwZ3JvdXB8ZW58MHx8fHwxNzM2OTgyOTk2fDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080" width="486" height="324" data-attrs="{&quot;src&quot;:&quot;https://images.unsplash.com/photo-1517649763962-0c623066013b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw0fHxiaWtlJTIwZ3JvdXB8ZW58MHx8fHwxNzM2OTgyOTk2fDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:3840,&quot;width&quot;:5760,&quot;resizeWidth&quot;:486,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;group of cyclist on asphalt road&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="group of cyclist on asphalt road" title="group of cyclist on asphalt road" srcset="https://images.unsplash.com/photo-1517649763962-0c623066013b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw0fHxiaWtlJTIwZ3JvdXB8ZW58MHx8fHwxNzM2OTgyOTk2fDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 424w, https://images.unsplash.com/photo-1517649763962-0c623066013b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw0fHxiaWtlJTIwZ3JvdXB8ZW58MHx8fHwxNzM2OTgyOTk2fDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 848w, https://images.unsplash.com/photo-1517649763962-0c623066013b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw0fHxiaWtlJTIwZ3JvdXB8ZW58MHx8fHwxNzM2OTgyOTk2fDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1272w, https://images.unsplash.com/photo-1517649763962-0c623066013b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw0fHxiaWtlJTIwZ3JvdXB8ZW58MHx8fHwxNzM2OTgyOTk2fDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Photo by <a href="true">Markus Spiske</a> on <a href="https://unsplash.com">Unsplash</a></figcaption></figure></div><h4>Run Pacing Cooperation</h4><p>A well executed run requires many factors, one of which is a well-dialed pace. Unlike the bike, where sensors can give precise speed and power measurements, keeping continual eye contact with one&#8217;s watch is impractical. Even the world&#8217;s most dominant marathoners leverage pacers to minimize variability in running speed. In a triathlon run leg, or running races more generally, pace variability can be reduced by forming pace groups: maintaining close proximity, similar to drafting, but for a new reason. Like in drafting, long-term pace cooperation yields little immediate competitive edge, but notable energy savings and pacing adherence. Zero pace cooperation utilizes maximum racing potential to outrun the others (go all-out), with an accepted chance of burnout. If clustered runners raise a mixed decision for too long, the benefits of each are wasted, with uneven pacing and unrealized speed bringing down results. These choices only become more decisive as the finish line approaches.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://images.unsplash.com/photo-1533547477463-bcffb9ef386d?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw5fHx0cmlhdGhsb24lMjBydW58ZW58MHx8fHwxNzM2OTgzMDQ3fDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://images.unsplash.com/photo-1533547477463-bcffb9ef386d?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw5fHx0cmlhdGhsb24lMjBydW58ZW58MHx8fHwxNzM2OTgzMDQ3fDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 424w, https://images.unsplash.com/photo-1533547477463-bcffb9ef386d?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw5fHx0cmlhdGhsb24lMjBydW58ZW58MHx8fHwxNzM2OTgzMDQ3fDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 848w, https://images.unsplash.com/photo-1533547477463-bcffb9ef386d?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw5fHx0cmlhdGhsb24lMjBydW58ZW58MHx8fHwxNzM2OTgzMDQ3fDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1272w, https://images.unsplash.com/photo-1533547477463-bcffb9ef386d?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw5fHx0cmlhdGhsb24lMjBydW58ZW58MHx8fHwxNzM2OTgzMDQ3fDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1456w" sizes="100vw"><img src="https://images.unsplash.com/photo-1533547477463-bcffb9ef386d?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw5fHx0cmlhdGhsb24lMjBydW58ZW58MHx8fHwxNzM2OTgzMDQ3fDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080" width="436" height="290.6945189727865" data-attrs="{&quot;src&quot;:&quot;https://images.unsplash.com/photo-1533547477463-bcffb9ef386d?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw5fHx0cmlhdGhsb24lMjBydW58ZW58MHx8fHwxNzM2OTgzMDQ3fDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:3479,&quot;width&quot;:5218,&quot;resizeWidth&quot;:436,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;two men running on field with people on side cheering for them&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="two men running on field with people on side cheering for them" title="two men running on field with people on side cheering for them" srcset="https://images.unsplash.com/photo-1533547477463-bcffb9ef386d?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw5fHx0cmlhdGhsb24lMjBydW58ZW58MHx8fHwxNzM2OTgzMDQ3fDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 424w, https://images.unsplash.com/photo-1533547477463-bcffb9ef386d?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw5fHx0cmlhdGhsb24lMjBydW58ZW58MHx8fHwxNzM2OTgzMDQ3fDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 848w, https://images.unsplash.com/photo-1533547477463-bcffb9ef386d?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw5fHx0cmlhdGhsb24lMjBydW58ZW58MHx8fHwxNzM2OTgzMDQ3fDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1272w, https://images.unsplash.com/photo-1533547477463-bcffb9ef386d?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw5fHx0cmlhdGhsb24lMjBydW58ZW58MHx8fHwxNzM2OTgzMDQ3fDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Photo by <a href="true">Victoire Joncheray</a> on <a href="https://unsplash.com">Unsplash</a></figcaption></figure></div><h4>Higher-Level Race Pacing</h4><p>Each athlete has their strengths and preferences. For strong swimmers, being first out of the water and holding the lead on the road is a preferable race plan. Strong runners or cyclists, by contrast, don&#8217;t mind a later water exit, expecting to pass others at high speed and erase their deficit. As a result, it pays to do your homework - know yourself, the competition, and the course. Though impossible to know exactly what your opponents are thinking, an informed and well-supported judgement just might keep you on the podium. Without a doubt, your opponents are looking to stump your race plan in their own right!</p><h2>Nuance Beyond Textbook Game Theory</h2><p>Surely, a triathlon is not a one-to-one demonstration of the Prisoner&#8217;s Dilemma. Let&#8217;s break down how theory transforms to practice.</p><h4>Multiple Stage Structure &amp; Group Dynamics</h4><p>As hinted with higher-level race pacing, athletes may cooperate in some stages, but fight head-to-head in others. Further, it may be sufficient to cooperate with a fraction of nearby athletes, or perhaps insufficient to pursue a lone attack against a prominent group. These notions adds real-world complexity and depth to the 2x2 payoff matrix model.</p><h4>Iterative Observation and Action</h4><p>In the classic variant of the Prisoner&#8217;s Dilemma, each prisoner is blind to the other&#8217;s choice, and a single decision is made. Throughout the race, athletes not only receive continuous feedback by observing the field, but can apply (and pivot) tactics as often as necessary. In practice, this is called a <em><strong>tit-for-tat</strong></em> strategy.</p><h4>Asymmetric Payoff</h4><p>The classic variant assumes equal payoff even if the prisoners swapped places. On the course, payoff received from cooperation will on the athlete and race discipline - the same is argued regarding the payoff from attacking, or competitive disadvantage incurred when cooperation is denied. In any case, expected payoff is merely an educated guess in the heat of the moment.</p><h2>Conclusion</h2><p>Triathlon is a sport where physical endurance meets mental acuity, and the principles of <em><strong>Game Theory</strong></em> provide a valuable lens through which to view race strategy. The interplay of cooperation and competition, exemplified by the <em><strong>Prisoner's Dilemma</strong></em>, underscores the tactical decisions athletes face at every stage of the race.</p><p>While the classic Prisoner's Dilemma offers a simplified view of decision-making under competition, a triathlon introduces layers of complexity that extend beyond a binary choice framework. Yet, this complexity introduces opportunity for athletes to enhance their decision-making processes, ultimately leading to smarter, more calculated performances. Mastering the game within the game is key to triathlon success.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blakesanie.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Takeaways from 4 Years of Trading Algorithm Research]]></title><description><![CDATA[Came seeking alpha, stayed for intrigue, and left with much more]]></description><link>https://blakesanie.substack.com/p/takeaways-from-4-years-of-trading</link><guid isPermaLink="false">https://blakesanie.substack.com/p/takeaways-from-4-years-of-trading</guid><dc:creator><![CDATA[Blake Sanie]]></dc:creator><pubDate>Sun, 19 Jan 2025 18:00:53 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffbbe634f-8b83-4c74-935b-3b625204a90f_2188x1236.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Zero to Hero to Zero</h2><p>Freshman year of college was the beginning of a transformative journey into the world of quantitative market analysis and trading. Armed with a deep fascination for computer science and mathematics, I sought to apply these skills to the financial markets, tackling the age-old question: &#8220;How will a given security move?&#8221;</p><p>Like many beginners, I dove into the deep end, training recurrent machine learning models to predict price action. I vividly recall predicting next day closing prices with near-perfect accuracy - if executed on present-day capital, this undeniable 2+ percent daily return would compound toward infinity itself. I cracked it, right? Predictably, these early models overfit the market data, providing flashy but ultimately unreliable results. I simply lacked the machine learning expertise to call it out, at this point. This initial failure taught me an important lesson: I needed to build a solid foundation.</p><h2>Building the Basics</h2><p>I shifted my focus to understanding the fundamentals of computational trading and investing: technical analysis, order flow, and even the tax implications of trading strategies. Along the way, I discovered <em><strong><a href="https://community.quantopian.com/feed">Quantopian</a></strong></em>, a platform for backtesting custom trading algorithms in Python. This became my sandbox for experimentation, where I developed strategies through trial and error, eventually crafting a high-performing algorithm.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!2ZBB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F662df9c0-669d-4869-addb-d7c6fd3b8f45_2168x854.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2ZBB!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F662df9c0-669d-4869-addb-d7c6fd3b8f45_2168x854.png 424w, https://substackcdn.com/image/fetch/$s_!2ZBB!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F662df9c0-669d-4869-addb-d7c6fd3b8f45_2168x854.png 848w, https://substackcdn.com/image/fetch/$s_!2ZBB!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F662df9c0-669d-4869-addb-d7c6fd3b8f45_2168x854.png 1272w, https://substackcdn.com/image/fetch/$s_!2ZBB!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F662df9c0-669d-4869-addb-d7c6fd3b8f45_2168x854.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2ZBB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F662df9c0-669d-4869-addb-d7c6fd3b8f45_2168x854.png" width="1456" height="574" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/662df9c0-669d-4869-addb-d7c6fd3b8f45_2168x854.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:574,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:130883,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!2ZBB!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F662df9c0-669d-4869-addb-d7c6fd3b8f45_2168x854.png 424w, https://substackcdn.com/image/fetch/$s_!2ZBB!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F662df9c0-669d-4869-addb-d7c6fd3b8f45_2168x854.png 848w, https://substackcdn.com/image/fetch/$s_!2ZBB!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F662df9c0-669d-4869-addb-d7c6fd3b8f45_2168x854.png 1272w, https://substackcdn.com/image/fetch/$s_!2ZBB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F662df9c0-669d-4869-addb-d7c6fd3b8f45_2168x854.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Cumulative backtested returns over my top-performing strategy, in hard-code</figcaption></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!KACP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffbbe634f-8b83-4c74-935b-3b625204a90f_2188x1236.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!KACP!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffbbe634f-8b83-4c74-935b-3b625204a90f_2188x1236.png 424w, https://substackcdn.com/image/fetch/$s_!KACP!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffbbe634f-8b83-4c74-935b-3b625204a90f_2188x1236.png 848w, https://substackcdn.com/image/fetch/$s_!KACP!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffbbe634f-8b83-4c74-935b-3b625204a90f_2188x1236.png 1272w, https://substackcdn.com/image/fetch/$s_!KACP!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffbbe634f-8b83-4c74-935b-3b625204a90f_2188x1236.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!KACP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffbbe634f-8b83-4c74-935b-3b625204a90f_2188x1236.png" width="1456" height="822" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fbbe634f-8b83-4c74-935b-3b625204a90f_2188x1236.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:822,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:159076,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!KACP!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffbbe634f-8b83-4c74-935b-3b625204a90f_2188x1236.png 424w, https://substackcdn.com/image/fetch/$s_!KACP!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffbbe634f-8b83-4c74-935b-3b625204a90f_2188x1236.png 848w, https://substackcdn.com/image/fetch/$s_!KACP!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffbbe634f-8b83-4c74-935b-3b625204a90f_2188x1236.png 1272w, https://substackcdn.com/image/fetch/$s_!KACP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffbbe634f-8b83-4c74-935b-3b625204a90f_2188x1236.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Distribution of weekly returns, compared to the S&amp;P 500</figcaption></figure></div><p>Through this process, I learned to optimize for key metrics like Sharpe ratio and drawdown, ensuring my strategies balanced returns with risk. Additionally, I learned that trading strategies are only as good as they are explainable. Shortening time intervals, such as using hourly candles, often introduced more noise than signal, and perfect trade execution was practically unachievable. Replicating these strategies in real-time proved difficult, as data collection was often obscure and mismatched with historical sources.</p><p>For these reasons, I concluded that trading should remain a human-centric process, at least for retail traders. </p><h2>Expanding the Scope</h2><p>Recognizing these limitations, I decided to widen my research objective. Instead of designing direct portfolio allocation strategies, I focused on general market intelligence to <em>guide</em> an investor&#8217;s decisions. In the summer of 2021, I developed an all-in-one web platform for security evaluation, presenting daily quotes across all listed stocks surrounding growth, risk, support &amp; resistance, momentum, cycle studies, candlestick patterns, and analyst consensus. These reports fell hand-in-hand with rankings, recommendations, and portfolio assessment tools. I even developed a Chrome extension that acted as an investment &#8220;copilot,&#8221; seamlessly integrating report intelligence into users&#8217; browser-based workflows on brokerage or financial research websites.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!KB_D!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4431af43-20a1-4af7-9fb1-5bfa226d9883_1200x742.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!KB_D!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4431af43-20a1-4af7-9fb1-5bfa226d9883_1200x742.png 424w, https://substackcdn.com/image/fetch/$s_!KB_D!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4431af43-20a1-4af7-9fb1-5bfa226d9883_1200x742.png 848w, https://substackcdn.com/image/fetch/$s_!KB_D!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4431af43-20a1-4af7-9fb1-5bfa226d9883_1200x742.png 1272w, https://substackcdn.com/image/fetch/$s_!KB_D!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4431af43-20a1-4af7-9fb1-5bfa226d9883_1200x742.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!KB_D!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4431af43-20a1-4af7-9fb1-5bfa226d9883_1200x742.png" width="1200" height="742" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4431af43-20a1-4af7-9fb1-5bfa226d9883_1200x742.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:742,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:263679,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!KB_D!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4431af43-20a1-4af7-9fb1-5bfa226d9883_1200x742.png 424w, https://substackcdn.com/image/fetch/$s_!KB_D!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4431af43-20a1-4af7-9fb1-5bfa226d9883_1200x742.png 848w, https://substackcdn.com/image/fetch/$s_!KB_D!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4431af43-20a1-4af7-9fb1-5bfa226d9883_1200x742.png 1272w, https://substackcdn.com/image/fetch/$s_!KB_D!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4431af43-20a1-4af7-9fb1-5bfa226d9883_1200x742.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Real-life screen capture of the &#8220;Copilot&#8221; providing investment insight via intuitive UX, overlaying the Robinhood price chart interface.</figcaption></figure></div><p>On one hand, this project emphasized the importance of user experience, making investment analysis accessible and intuitive. However, it also highlighted a critical weakness in approach: the glamorization of past performance and market behavior.</p><p>To generate actionable insights leading to true alpha, I needed to narrow my focus even further. My research shifted to analyzing a single security, such as $SPY, and reducing actions to simple buy/sell decisions.</p><h2>Embracing a Gamified Approach</h2><p>Automated trading held little appeal for me. Retail API trading systems often seemed fragile and unreliable, which led me to prefer a hybrid approach: a notification system that would alert me to opportunities, allowing me to execute trades manually at market open or close.</p><p>To refine my strategies further, I turned to reinforcement learning, framing the trading process as a well-defined and structured game using <em><strong><a href="https://github.com/openai/gym">OpenAI Gym</a></strong></em>. This approach allowed me to simulate realistic trading environments, down to the granularity of how brokerages handle fractional shares, to the <em><strong><a href="https://www.investopedia.com/ask/answers/what-do-t1-t2-and-t3-mean/">T+2</a></strong></em> settlement cycle, to the <em><strong><a href="https://codes.findlaw.com/us/title-26-internal-revenue-code/26-usc-sect-1222/#:~:text=Internal%20Revenue%20Code%20%C2%A7%201222.,to%20capital%20gains%20and%20losses&amp;text=(1)%20Short%2Dterm%20capital,account%20in%20computing%20gross%20income.">capital gains and losses tax code</a></strong></em> and <em><strong><a href="https://www.investopedia.com/terms/w/washsale.asp">wash sale</a></strong></em> rules.</p><p>Diving into top academic journals, I became well versed in actor-critic based methods with a neural network as the underlying engine for action evaluation within the current state.</p><p>The beauty of this method lies in a simple fact: an agent could learn an optimal policy based as a function of its currently observed state &#8212; encoding holdings, past market performance, even past investment decisions. Rewards were tied to risk-adjusted returns, encouraging balanced and sustainable strategies. No hard-coded market assumptions or target data with risk of overfitting. The agent learns by pure Pavlovian trial and error.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ACYm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7bf119b-a152-4498-99f8-6d15d4d9e54d_932x330.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ACYm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7bf119b-a152-4498-99f8-6d15d4d9e54d_932x330.png 424w, https://substackcdn.com/image/fetch/$s_!ACYm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7bf119b-a152-4498-99f8-6d15d4d9e54d_932x330.png 848w, https://substackcdn.com/image/fetch/$s_!ACYm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7bf119b-a152-4498-99f8-6d15d4d9e54d_932x330.png 1272w, https://substackcdn.com/image/fetch/$s_!ACYm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7bf119b-a152-4498-99f8-6d15d4d9e54d_932x330.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ACYm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7bf119b-a152-4498-99f8-6d15d4d9e54d_932x330.png" width="932" height="330" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f7bf119b-a152-4498-99f8-6d15d4d9e54d_932x330.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:330,&quot;width&quot;:932,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Selecting an Algorithm &#8212; Reinforcement Learning Coach 0.12.0 documentation&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Selecting an Algorithm &#8212; Reinforcement Learning Coach 0.12.0 documentation" title="Selecting an Algorithm &#8212; Reinforcement Learning Coach 0.12.0 documentation" srcset="https://substackcdn.com/image/fetch/$s_!ACYm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7bf119b-a152-4498-99f8-6d15d4d9e54d_932x330.png 424w, https://substackcdn.com/image/fetch/$s_!ACYm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7bf119b-a152-4498-99f8-6d15d4d9e54d_932x330.png 848w, https://substackcdn.com/image/fetch/$s_!ACYm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7bf119b-a152-4498-99f8-6d15d4d9e54d_932x330.png 1272w, https://substackcdn.com/image/fetch/$s_!ACYm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7bf119b-a152-4498-99f8-6d15d4d9e54d_932x330.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">A breakdown of reinforcement learning algorithms by optimization method. My efforts ventured into policy optimization, as the action space (transaction volume) is continuous.</figcaption></figure></div><p>At the same time, I was hired as a teaching assistant for an AI course with reinforcement learning as a core topic. Addressing student questions led me to evolve my intuition in this space, and solidify my approach.</p><p>Framing trading with regards to game theory also helped me understand the nuances of decision-making in complex, uncertain environments. It allowed me to explore how different variables influenced outcomes and how to adjust experiments dynamically to improve the agent&#8217;s pathway to profitable performance.</p><h2>The Ultimate Lesson</h2><p>After countless iterations and trials, I arrived at a humbling conclusion: no trading policy reliably outperformed the classic buy-and-hold approach for long-term risk-adjusted returns. Warren Buffett&#8217;s timeless wisdom rang true.</p><p>Though not flashy, I found myself growing more confident in the uninspiring &#8220;set and forget&#8221; method because I validated it through exhaustive scientific means.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!H_D1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a55fc7c-ab0c-44d7-a303-4a93b0140126_1660x1158.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!H_D1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a55fc7c-ab0c-44d7-a303-4a93b0140126_1660x1158.png 424w, https://substackcdn.com/image/fetch/$s_!H_D1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a55fc7c-ab0c-44d7-a303-4a93b0140126_1660x1158.png 848w, https://substackcdn.com/image/fetch/$s_!H_D1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a55fc7c-ab0c-44d7-a303-4a93b0140126_1660x1158.png 1272w, https://substackcdn.com/image/fetch/$s_!H_D1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a55fc7c-ab0c-44d7-a303-4a93b0140126_1660x1158.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!H_D1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a55fc7c-ab0c-44d7-a303-4a93b0140126_1660x1158.png" width="1660" height="1158" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7a55fc7c-ab0c-44d7-a303-4a93b0140126_1660x1158.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1158,&quot;width&quot;:1660,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;TradingView chart&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="TradingView chart" title="TradingView chart" srcset="https://substackcdn.com/image/fetch/$s_!H_D1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a55fc7c-ab0c-44d7-a303-4a93b0140126_1660x1158.png 424w, https://substackcdn.com/image/fetch/$s_!H_D1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a55fc7c-ab0c-44d7-a303-4a93b0140126_1660x1158.png 848w, https://substackcdn.com/image/fetch/$s_!H_D1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a55fc7c-ab0c-44d7-a303-4a93b0140126_1660x1158.png 1272w, https://substackcdn.com/image/fetch/$s_!H_D1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a55fc7c-ab0c-44d7-a303-4a93b0140126_1660x1158.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Inception-to-date $SPY returns, created with <a href="https://tradingview.com">TradingView</a></figcaption></figure></div><p>There is no magic algorithm or chart pattern to memorize. I hold no doubt here, as my research gave opportunity to every candidate measure. Fundamentally, for trading to be a game of wits, it must first be a game of information - of which retails traders are bound to lose.</p><p>Institutional trading is an entirely different story. Firms pay millions for propriety datasets and streams in their own chase for alpha. If they aren&#8217;t managing a portfolio, they&#8217;re market making through bids and asks coming off the Exchange&#8217;s wire. Retails trader need to recognize we play in the minor leagues.</p><h2>My Return on Investment</h2><p>This journey wasn&#8217;t just about building computational tools or testing strategies; it was about developing a deeper understanding of markets and my own approach to investing. In a poetic way, the nerves of wonder and ambitious hustle towards million-dollar strategies ended up cementing my appreciation for simplicity and patience in investing.</p><p>I have countless more technical questions to tackling, anyways.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blakesanie.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p>]]></content:encoded></item><item><title><![CDATA[Stravart: A Christmas Tree in Chicago]]></title><description><![CDATA[Run run Rudolph &#129420;&#128759;&#127877;]]></description><link>https://blakesanie.substack.com/p/stravart-a-christmas-tree-in-chicago</link><guid isPermaLink="false">https://blakesanie.substack.com/p/stravart-a-christmas-tree-in-chicago</guid><dc:creator><![CDATA[Blake Sanie]]></dc:creator><pubDate>Sun, 05 Jan 2025 19:12:24 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/d9b19d46-17f8-4e22-9ae8-6e4d7a6e38c7_1198x1195.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>On Christmas Eve, I embarked on a unique and exhilarating project: running to create Stravart&#8212;a GPS-tracked artwork&#8212;of a Christmas tree in Chicago. Combining physical endurance, artistic vision, and technical precision, this adventure was as much about the journey as the finished design. Let me take you through the process of bringing this festive creation to life.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!uyMx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F66461f8b-d5ba-4683-8024-4ac636ee2fe6_1198x1608.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!uyMx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F66461f8b-d5ba-4683-8024-4ac636ee2fe6_1198x1608.png 424w, https://substackcdn.com/image/fetch/$s_!uyMx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F66461f8b-d5ba-4683-8024-4ac636ee2fe6_1198x1608.png 848w, https://substackcdn.com/image/fetch/$s_!uyMx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F66461f8b-d5ba-4683-8024-4ac636ee2fe6_1198x1608.png 1272w, https://substackcdn.com/image/fetch/$s_!uyMx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F66461f8b-d5ba-4683-8024-4ac636ee2fe6_1198x1608.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!uyMx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F66461f8b-d5ba-4683-8024-4ac636ee2fe6_1198x1608.png" width="460" height="617.4290484140233" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/66461f8b-d5ba-4683-8024-4ac636ee2fe6_1198x1608.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1608,&quot;width&quot;:1198,&quot;resizeWidth&quot;:460,&quot;bytes&quot;:941717,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!uyMx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F66461f8b-d5ba-4683-8024-4ac636ee2fe6_1198x1608.png 424w, https://substackcdn.com/image/fetch/$s_!uyMx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F66461f8b-d5ba-4683-8024-4ac636ee2fe6_1198x1608.png 848w, https://substackcdn.com/image/fetch/$s_!uyMx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F66461f8b-d5ba-4683-8024-4ac636ee2fe6_1198x1608.png 1272w, https://substackcdn.com/image/fetch/$s_!uyMx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F66461f8b-d5ba-4683-8024-4ac636ee2fe6_1198x1608.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Final work, <em><strong><a href="https://www.strava.com/activities/13184769283">as found on Strava</a></strong></em> </figcaption></figure></div><h3>What is Stravart?</h3><p><em><strong><a href="https://www.strav.art/">Stravart</a></strong></em>, short for Strava Art, is the practice of using GPS tracking to create drawings by following specific routes while running, cycling, or walking. It&#8217;s an innovative way to merge exercise with creativity. The miles seem to fly by when you&#8217;re focused on replicating a design, and the results can be incredibly rewarding&#8212;a unique blend of art and physical achievement.</p><h3>Ideation</h3><p>Creating a piece of Stravart begins with choosing a theme. For this project, the Christmas tree motif was inspired by the holiday season. Themes can draw from world events, celebrations, or personal messages to make the art more meaningful.</p><p>Next, I analyzed Chicago&#8217;s map, looking for naturally occurring features like road shapes and land formations that could serve as the skeleton of the design. Scale is another critical factor. The route needs to be long enough to create a detailed drawing but manageable within the constraints of your activity, whether running or cycling. With an evening run in mind, I targeted a distance of 10 to 15 miles to simultaneously achieve high graphical detail without pushing my IT band too far.</p><blockquote><p><em>I find maps fascinating in their fractal-like composition. Zooming into sections reveals increasingly granular paths, from major roads to alleyways. This level of detail can help achieve higher resolution in your Stravart, but it also requires meticulous planning.</em></p></blockquote><h3>Design</h3><p>Once I settled on the concept, I began designing the route. The goal was to create a continuous circuit without any discontinuities. Breaking the art into subcomponents&#8212;such as the tree, a star-like shape on top, and the presents below&#8212;not only allowed for a logical progression, but resilience in execution. If I couldn&#8217;t complete the <em>entire</em> route, at least part of the design remains salvageable enough for presentation. I was especially in favor of drawing fine details&#8212;such as the crosses on the presents&#8212;after the objects&#8217; outlines were completed. This way, if my endurance ran out beyond the half marathon point, the artistic idea of presents would still be conveyed.</p><p>For curves, I utilized several techniques: taking naturally curved roads, planning diagonally road crossings, and strategically cutting through grassy parks and parking lots. Sometimes, the drawing required tracing paths multiple times. Without a doubt, finding the intuition to minimize these duplicate traces was a true puzzle. <em>I could hear my mind stepping through algorithms in real time</em>.</p><p><em><strong><a href="https://www.strava.com/dashboard">Strava</a></strong></em> Premium was my primary tool for route design. Its waypoint functionality helped refine the route along common paths (via the <em><strong><a href="https://www.strava.com/maps/global-heatmap?sport=All&amp;style=dark&amp;terrain=false&amp;labels=true&amp;poi=true&amp;cPhotos=true&amp;gColor=blue&amp;gOpacity=100#11.14/41.8872/-87.6439">Global Heatmap</a></strong></em>). At the same time, the platform enabled manual adjustments were necessary for paths that weren&#8217;t officially registered, or one-way streets I was willing to traverse on the sidewalk. GPS accuracy was a constant concern, especially in Chicago&#8217;s dense urban environment. Sharp edges and intricate details are challenging when signal interference can blur the drawing.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!GG9c!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F446fbc18-57e7-40d1-a70b-681c9ad4e57f_1880x1630.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!GG9c!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F446fbc18-57e7-40d1-a70b-681c9ad4e57f_1880x1630.png 424w, https://substackcdn.com/image/fetch/$s_!GG9c!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F446fbc18-57e7-40d1-a70b-681c9ad4e57f_1880x1630.png 848w, https://substackcdn.com/image/fetch/$s_!GG9c!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F446fbc18-57e7-40d1-a70b-681c9ad4e57f_1880x1630.png 1272w, https://substackcdn.com/image/fetch/$s_!GG9c!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F446fbc18-57e7-40d1-a70b-681c9ad4e57f_1880x1630.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!GG9c!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F446fbc18-57e7-40d1-a70b-681c9ad4e57f_1880x1630.png" width="1456" height="1262" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/446fbc18-57e7-40d1-a70b-681c9ad4e57f_1880x1630.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1262,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:3069004,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!GG9c!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F446fbc18-57e7-40d1-a70b-681c9ad4e57f_1880x1630.png 424w, https://substackcdn.com/image/fetch/$s_!GG9c!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F446fbc18-57e7-40d1-a70b-681c9ad4e57f_1880x1630.png 848w, https://substackcdn.com/image/fetch/$s_!GG9c!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F446fbc18-57e7-40d1-a70b-681c9ad4e57f_1880x1630.png 1272w, https://substackcdn.com/image/fetch/$s_!GG9c!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F446fbc18-57e7-40d1-a70b-681c9ad4e57f_1880x1630.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">A detailed glimpse into the <em><strong><a href="https://www.strava.com/maps/create/global-heatmap?routeId=3306679979080568054&amp;sport=Run&amp;style=dark&amp;terrain=false&amp;labels=true&amp;poi=true&amp;cPhotos=true&amp;gColor=blue&amp;gOpacity=100#14.69/41.89155/-87.62847">route</a></strong></em>&#8217;s present &#127873;  section, leveraging manual waypoint connections with the Global heatmap in the background</figcaption></figure></div><blockquote><p><em>More on <strong><a href="https://medium.com/strava-engineering/the-global-heatmap-now-6x-hotter-23fc01d301de">&#8220;Building the Global Heatmap&#8221;</a></strong> from Strava&#8217;s engineering blog&#8212;an impressive feat with many technical takeaways</em></p></blockquote><h3>Execution</h3><p>Executing a Stravart design is as much about navigation as endurance. A few feasible navigation methods come to mind: preparing a detailed list of turn-by-turn directions; using a smartphone to overlay the drawn route with current GPS position; and my favorite&#8212;Running with a bike computer in my hand, bringing an intuitive navigation interface without draining my phone battery. It&#8217;s a nice hack, I&#8217;ll admit, but far from a need.</p><p>When it comes to the GPS tracking device, precision is paramount. Luckily, many smart watches and other activity-focused devices ship with multi-band GPS recording.</p><p>When repeating sections of the route, I was mindful of aligning the duplicate traces as cleanly as possible. This meant running along the same sidewalks and crosswalks. Interestingly, this tactic even withstands GPS inaccuracies. In theory, similar positions will incur similar environmental biases during GPS recording, thus finding consistency between the traces themselves.</p><p>Frustratingly, detours are inevitable. Road closures, construction zones, gates and fences, among other unexpected barriers feel like a near-guarantee. Detours require quick thinking, relying on a mental projection of the map in bird&#8217;s-eye view to minimize the artistic damage stay on track. During a previous Stravart attempt in NYC, I had planned to trace elegant curves through green areas on the map, only to discover they were cemeteries with no public access.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!EUpc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64dd17da-4918-4879-8ed5-a8dc794319f6_1170x535.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!EUpc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64dd17da-4918-4879-8ed5-a8dc794319f6_1170x535.jpeg 424w, https://substackcdn.com/image/fetch/$s_!EUpc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64dd17da-4918-4879-8ed5-a8dc794319f6_1170x535.jpeg 848w, https://substackcdn.com/image/fetch/$s_!EUpc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64dd17da-4918-4879-8ed5-a8dc794319f6_1170x535.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!EUpc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64dd17da-4918-4879-8ed5-a8dc794319f6_1170x535.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!EUpc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64dd17da-4918-4879-8ed5-a8dc794319f6_1170x535.jpeg" width="389" height="177.8760683760684" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/64dd17da-4918-4879-8ed5-a8dc794319f6_1170x535.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:535,&quot;width&quot;:1170,&quot;resizeWidth&quot;:389,&quot;bytes&quot;:180350,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!EUpc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64dd17da-4918-4879-8ed5-a8dc794319f6_1170x535.jpeg 424w, https://substackcdn.com/image/fetch/$s_!EUpc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64dd17da-4918-4879-8ed5-a8dc794319f6_1170x535.jpeg 848w, https://substackcdn.com/image/fetch/$s_!EUpc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64dd17da-4918-4879-8ed5-a8dc794319f6_1170x535.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!EUpc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64dd17da-4918-4879-8ed5-a8dc794319f6_1170x535.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!0Xkh!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b8e928b-a798-445f-af97-3d01682c7905_1170x1377.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!0Xkh!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b8e928b-a798-445f-af97-3d01682c7905_1170x1377.jpeg 424w, https://substackcdn.com/image/fetch/$s_!0Xkh!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b8e928b-a798-445f-af97-3d01682c7905_1170x1377.jpeg 848w, https://substackcdn.com/image/fetch/$s_!0Xkh!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b8e928b-a798-445f-af97-3d01682c7905_1170x1377.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!0Xkh!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b8e928b-a798-445f-af97-3d01682c7905_1170x1377.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!0Xkh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b8e928b-a798-445f-af97-3d01682c7905_1170x1377.jpeg" width="384" height="451.9384615384615" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0b8e928b-a798-445f-af97-3d01682c7905_1170x1377.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1377,&quot;width&quot;:1170,&quot;resizeWidth&quot;:384,&quot;bytes&quot;:1205675,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!0Xkh!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b8e928b-a798-445f-af97-3d01682c7905_1170x1377.jpeg 424w, https://substackcdn.com/image/fetch/$s_!0Xkh!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b8e928b-a798-445f-af97-3d01682c7905_1170x1377.jpeg 848w, https://substackcdn.com/image/fetch/$s_!0Xkh!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b8e928b-a798-445f-af97-3d01682c7905_1170x1377.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!0Xkh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b8e928b-a798-445f-af97-3d01682c7905_1170x1377.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Attempted Stravart of USA Mainland</figcaption></figure></div><p>By some stroke of luck, my attempt at the Christmas tree met no navigational pushback; Well, a few tunnels and stairs between levels, but I&#8217;ll take it.</p><h3>Conclusion</h3><p>Creating Stravart is a dynamic fusion of art, exercise, and problem-solving. My Christmas tree in Chicago stands as a testament to the creativity and determination this process demands. Whether you&#8217;re an athlete seeking a fresh challenge or an artist looking for a new medium, Stravart offers endless possibilities. So, lace up your shoes, pump up your tires, map out your vision, and let the roads become your canvas.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blakesanie.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Ironman 70.3 - So Much to Learn]]></title><description><![CDATA[Before, after, and during the swim, bike, and run]]></description><link>https://blakesanie.substack.com/p/ironman-703-so-much-to-learn</link><guid isPermaLink="false">https://blakesanie.substack.com/p/ironman-703-so-much-to-learn</guid><dc:creator><![CDATA[Blake Sanie]]></dc:creator><pubDate>Sun, 15 Sep 2024 17:58:00 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/899b16db-8150-4593-a7f6-72a198ba9900_1514x1490.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!TAVO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96e61355-e4da-48b1-a09c-8505af88a97a_1514x1490.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!TAVO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96e61355-e4da-48b1-a09c-8505af88a97a_1514x1490.jpeg 424w, https://substackcdn.com/image/fetch/$s_!TAVO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96e61355-e4da-48b1-a09c-8505af88a97a_1514x1490.jpeg 848w, https://substackcdn.com/image/fetch/$s_!TAVO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96e61355-e4da-48b1-a09c-8505af88a97a_1514x1490.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!TAVO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96e61355-e4da-48b1-a09c-8505af88a97a_1514x1490.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!TAVO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96e61355-e4da-48b1-a09c-8505af88a97a_1514x1490.jpeg" width="328" height="322.81868131868134" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/96e61355-e4da-48b1-a09c-8505af88a97a_1514x1490.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1433,&quot;width&quot;:1456,&quot;resizeWidth&quot;:328,&quot;bytes&quot;:1294161,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!TAVO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96e61355-e4da-48b1-a09c-8505af88a97a_1514x1490.jpeg 424w, https://substackcdn.com/image/fetch/$s_!TAVO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96e61355-e4da-48b1-a09c-8505af88a97a_1514x1490.jpeg 848w, https://substackcdn.com/image/fetch/$s_!TAVO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96e61355-e4da-48b1-a09c-8505af88a97a_1514x1490.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!TAVO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96e61355-e4da-48b1-a09c-8505af88a97a_1514x1490.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2>How does an infielder become a triathlete?</h2><p>So long are my days of fielding ground balls and swinging at fastballs. Though I grew up casually cruising mountain bikes in California, my time jumping apartments and cities throughout college prevented me from leveling up in endurance efforts.</p><p>During grad school, a friend recommended I try my hand at <em><strong><a href="https://w4.crc.gatech.edu/node/392">Georgia Tech&#8217;s Navy Seal Fitness Challenge</a></strong></em> - one tribulation of which was to complete a 500-yard swim in fewer than 10 minutes. I lowered myself down the ladder, into the pool. In the summer that followed, a group of fellow associates invited me to run down the West Side Highway from the Flatiron office to the World Trade Center, and back. Seeing that running was more than a punishment for losing games by over five runs, I (over)ambitiously embarked on a <em><strong><a href="https://www.strava.com/activities/9856392961">do-it-yourself marathon two months after</a></strong></em>.</p><p>I was content. I felt good with my level of activity. But I will never forget the shock I experienced when catching wind of my high school classmate competing in Ironman California. I tracked every split while architecting machine learning models for a group project in a Georgia Tech research building. He finished the course, a major accomplishment - and he did so faster than every competitor in his age group. He kindly offered his time to meet and address my curiosity - but he only expanded it. I thought: maybe, possibly, perhaps a 70.3 was in sight.</p><p>I was missing one piece - the bike. With the completion of my Master&#8217;s degree in sight, I planned my move to Chicago with its lakefront trail in mind. I found the final piece to the puzzle, and I registered for Ironman 70.3 Wisconsin.</p><p>Once getting situated, my training dedication increased, and my learning soared. Here&#8217;s a brain dump of takeaways spanning the complete timeline of my Ironman 70.3 experience.</p><h2>Before Race Week: Research, Training, &amp; Everyday Life</h2><ul><li><p><em><strong>One week doesn&#8217;t change anything</strong></em></p><ul><li><p>Enjoy a vacation. You practically won&#8217;t fall off track. At the same time, a week of AWOL training won&#8217;t get you too far.</p></li></ul></li><li><p><em><strong>Open water will induce panic</strong></em></p><ul><li><p>Build comfort by looking down through endless green. Even now, swallowing less water remains a goal.</p></li></ul></li><li><p><em><strong>Don&#8217;t kick so hard</strong></em></p><ul><li><p>Over an endurance distance, invest in breathing comfort and lowering lactic acid buildup. Focus on an immaculate catch, pull, and stroke recovery.</p></li></ul></li><li><p><em><strong>Respect the 10% rule</strong></em></p><ul><li><p>Don&#8217;t increase weekly efforts too quickly, or you&#8217;ll be forced to pull back even quicker.</p></li></ul></li><li><p><em><strong>Peeing mid-swim/bike is a skill</strong></em></p><ul><li><p>Still a work in progress.</p></li></ul></li><li><p><em><strong>Don&#8217;t neglect legs</strong></em></p><ul><li><p>Your IT band will thank you. Single leg everything, if possible.</p></li></ul></li><li><p><em><strong>Practice peeling off your wetsuit</strong></em></p><ul><li><p>You need to take it off after training swims, anyway.</p></li></ul></li><li><p><em><strong>Practice a <a href="https://www.strava.com/activities/12291262434">chaos swim</a></strong></em></p><ul><li><p>During a race, swimming is a contact sport. It may be best to know the feeling of a foot to the goggles before the big day.</p></li></ul></li><li><p><em><strong>Go nuts</strong></em></p><ul><li><p>Train like an animal if you feel like it.</p></li></ul></li><li><p><em><strong>Race fees are expensive</strong></em></p><ul><li><p>Better to accept this fact sooner rather than later. Yes, fees largely cover insurance and logistics, but non-Ironman-branded races will be lighter on the wallet.</p></li></ul></li><li><p><em><strong>Learn how Strava works</strong></em></p><ul><li><p>More than Instagram for athletes who want to level up their coworkers - a training tool to track fitness, plan routes, compete on segment leaderboards, integrate metrics with wearable devices, build training plans&#8230; the list goes on!</p></li></ul></li><li><p><em><strong>Register</strong></em></p><ul><li><p>Only then does the finish line become real. Indulge in the &#8220;what did I just sign up for?&#8221; feeling and double down on your grind.</p></li></ul></li><li><p><em><strong>Learn the Physics</strong></em></p><ul><li><p>Buoyancy, hydrodynamics, and aerodynamics will take you just as far as fitness itself!</p></li></ul></li><li><p><em><strong>Learn the anatomy (legs)</strong></em></p><ul><li><p>The body is smart, but it isn&#8217;t simple. Learn to stay healthy, improve oxygen utilization, and build endurance throughout your musculoskeletal system.</p></li></ul></li><li><p><em><strong>Avoid an infinite training cycle</strong></em></p><ul><li><p>Define a training season and offseason. Don&#8217;t lose purpose because there is no end (checkpoint, really) in sight.</p></li></ul></li><li><p><em><strong>Figure out an indoor setup</strong></em></p><ul><li><p>The sun doesn&#8217;t always shine. Chicagoans know what I&#8217;m talking about.</p></li></ul></li><li><p><em><strong>Find a flow from workouts to work, and vice versa</strong></em></p><ul><li><p>Building a training schedule that integrates with work and life is a balancing act in itself. Find the best bang-for-buck within your own time.</p></li></ul></li><li><p><em><strong>Scout the course</strong></em></p><ul><li><p>Know what it means for hills to be &#8220;rolling&#8221;. Build familiarity and gain a home-field advantage. Better yet, bring some friends and <em><strong><a href="https://www.instagram.com/p/C-Tija_vf6X/?img_index=1">share the experience</a></strong></em>!</p><div class="instagram-embed-wrap" data-attrs="{&quot;instagram_id&quot;:&quot;C-Tija_vf6X&quot;,&quot;title&quot;:&quot;A post shared by @blake_sanie&quot;,&quot;author_name&quot;:&quot;blake_sanie&quot;,&quot;thumbnail_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/__ss-rehost__IG-meta-C-Tija_vf6X.jpg&quot;,&quot;timestamp&quot;:null,&quot;belowTheFold&quot;:false}" data-component-name="InstagramToDOM"><iframe class="instagram-embed-frame" srcdoc="<!doctype html>
<html>
  <head>
    <meta charset=&quot;utf-8&quot; />
    <meta name=&quot;viewport&quot; content=&quot;width=device-width,initial-scale=1&quot; />
    <style>
      html, body {
        margin: 0;
        padding: 0;
        overflow: hidden;
        background: transparent;
      }

      .instagram-media {
        margin: 1px auto 0 !important;
      }
    </style>
  </head>
  <body>
    <blockquote
      class=&quot;instagram-media&quot;
      data-instgrm-permalink=&quot;https://instagram.com/p/C-Tija_vf6X/?utm_source=ig_embed&amp;utm_campaign=loading&quot;
      data-instgrm-version=&quot;14&quot;
      style=&quot;background:#FFF; border:0; border-radius:3px; box-shadow:none; margin:1px auto 0; max-width:540px; min-width:326px; padding:0; width:calc(100% - 2px);&quot;
    ></blockquote>
    <script async src=&quot;https://www.instagram.com/embed.js&quot;></script>
    <script>
      (function() {
        const postHeight = () => {
          const body = document.body;
          const doc = document.documentElement;
          const height = Math.ceil(Math.max(
            body ? body.scrollHeight : 0,
            body ? body.offsetHeight : 0,
            doc ? doc.scrollHeight : 0,
            doc ? doc.offsetHeight : 0
          ));

          if (height > 0) {
            parent.postMessage({ type: 'substack-instagram-embed-resize', height }, '*');
          }
        };

        const scheduleMeasure = () => {
          window.requestAnimationFrame(() => {
            window.setTimeout(postHeight, 50);
          });
        };

        window.addEventListener('load', scheduleMeasure);
        window.setTimeout(scheduleMeasure, 250);
        window.setTimeout(scheduleMeasure, 1000);

        const root = document.documentElement || document.body;
        if (root &amp;&amp; typeof MutationObserver !== 'undefined') {
          const observer = new MutationObserver(scheduleMeasure);
          observer.observe(root, { attributes: true, childList: true, subtree: true, characterData: true });
        }

        if (document.body &amp;&amp; typeof ResizeObserver !== 'undefined') {
          const resizeObserver = new ResizeObserver(scheduleMeasure);
          resizeObserver.observe(document.body);
        }
      })();
    </script>
  </body>
</html>" title="Instagram post" frameborder="0" scrolling="no" allowfullscreen="true" allow="encrypted-media" sandbox="allow-same-origin allow-scripts allow-popups allow-popups-to-escape-sandbox" height="520px"></iframe><script type="text/javascript">(function() {
    const iframe = document.currentScript && document.currentScript.previousElementSibling;
    if (!(iframe instanceof HTMLIFrameElement)) {
      return;
    }

    window.addEventListener('message', function(event) {
      if (event.source !== iframe.contentWindow) {
        return;
      }

      const data = event.data;
      if (!data || data.type !== 'substack-instagram-embed-resize' || typeof data.height !== 'number') {
        return;
      }

      if (data.height > 0) {
        iframe.style.height = data.height + 'px';
      }
    });
  })();</script></div></li></ul></li></ul><ul><li><p><em><strong>If you don&#8217;t know what a saddle sore is, you will</strong></em></p><ul><li><p>Pick up some zinc oxide.</p></li></ul></li><li><p><em><strong>Caffeine is a PED</strong></em></p><ul><li><p>And probably the most researched stimulant. It&#8217;s hard to go back.</p></li></ul></li><li><p><em><strong>Swimming heals all</strong></em></p><ul><li><p>Not just a skill to improve, but a form of physical therapy and meditation in itself.</p></li></ul></li><li><p><em><strong>Apple Watch can&#8217;t hang</strong></em></p><ul><li><p>The &#8220;Series&#8221; models may die before you finish a marathon. The Ultra may die before you finish a century ride. If any triathlon longer than a 70.3 is in mind, go Garmin.</p></li></ul></li><li><p><em><strong>Real men wear speedos</strong></em></p><ul><li><p>The talk of the town: jammers are for twelve-year-olds.</p></li></ul></li></ul><h2>Race Week: Gearing Up for the Big Day</h2><ul><li><p><em><strong>Amazon Prime is your best friend</strong></em></p><ul><li><p>In the week leading up to your race, you will acquire so many products and gadgets out of panic. Dominate the race and return what didn&#8217;t work!</p></li></ul></li><li><p><em><strong>Charge your groupset batteries</strong></em></p><ul><li><p>Don&#8217;t ride a fixie into the finish line. SRAM cultists know that the front and rear derailer batteries are interchangeable (swap if the rear dies)&#8230; Shimano falls short in this category!</p></li></ul></li><li><p><em><strong>Body glide everything</strong></em></p><ul><li><p>Staying slippery will prevent swimmers from pulling you back, ease wetsuit peeling, putting on socks, and eliminating chaffing. Cover every square inch of skin, if you&#8217;re dedicated.</p></li></ul></li><li><p><em><strong>There will be dummies</strong></em></p><ul><li><p>Too many of the &#8220;of course I can swim&#8221; type who proceed to trot a half marathon, untrained. Don&#8217;t get me started on competitors wearing finisher gear before the gun.</p></li></ul></li><li><p><em><strong>The timing chip goes on the left</strong></em></p><ul><li><p>Otherwise, you&#8217;ll drop your chain!</p></li></ul></li><li><p><em><strong>Wear identifiable gear</strong></em></p><ul><li><p>Don&#8217;t tell friends and family to look for the black wetsuit or white road bike.</p></li></ul></li><li><p><em><strong>Pack transition with options in mind</strong></em></p><ul><li><p>Allow for mid-transition flexibility. Lay out socks of all lengths, sleeves for all appendages, gloves, a gilet, and even a waterproof shell.</p></li></ul></li><li><p><em><strong>Know which gear you&#8217;re good to toss</strong></em></p><ul><li><p>Be prepared to toss bottles if additional hydration is needed, or any clothing if it isn&#8217;t serving you well.</p></li></ul></li><li><p><em><strong>Goggles under the cap</strong></em></p><ul><li><p>Don&#8217;t lose your goggles due to contact with another swimmer. Are you prepared to finish the swim with your bare eyes?</p></li></ul></li><li><p><em><strong>Choose to start on the inside</strong></em></p><ul><li><p>Where you line up is free - may as well start on track to shave yards before everyone else.</p></li></ul></li><li><p><em><strong>Swim turns are highly contested</strong></em></p><ul><li><p>Determine how hard you want to battle for shaving a few yards, and at what cost.</p></li></ul></li><li><p><em><strong>Transition 1 sucks</strong></em></p><ul><li><p>Generally where heart rate peaks during a triathlon. A full sprint, still wet and disoriented from the swim, into a clean bike mount? Thank goodness you only do it once.</p></li></ul></li><li><p><em><strong>Don&#8217;t worry about the bike drafting rule</strong></em></p><ul><li><p>Cyclists become spread out after T1. Drafting truly requires the intention to draft, and risk a penalty. Focus on simply gaining ground.</p></li></ul></li><li><p><em><strong>Bottle handoffs are harder than they look</strong></em></p><ul><li><p>Going 20mph, bottles will bounce off your palm and leave you off balance. Call it a skill issue, but slowing down may be worth a more secure transfer.</p></li></ul></li><li><p><em><strong>Overcommunicate</strong></em></p><ul><li><p>Always give a firm &#8220;on your left&#8221; to avoid confusion of any degree. If they don&#8217;t like it, they can try being faster.</p></li></ul></li><li><p><em><strong>Passing others is such a joy</strong></em></p><ul><li><p>Especially if they sport an Ironman calf tattoo or ride a $14k TT bike.</p></li></ul></li><li><p><em><strong>Become a Chatty Kathy</strong></em></p><ul><li><p>Being on the course for hours, get to know other athletes just as crazy as you are. Conversation will also keep you in Zone 2 and prevent you from starting the bike/run too hot!</p></li></ul></li><li><p><em><strong>Be nutrition flexible</strong></em></p><ul><li><p>Bottles and gels fall. Be prepared to feast on gels and electrolyte drinks, if necessary.</p></li></ul></li><li><p><em><strong>Gels are barely caloric</strong></em></p><ul><li><p>A typical gel only contains 100 calories, which you will burn each mile you run. As a warning, the caffeine does add up quickly.</p></li></ul></li><li><p><em><strong>The course isn&#8217;t 70.3 miles</strong></em></p><ul><li><p>A combination of inaccurate segment lengths, unintuitive transition points, and your affinity for corner cutting.</p></li></ul></li><li><p><em><strong>Show up to slot allocation</strong></em></p><ul><li><p>Qualifications are highly forgiving of finishing place and may catch you by surprise!</p></li></ul></li><li><p><em><strong>Ask someone else to drive home</strong></em></p><ul><li><p>Either you raced so hard that walking becomes a challenge, or you partied so hard that you need a DD. Go for both.</p></li></ul></li></ul><h2>After Race Week: All Done, What&#8217;s Next?</h2><ul><li><p><em><strong>Who needs a Tattoo?</strong></em></p><ul><li><p>Is it necessary for you to internalize your self-worth? If you didn&#8217;t finish a full, don&#8217;t consider it, either.</p></li></ul></li><li><p><em><strong>Finisherpix is not worth it</strong></em></p><ul><li><p>The photos that draw smiles (and Instagram likes) are with friends and family after your big accomplishment.</p><div class="instagram-embed-wrap" data-attrs="{&quot;instagram_id&quot;:&quot;C_sv105uvj5&quot;,&quot;title&quot;:&quot;A post shared by @blake_sanie&quot;,&quot;author_name&quot;:&quot;blake_sanie&quot;,&quot;thumbnail_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/__ss-rehost__IG-meta-C_sv105uvj5.jpg&quot;,&quot;timestamp&quot;:null,&quot;belowTheFold&quot;:true}" data-component-name="InstagramToDOM"><iframe class="instagram-embed-frame" srcdoc="<!doctype html>
<html>
  <head>
    <meta charset=&quot;utf-8&quot; />
    <meta name=&quot;viewport&quot; content=&quot;width=device-width,initial-scale=1&quot; />
    <style>
      html, body {
        margin: 0;
        padding: 0;
        overflow: hidden;
        background: transparent;
      }

      .instagram-media {
        margin: 1px auto 0 !important;
      }
    </style>
  </head>
  <body>
    <blockquote
      class=&quot;instagram-media&quot;
      data-instgrm-permalink=&quot;https://instagram.com/p/C_sv105uvj5/?utm_source=ig_embed&amp;utm_campaign=loading&quot;
      data-instgrm-version=&quot;14&quot;
      style=&quot;background:#FFF; border:0; border-radius:3px; box-shadow:none; margin:1px auto 0; max-width:540px; min-width:326px; padding:0; width:calc(100% - 2px);&quot;
    ></blockquote>
    <script async src=&quot;https://www.instagram.com/embed.js&quot;></script>
    <script>
      (function() {
        const postHeight = () => {
          const body = document.body;
          const doc = document.documentElement;
          const height = Math.ceil(Math.max(
            body ? body.scrollHeight : 0,
            body ? body.offsetHeight : 0,
            doc ? doc.scrollHeight : 0,
            doc ? doc.offsetHeight : 0
          ));

          if (height > 0) {
            parent.postMessage({ type: 'substack-instagram-embed-resize', height }, '*');
          }
        };

        const scheduleMeasure = () => {
          window.requestAnimationFrame(() => {
            window.setTimeout(postHeight, 50);
          });
        };

        window.addEventListener('load', scheduleMeasure);
        window.setTimeout(scheduleMeasure, 250);
        window.setTimeout(scheduleMeasure, 1000);

        const root = document.documentElement || document.body;
        if (root &amp;&amp; typeof MutationObserver !== 'undefined') {
          const observer = new MutationObserver(scheduleMeasure);
          observer.observe(root, { attributes: true, childList: true, subtree: true, characterData: true });
        }

        if (document.body &amp;&amp; typeof ResizeObserver !== 'undefined') {
          const resizeObserver = new ResizeObserver(scheduleMeasure);
          resizeObserver.observe(document.body);
        }
      })();
    </script>
  </body>
</html>" title="Instagram post" frameborder="0" scrolling="no" allowfullscreen="true" allow="encrypted-media" sandbox="allow-same-origin allow-scripts allow-popups allow-popups-to-escape-sandbox" height="520px" loading="lazy"></iframe><script type="text/javascript">(function() {
    const iframe = document.currentScript && document.currentScript.previousElementSibling;
    if (!(iframe instanceof HTMLIFrameElement)) {
      return;
    }

    window.addEventListener('message', function(event) {
      if (event.source !== iframe.contentWindow) {
        return;
      }

      const data = event.data;
      if (!data || data.type !== 'substack-instagram-embed-resize' || typeof data.height !== 'number') {
        return;
      }

      if (data.height > 0) {
        iframe.style.height = data.height + 'px';
      }
    });
  })();</script></div></li></ul></li></ul><ul><li><p><em><strong>Everyone will ask you what&#8217;s next</strong></em></p><ul><li><p>And saying &#8220;I don&#8217;t know&#8221; is arguably the most appropriate and respectable response.</p></li></ul></li><li><p><em><strong>Hold your horses on a new bike</strong></em></p><ul><li><p>How much higher could you have placed if you saved a few dozen watts? Just as high as if you dedicated time to strength training and Zwift in the offseason for $20 per month. But I understand the temptation. Believe me.</p></li></ul></li><li><p><em><strong>Now&#8217;s a great opportunity to cool down</strong></em></p><ul><li><p>Settle back into a &#8220;normal&#8221; lifestyle, you earned it! Go enjoy every season of that new Netflix show. Sleep in until noon on Saturdays.</p></li></ul></li><li><p><em><strong>Now&#8217;s a great opportunity to heat up</strong></em></p><ul><li><p>Alternatively, you&#8217;ve come so far - why slow down? Treat the moment as a checkpoint for an even greater goal. Don&#8217;t waste time by telling yourself you&#8217;ll rise back to your current level of fitness &#8220;one day&#8221;.</p></li></ul></li><li><p><em><strong>Cut your bracelet off, but the bike stem sticker can stay</strong></em></p><ul><li><p>Enjoy your aura, but ground back to reality by Monday. Still, I&#8217;m a fan of the tradition of seeing your race number on your bike - until it gets replaced in the next race.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blakesanie.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div></li></ul></li></ul>]]></content:encoded></item><item><title><![CDATA[Aero: Virtual Cycling Wind Tunnel]]></title><description><![CDATA[How machine learning, mathematics, and physical mechanics join to maximize cycling performance.]]></description><link>https://blakesanie.substack.com/p/aero-virtual-cycling-wind-tunnel</link><guid isPermaLink="false">https://blakesanie.substack.com/p/aero-virtual-cycling-wind-tunnel</guid><dc:creator><![CDATA[Blake Sanie]]></dc:creator><pubDate>Thu, 01 Feb 2024 18:38:00 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!lFbe!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad476436-83aa-4f20-bc4b-470af4a98158_1600x900.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Progressing along my endurance triathlon adventure during the cold winter means crafting an indoor training regiment without compromise. Yes, I converted my bike into a stationary rig and sprinted away on virtual routes (all standard practice), though diving deeper, I sought a way to optimize my body positioning before hitting the road again in the spring.</p><p>My search for existing tools turned empty - applying advanced kinematic theory within a computationally defined environment seemed too much of a moonshot, especially when targeting a consumer hardware runtime. Still, no reason stood to prove my vision unattainable.</p><p>Being equal parts athletic competitor and technological innovator, I took matters into my own hands.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!lFbe!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad476436-83aa-4f20-bc4b-470af4a98158_1600x900.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!lFbe!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad476436-83aa-4f20-bc4b-470af4a98158_1600x900.webp 424w, https://substackcdn.com/image/fetch/$s_!lFbe!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad476436-83aa-4f20-bc4b-470af4a98158_1600x900.webp 848w, https://substackcdn.com/image/fetch/$s_!lFbe!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad476436-83aa-4f20-bc4b-470af4a98158_1600x900.webp 1272w, https://substackcdn.com/image/fetch/$s_!lFbe!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad476436-83aa-4f20-bc4b-470af4a98158_1600x900.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!lFbe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad476436-83aa-4f20-bc4b-470af4a98158_1600x900.webp" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ad476436-83aa-4f20-bc4b-470af4a98158_1600x900.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!lFbe!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad476436-83aa-4f20-bc4b-470af4a98158_1600x900.webp 424w, https://substackcdn.com/image/fetch/$s_!lFbe!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad476436-83aa-4f20-bc4b-470af4a98158_1600x900.webp 848w, https://substackcdn.com/image/fetch/$s_!lFbe!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad476436-83aa-4f20-bc4b-470af4a98158_1600x900.webp 1272w, https://substackcdn.com/image/fetch/$s_!lFbe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad476436-83aa-4f20-bc4b-470af4a98158_1600x900.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2>Creating Aero</h2><p>To kick off 2024, I designed and developed <em><strong><a href="https://www.blakesanie.com/aero">Aero</a></strong></em> - the world&#8217;s first consumer-accessible virtual wind tunnel, focused on helping cyclists minimize air resistance due to suboptimal body geometry. Even better, complete functionality sits right behind the same web browser you are using to read this.</p><p>Finding success in Aero&#8217;s creation required seamlessly stitching together advanced applications of physical mechanics and machine learning. The below sections outline and further dissect these respective components.</p><h2>Physics Theory, Applied</h2><p>Rocketing at significant speeds through the still air simplifies to the disruption of a fluid at equilibrium. In the most basic of forms, air resistance increases linearly with respect to cross-sectional area, and quadratically with respect to velocity:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;F_{D}=\\frac{1}{2}\\rho v^2 C_D A&quot;,&quot;id&quot;:&quot;ZRKDHXSMIM&quot;}" data-component-name="LatexBlockToDOM"></div><p>with drag force <em><strong>F_D</strong></em>&#8203;, fluid density &#961;, velocity v, drag coefficient <em><strong>C_D&#8203;</strong></em>, and cross sectional area A. However, this baseline kinematic model relies on many material generalizations and does not consider chaotic fluid dynamics (i.e. turbulent flow) that result from nontrivial object shapes and positions. My desire to model the effects of <em>arbitrary</em> body shapes eliminate all possibilities of a closed-form approximation for air resistance. Putting pen and paper aside, pivoting towards a simulation-based approach allows for situational precision while leveraging academically studied numerical and computational methods.</p><h3>Modelling Fluid Dynamics</h3><p>Cutting-edge fluid simulation methods follow one of two paradigms.</p><ul><li><p><em>Eulerian</em> approaches discretize and fix the environment (grid or mesh), each managing fluid behavior within their respective bounds.</p></li><li><p><em>LaGrangian</em> approaches discretize and fix the fluid (as particles), each managing their respective state (position, velocity, etc) within the environment.</p></li></ul><p>Aero&#8217;s fluid simulation relies on an Eulerian method to ensure uniform measurement across the environment while easily parallelizing underlying grid-based computations.</p><p>Deeper, I evolved the <em><strong><a href="https://en.wikipedia.org/wiki/Lattice_Boltzmann_methods">Lattice-Boltzmann Algorithm</a></strong></em> to support the platform&#8217;s wind tunnel dynamics - more on improvements later. The method operates as follows:</p><ol><li><p>Form a lattice-structured environment, where each cell of the environment grid stores an eight-way particle distribution: moving North, North-East, East, South-East, South, South-West, West, North-West, and staying at rest. The density of particles in each category are initialized to reflect a constant rate of laminar flow (a state of equilibrium that observes the <em><strong><a href="https://en.wikipedia.org/wiki/Navier%E2%80%93Stokes_equations">Navier-Stokes Equations</a></strong></em>).</p></li><li><p>Propagate the expected densities to the corresponding cell. For instance, transfer the density of North-traveling particles to the cell above the current. Careful formulation of this sequential process is necessary to ensure densities are not overwritten while still a dependency in pending computations. This is called the &#8220;Stream&#8221; step. <em>Handle collisions by reflecting movement into barriers back onto the source cell</em>.</p></li><li><p>Smooth each cell&#8217;s new fluid movement distribution towards an equilibrium state. This &#8220;Collide&#8221; phase introduces nonlinearity to fluid movement - a realistic mechanism to handle movement dampening and compounding. Find an in-depth explanation of the relevant mathematical foundation <em><strong><a href="https://www.ndsu.edu/fileadmin/physics.ndsu.edu/Wagner/LBbook.pdf">here</a></strong></em>.</p></li><li><p>Jump to step 2, forming a cycle that models the passage of time.</p></li></ol><p>A few details in technical implementation require attention to complete an effective simulation. These include:</p><ul><li><p>Resetting environment boundaries to uniform equilibrium density (repeat as step 1 at edges of the canvas) to keep the fluid moving in the intended direction. This can happen with any time interval, though tighter intervals promote simulation stability.</p></li><li><p>Dynamically shifting the initial air flow point (front of the wind tunnel) to accommodate the object&#8217;s shape and position within the wind tunnel. This extension to the Lattice-Boltzmann algorithm prevents differences in fluid behavior across ends of the wind tunnel because the object&#8217;s position relative within the wind tunnel is unchanging.</p></li></ul><h3>Relating Speed, Position, Power, and Force</h3><p>With the appropriate simulation method by my side, I then needed a quantitative model between the measures of interest. As a starting point, I discovered the below real-world data aggregated by the team at <em><strong><a href="https://silca.cc/blogs/silca/body-position-and-aerodynamics-on-a-bike">Silca</a></strong></em> relates power savings and cycling speed in various body positions.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!mwAe!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa791447-f3ea-4c76-a33d-0a5ea12cb393_1600x983.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mwAe!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa791447-f3ea-4c76-a33d-0a5ea12cb393_1600x983.webp 424w, https://substackcdn.com/image/fetch/$s_!mwAe!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa791447-f3ea-4c76-a33d-0a5ea12cb393_1600x983.webp 848w, https://substackcdn.com/image/fetch/$s_!mwAe!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa791447-f3ea-4c76-a33d-0a5ea12cb393_1600x983.webp 1272w, https://substackcdn.com/image/fetch/$s_!mwAe!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa791447-f3ea-4c76-a33d-0a5ea12cb393_1600x983.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!mwAe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa791447-f3ea-4c76-a33d-0a5ea12cb393_1600x983.webp" width="1456" height="895" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/aa791447-f3ea-4c76-a33d-0a5ea12cb393_1600x983.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:895,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Power savings with body positions versus speed, by Silca.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Power savings with body positions versus speed, by Silca." title="Power savings with body positions versus speed, by Silca." srcset="https://substackcdn.com/image/fetch/$s_!mwAe!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa791447-f3ea-4c76-a33d-0a5ea12cb393_1600x983.webp 424w, https://substackcdn.com/image/fetch/$s_!mwAe!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa791447-f3ea-4c76-a33d-0a5ea12cb393_1600x983.webp 848w, https://substackcdn.com/image/fetch/$s_!mwAe!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa791447-f3ea-4c76-a33d-0a5ea12cb393_1600x983.webp 1272w, https://substackcdn.com/image/fetch/$s_!mwAe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa791447-f3ea-4c76-a33d-0a5ea12cb393_1600x983.webp 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Power savings with body positions versus speed, by Silca</figcaption></figure></div><p>I am mainly interested in modeling maximum power savings, which occurs in the Aero Bars position. Using <em><strong><a href="https://www.desmos.com/calculator/moh6irec7q">this Desmos plot</a></strong></em>, I found the relationship between maximum force savings (N) and cycling speed (m/s) to be:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;F_\\text{saved}=c v^2,\\hspace{2mm} c=.0450363&quot;,&quot;id&quot;:&quot;HCPQWHKMST&quot;}" data-component-name="LatexBlockToDOM"></div><p>Which maintains the quadratic order held by the ideal drag force equation!</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!7Zd7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffaf13703-ae88-46c6-bf3a-8cb88647ff43_1600x1447.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7Zd7!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffaf13703-ae88-46c6-bf3a-8cb88647ff43_1600x1447.webp 424w, https://substackcdn.com/image/fetch/$s_!7Zd7!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffaf13703-ae88-46c6-bf3a-8cb88647ff43_1600x1447.webp 848w, https://substackcdn.com/image/fetch/$s_!7Zd7!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffaf13703-ae88-46c6-bf3a-8cb88647ff43_1600x1447.webp 1272w, https://substackcdn.com/image/fetch/$s_!7Zd7!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffaf13703-ae88-46c6-bf3a-8cb88647ff43_1600x1447.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!7Zd7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffaf13703-ae88-46c6-bf3a-8cb88647ff43_1600x1447.webp" width="1456" height="1317" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/faf13703-ae88-46c6-bf3a-8cb88647ff43_1600x1447.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1317,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Regression model between cycling speed and maximum force savings.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Regression model between cycling speed and maximum force savings." title="Regression model between cycling speed and maximum force savings." srcset="https://substackcdn.com/image/fetch/$s_!7Zd7!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffaf13703-ae88-46c6-bf3a-8cb88647ff43_1600x1447.webp 424w, https://substackcdn.com/image/fetch/$s_!7Zd7!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffaf13703-ae88-46c6-bf3a-8cb88647ff43_1600x1447.webp 848w, https://substackcdn.com/image/fetch/$s_!7Zd7!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffaf13703-ae88-46c6-bf3a-8cb88647ff43_1600x1447.webp 1272w, https://substackcdn.com/image/fetch/$s_!7Zd7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffaf13703-ae88-46c6-bf3a-8cb88647ff43_1600x1447.webp 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Regression model between cycling speed and maximum force savings.</figcaption></figure></div><p>At this point, I needed a means of relating simulation mechanics to the above regression model. The simulation progresses with a frame rate f=24 frames per second, with each frame running n=40 iterations of the &#8220;Streaming&#8221; and &#8220;Colliding&#8221; process.</p><p>During the computation of each frame, I accumulate the mass colliding in the net x and y directions across all barrier cells B (areas occupied by the bike and cyclist). Together, these components form a vector <em><strong>m_air&#8203;&#8203;</strong></em>.</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;m_{\\text{air}_x}=\\sum_{i=0}^{n}\\sum_{b\\in B}(\\text{NE}_b + \\text{E}_b + \\text{SE}_b - \\text{SW}_b - \\text{W}_b - \\text{NW}_b)&quot;,&quot;id&quot;:&quot;ZJQRVJHKZV&quot;}" data-component-name="LatexBlockToDOM"></div><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;m_{\\text{air}_y}=\\sum_{i=0}^{n}\\sum_{b\\in B}(\\text{SW}_b + \\text{S}_b + \\text{SE}_b - \\text{NE}_b - \\text{N}_b - \\text{NW}_b)&quot;,&quot;id&quot;:&quot;PSBEYVCWXN&quot;}" data-component-name="LatexBlockToDOM"></div><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\vec{m_\\text{air}}=\\langle m_{\\text{air}_x},m_{\\text{air}_y} \\rangle&quot;,&quot;id&quot;:&quot;APYWEGNQPF&quot;}" data-component-name="LatexBlockToDOM"></div><p>On the road, the cyclist&#8217;s kinetic energy is lost to the surrounding air. Analogously, the air in the wind tunnel transfers its kinetic energy into the body. The amount of work (joules), or change in energy, subjected to the body is expressed as:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\vec{W_\\text{air}} = \\frac{1}{2}\\vec{m_\\text{air}}v^2&quot;,&quot;id&quot;:&quot;DYRHSYCQOV&quot;}" data-component-name="LatexBlockToDOM"></div><p>Further, the air resistance force vector is found by applying the computed work over the traversed distance, which is itself the quotient of velocity and frame rate.</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\vec{F_\\text{air}} = \\vec{W_\\text{air}} \\Delta x,\\hspace{2mm}\\Delta x = v \\Delta t = \\frac{v}{f}&quot;,&quot;id&quot;:&quot;HTLHKAITEY&quot;}" data-component-name="LatexBlockToDOM"></div><p>Keep in mind that a cyclist must combat a horizontal force working against them, however, <em><strong>F_air</strong></em>&#8203;&#8203; has an unconsidered vertical component. This detail should not be overlooked, as Fairy<em>F</em>air<em>y</em>&#8203;&#8203; induces an increase in <em><strong><a href="https://silca.cc/blogs/silca/part-4b-rolling-resistance-and-impedance">Rolling Resistance</a></strong></em>, <em><strong>F_rr</strong></em>&#8203;, which is a horizontally acting force on the cyclist. <em><strong>C_rr</strong></em>=0.004 is the empirical rolling resistance constant for road tires with intended pressure on smooth asphalt, found by <em><strong><a href="https://silca.cc/blogs/silca/part-4b-rolling-resistance-and-impedance">Silca</a></strong></em>.</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;F_\\text{resistance} = F_{\\text{air}_x} + F_\\text{rr}&quot;,&quot;id&quot;:&quot;LQWGATEGCA&quot;}" data-component-name="LatexBlockToDOM"></div><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;F_\\text{rr} = C_\\text{rr} F_{\\text{air}_y},\\hspace{2mm} C_\\text{rr} = 0.004&quot;,&quot;id&quot;:&quot;NJFHGWEVPX&quot;}" data-component-name="LatexBlockToDOM"></div><h3>Chasing Power and Force Savings</h3><p>At this point, relative values of <em><strong>F_resistance</strong></em>&#8203; hold physically accurate, but the values in absolute may be inflated by barrier configuration, simulation speed, and scene width, among other external variables. I eliminate the effect of these factors by imposing a calibration step - for 10 seconds, the cyclist alternates between a &#8220;Hoods&#8221; position to record <em><strong>F</strong></em><strong>&#729;</strong><em><strong>_high</strong></em><strong>&#8203;</strong> (baseline for zero force savings) and the lowest possible &#8220;Aero Bars&#8221; position to record <em><strong>F&#729;_low</strong></em>&#8203; (baseline for maximum force savings). Here, all forces vary in third degree with speed, tracing all derivations steps. Thus, <em><strong>F&#729;_high&#8203;</strong></em> and <em><strong>F&#729;_low&#8203;</strong></em> take into account a <em><strong>v^3</strong></em> normalization factor so that the baselines remain valid independent of airspeed, which may change throughout the simulation. To recompute force from the baseline space, a factor of <em><strong>v^3</strong></em> is applied. Once calibrated, force savings are quickly estimated by interpolating the normalized observed horizontal resistance force between the two bounds and scaling the force savings regression model accordingly.</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;F_\\text{saved} = v^3 * \\frac{\\dot{F}_\\text{high} - F_\\text{resistance}/ v^3}{\\dot{F}_\\text{high}-\\dot{F}_\\text{low}} * cv^2&quot;,&quot;id&quot;:&quot;GKUGTMDNLH&quot;}" data-component-name="LatexBlockToDOM"></div><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;= \\frac{\\dot{F}_\\text{high} - F_\\text{resistance}/ v^3}{\\dot{F}_\\text{high}-\\dot{F}_\\text{low}} cv^5&quot;,&quot;id&quot;:&quot;JEYPHHAQCH&quot;}" data-component-name="LatexBlockToDOM"></div><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;P_\\text{saved} = F_\\text{saved}v&quot;,&quot;id&quot;:&quot;HRHEOYUOKZ&quot;}" data-component-name="LatexBlockToDOM"></div><h2>Computer Vision Considerations</h2><p>The proposed theoretical physics backing only holds half the weight of the simulation - missing is environment formulation and interactivity. To achieve this, I rely on a key computer vision method: Image Segmentation.</p><h3>Image Segmentation</h3><p>To enable detection of the cycle and cyclist in real time using only the device&#8217;s webcam, I leverage a machine learning-based method called semantic image segmentation. In short, a segmentation model takes an image as input and analyzes its features to extract visual information from within. The output, microscopically, embodies a pixel-wise classification result. Is this pixel belonging to a cycle or cyclist, or something else? These values are represented probabilistically. Macroscopically, these pixel classifications join to assign image regions to object categories. This is the same computer vision technology that drives cutting-edge autonomous vehicle perception, picture below.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Hdro!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febf4031e-bc5e-45d7-aaed-1295a4cd1069_1600x1067.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Hdro!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febf4031e-bc5e-45d7-aaed-1295a4cd1069_1600x1067.webp 424w, https://substackcdn.com/image/fetch/$s_!Hdro!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febf4031e-bc5e-45d7-aaed-1295a4cd1069_1600x1067.webp 848w, https://substackcdn.com/image/fetch/$s_!Hdro!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febf4031e-bc5e-45d7-aaed-1295a4cd1069_1600x1067.webp 1272w, https://substackcdn.com/image/fetch/$s_!Hdro!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febf4031e-bc5e-45d7-aaed-1295a4cd1069_1600x1067.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Hdro!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febf4031e-bc5e-45d7-aaed-1295a4cd1069_1600x1067.webp" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ebf4031e-bc5e-45d7-aaed-1295a4cd1069_1600x1067.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Semantic image segmentation output example by scale.com (Scale AI).&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Semantic image segmentation output example by scale.com (Scale AI)." title="Semantic image segmentation output example by scale.com (Scale AI)." srcset="https://substackcdn.com/image/fetch/$s_!Hdro!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febf4031e-bc5e-45d7-aaed-1295a4cd1069_1600x1067.webp 424w, https://substackcdn.com/image/fetch/$s_!Hdro!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febf4031e-bc5e-45d7-aaed-1295a4cd1069_1600x1067.webp 848w, https://substackcdn.com/image/fetch/$s_!Hdro!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febf4031e-bc5e-45d7-aaed-1295a4cd1069_1600x1067.webp 1272w, https://substackcdn.com/image/fetch/$s_!Hdro!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febf4031e-bc5e-45d7-aaed-1295a4cd1069_1600x1067.webp 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Semantic image segmentation output example by scale.com (Scale AI).</figcaption></figure></div><h3>Barrier Detection Workflow</h3><p>With this model up and running, we may capture stills from the video webcam feed and invoke inference. Once the output is collected, it is converted into a boolean mask, where <em><strong>true</strong></em> represents a barrier (dominant cycle or cyclist classification), or <em><strong>false</strong></em> otherwise. This mask is then resized to fit the dimensions of the discretized simulation algorithm and subsequently rendered onscreen. Because running a machine learning model in continuation requires high computational cost, other app processes such as the simulation itself may see less priority by the page&#8217;s process scheduler. Hence, choosing a segmentation inference interval that balances smooth, real-time updates with a reasonable computation budget. This task is also aided by improving computational efficiency across this process itself. Let&#8217;s dive deeper.</p><h2>Web-Optimized Implementation and Runtime</h2><p>Today, it is fairly uncommon to have high-intensity machine learning models run client-side in the browser. The main reason for this is excess computation time and resource overload, as mentioned, which can be avoided by invoking the machine learning task on the backend. This design pattern works effectively for one-time tasks with low data volume, such as a basic chat. However, continuously streaming video or image data to a backend invites a new computational bottleneck to the party - network I/O. Therefore, if the model is suitably compact, it is more appropriate to load the model once over the network, and then dispatch inference tasks locally as needed.</p><p>One of the primary industry-standard frameworks for machine learning development is Google&#8217;s <em><strong><a href="https://www.tensorflow.org/">Tensorflow</a></strong></em>. The toolkit&#8217;s greatest strengths lie in its Python package, which is central to model training, experimentation, and export. Deployment and real-world model usage present a few more options, one of which is the web-enabling <em><strong><a href="https://www.tensorflow.org/js">Tensorflow.js</a></strong></em> runtime.</p><p>The high-level workflow is simple - load the framework with the webpage, pull down the model of choice, and perform inference by casting to/from Tensorflow.js compatible datatypes.</p><h3>Model Optimization and Memory Management</h3><p>Effective and robust models are not slim. My model of choice has over 50 million fine-tuned parameters to support its intelligent process. Quantization is a method to reduce model size without sacrificing parameter count. Model parameters are typically stored as 32-bit floats: high precision with high payload. Such parameters may be quantized to a smaller representation, settling for less-than-perfect precision to fit an 8 or 16-bit representation.</p><p>I opted for 8-bit quantization to fully minimize model loading time (streaming fewer bytes over the network) and simultaneously minimize memory footprint within the page&#8217;s browser process. In the end, this precision sacrifice is hardly felt, since the dominant pixel-wise classifications remain accurate and each region retrains a refined boundary.</p><p>Tensorflow.js also allows for programmatic memory management. Although its tensor datatypes occupy large heaps of memory, we can free these blocks as soon as they become obsolete. Utilization of this feature is especially critical when considering that all operations return a new tensor - pipelining a series of operations creates many auxiliary tensor objects, none of which are needed except the final output. Purging unused tensors as the inference step progresses keeps memory usage as tidy as possible, thus keeping machine learning in the browser as feasible as possible.</p><h3>Hardware Optimization for Machine Learning</h3><p>Further, Tensorflow.js builds upon tensor computation, where data is stored contiguously in memory for fast access and efficient computation. These operations consist of matrix calculations commonly found in computer graphics processing. Along this connection is the <em><strong><a href="https://get.webgl.org/">Web Graphics Library (WebGL)</a></strong></em>, a high-performance graphics engine with near-ubiquitous browser compatibility. Though designed for direct rending tasks, its underlying matrix operation capability allows for machine learning tensor computation to live closer to accelerated hardware, such as GPUs. This technology closes the gap between standard JavaScript execution in the browser and the unbounded local computation ability of Tensorflow&#8217;s Python framework.</p><p>Tensorflow.js is smart enough to detect WebGL compatibility with your browser, leveraging the underlying hardware acceleration if possible, and defaulting to standard JavaScript computation otherwise. As a result, all browsers support the model&#8217;s execution, with all hardware-driven performance gains applied where possible.</p><h2>Closing Thoughts</h2><p>The vision behind <em><strong><a href="https://www.blakesanie.com/aero">Aero</a></strong></em> came to life thanks to numerous key mathematical and computational modeling considerations, not to mention an optimization-focused technical execution within the runtime constraints of a web browser. Scratch paper, debuggers, and head-banging of the past aside, go save some Watts!</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blakesanie.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Fantasy Football System Design]]></title><description><![CDATA[Realtime Stream Processing & Analytics Case Study]]></description><link>https://blakesanie.substack.com/p/fantasy-football-system-design</link><guid isPermaLink="false">https://blakesanie.substack.com/p/fantasy-football-system-design</guid><dc:creator><![CDATA[Blake Sanie]]></dc:creator><pubDate>Mon, 01 May 2023 15:45:00 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!IRac!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa59d0ec9-8128-4148-b991-8f419cf60969_1600x1111.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction: Game Event Stream Processing</h2><p><strong>Fantasy Football is a popular speculatory game intended as a friendly competition between American football fans. Groups of individuals, forming Fantasy Football &#8220;leagues&#8221;, imitate National Football League (NFL) organizations as they draft players and set rosters before each weekly matchup. Football players earn points based on their real-life performance - these points are then accumulated by users who claimed such players on their rosters. The objective is simple - solidify a roster to earn as many points as possible over the following week.</strong></p><p><strong>Several sports media companies offer app-driven Fantasy Football experiences, though, under the hood, intricate software architecture is imperative to driving a robust user experience.</strong></p><p><strong>This piece aims to explore crucial design decisions, system design principles, and technology and tooling considerations that fulfill the business needs of Fantasy Football platforms from the perspective of a sports media company.</strong></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!IRac!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa59d0ec9-8128-4148-b991-8f419cf60969_1600x1111.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!IRac!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa59d0ec9-8128-4148-b991-8f419cf60969_1600x1111.webp 424w, https://substackcdn.com/image/fetch/$s_!IRac!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa59d0ec9-8128-4148-b991-8f419cf60969_1600x1111.webp 848w, https://substackcdn.com/image/fetch/$s_!IRac!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa59d0ec9-8128-4148-b991-8f419cf60969_1600x1111.webp 1272w, https://substackcdn.com/image/fetch/$s_!IRac!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa59d0ec9-8128-4148-b991-8f419cf60969_1600x1111.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!IRac!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa59d0ec9-8128-4148-b991-8f419cf60969_1600x1111.webp" width="1456" height="1011" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a59d0ec9-8128-4148-b991-8f419cf60969_1600x1111.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1011,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Fantasy Football Backend System Design Overview&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Fantasy Football Backend System Design Overview" title="Fantasy Football Backend System Design Overview" srcset="https://substackcdn.com/image/fetch/$s_!IRac!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa59d0ec9-8128-4148-b991-8f419cf60969_1600x1111.webp 424w, https://substackcdn.com/image/fetch/$s_!IRac!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa59d0ec9-8128-4148-b991-8f419cf60969_1600x1111.webp 848w, https://substackcdn.com/image/fetch/$s_!IRac!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa59d0ec9-8128-4148-b991-8f419cf60969_1600x1111.webp 1272w, https://substackcdn.com/image/fetch/$s_!IRac!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa59d0ec9-8128-4148-b991-8f419cf60969_1600x1111.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><em><strong>Fantasy Football Backend System Design Overview</strong></em></p><h2>Requirement Analysis</h2><h3>Context</h3><ul><li><p><strong>Up to 10 simultaneous games, each transmitting events every 3s, on average, though transmissions may be back-to-back.</strong></p></li><li><p><strong>90% of users reside in North America or Western Europe.</strong></p></li><li><p><strong>Play results and events may change, for example, if overturned by a challenge or nullified by a penalty.</strong></p></li><li><p><strong>Data platform must act as the source of truth for all football data, also supporting other user-facing solutions such as play-by-play or sports betting interfaces.</strong></p></li></ul><h3>Technical Demands</h3><ul><li><p><strong>Points and statistics must be objectively accurate and up to date</strong></p></li><li><p><strong>Zero data loss policy</strong></p></li><li><p><strong>System-wide fault tolerance and downtime recovery</strong></p></li></ul><h3>Scope and Simplicity</h3><p><strong>Football, and sports more generally, are complex to model in full. For simplicity&#8217;s sake, let us only track snaps, passes, runs, tackles, and touchdowns. Outside of direct gameplay, challenges and penalties will be considered. Assume all contextual game and player data is already populated.</strong></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!kMQT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4709b31-be9b-489f-81ca-a775d0d6a6d9_1600x877.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!kMQT!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4709b31-be9b-489f-81ca-a775d0d6a6d9_1600x877.webp 424w, https://substackcdn.com/image/fetch/$s_!kMQT!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4709b31-be9b-489f-81ca-a775d0d6a6d9_1600x877.webp 848w, https://substackcdn.com/image/fetch/$s_!kMQT!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4709b31-be9b-489f-81ca-a775d0d6a6d9_1600x877.webp 1272w, https://substackcdn.com/image/fetch/$s_!kMQT!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4709b31-be9b-489f-81ca-a775d0d6a6d9_1600x877.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!kMQT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4709b31-be9b-489f-81ca-a775d0d6a6d9_1600x877.webp" width="1456" height="798" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a4709b31-be9b-489f-81ca-a775d0d6a6d9_1600x877.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:798,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Game Event Data Ingestion Overview&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Game Event Data Ingestion Overview" title="Game Event Data Ingestion Overview" srcset="https://substackcdn.com/image/fetch/$s_!kMQT!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4709b31-be9b-489f-81ca-a775d0d6a6d9_1600x877.webp 424w, https://substackcdn.com/image/fetch/$s_!kMQT!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4709b31-be9b-489f-81ca-a775d0d6a6d9_1600x877.webp 848w, https://substackcdn.com/image/fetch/$s_!kMQT!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4709b31-be9b-489f-81ca-a775d0d6a6d9_1600x877.webp 1272w, https://substackcdn.com/image/fetch/$s_!kMQT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4709b31-be9b-489f-81ca-a775d0d6a6d9_1600x877.webp 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><em><strong>Game Event Data Ingestion Overview</strong></em></p><h2>Stream Management and Usage</h2><h3>The Scorer&#8217;s Box</h3><p><strong>At the game&#8217;s stadium, an official scorer inputs a complete sequence of play-by-play events into the Game Data Stream. This data queue is a foundational component of the business, as many other orthogonal services and platforms may subscribe to the scorer&#8217;s published updates for their own respective needs.</strong></p><p><strong>At a scorer&#8217;s fingertips is an interface that establishes a unique </strong><code>gameID</code><strong>, </strong><code>playNumber</code><strong>, and </strong><code>eventNumber</code><strong>. </strong><code>gameID</code><strong> is an unambiguous identifier for the match being scored. </strong><code>playNumber</code><strong> is a counter that increments after each play. Similarly, </strong><code>eventNumber</code><strong> is a counter that increments after every submitted event, since events are published sequentially and synchronously. These three values allow the scorer to reference specific plays (following a snap) on top of which multiple specific events may occur. Later on, </strong><code>eventNumber</code><strong> will be especially necessary for handling game revisions resulting from overturned calls or penalties.</strong></p><h3>Apache Kafka</h3><p><strong>Apache Kafka is the chosen Publisher-Subscriber queue technology because of its robust buffer policy. Messages are written to high-throughput topics backed by log files. Each subscriber manages its location in the queue, thus able to catch up at its own pace and even replay previous messages in order if needed - since this buffer is the entrance of event data into our backend, consumption retries and behavior reproducibility are paramount in case of bugs or downtime.</strong></p><p><strong>To be safe, this topic will persist messages for a week, after which they will be archived in blob file storage. Also, we can configure Kafka to distribute topic logs across multiple partitions, each on a different broker, and replicate for durability. Proactively, if a broker goes down, the topic will still be available for consumption and any temporarily lost data can be recovered from its copy.</strong></p><p><strong>Finally, Kafka&#8217;s log file design guarantees at-least-once delivery. When a consumer successfully receives a message, it will acknowledge the delivery and update its new queue offset. When consumption failure occurs, the acknowledgment is not sent and Kafka attempts retransmission. This is not as ideal as exactly-once delivery, but it at least ensures that data loss is a nonpossibility; the only drawback is implementing the safe handling of duplicate messages.</strong></p><h3>Stream Organization</h3><p><strong>Events must be consumed in the order of transmission to accurately depict game state. However, ordering is only necessary for events within a single game. To ensure this, we first require scorers to register or declare a unique </strong><code>gameID</code><strong> before the start of each game. Then, we configure Kafka to balance events between partitions by </strong><code>gameID</code><strong>, thus guaranteeing that all events for a single game are read in relative order. This is useful when replaying past events in the case of an error. By contrast, if events from simultaneous games are woven together uniformly across all partitions, the relative order of same-game events is jeopardized.</strong></p><p><strong>Kafka partitions allow for messages to be split between multiple consumers. Thus to prepare for maximum consumer scalability, the more partitions, the marrier. However, since there are only ever 10 simulatanous games each emmitting events every 3 seconds, there is no signmificant need for further partition orchestration.</strong></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!QYuL!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa40548c-5c7e-4e02-a6dc-c576e238f46c_1600x748.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!QYuL!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa40548c-5c7e-4e02-a6dc-c576e238f46c_1600x748.webp 424w, https://substackcdn.com/image/fetch/$s_!QYuL!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa40548c-5c7e-4e02-a6dc-c576e238f46c_1600x748.webp 848w, https://substackcdn.com/image/fetch/$s_!QYuL!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa40548c-5c7e-4e02-a6dc-c576e238f46c_1600x748.webp 1272w, https://substackcdn.com/image/fetch/$s_!QYuL!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa40548c-5c7e-4e02-a6dc-c576e238f46c_1600x748.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!QYuL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa40548c-5c7e-4e02-a6dc-c576e238f46c_1600x748.webp" width="1456" height="681" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/aa40548c-5c7e-4e02-a6dc-c576e238f46c_1600x748.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:681,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Kafka Topic Partitioning&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Kafka Topic Partitioning" title="Kafka Topic Partitioning" srcset="https://substackcdn.com/image/fetch/$s_!QYuL!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa40548c-5c7e-4e02-a6dc-c576e238f46c_1600x748.webp 424w, https://substackcdn.com/image/fetch/$s_!QYuL!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa40548c-5c7e-4e02-a6dc-c576e238f46c_1600x748.webp 848w, https://substackcdn.com/image/fetch/$s_!QYuL!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa40548c-5c7e-4e02-a6dc-c576e238f46c_1600x748.webp 1272w, https://substackcdn.com/image/fetch/$s_!QYuL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa40548c-5c7e-4e02-a6dc-c576e238f46c_1600x748.webp 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><em><strong>Kafka Topic Partitioning</strong></em></p><h3>Ingestion Service</h3><p><strong>When the scorer speaks, the Ingestion Service listens. It employs a scalable cluster of processing workers that transform incoming messages into actionable outcomes. In this case, upon receiving a new game event through Kafka, corresponding database entries are created.</strong></p><p><strong>The simplest solution is to spin up a few compute instances to form a consumer group across all partitions. The incoming message load can be divided and conquered by the finite compute instances, but this approach does not scale to message volume.</strong></p><p><strong>Alternatively, we may deploy a horizontally scalable cluster of general event ingestion workers. Like before, these workers form a consumer group to optimally distribute incoming messages. If a worker goes down, more are already running and will take on a temporarily heightened load until the replacement node spins up. Additionally, the number of workers may be scaled during gametime. But this method is not perfect. We will need more advanced logic to handle out-of-order data operations - in other words, when batch 2 begins before batch 1 completes since events are ingested asynchronously. Though more complex, this method allows us to achieve the stated goals with some clever software design.</strong></p><p><strong>Because each consumer must commit consumption acknoledgements to the Kafka partition it reads from, the number of performing concurrent workers is limited by the number of partitions. Any more than this breaks the data consumption guarantee by greedily reading ahead before knowing if the current read succeeds. Therefore, as hinted at before, the more partitions, the better. Excess workers are idle, though a few extra instances are beneficial for immediate failover.</strong></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!yntl!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a5acf95-a19c-47d2-8e0f-87b8f878f704_1600x923.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!yntl!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a5acf95-a19c-47d2-8e0f-87b8f878f704_1600x923.webp 424w, https://substackcdn.com/image/fetch/$s_!yntl!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a5acf95-a19c-47d2-8e0f-87b8f878f704_1600x923.webp 848w, https://substackcdn.com/image/fetch/$s_!yntl!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a5acf95-a19c-47d2-8e0f-87b8f878f704_1600x923.webp 1272w, https://substackcdn.com/image/fetch/$s_!yntl!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a5acf95-a19c-47d2-8e0f-87b8f878f704_1600x923.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!yntl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a5acf95-a19c-47d2-8e0f-87b8f878f704_1600x923.webp" width="1456" height="840" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5a5acf95-a19c-47d2-8e0f-87b8f878f704_1600x923.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:840,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Ingestion Service Worker Cluster&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Ingestion Service Worker Cluster" title="Ingestion Service Worker Cluster" srcset="https://substackcdn.com/image/fetch/$s_!yntl!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a5acf95-a19c-47d2-8e0f-87b8f878f704_1600x923.webp 424w, https://substackcdn.com/image/fetch/$s_!yntl!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a5acf95-a19c-47d2-8e0f-87b8f878f704_1600x923.webp 848w, https://substackcdn.com/image/fetch/$s_!yntl!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a5acf95-a19c-47d2-8e0f-87b8f878f704_1600x923.webp 1272w, https://substackcdn.com/image/fetch/$s_!yntl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a5acf95-a19c-47d2-8e0f-87b8f878f704_1600x923.webp 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><em><strong>Ingestion Service Worker Cluster</strong></em></p><h3>Container Orchestration and Scalability</h3><p><strong>As mentioned, workers are designed to be horizontally scalable to fit variable demand. This is accomplished by orchestrating a cluster of Docker containers, each running an instance of the ingestion service. Docker Swarm provides stable cluster network configuration and scalability basics. Kubernetes is the Swiss-Army knife of advanced container orchestration, though it is overkill for our design. A simple Docker contrainer scheduler based on the game schedule will suffice.</strong></p><h2>Data Modeling, Organization, and Operations</h2><p><strong>Our data space consists of known, fixed-schema entities, between which are one-to-one, one-to-many, or even many-to-many relations. For instance, one play may be linked to 3 tackles, but only one touchdown can occur per play. A relational database fits our needs.</strong></p><h3>The Relational Model</h3><p><strong>Beyond drawing lines between entities, the relational model brings many bonuses. Key and Referential Integrity constraints ensure that the data being added belongs - unwanted duplicates and invalid relationships are avoided altogether, by design. Since entity schema is known, an RDBMS may intelligently apply optimal memory layout and compression to best fit the given column datatypes or leverage consistent data patterns. And of course, ACID compliance is wonderful for ensuring expected behavior. But which database to use? PostgreSQL is an open-source RDBMS with many modern features (for future product growth) available out of the box or through plugins - a clear top choice.</strong></p><h3>Data Entity Constraints</h3><p><strong>There exists a scenario where an ingestion process fails, after which the Kafka queue must rewind to ensure the missed data is retried. However, each unique event should only be handled once. The secret here is to enforce idempotency - meaning operations applied over and over should equate to the same operation only applied once. For this reason, only insertion operations occur and each entity has its Key Integrity constraints to ensure duplicate insertions are rejected. Direct row modification is reserved for overturned calls and manual intervention to correct a scorer&#8217;s error.</strong></p><p><strong>Note that in this example, Referential Integrity constraints are ignored because every event has a unique </strong><code>gameID</code><strong>, </strong><code>playNumber</code><strong>, and </strong><code>eventNumber</code><strong> with concesous maintained by the scorer - not a member within the database. Even if database insertions occur slightly out of order due to execution time variability, we can trust that dependent rows will soon be inserted instead of rejecting eager writes altogether. To illustrate, if a pass is written before the snap, we allow the snap to be lazily inserted shortly after instead of unnecessarily rejecting the pass insertion, blocking for the snap insertion, then retrying the pass insertion.</strong></p><h3>Handling Overturned and Reversed Calls</h3><p><strong>Event handling is a straightforward process until events are overturned by challenges or penalties. The original event cannot be erased from the historical timeline of the game, though must be marked as invalidated in favor of a new ruling.</strong></p><p><strong>But did we not establish that row modification is a no-no? Yes, though this case presents an exception while retaining operation idempotency. Let us add a </strong><code>valid</code><strong> column to each event&#8217;s schema. Upon initial row insertion, this value defaults to true. If the event is overturned, the </strong><code>valid</code><strong> entry is set to false, and cannot ever become true again. Simply put, this does break our rule of no modification, but since modifications are unidirectional and applied to previously unset fields, no previous data is overwritten - our main intent.</strong></p><p><strong>Yet a simple </strong><code>valid</code><strong> column is not enough. This is only satisfactory when an event is nullified. For instance, a touchdown pass may be nullified after Offensive Pass Interference is called. The entire play resets with a less favorable field position for the offense. However, there are times when an event is entirely overridden by a different outcome, such as a 60-yard run overturned to a 40-yard run following a successful review. In these cases, the event&#8217;s current row is invalidated and a newly updated entry is inserted. Thus, for a given entity, each event will have at most one valid row, allowing valid plays to be retrieved without duplication.</strong></p><p><strong>Planning ahead, if future rules allow for an event to be overturned multiple times, our design still accurately depicts the scenario: just invalidate the only valid entry for that event (could be the original or previously corrected), and insert the corrected row.</strong></p><h3>Proposed Entities</h3><p><strong>Below, we materialize these ideas into concrete schemata.</strong></p><h4>Plays</h4><p><strong>gameID, playNumber, eventNumber, startTimestamp, gameSecondsPlayed, posession, fieldPosition, down</strong></p><h4>Passes</h4><p><strong>gameID, playNumber, eventNumber, passerID, throwYard, receptionYard, recieverID, isTouchdown</strong></p><h4>Tackles</h4><p><strong>gameID, playNumber, tacklerID, tackledID, fieldPosition, valid</strong></p><h4>Runs</h4><p><strong>gameID, playNumber, eventNumber, playerID, startYard, endYard, isRush, isTouchdown</strong></p><p><strong>With these simplified entities, basic football plays can be tracked and queried for insight. Below are a few relevant queries that could be useful within our Fantasy Football use case.</strong></p><h3>Proposed Queries</h3><p><strong>The notion of &#8220;raw&#8221; events in the database successfully captures the complete story of each game, though passes complexity to the data consumer; in reality, this is no issue since queries themselves are static in nature. In other words, a more complex query can be written once and never again.</strong></p><ol><li><p><strong>Find a player&#8217;s rushing yards for a given game</strong></p></li></ol><pre><code><code>select sum(endYard - startYard) from Runs
where playerID = ... and gameID = ... and valid = true;</code></code></pre><ol start="2"><li><p><strong>Find a player&#8217;s passing yards for a given game</strong></p></li></ol><pre><code><code>select sum(throwYard - receptionYard) from Passes
where passerID = ... and gameID = ... and valid = true;</code></code></pre><ol start="3"><li><p><strong>Find a how many solo tackles are attributed to a player for a given game</strong></p></li></ol><pre><code><code>select count(*) from (
   select count(*) from Tackles
   where valid = true and gameID, playNumber in
      (select gameID, playNumber from Tackles
      where tacklerID = ... and gameID = ... and valid = true)
   group by gameID, playNumber
   having count(*) = 1
) soloTackles;</code></code></pre><ol start="4"><li><p><strong>Find all touchdown timestamps for a given game, and the players credited</strong></p></li></ol><pre><code><code>select startTimestamp from (
   select playNumber from Passes
   where gameID = ... and touchdown = true and valid = true
   union
   select playNumber from Runs
   where gameID = ... and touchdown = true and valid = true
) touchdowns
join Plays on touchdowns.playNumber = Plays.playNumber;</code></code></pre><h3>Out-of-Order Data Operations</h3><p><strong>Due to extreme network or program conditions, an original event can be written to the database after its correction. This is a rare occurrence, but we must be prepared to handle it. Even worse, the out-of-order process to nullify and overturn events are separate.</strong></p><p><strong>One approach is to accept all incoming writes and scan for an event&#8217;s corrections before the insertion of the original event. Essentially assuming all writes are out of order, every write will follow an expensive read to determine if the prerequisite or correction row exist - performance will be constantly impacted for a scenario rarely encountered. This also does not handle the case of nullifying an event before its original insertion, as it is impossible to modify a nonexistant row. An additional layer of event management is required.</strong></p><p><strong>A better approach is to not complicate writing patterns at the expense of infrequent inefficiencies. Instead, assume all data is written in order, and only apply the scan when inserting the less frequent call reversals. Before nullifying or overturning an event, check if the prerequisite row exists. If it does, the operation completes like before. If not, wait </strong><code>50ms</code><strong> or so for a parallel process to complete the original event insertion, then try again. As stated, this may lead to a slight increase in event insertion latency following official reviews, but keep general performance at its optimum.</strong></p><p><strong>In SQL, let us demonstrate the improved writting pattern for a </strong><code>Run</code><strong> event.</strong></p><ol><li><p><strong>Insert an </strong><code>Run</code><strong> event</strong></p></li></ol><pre><code><code>insert into Runs values (...);</code></code></pre><ol start="2"><li><p><strong>Nullify the </strong><code>Run</code><strong> event</strong></p></li></ol><pre><code><code>update Runs
set valid = false
where gameID = ... and playNumber = ... and eventNumber = ...
returning eventNumber;
/* if no rows are returning, retry from the ingestion service worker after a brief timeout. */</code></code></pre><ol start="3"><li><p><strong>Overturn the </strong><code>Run</code><strong> event</strong></p></li></ol><pre><code><code>begin
   update Runs
   set valid = false
   where gameID = ... and playNumber = ... and eventNumber = ...;
   if not found raise exception 'Original event not found';
   insert into Runs values (...);
end;
/* on catching the exception from the ingestion service worker, retry after a brief timeout. */</code></code></pre><h2>Realtime Client Delivery, Caching, and Querying</h2><p><strong>A topic for a different day</strong></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blakesanie.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Deconstructing the Iconic Apple Watch Bubble UI]]></title><description><![CDATA[Theoretical foundations in math, graphical execution in code]]></description><link>https://blakesanie.substack.com/p/deconstructing-the-iconic-apple-watch</link><guid isPermaLink="false">https://blakesanie.substack.com/p/deconstructing-the-iconic-apple-watch</guid><dc:creator><![CDATA[Blake Sanie]]></dc:creator><pubDate>Thu, 17 Dec 2020 16:30:00 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f5a1fad-3d4f-4178-9ef0-07b5436c9ca9_800x489.gif" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When the first <a href="https://en.wikipedia.org/wiki/Apple_Watch">Apple Watch</a> launched in 2015, I was blown away by the design of the home screen in <a href="https://en.wikipedia.org/wiki/WatchOS">WatchOS</a>. The layout deviates from more standard, grid-based app organization methods, and instead proposes an original, visually dynamic interface.</p><p>Five years later, I still find myself in awe when opening my watch to this smooth, chic UI. However, from an engineering point of view, I continue to be perplexed by the layout&#8217;s under-the-hood functionality.</p><p>As an experienced application developer, I know that constructing navigation flows and layouts are critical to any app&#8217;s foundation. Apple accomplishes all this, plus a touch of flexibility, satisfaction, and curiosity.</p><p>Sure, I enjoy building robust app layouts with <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout">CSS Grid</a> and <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox">Flexbox</a>, among other web and mobile technologies, but the complexity behind the Apple Watch Bubble UI does not fit any of these molds. I made it my mission to investigate all aspects of the layout, especially exploring the geometry and surrounding mathematics that orchestrate the layout&#8217;s visual design.</p><p>Disclaimer: <em>The discussion of the UI&#8217;s underlying functionality and design stems only from my personal insights; Apple most likely implemented the layout a bit, or a lot, differently.</em></p><h2>Basic Layout Geometry</h2><p>Let&#8217;s start with a basic honeycomb grid for our bubbles. We&#8217;ll handle sizing and other effects later on. Every other row is one bubble shorter than the others, and the last row may be incomplete, though centered.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!C8er!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3083287-31a1-4d46-abf7-3ad9e68b49b8_1164x1036.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!C8er!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3083287-31a1-4d46-abf7-3ad9e68b49b8_1164x1036.png 424w, https://substackcdn.com/image/fetch/$s_!C8er!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3083287-31a1-4d46-abf7-3ad9e68b49b8_1164x1036.png 848w, https://substackcdn.com/image/fetch/$s_!C8er!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3083287-31a1-4d46-abf7-3ad9e68b49b8_1164x1036.png 1272w, https://substackcdn.com/image/fetch/$s_!C8er!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3083287-31a1-4d46-abf7-3ad9e68b49b8_1164x1036.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!C8er!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3083287-31a1-4d46-abf7-3ad9e68b49b8_1164x1036.png" width="272" height="242.0893470790378" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e3083287-31a1-4d46-abf7-3ad9e68b49b8_1164x1036.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1036,&quot;width&quot;:1164,&quot;resizeWidth&quot;:272,&quot;bytes&quot;:139400,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!C8er!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3083287-31a1-4d46-abf7-3ad9e68b49b8_1164x1036.png 424w, https://substackcdn.com/image/fetch/$s_!C8er!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3083287-31a1-4d46-abf7-3ad9e68b49b8_1164x1036.png 848w, https://substackcdn.com/image/fetch/$s_!C8er!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3083287-31a1-4d46-abf7-3ad9e68b49b8_1164x1036.png 1272w, https://substackcdn.com/image/fetch/$s_!C8er!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3083287-31a1-4d46-abf7-3ad9e68b49b8_1164x1036.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Model starting point: honeycomb layout</figcaption></figure></div><p>As seen in the graphic, the UI can be broken down into three concentric regions: the center, fringe, and outer regions. The former two will be most critical when modeling how bubble size and position changes across the screen. For all cases, a bubble is considered to be inside a region if that region contains the bubble&#8217;s center.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1Zeu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F149a14af-ac7d-449c-8fbe-e9adcd62fbd5_800x532.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1Zeu!,w_424,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F149a14af-ac7d-449c-8fbe-e9adcd62fbd5_800x532.gif 424w, https://substackcdn.com/image/fetch/$s_!1Zeu!,w_848,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F149a14af-ac7d-449c-8fbe-e9adcd62fbd5_800x532.gif 848w, https://substackcdn.com/image/fetch/$s_!1Zeu!,w_1272,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F149a14af-ac7d-449c-8fbe-e9adcd62fbd5_800x532.gif 1272w, https://substackcdn.com/image/fetch/$s_!1Zeu!,w_1456,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F149a14af-ac7d-449c-8fbe-e9adcd62fbd5_800x532.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1Zeu!,w_1456,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F149a14af-ac7d-449c-8fbe-e9adcd62fbd5_800x532.gif" width="800" height="532" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/149a14af-ac7d-449c-8fbe-e9adcd62fbd5_800x532.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:532,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:5025655,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!1Zeu!,w_424,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F149a14af-ac7d-449c-8fbe-e9adcd62fbd5_800x532.gif 424w, https://substackcdn.com/image/fetch/$s_!1Zeu!,w_848,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F149a14af-ac7d-449c-8fbe-e9adcd62fbd5_800x532.gif 848w, https://substackcdn.com/image/fetch/$s_!1Zeu!,w_1272,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F149a14af-ac7d-449c-8fbe-e9adcd62fbd5_800x532.gif 1272w, https://substackcdn.com/image/fetch/$s_!1Zeu!,w_1456,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F149a14af-ac7d-449c-8fbe-e9adcd62fbd5_800x532.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">A graphic overlay showcaas core regions and variable dimensions of the Bubble UI layout</figcaption></figure></div><p>The center region is defined as the centered (rounded) rectangle bounded by a x radius and y radius, and a corner radius measured from the outer edge. All bubbles in the center region are rendered at their maximum size.</p><p>The fringe region is defined as the space outside the center region within a certain fringe width of its outer edge. This region is used to contain each bubble&#8217;s transition from minimum to maximum size. When a bubble enters this region, it does so at its minimum size, which increases linearly until reaching its maximum size upon entry of the center region.</p><p>The outer region is defined as all space on the 2D canvas not comprising the center and fringe regions. Here, all bubbles are minimized.</p><h3>What about Circular and Unrounded Rectangular Regions?</h3><p>The center and fringe regions take circular form when x radius, y radius, and corner radius are all equal. Furthermore, the center region becomes unrounded when corner radius is zero; however, the fringe region&#8217;s corners will still be rounded with a radius of fringe width.</p><h2>Calculating Bubble Size From Location</h2><p>Diving deeper into the layout&#8217;s underlying mechanisms, let&#8217;s use our defined regions to develop a mathematical model that calculates a bubble&#8217;s size as a function of its location on the screen.</p><p>First, we need to define another key visual landmark: the corner zone.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1-nU!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31f574ab-8e71-42af-a4bb-b3b12e832a7b_1564x958.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1-nU!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31f574ab-8e71-42af-a4bb-b3b12e832a7b_1564x958.png 424w, https://substackcdn.com/image/fetch/$s_!1-nU!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31f574ab-8e71-42af-a4bb-b3b12e832a7b_1564x958.png 848w, https://substackcdn.com/image/fetch/$s_!1-nU!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31f574ab-8e71-42af-a4bb-b3b12e832a7b_1564x958.png 1272w, https://substackcdn.com/image/fetch/$s_!1-nU!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31f574ab-8e71-42af-a4bb-b3b12e832a7b_1564x958.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1-nU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31f574ab-8e71-42af-a4bb-b3b12e832a7b_1564x958.png" width="1456" height="892" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/31f574ab-8e71-42af-a4bb-b3b12e832a7b_1564x958.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:892,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:122335,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!1-nU!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31f574ab-8e71-42af-a4bb-b3b12e832a7b_1564x958.png 424w, https://substackcdn.com/image/fetch/$s_!1-nU!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31f574ab-8e71-42af-a4bb-b3b12e832a7b_1564x958.png 848w, https://substackcdn.com/image/fetch/$s_!1-nU!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31f574ab-8e71-42af-a4bb-b3b12e832a7b_1564x958.png 1272w, https://substackcdn.com/image/fetch/$s_!1-nU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31f574ab-8e71-42af-a4bb-b3b12e832a7b_1564x958.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Corner Zones visualized over the graphic Bubble UI model</figcaption></figure></div><p>Corner Zones are defined as the four regions bounded by the corners of the canvas and the internal corner of the center region (inset corner radius from the edge). In corner zones, size remains constant radially with respect to the internal corner. By contrast, bubbles outside corner zones maintain constant size with a constant x or y position.</p><p>Note: <em>If the center region is circular, all four internal corners are located at the center. Otherwise, if the center region forms an unrounded rectangle, internal corners are not offset from the rectangle&#8217;s outer edge.</em></p><h3>Step 1: Determine if Bubble is in Corner Zone</h3><p>At first glance, it may appear that this would require four separate operations. However, looking at the similarities between all corner zones yields a single expression: A bubble is inside a corner zone if</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;|\\text{bubble.x}|>\\text{xRadius}\\hspace{4mm}, \\hspace{4mm}|\\text{bubble.y}|>\\text{yRadius}&quot;,&quot;id&quot;:&quot;HPDKSBGYBS&quot;}" data-component-name="LatexBlockToDOM"></div><p>since the variables x radius and y radius are positive by nature.</p><h3>Step 2: Determine Concentric Region that Contains Bubble</h3><p>As previously discussed, bubble size is partially dependent on which concentric region contains its center.</p><p>If the bubble is in a corner zone, first calculate its distance to the corresponding internal corner according to the <a href="https://www.purplemath.com/modules/distform.htm">Pythagorean Distance Formula</a></p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\text{xDistance}=\\text{bubble.x} - (\\text{xRadius} - \\text{cornerRadius})&quot;,&quot;id&quot;:&quot;MMANOCFEMG&quot;}" data-component-name="LatexBlockToDOM"></div><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\text{yDistance}=\\text{bubble.y} - (\\text{yRadius} - \\text{cornerRadius})&quot;,&quot;id&quot;:&quot;DEUZVEKZMU&quot;}" data-component-name="LatexBlockToDOM"></div><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\text{distanceToInternalCorner}=\\sqrt{\\text{xDistance}^2 + \\text{yDistance}^2}&quot;,&quot;id&quot;:&quot;WUDMJUIDDG&quot;}" data-component-name="LatexBlockToDOM"></div><p>The bubble is contained by the center region if this distance is less than corner radius, or the fringe region if this distance is less than the sum of corner radius and fringe width. Otherwise, the bubble lies in the outer region.</p><p>If the bubble is not bounded inside a corner zone, compute its distance to the center of the canvas with the expression:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\text{distanceToCenter} = max(|\\text{bubble.x}|, |\\text{bubble.y}|)&quot;,&quot;id&quot;:&quot;ACNLXVBDVK&quot;}" data-component-name="LatexBlockToDOM"></div><p>If this distance is less than the corresponding radius (x or y), it is found inside the center region. Otherwise, if the distance is still less than the sum of the radius and fringe width, the bubble is located in the fringe region. Else, the outer region contains the bubble.</p><h3>Step 3: Calculate Bubble Size</h3><p>Bubbles within the center region render with maximum size, while bubbles in the outer region stay completely unmagnified.</p><p><em>The fringe region is where things get interesting</em>, since this region oversees the bubbles&#8217; transition between large and small states.</p><p>Any bubble&#8217;s current size change is proportional to its current progression through the fringe. In other words, bubbles 30% away from the outer edge have undergone 30% of their upscaling, and bubbles 20% away from the inner edge have done 80% of their upscaling.</p><p>Finding a bubble&#8217;s current size is therefore accomplished by interpolating its distance to the middle region from the range (0, fringe width) to the range (max size, min size). The computation is as follows:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\text{distanceToMiddleRegion} = \\text{distanceToInternalCorner} - \\text{cornerRadius}&quot;,&quot;id&quot;:&quot;TDGVSNQMZN&quot;}" data-component-name="LatexBlockToDOM"></div><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\text{currentSize} = \\text{maxSize} + \\frac{\\text{distanceToMiddleRegion}}{\\text{fringeWidth} * (\\text{minSize} - \\text{maxSize})}&quot;,&quot;id&quot;:&quot;GTHXXWRSLB&quot;}" data-component-name="LatexBlockToDOM"></div><p>Where distance to middle region can be expressed as:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\text{distanceToMiddleRegion} = \\text{distanceToInternalCorner} - \\text{cornerRadius}&quot;,&quot;id&quot;:&quot;HFGTVXNGWF&quot;}" data-component-name="LatexBlockToDOM"></div><p>if the bubble is in a corner zone, otherwise:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;max(|\\text{bubble.x}| - \\text{xRadius}, |\\text{bubble.y}|- \\text{yRadius})&quot;,&quot;id&quot;:&quot;YZFRCCNYOB&quot;}" data-component-name="LatexBlockToDOM"></div><h2>Advanced Features</h2><h3>Compactness</h3><p>I can&#8217;t help but notice that the Apple Watch UI manages to optimize bubbles compactness. Whenever bubbles undergo a size transformation in the fringe region, they maintain the same gutter width as the nearest bubble.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!eNIN!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2dcf7eb-0c6a-49fe-acf3-c522a7e78ce9_640x360.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!eNIN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2dcf7eb-0c6a-49fe-acf3-c522a7e78ce9_640x360.gif 424w, https://substackcdn.com/image/fetch/$s_!eNIN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2dcf7eb-0c6a-49fe-acf3-c522a7e78ce9_640x360.gif 848w, https://substackcdn.com/image/fetch/$s_!eNIN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2dcf7eb-0c6a-49fe-acf3-c522a7e78ce9_640x360.gif 1272w, https://substackcdn.com/image/fetch/$s_!eNIN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2dcf7eb-0c6a-49fe-acf3-c522a7e78ce9_640x360.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!eNIN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2dcf7eb-0c6a-49fe-acf3-c522a7e78ce9_640x360.gif" width="640" height="360" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b2dcf7eb-0c6a-49fe-acf3-c522a7e78ce9_640x360.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:360,&quot;width&quot;:640,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:731038,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!eNIN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2dcf7eb-0c6a-49fe-acf3-c522a7e78ce9_640x360.gif 424w, https://substackcdn.com/image/fetch/$s_!eNIN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2dcf7eb-0c6a-49fe-acf3-c522a7e78ce9_640x360.gif 848w, https://substackcdn.com/image/fetch/$s_!eNIN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2dcf7eb-0c6a-49fe-acf3-c522a7e78ce9_640x360.gif 1272w, https://substackcdn.com/image/fetch/$s_!eNIN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2dcf7eb-0c6a-49fe-acf3-c522a7e78ce9_640x360.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Currently, our model maintains a constant distance between bubbles at all times. Visualized below is our current progress versus our end goal (glimpse ahead).</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!F-nJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96806a47-01d9-4633-9faf-da158e6b6806_800x405.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!F-nJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96806a47-01d9-4633-9faf-da158e6b6806_800x405.gif 424w, https://substackcdn.com/image/fetch/$s_!F-nJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96806a47-01d9-4633-9faf-da158e6b6806_800x405.gif 848w, https://substackcdn.com/image/fetch/$s_!F-nJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96806a47-01d9-4633-9faf-da158e6b6806_800x405.gif 1272w, https://substackcdn.com/image/fetch/$s_!F-nJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96806a47-01d9-4633-9faf-da158e6b6806_800x405.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!F-nJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96806a47-01d9-4633-9faf-da158e6b6806_800x405.gif" width="800" height="405" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/96806a47-01d9-4633-9faf-da158e6b6806_800x405.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:405,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2124758,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!F-nJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96806a47-01d9-4633-9faf-da158e6b6806_800x405.gif 424w, https://substackcdn.com/image/fetch/$s_!F-nJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96806a47-01d9-4633-9faf-da158e6b6806_800x405.gif 848w, https://substackcdn.com/image/fetch/$s_!F-nJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96806a47-01d9-4633-9faf-da158e6b6806_800x405.gif 1272w, https://substackcdn.com/image/fetch/$s_!F-nJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96806a47-01d9-4633-9faf-da158e6b6806_800x405.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Not compact (left) vs. compact (right)</figcaption></figure></div><p>Implementing optimal compactness introduces a new layer of complexity, since now, in addition to manipulating the size, we need to directly manipulate bubble position.</p><p>Similar to before, we are going to translate each bubble according to which concentric region contains it, as well as if the bubble lies in a corner zone.</p><p>Bubbles in the center region are already compact and hence do not require translation.</p><p>Bubbles in the outer region are translated inward by the amount of its maximum size. If such bubbles reside in corner zones, they translate towards the corresponding internal corner or, otherwise, the canvas&#8217;s center.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!30Fg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3f8bf43-4e1e-40d6-b196-8a12eb248b2e_1582x983.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!30Fg!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3f8bf43-4e1e-40d6-b196-8a12eb248b2e_1582x983.png 424w, https://substackcdn.com/image/fetch/$s_!30Fg!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3f8bf43-4e1e-40d6-b196-8a12eb248b2e_1582x983.png 848w, https://substackcdn.com/image/fetch/$s_!30Fg!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3f8bf43-4e1e-40d6-b196-8a12eb248b2e_1582x983.png 1272w, https://substackcdn.com/image/fetch/$s_!30Fg!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3f8bf43-4e1e-40d6-b196-8a12eb248b2e_1582x983.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!30Fg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3f8bf43-4e1e-40d6-b196-8a12eb248b2e_1582x983.png" width="1456" height="905" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f3f8bf43-4e1e-40d6-b196-8a12eb248b2e_1582x983.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:905,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:206534,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!30Fg!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3f8bf43-4e1e-40d6-b196-8a12eb248b2e_1582x983.png 424w, https://substackcdn.com/image/fetch/$s_!30Fg!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3f8bf43-4e1e-40d6-b196-8a12eb248b2e_1582x983.png 848w, https://substackcdn.com/image/fetch/$s_!30Fg!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3f8bf43-4e1e-40d6-b196-8a12eb248b2e_1582x983.png 1272w, https://substackcdn.com/image/fetch/$s_!30Fg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3f8bf43-4e1e-40d6-b196-8a12eb248b2e_1582x983.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Direction of translation based on canvas location</figcaption></figure></div><p>The fringe region, yet again, oversees the transition between these two states. Just like with size, translation magnitude is derived by distance to center region interpolated from the range (fringe width, 0) to the range (max size, 0).</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\text{translationMagnitude} = \\text{distanceToMiddleRegion} / \\text{fringeWidth} * \\text{maxSize}&quot;,&quot;id&quot;:&quot;CXUBZPUYIC&quot;}" data-component-name="LatexBlockToDOM"></div><p>The same direction rules apply from before.</p><h3>Gravitation</h3><p>This feature is a conception of my own imagination &#8212; Apple&#8217;s Bubble Layout doesn&#8217;t necessarily showcase it. Nonetheless, I want to increase bubble compactness further by gravitating distant bubbles towards the center.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!eCDs!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef1c2292-88a1-4693-9afa-52dd72b9370e_800x403.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!eCDs!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef1c2292-88a1-4693-9afa-52dd72b9370e_800x403.gif 424w, https://substackcdn.com/image/fetch/$s_!eCDs!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef1c2292-88a1-4693-9afa-52dd72b9370e_800x403.gif 848w, https://substackcdn.com/image/fetch/$s_!eCDs!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef1c2292-88a1-4693-9afa-52dd72b9370e_800x403.gif 1272w, https://substackcdn.com/image/fetch/$s_!eCDs!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef1c2292-88a1-4693-9afa-52dd72b9370e_800x403.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!eCDs!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef1c2292-88a1-4693-9afa-52dd72b9370e_800x403.gif" width="800" height="403" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ef1c2292-88a1-4693-9afa-52dd72b9370e_800x403.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:403,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:3431681,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!eCDs!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef1c2292-88a1-4693-9afa-52dd72b9370e_800x403.gif 424w, https://substackcdn.com/image/fetch/$s_!eCDs!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef1c2292-88a1-4693-9afa-52dd72b9370e_800x403.gif 848w, https://substackcdn.com/image/fetch/$s_!eCDs!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef1c2292-88a1-4693-9afa-52dd72b9370e_800x403.gif 1272w, https://substackcdn.com/image/fetch/$s_!eCDs!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef1c2292-88a1-4693-9afa-52dd72b9370e_800x403.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">No gravitation (left) vs. high gravitation (right)</figcaption></figure></div><p>Surprisingly, implementing gravitation is easier than any other transformation deconstructed so far.</p><p>Put simply, the gravitation effect involves translating bubbles in the outer region towards the fringe region, proportional to the bubble&#8217;s distances from the fringe edge. For our purposes, we define a linear relationship between distance to fringe and displacement, but this can be implemented in a number of different ways (exponential, square, square root, etc).</p><p>Bubbles in the outer region shall be translated by the amount described in the Compactness section, <em>plus</em> an extra</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\text{distanceToFringeRegion} * \\text{gravitation}&quot;,&quot;id&quot;:&quot;RIGWGCSFND&quot;}" data-component-name="LatexBlockToDOM"></div><p>where distance to fringe region is expressed as:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\text{distanceToMiddleRegion} - \\text{fringeWidth}\n&quot;,&quot;id&quot;:&quot;FITSYRBOIE&quot;}" data-component-name="LatexBlockToDOM"></div><p>and gravitation is the constant of proportionality. A value of 0 allows for no gravitation effect, while a value of 1 yields no separation between outer bubbles. The effect looks best when gravitation is somewhere between these two extrema.</p><h2>From Theory to Application</h2><p>As a web developer who is fascinated with <a href="https://reactjs.org/">React.js</a>, I want to open up my findings to the design and development community. Following the steps outlined in this article, I created an <a href="https://bubbleui.blakesanie.com/">open source React component</a> available for your team to use today.</p><p>The abstraction is highly configurable, with controls for all the discussed variables, plus more. The layout also enables the use of custom bubble components for ultimate customizability. I can&#8217;t wait to see what you&#8217;ll create!</p><h2>Conclusion</h2><p>Thanks for reading, I hope you found it informative! Feel free to leave feedback or questions in the comments section.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Rs_Q!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f5a1fad-3d4f-4178-9ef0-07b5436c9ca9_800x489.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Rs_Q!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f5a1fad-3d4f-4178-9ef0-07b5436c9ca9_800x489.gif 424w, https://substackcdn.com/image/fetch/$s_!Rs_Q!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f5a1fad-3d4f-4178-9ef0-07b5436c9ca9_800x489.gif 848w, https://substackcdn.com/image/fetch/$s_!Rs_Q!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f5a1fad-3d4f-4178-9ef0-07b5436c9ca9_800x489.gif 1272w, https://substackcdn.com/image/fetch/$s_!Rs_Q!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f5a1fad-3d4f-4178-9ef0-07b5436c9ca9_800x489.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Rs_Q!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f5a1fad-3d4f-4178-9ef0-07b5436c9ca9_800x489.gif" width="800" height="489" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7f5a1fad-3d4f-4178-9ef0-07b5436c9ca9_800x489.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:489,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:3958562,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Rs_Q!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f5a1fad-3d4f-4178-9ef0-07b5436c9ca9_800x489.gif 424w, https://substackcdn.com/image/fetch/$s_!Rs_Q!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f5a1fad-3d4f-4178-9ef0-07b5436c9ca9_800x489.gif 848w, https://substackcdn.com/image/fetch/$s_!Rs_Q!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f5a1fad-3d4f-4178-9ef0-07b5436c9ca9_800x489.gif 1272w, https://substackcdn.com/image/fetch/$s_!Rs_Q!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f5a1fad-3d4f-4178-9ef0-07b5436c9ca9_800x489.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Taken from the live demo of React-Bubble-UI, beautifully showcasing S&amp;P 500 companies</figcaption></figure></div><h3>Resources</h3><ol><li><p><a href="https://bubbleui.blakesanie.com/#/demo">Live Demo</a></p></li><li><p><a href="https://github.com/blakesanie/React-Bubble-UI">Github Repository</a></p></li></ol><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blakesanie.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Generating Optimal Keyboard Layouts]]></title><description><![CDATA[Does QWERTY cut it?]]></description><link>https://blakesanie.substack.com/p/generating-optimal-keyboard-layouts</link><guid isPermaLink="false">https://blakesanie.substack.com/p/generating-optimal-keyboard-layouts</guid><dc:creator><![CDATA[Blake Sanie]]></dc:creator><pubDate>Sat, 28 Nov 2020 15:00:00 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!QnVu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4daad334-40e9-42b8-b7ce-b73a6ee14484_1080x720.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!QnVu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4daad334-40e9-42b8-b7ce-b73a6ee14484_1080x720.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!QnVu!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4daad334-40e9-42b8-b7ce-b73a6ee14484_1080x720.jpeg 424w, https://substackcdn.com/image/fetch/$s_!QnVu!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4daad334-40e9-42b8-b7ce-b73a6ee14484_1080x720.jpeg 848w, https://substackcdn.com/image/fetch/$s_!QnVu!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4daad334-40e9-42b8-b7ce-b73a6ee14484_1080x720.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!QnVu!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4daad334-40e9-42b8-b7ce-b73a6ee14484_1080x720.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!QnVu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4daad334-40e9-42b8-b7ce-b73a6ee14484_1080x720.jpeg" width="392" height="261.3333333333333" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4daad334-40e9-42b8-b7ce-b73a6ee14484_1080x720.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;normal&quot;,&quot;height&quot;:720,&quot;width&quot;:1080,&quot;resizeWidth&quot;:392,&quot;bytes&quot;:52594,&quot;alt&quot;:&quot;the words houston, we have problem written on a red background&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="the words houston, we have problem written on a red background" title="the words houston, we have problem written on a red background" srcset="https://substackcdn.com/image/fetch/$s_!QnVu!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4daad334-40e9-42b8-b7ce-b73a6ee14484_1080x720.jpeg 424w, https://substackcdn.com/image/fetch/$s_!QnVu!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4daad334-40e9-42b8-b7ce-b73a6ee14484_1080x720.jpeg 848w, https://substackcdn.com/image/fetch/$s_!QnVu!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4daad334-40e9-42b8-b7ce-b73a6ee14484_1080x720.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!QnVu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4daad334-40e9-42b8-b7ce-b73a6ee14484_1080x720.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Photo by <a href="true">ostudio</a> on <a href="https://unsplash.com">Unsplash</a></figcaption></figure></div><p>Today, the ubiquitous <a href="https://en.wikipedia.org/wiki/QWERTY">QWERTY</a> keyboard is assumed to exhibit the optimal layout for typing in the English language. Because QWERTY was developed in the 1870&#8217;s, I challenged myself to leverage computational processes to generate a more optimal keyboard.</p><p>More generally, this task can be applied to any language or text corpus. More on this later!</p><h2>Necessary Assumptions</h2><p>To find the one, true best keyboard layout, one must use brute force: testing every permutation of keys for typing efficiency.</p><p><em>I, for one, do not have infinite computing power, or free time.</em></p><p>To accomplish this task in a reasonable timeframe, let&#8217;s follow these assumptions:</p><ul><li><p>Hitting keys on the home row is always faster than the top row, and the top row is always faster than the bottom row</p></li><li><p>The number, function, and special character keys are not to be repositioned. Their effect on typing efficiency is assumed to be negligible.</p></li><li><p>The sample text accurately represents the extent of the language.</p></li></ul><h2>Method Overview</h2><ol><li><p>Model transitions between characters with respect to corpus of interest</p></li><li><p>Form a candidate keyboard layout fueled by the model&#8217;s findings </p></li><li><p>Evaluate the new layout via typing simulation</p></li></ol><h2>Generate Markov Chain from Provided Text</h2><p>The method we are using extracts language from a text file. The more expansive the file, the better.</p><pre><code>// sample.txt

It is a truth universally acknowledged, that a single man in possession of a good fortune, must be in want of a wife.

However little known the feelings or views of such a man may be on his first entering a neighbourhood, this truth is so well fixed in the minds of the surrounding families, that he is considered the rightful property of some one or other of their daughters.
...

(13k lines)</code></pre><p><em>Have you read this one?</em></p><p>Our keyboard models need to understand how characters relate to each other in various contexts. Introducing the <a href="https://en.wikipedia.org/wiki/Markov_chain">Markov Chain</a>. A Markov Chain, in this case, is a statistical model that maps each character to the frequency of each character that follows it. This is easily achieved by traversing the text (cleared of non-alphabetical characters) and updating the Markov Chain at every iteration.</p><pre><code>// Markov Chain
{
    i: {
        freq: 104530,
        t: 13167,
        s: 14064,
        v: 2299,
        ...
    },
    t: { ... },
    s: { ... },
    ...
}</code></pre><h2>Assigning Characters to Key Rows</h2><p>The letters on modern keyboards make up three rows: the home (middle), top, and bottom rows. Let&#8217;s start by grouping all 26 characters into these rows.</p><p>The most frequently read characters are to be placed in the middle row for fast access, followed by the top row, then the bottom.</p><pre><code>// Top Row
["m", "f", "l", "d", "u", "w", "y", "g", "c", "b"]

// Home Row
["n", "t", "s", "r", "a", "h", "o", "i", "e"]

// Bottom Row
["x", "p", "k", "v", "q", "j", "z"]</code></pre><h2>Determining Optimal Permutations for Rows</h2><p>Now that the keys are divided into rows, we need to reconfigure each row such that finger travel distance is minimized.</p><p>For each row, iterate through all key permutations. Let&#8217;s consider the optimal order of keys to evenly spread out each character&#8217;s frequency in the text. Performing this action on each row then yields the final product: <em>our new and improved keyboard layout.</em></p><pre><code>// Final Keyboard

["c", "w", "b", "m", "f", "g", "l", "d", "u", "y"]
["n", "h", "r", "o", "i", "s", "e", "t", "a"]
["v", "q", "j", "k", "x", "z", "p"]</code></pre><h2>Comparing to QWERTY</h2><p>To ensure that our own keyboard layout is more efficient than QWERTY for our given text, let&#8217;s run each keyboard through a typing simulation by having each keyboard re-type the sampled text.</p><p>The simulation tracks a total cost score for each keyboard (lower is better). We track the position of every finger on each hand, changing these positions with finger movement. When a finger must change rows, a full point is added to the cost. When a finger moves laterally, a half-point is added. When typing a character requires the active hand to switch, no point is added, since that hand already had time to move into place.</p><h2>Results</h2><ul><li><p>QWERTY original)</p><ul><li><p>1347859.5 points accumulated</p></li><li><p>100% efficiency (by default).</p></li></ul></li><li><p>CWBMFG (our creation)</p><ul><li><p>1109799 points accumulated</p></li><li><p><strong>121% efficiency</strong></p></li></ul></li></ul><h2>Fun Use Cases and Applications</h2><p>As mentioned earlier, this method can be used to generate keyboard layouts for any target language, where a language is just a collection of words. For fun, I tried my method on an extensive collection of Shakespearean plays and sonnets.</p><pre><code>// sample.txt

From fairest creatures we desire increase,
That thereby beauty's rose might never die,
But as the riper should by time decease,
His tender heir might bear his memory:
But thou contracted to thine own bright eyes,
Feed'st thy light's flame with self-substantial fuel,
...
(124k lines)</code></pre><p>Still, our keyboard remained more efficient for this language sample than QWERTY, with 121% Efficiency.</p><pre><code>// Keyboard

['w','c','b','m','f','g','l','d','u','y']
['n','r','h','o','i','s','e','t','a']
['j','q','z','v','k','x','p']</code></pre><h2>Takeaways</h2><p>Now that we have determined a keyboard layout more efficient than QWERTY, we can start to expand our keyboard empire, right? Wrong. QWERTY is dominant in today&#8217;s modern world; it&#8217;s not going anywhere. Still, this experiment supports that old, ubiquitous technologies are not necessarily the best; they can always be improved. Without inquisition, innovation is out of reach.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blakesanie.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item></channel></rss>