<?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"><channel><title><![CDATA[Rahim Nathwani]]></title><description><![CDATA[Rahim Nathwani's blog]]></description><link>https://www.encona.com</link><generator>GatsbyJS</generator><lastBuildDate>Tue, 14 Jan 2025 19:31:33 GMT</lastBuildDate><item><title><![CDATA[Custom statistics for Anki flashcard reviews]]></title><description><![CDATA[Custom statistics for Anki flashcard reviews]]></description><link>https://www.encona.com/posts/custom-statistics-for-anki-flashcard-reviews</link><guid isPermaLink="false">https://www.encona.com/posts/custom-statistics-for-anki-flashcard-reviews</guid><pubDate>Tue, 14 Jan 2025 16:02:08 GMT</pubDate><content:encoded>&lt;p&gt;Anki stores a record for each review. This powers the built-in stats page, which is quite limited. Luckily, it’s easy to get the data:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;File -&gt; Export&lt;/li&gt;
&lt;li&gt;Choose Anki Deck Package, Include Scheduling Information and Support older Anki versions
&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 646px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/6b2126a223c72c1e37fcd44eb922e316/27524/anki-export-options.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 37.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsTAAALEwEAmpwYAAABeElEQVQoz32STW/TQBBA/f/PXDj2wrkViAYRUKuk7SGViA/9wI3TJsF1ih1/7q7XNvCYNSC1UsvhaXZn5Tezs/ayLCNNU6qqGsjznFxyhYtCWZY0TYMx5kVaa4gLQ5QpvC/zOZdXVyQije7vCW5uWG82rByrFbHkuq7DWvssTWOht1w8WOaRxluKoJcOejlMt1tiEXVS9Yfs+7YdZK7Dl4RGhL86S5BYLrciDN5/YPnuLV/39wkODliNRtweHlIeH1NHEZXIaqVQ/8GdG4eWK88mJ/gnU/zTUxa+z269po5jmiShlZnausZI1PKB1vopTiixUpqy/hO989EngvFHrsdj4tmMzdkZ34TbyYTw6GiI6XSKkSJKrqj/duWE7kEao6ATesVPKx3m4ZJyGVKEIZnMM18sKIRc1sNe8nUQoOXRlAj+yfKiINslxLnmzYXl9bxlctfgGVfVDdchjzDweC1owcked+d+t+8PMdFOsee3vDpv+bww/Ab+81dB7JWJpQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/6b2126a223c72c1e37fcd44eb922e316/8ac56/anki-export-options.webp 240w,
/static/6b2126a223c72c1e37fcd44eb922e316/d3be9/anki-export-options.webp 480w,
/static/6b2126a223c72c1e37fcd44eb922e316/8c2f2/anki-export-options.webp 646w&quot;
              sizes=&quot;(max-width: 646px) 100vw, 646px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/6b2126a223c72c1e37fcd44eb922e316/8ff5a/anki-export-options.png 240w,
/static/6b2126a223c72c1e37fcd44eb922e316/e85cb/anki-export-options.png 480w,
/static/6b2126a223c72c1e37fcd44eb922e316/27524/anki-export-options.png 646w&quot;
            sizes=&quot;(max-width: 646px) 100vw, 646px&quot;
            type=&quot;image/png&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/6b2126a223c72c1e37fcd44eb922e316/27524/anki-export-options.png&quot;
            alt=&quot;Screenshot of Anki export options&quot;
            title=&quot;Screenshot of Anki export options&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Unzip the resulting file&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Extract the review log into a CSV:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;sqlite3 collection.anki21 -header -csv &lt;span class=&quot;token string&quot;&gt;&quot;SELECT * FROM revlog;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; output.csv&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;Load the CSV into pandas&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add date, datetime and week columns:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;df&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;datetime&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; pd&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;to_datetime&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;df&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;id&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; unit&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;ms&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
df&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;date&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; df&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;datetime&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;date&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Now you can do things like see the median number of cards per session, seconds per card etc. for a particular period:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;df&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;groupby&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;date&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;time&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;agg&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;sum&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;count&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;assign&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;minutes&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;lambda&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;sum&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;astype&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;assign&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;seconds_per_card&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;lambda&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;sum&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;count&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;astype&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;tail&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;21&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;median&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;aggregation&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#aggregation&quot; aria-label=&quot;aggregation permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Aggregation&lt;/h2&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;df&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;groupby&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;date&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;time&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;agg&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;sum&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;count&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;assign&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;minutes&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;lambda&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;sum&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;assign&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;seconds_per_card&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;lambda&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;sum&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;count&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;tail&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;21&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;custom-percentiles-instead-of-histogram&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#custom-percentiles-instead-of-histogram&quot; aria-label=&quot;custom percentiles instead of histogram permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Custom percentiles (instead of histogram)&lt;/h2&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;custom_percentiles &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0.01&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.05&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.25&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.75&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.9&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.95&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.99&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
df&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;values&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;describe&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;percentiles&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;custom_percentiles&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[College textbook scams]]></title><description><![CDATA[College textbooks aren't just books any more - they're a wrapper for a bundle of services for the buyer and the professor]]></description><link>https://www.encona.com/posts/college-textbook-scams</link><guid isPermaLink="false">https://www.encona.com/posts/college-textbook-scams</guid><pubDate>Fri, 23 Apr 2021 20:17:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;college-textbooks-arent-just-books-any-more&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#college-textbooks-arent-just-books-any-more&quot; aria-label=&quot;college textbooks arent just books any more permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;College textbooks aren’t just books any more&lt;/h2&gt;
&lt;p&gt;When I went to university (a long time ago…) books were just books. Paper with printed words. When you bought a book, you were entitled to read the book. Nothing more, nothing less.&lt;/p&gt;
&lt;p&gt;Today’s textbooks are often a wrapper for a bundle of services. When someone buys a textbook, they’re often buying:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a physical book&lt;/li&gt;
&lt;li&gt;a token to access some other services&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;students-are-forced-to-buy-a-bundle-of-services&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#students-are-forced-to-buy-a-bundle-of-services&quot; aria-label=&quot;students are forced to buy a bundle of services permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Students are forced to buy a bundle of services&lt;/h2&gt;
&lt;p&gt;This might seem fine, except when you consider that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the services can only be used once, or by one student&lt;/li&gt;
&lt;li&gt;the services are often not for the benefit of the student, but for that of the professor (more on that below)&lt;/li&gt;
&lt;li&gt;the student is forced to buy this bundle, even if they already know everything the book teaches&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;the-background&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-background&quot; aria-label=&quot;the background permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The background&lt;/h2&gt;
&lt;p&gt;Let’s say I’m a professor, and it is an accepted part of my job to set homework, and provide feedback on that homework in the form of grades (or a % score) and some comments.&lt;/p&gt;
&lt;p&gt;Assume the subject I’m teaching doesn’t change much year to year (as far as undergraduates are concerned anyway). So for the last 10 years my course has been based on the same edition of the same textbook. As it’s now 10 years old, there are plenty of used copies available for 20 USD, even though new copies are 50 USD.&lt;/p&gt;
&lt;h2 id=&quot;the-offer&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-offer&quot; aria-label=&quot;the offer permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The offer&lt;/h2&gt;
&lt;p&gt;Let’s say a publisher approaches me with an offer that provides ME with more value: a textbook that comes with a code for online access to homework and automatic grading, good for one student for one year only. The catch? The students need to buy the textbook for 50 USD and, because it’s the only way to get a code to allow students to submit homework, they can’t buy a used copy.&lt;/p&gt;
&lt;p&gt;If I accept, then:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;my students need to shell out 50 USD each for a new textbook (vs. the existing one which would have been effectively free, as they could recoup their 20 USD outlay by selling it at the end of the year)&lt;/li&gt;
&lt;li&gt;I get paid the same, but the textbook company takes over some of my work (and I still get paid the same!)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;the-incentive-and-the-bribe&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-incentive-and-the-bribe&quot; aria-label=&quot;the incentive and the bribe permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The incentive and the bribe&lt;/h2&gt;
&lt;p&gt;If I’m the professor in this case, the textbook is offering me something of value (doing some work that I’m already being paid for through students’ tuition fees paid to my employer) in exchange for me forcing my students to give the textbook company money.&lt;/p&gt;
&lt;p&gt;This seems no different from a bribe: the publisher will do all your homework marking, if the professor will use their position of authority to funnel student money to the publisher.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Debits and Credits]]></title><description><![CDATA[Debits and credits are easy to understand]]></description><link>https://www.encona.com/posts/debits-and-credits</link><guid isPermaLink="false">https://www.encona.com/posts/debits-and-credits</guid><pubDate>Fri, 23 Apr 2021 19:36:13 GMT</pubDate><content:encoded>&lt;h2 id=&quot;people-are-confused-by-debits-and-credits&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#people-are-confused-by-debits-and-credits&quot; aria-label=&quot;people are confused by debits and credits permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;People are confused by debits and credits&lt;/h2&gt;
&lt;p&gt;A lot of people (approximately all people who are not accountants!) don’t understand debits and credits. I suspect even many professional book-keepers and accountants just memorise some rules. It’s easier than trying to understand things, especially when many explanations are difficult to understand, or just plain wrong.&lt;/p&gt;
&lt;h2 id=&quot;there-is-no-need-to-be-confused-and-no-need-to-memorise-anything&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#there-is-no-need-to-be-confused-and-no-need-to-memorise-anything&quot; aria-label=&quot;there is no need to be confused and no need to memorise anything permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;There is no need to be confused, and no need to memorise anything&lt;/h2&gt;
&lt;p&gt;You don’t need to memorize which accounts are negative and which are positive. Just relate them to the English words ‘debtor’ (someone who owes money) and ‘creditor’ (someone who is owed money), and you can work out the right entries for any transaction.&lt;/p&gt;
&lt;p&gt;You credit (CR) an account when you’re recording:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;an increase in the amount your company owes, or&lt;/li&gt;
&lt;li&gt;(equivalent) a decrease in the amount some other entity owes your company&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The other entity could be a supplier, a customer, or one of your own shareholders. Shareholders are just like creditors, except that they’re last in line.&lt;/p&gt;
&lt;p&gt;Examples of credits that can be identified by the above rule:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A customer pays you some money they owed you: CR &lt;em&gt;Assets - Accounts Receivable&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;A supplier sends you an invoice: CR &lt;em&gt;Assets - Accounts Payable&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;You send an invoice to a customer: CR &lt;em&gt;Revenue&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The last example might be confusing at first. Why is revenue like something you ‘owe’ someone? Because any profit the company you make does not really belong to the company, but to the shareholders.&lt;/p&gt;
&lt;p&gt;If you can work out whether one side of a transaction is a debit or a credit, you know the other side is the opposite. So, for the above transactions:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;CR&lt;/th&gt;
&lt;th&gt;DR&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Assets - Accounts Receivable&lt;/td&gt;
&lt;td&gt;Cash&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Assets - Accounts Payable&lt;/td&gt;
&lt;td&gt;Expenses&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Revenue&lt;/td&gt;
&lt;td&gt;Assets - Accounts Receivable&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;</content:encoded></item><item><title><![CDATA[Building AGI Using Language Models]]></title><description><![CDATA[Summary of an excellent article about Artificial General Intelligence]]></description><link>https://www.encona.com/posts/building-agi-using-language-models</link><guid isPermaLink="false">https://www.encona.com/posts/building-agi-using-language-models</guid><pubDate>Fri, 23 Apr 2021 19:31:44 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://bmk.sh/2020/08/17/Building-AGI-Using-Language-Models/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;This article&lt;/a&gt; is great. You should go and read it. Afterwards, if you’re scratching your head about the overall point, this might be helpful:&lt;/p&gt;
&lt;p&gt;tl;dr Language models like GPT-3 include incorporate some model of the world. That’s why they can generate plausible-sounding text. Future language models will be larger, more powerful, and have more complete models of the world. So we will be able to ask the language model questions, like ‘what will happen if we do X?‘. By compiling the answers to many such questions, we can figure out the best[0] thing to do.&lt;/p&gt;
&lt;p&gt;[0] Assuming you have some utility function you can maximize.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Reading epub files]]></title><description><![CDATA[The best ePub readers]]></description><link>https://www.encona.com/posts/reading-epub-files</link><guid isPermaLink="false">https://www.encona.com/posts/reading-epub-files</guid><pubDate>Fri, 23 Apr 2021 19:06:09 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://www.w3.org/publishing/epub32/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;ePub&lt;/a&gt; is a popular format for electronic books. Just like the mobipocket format (used for Kindle books), ePub is a container for HTML and CSS. For this reason, you’d think that reading ePub books on any platform would be as easy as opening a web page.&lt;/p&gt;
&lt;p&gt;Sadly, this isn’t the case. On any platform, it’s easy to find an ePub reader, but you won’t necessarily get a good one. An ePub is much easier to read if the reader renders sharp text without distractions, and lets you change the font size and padding.&lt;/p&gt;
&lt;p&gt;My favourites for each major platform:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Linux: &lt;a href=&quot;https://johnfactotum.github.io/foliate/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Foliate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;MacOS or iOS: Books (formerly known as Apple iBooks, this comes pre-installed)&lt;/li&gt;
&lt;li&gt;Windows: &lt;a href=&quot;https://www.sumatrapdfreader.org/download-free-pdf-viewer.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Sumatra PDF&lt;/a&gt; (don’t let the name fool you!)&lt;/li&gt;
&lt;li&gt;Android: &lt;a href=&quot;https://play.google.com/store/apps/details?id=com.flyersoft.moonreader&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Moon+ Reader&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Monty Hall Problem]]></title><description><![CDATA[An intuitive explanation of the Monty Hall Problem]]></description><link>https://www.encona.com/posts/monty-hall-problem</link><guid isPermaLink="false">https://www.encona.com/posts/monty-hall-problem</guid><pubDate>Fri, 23 Apr 2021 18:53:03 GMT</pubDate><content:encoded>&lt;h2 id=&quot;the-game&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-game&quot; aria-label=&quot;the game permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The game&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&quot;https://en.wikipedia.org/wiki/Monty_Hall_problem&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Monty Hall Problem&lt;/a&gt; is a brain teaser that is (was?) often used in investment banking interviews. If you’ve never heard of it, here’s a summary:&lt;/p&gt;
&lt;p&gt;You’re on a TV game show. There are three closed doors:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;One door has a car, which will be your prize if you choose that door&lt;/li&gt;
&lt;li&gt;The other two doors each have a donkey&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The aim of the game is to choose the door with the car. The game mechanics are thus:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;You choose a door&lt;/li&gt;
&lt;li&gt;Monty (the host) opens one of the other two doors, revealing a donkey.&lt;/li&gt;
&lt;li&gt;Now there are two unopened doors. You choose whether to stick with your original choice, or switch to the other unopened door.&lt;/li&gt;
&lt;li&gt;All is revealed.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The question is: at step 3, should you switch?&lt;/p&gt;
&lt;h2 id=&quot;the-mistake&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-mistake&quot; aria-label=&quot;the mistake permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The mistake&lt;/h2&gt;
&lt;p&gt;Most people, when encountering this problem for the first time, think there’s no benefit to switching. But, oddly, this isn’t right.&lt;/p&gt;
&lt;h2 id=&quot;another-way-to-think-about-it&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#another-way-to-think-about-it&quot; aria-label=&quot;another way to think about it permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Another way to think about it&lt;/h2&gt;
&lt;p&gt;Assuming you understand the rule (that Monty will always open a door you didn’t choose, and that door always has a donkey behind it), then one way to understand the game is:&lt;/p&gt;
&lt;p&gt;You can choose to have:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The most valuable prize that’s behind door A, or&lt;/li&gt;
&lt;li&gt;The most valuable prize that’s behind doors B or C&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When you look at it this way, it’s obvious that you would rather have the most valuable prize from the ‘other’ doors, and the way to do that is to switch.&lt;/p&gt;
&lt;p&gt;The intuition above is easier than trying to compute probabilities, and thinking about whether the probabilities change once Monty opens the door with the donkey.&lt;/p&gt;
&lt;p&gt;If you need convincing, here’s a simple python script based on the above:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; random

donkey &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
car &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# car is worth more than a donkey&lt;/span&gt;
prizes &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;car&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; donkey&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; donkey&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# there&apos;s always exactly one car&lt;/span&gt;
N &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000000&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;pick_a_door&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;prizes&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    random&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;shuffle&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;prizes&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    my_pick&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;other_doors &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; prizes
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;my_pick&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; other_doors&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;keep_or_swap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;my_picks&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; keep&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; keep&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; my_picks&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# if you switch, and one of the other doors had the car, you&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# will definitely get it, so you get the max() of those two doors&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;my_picks&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;keep_or_swap&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pick_a_door&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;prizes&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; N&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;keep_or_swap&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pick_a_door&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;prizes&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; keep&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; N&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you’re still thinking about whether the probabilities change, consider whether ‘Monty opens a door with a donkey behind it’ is new information. It’s not because he always does that. And the two doors you picked are fungible/identical except for physical position, as both are in the set of doors you didn’t pick. So which one he opens is irrelevant.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Central Bank Digital Currencies: A common misunderstanding]]></title><description><![CDATA[If you're living in 2021, and think you already have digital dollars or pounds, you're probably wrong.]]></description><link>https://www.encona.com/posts/central-bank-digital-currencies-misunderstanding</link><guid isPermaLink="false">https://www.encona.com/posts/central-bank-digital-currencies-misunderstanding</guid><pubDate>Fri, 23 Apr 2021 18:05:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;there-has-been-a-lot-of-talk-recently-about-central-bank-digital-currencies-cbdcs&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#there-has-been-a-lot-of-talk-recently-about-central-bank-digital-currencies-cbdcs&quot; aria-label=&quot;there has been a lot of talk recently about central bank digital currencies cbdcs permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;There has been a lot of talk recently about Central Bank Digital Currencies (CBDCs)&lt;/h2&gt;
&lt;p&gt;Central banks around the world, including those in China (People’s Bank of China) and the UK (Bank of England) have shared plans or ideas about how they will make their currencies digital.&lt;/p&gt;
&lt;p&gt;The idea of a digital pound (or digital Yuan, or digital dollar) is often misunderstood. Many people have virtually stopped using cash:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In China, people use AliPay or WeChat for virtually all daily transactions&lt;/li&gt;
&lt;li&gt;In the UK and US, people use credit/debit cards to pay businesses, and apps like Venmo or Zelle to pay individuals&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;peoples-day-to-day-experience-with-money-is-that-its-all-digital-numbers-on-computers-so-how-might-cbdcs-be-any-different&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#peoples-day-to-day-experience-with-money-is-that-its-all-digital-numbers-on-computers-so-how-might-cbdcs-be-any-different&quot; aria-label=&quot;peoples day to day experience with money is that its all digital numbers on computers so how might cbdcs be any different permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;People’s day-to-day experience with money is that it’s all digital: numbers on computers. So how might CBDCs be any different?&lt;/h2&gt;
&lt;p&gt;Let’s take a simple transaction: I send money from my UK bank account to someone else’s UK bank account. This sure seems like I’m transferring digital pounds. But this transaction simply transfers an obligation (a debt) denominated in pounds between parties. Before the transaction, the bank owed me some money. Now, the bank (or some other bank) owes a different customer some money. No actual pounds (i.e. no central bank currency) changed hands.&lt;/p&gt;
&lt;h2 id=&quot;the-fact-that-a-payment-happens-electronically-doesnt-mean-that-the-thing-youre-trading-is-digital&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-fact-that-a-payment-happens-electronically-doesnt-mean-that-the-thing-youre-trading-is-digital&quot; aria-label=&quot;the fact that a payment happens electronically doesnt mean that the thing youre trading is digital permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;strong&gt;The fact that a payment happens electronically doesn’t mean that the thing you’re trading is digital&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;You can trade ‘pork bellies futures’ quickly, and using nothing but a computer. But no one claims pork bellies are digital. When people trade, they’re effectively trading IOUs, and not the actual bellies.&lt;/p&gt;
&lt;h2 id=&quot;cbdcs-already-exist-but-not-everyone-can-use-them&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#cbdcs-already-exist-but-not-everyone-can-use-them&quot; aria-label=&quot;cbdcs already exist but not everyone can use them permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;CBDCs already exist, but not everyone can use them&lt;/h2&gt;
&lt;p&gt;Retail banks and other important financial institutions already have digital central bank money. In the UK, these are called ‘central bank reserves’. They’re just like bank accounts that you and I have, except that the ‘bank’ where the account is held is the Bank of England, i.e. the entity that issues the money in which the account is denominated.&lt;/p&gt;
&lt;p&gt;If you have a piece of paper signed by the Bank of England governor, saying that the Bank owes you 50 GBP, this is actually 50 GBP. The same goes for a numbers on a screen (say if the Bank of England gave you an account, along with a way to see your balance online). But the ‘money’ shown in your regular bank account is not central bank money: it’s an obligation/debt of your bank (HSBC, Barclays, etc.).&lt;/p&gt;
&lt;p&gt;Bank balances are similar, but not the same&lt;/p&gt;
&lt;p&gt;Maybe you’re not convinced by what I’ve written above. Maybe you think that, because the money in your current account (aka checking account) is just as useful as central bank money, that it really isn’t any different.&lt;/p&gt;
&lt;p&gt;If so, consider this question: If you have 200k GBP in your current account, and the bank goes bust, do you still own 200k GBP? (BTW I chose 200k GBP as as the figure here, because then any arguments about FSCS, the UK’s FDIC equivalent, are irrelevant.)&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;A Central Bank Digital Currency would allow individuals to hold and transfer ‘real’ pounds (M0). Currently, only banks and selected other financial institutions can open accounts at the Bank of England.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Learning Python for Data Analysis]]></title><description><![CDATA[Short, suggested curriculum based on a couple of books. For someone tech-savvy but with no programming background.]]></description><link>https://www.encona.com/posts/python-for-data-analysis</link><guid isPermaLink="false">https://www.encona.com/posts/python-for-data-analysis</guid><pubDate>Mon, 05 Oct 2020 02:11:00 GMT</pubDate><content:encoded>&lt;p&gt;A friend-of-a-friend who recently graduated from a great university with a non-STEM degree asked how to learn python for data analysis and data science. After understanding their level (zero programming experience) and initial goal (be able to analyse structured data in Python), I suggested they work through these resources, in this order, doing all exercises suggested in the text:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Learn Python 3 the Hard Way, exercises 1-39&lt;/li&gt;
&lt;li&gt;Data Science from Scratch, chapters 1-3&lt;/li&gt;
&lt;li&gt;Pandas for Data Analysis, chapters 1-6&lt;/li&gt;
&lt;li&gt;These &lt;a href=&quot;https://github.com/guipsamora/pandas_exercises&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;pandas exercises&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Pandas for Data Analysis, chapters 7-12&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I also told them…&lt;/p&gt;
&lt;p&gt;If, after the first two items above, you want a slower introduction to Python, &lt;a href=&quot;https://www.coursera.org/specializations/python&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;this coursera course&lt;/a&gt; would do the trick.&lt;/p&gt;
&lt;p&gt;The Coursera course on Data Analysis covers some of the same ground as the above, and has good reviews. I’ve not used it myself so can’t say how the sequence of topics covered is different.&lt;/p&gt;
&lt;p&gt;Most important:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Do the exercises. You will not learn otherwise.&lt;/li&gt;
&lt;li&gt;Find some data you want to analyse yourself, and apply what you’ve learned to find answers to questions&lt;/li&gt;
&lt;li&gt;Next time you reach for Excel to analyse some data, try to do the same analysis using python/pandas&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Finding a technical co-founder]]></title><description><![CDATA[Generic advice for finding a technical co-founder]]></description><link>https://www.encona.com/posts/finding-a-technical-co-founder</link><guid isPermaLink="false">https://www.encona.com/posts/finding-a-technical-co-founder</guid><pubDate>Mon, 05 Oct 2020 00:49:00 GMT</pubDate><content:encoded>&lt;p&gt;A smart friend recently emailed me about a business idea, and asked for my advice. I realised the reply I sent would be equally helpful (or unhelpful!) to anyone in a similar situation, so here it is:&lt;/p&gt;
&lt;p&gt;Glad to hear you’ve found something you want to work on! Exciting times ahead.&lt;/p&gt;
&lt;p&gt;I’ve written some initial thoughts and included some links below. But it’s probably best if we find some time to talk. My calendar is &lt;a href=&quot;...&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Regarding finding a technical co-founder, a few immediate thoughts:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;There are many more people who have an idea but little/no ability to execute independently, than there are engineers who lack an idea. So you will need luck and/or a compelling pitch.&lt;/li&gt;
&lt;li&gt;When you say ‘technical co-founder’, I assume you mean ‘engineer willing to work with zero cash compensation’. (Maybe I’m mistaken, but this is usually what people mean.) Given that good engineers are in high demand (at least here in North America), the opportunity cost needs to be worthwhile. So you need to be willing to see them as a partner, with a decent chunk of equity. Many people think that just by bringing an idea, they should have 95% of the initial equity, whilst the technical co-founder (whose skills are equally, if not more, valuable) should get 5%. So it’s important to be realistic about this. When you co-found a company with people, it’s important for &lt;a href=&quot;https://avc.com/2018/03/founder-vesting/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;founders’ equity to vest&lt;/a&gt;. Otherwise, if one person leaves, they have a large chunk of equity even though most of the work is still to be done.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The most impactful things you might do to to attract and close a co-founder:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;have committed seed money (either your own, or from an angel or VC)&lt;/li&gt;
&lt;li&gt;have built a prototype of the thing that you can shop around to potential customers&lt;/li&gt;
&lt;li&gt;have several years of domain experience in the specific industry or problem space, and a network of people you can tap for learning about customer needs, or sales pitches&lt;/li&gt;
&lt;li&gt;have some potential customers who have signed letters of intent, or have given you money&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The more of the items in #3 you have, the higher chance that someone good would agree to be a co-founder with you. Those things will appear valuable to a potential co-founder exactly because they’re valuable to the business (i.e. increase the chance of the business succeeding).&lt;/p&gt;
&lt;p&gt;As far as sourcing people, I don’t know anyone who’s looking for an opportunity like this right now. One good place to find people is Hacker News (&lt;a href=&quot;https://news.ycombinator.com/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;https://news.ycombinator.com&lt;/a&gt;)​, a discussion forum for startup/engineer folks. It’s worth spending an hour reading:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;how other people have pitched when looking for technical co-founders&lt;/li&gt;
&lt;li&gt;how engineers have reacted&lt;/li&gt;
&lt;li&gt;how (some) engineers think about the decision&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can search previous discussions here:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://hn.algolia.com/?dateRange=all&amp;#x26;page=0&amp;#x26;prefix=false&amp;#x26;query=Technical%20co-founder&amp;#x26;sort=byPopularity&amp;#x26;type=story&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;https://hn.algolia.com/?​dateRange=all&amp;#x26;page=0&amp;#x26;prefix=​false&amp;#x26;query=Technical%20co-​founder&amp;#x26;sort=byPopularity&amp;#x26;​type=story&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;and here:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://hn.algolia.com/?dateRange=all&amp;#x26;page=0&amp;#x26;prefix=false&amp;#x26;query=Technical%20co-founder&amp;#x26;sort=byPopularity&amp;#x26;type=comment&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;https://hn.algolia.com/?​dateRange=all&amp;#x26;page=0&amp;#x26;prefix=​false&amp;#x26;query=Technical%20co-​founder&amp;#x26;sort=byPopularity&amp;#x26;​type=comment&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Some common perspectives worth reading:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://humbledmba.com/please-please-please-stop-asking-how-to-find&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;https://humbledmba.com/please-​please-please-stop-asking-how-​to-find&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://news.ycombinator.com/item?id=2714437&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;https://news.ycombinator.com/​item?id=2714437&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://news.ycombinator.com/item?id=2717153&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;https://news.ycombinator.com/​item?id=2717153&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Understanding your target co-founder profile better will help you refine your pitch, anticipate objections and, most importantly, help focus your current effort on things that are most valuable. Those things will be valuable to a potential co-founder precisely because they’re valuable for your startup.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Learning about Machine Learning]]></title><description><![CDATA[A short list of great books/courses for engineers who want to learn about machine learning]]></description><link>https://www.encona.com/posts/learning-ml</link><guid isPermaLink="false">https://www.encona.com/posts/learning-ml</guid><pubDate>Sun, 04 Oct 2020 23:57:00 GMT</pubDate><content:encoded>&lt;p&gt;A friend recently asked for pointers to learn about machine learning. I’m not an expert, but have spent a bunch of time learning and experimenting, using many different resources. The list below is for people who can already code well enough to build products, but have little/no background in machine learning.&lt;/p&gt;
&lt;p&gt;I wrote this list in Fall 2020.&lt;/p&gt;
&lt;p&gt;To learn how to do stuff:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;(free online course; excellent pedagogy) &lt;a href=&quot;https://course.fast.ai/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Practical Deep Learning for Coders&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To learn about what’s possible:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.amazon.com/Hundred-Page-Machine-Learning-Book/dp/199957950X&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;The Hundred Page Machine Learning Book&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To learn from fundamentals - books:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.amazon.com/Data-Science-Scratch-Principles-Python/dp/1492041130&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Data Science from Scratch (2nd edition)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.amazon.com/gp/product/B07XGF2G87&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Hands-On Machine Learning with Scikit-Learn, Keras, and TensorFlow (2nd Edition)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To learn from fundamentals - video courses:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.coursera.org/learn/machine-learning&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Machine Learning&lt;/a&gt; (this is Andrew Ng’s original machine learning course, and has stood the test of time). NOTE: even though the course says to use Matlab/Octave, you can do all the exercises using python/pandas, using &lt;a href=&quot;https://github.com/dibgerge/ml-coursera-python-assignments%3E&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;these jupyter notebooks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.coursera.org/specializations/deep-learning&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Deep Learning Specialization&lt;/a&gt; (this is newer, and is less theoretical than the one above, with more focus on modern tools)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you’re not sure where to start, start with Deep Learning for Coders.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Converting a server-rendered Python app into a single page Progressive Web App]]></title><description><![CDATA[My experience translating a very simple server-rendered app into a front-end-only PWA]]></description><link>https://www.encona.com/posts/python-to-js-pwa</link><guid isPermaLink="false">https://www.encona.com/posts/python-to-js-pwa</guid><pubDate>Wed, 29 May 2019 07:25:57 GMT</pubDate><content:encoded>&lt;p&gt;I wrote before about a simple web app I created to teach my son maths. You can find the &lt;a href=&quot;/posts/doman-dots/&quot;&gt;article here&lt;/a&gt;, the &lt;a href=&quot;https://github.com/rahimnathwani/doman-web&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;code here&lt;/a&gt;, and the &lt;a href=&quot;https://doman-236804.appspot.com/5/10&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;live app here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Looking at the code, you might wonder: why would you require server round-trip for every new card? Why  can’t you just generate the next set of random dots on the client side?&lt;/p&gt;
&lt;p&gt;I had the same thought, so I set about translating the code to client-side JavaScript. If you’re impatient, you can see &lt;a href=&quot;https://dots.twilam.com/#1/5&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;the result here&lt;/a&gt;. If you want to know what I did, it was mostly these pretty painless steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Paste the existing code into a &lt;code class=&quot;language-text&quot;&gt;&amp;lt;SCRIPT&amp;gt;&lt;/code&gt; tag in an HTML file&lt;/li&gt;
&lt;li&gt;Add parentheses around &lt;code class=&quot;language-text&quot;&gt;if&lt;/code&gt; conditions&lt;/li&gt;
&lt;li&gt;Change the format of function definitions and if clauses, by using &lt;code class=&quot;language-text&quot;&gt;{}&lt;/code&gt; instead of &lt;code class=&quot;language-text&quot;&gt;:&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Convert list comprehensions into &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt; loops&lt;/li&gt;
&lt;li&gt;Instead of assembling the DOM using string interpolation, do it piece by piece using &lt;code class=&quot;language-text&quot;&gt;document.createElementNS()&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;.setAttribute()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Replace some &lt;code class=&quot;language-text&quot;&gt;random.normalvariate(0,1)&lt;/code&gt; with &lt;code class=&quot;language-text&quot;&gt;Math.random() * 2 - 1&lt;/code&gt;, which doesn’t do the same thing, but works well enough&lt;/li&gt;
&lt;li&gt;A very small amount of other cleanup&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The above was enough to make the app work, but I was unhappy with needing to enter the min/max values in the URL. So I also used the excellent &lt;a href=&quot;https://tailwindcss.com/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Tailwind CSS&lt;/a&gt; to add a footer and some buttons to increment/decrement these values. I wanted two-way binding between the values shown in the UI, and the values in the URL. Using a sophisticated mechanism (or a library) for such a simple app would be overkill, so I wrote some ugly code instead:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;get_values_from_hash&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;location&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hash&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;lower&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; upper&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; location&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hash&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;#&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        lower &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;parseInt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;lower&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        upper &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;parseInt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;upper&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;lower&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; upper&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;lower&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; upper&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;set_values&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;lower&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; upper&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      location&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hash &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;#&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; lower&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; upper&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;lower&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; lower&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;upper&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; upper&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;adjust_lower&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;lower&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; upper&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;get_values_from_hash&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      lower &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lower &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      upper &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;upper&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lower &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;set_values&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;lower&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; upper&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;adjust_upper&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;lower&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; upper&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;get_values_from_hash&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      upper &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; upper &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      lower &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;lower&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; upper &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;set_values&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;lower&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; upper&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now the code doesn’t need a server, I figured I should make it work offline, and installable as a PWA. It turned out this was pretty simple, using some &lt;a href=&quot;https://dots.twilam.com/sw.js&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;example service worker code from Google&lt;/a&gt;, and adding a simple &lt;a href=&quot;https://dots.twilam.com/manifest.json&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;web manifest&lt;/a&gt; and icon.&lt;/p&gt;
&lt;p&gt;There’s one thing left to do: make the bottom bar stick to the bottom of the screen. Currently, I’m using the CSS style &lt;code class=&quot;language-text&quot;&gt;height: 100vh&lt;/code&gt; via Tailwind’s &lt;code class=&quot;language-text&quot;&gt;h-screen&lt;/code&gt; utility class. This works fine on desktop, and when the app is installed and launched via a mobile launcher icon.&lt;/p&gt;
&lt;p&gt;But, when the app is opened on a mobile web browser (e.g. Chrome on Android), the visible part of the page is shorter than the screen (due to the address bar and browser navigation bar), so part/all of my bottom bar scrolls off the page. This is a well known problem with using &lt;code class=&quot;language-text&quot;&gt;height: 100vh&lt;/code&gt; and there are lots of workarounds. I had a quick look, and none of the workarounds I saw look elegant, so I’ll fix this another day.&lt;/p&gt;
&lt;p&gt;The app is at &lt;a href=&quot;https://dots.twilam.com/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;https://dots.twilam.com/&lt;/a&gt;. To see the source, just &lt;em&gt;view source&lt;/em&gt; in your browser.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Persistent State in Vue/Svelte NativeScript apps]]></title><description><![CDATA[Alternatives for keeping state in NativeScript apps, that persists after an app is quit and reloaded.]]></description><link>https://www.encona.com/posts/nativescript-persist-state</link><guid isPermaLink="false">https://www.encona.com/posts/nativescript-persist-state</guid><pubDate>Thu, 09 May 2019 16:13:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;what-is-nativescript&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#what-is-nativescript&quot; aria-label=&quot;what is nativescript permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;What is NativeScript?&lt;/h2&gt;
&lt;p&gt;NativeScript is a framework for building mobile apps with JavaScript. At the time of writing, there’s official support for Angular, Vue and plain JavaScript/TypeScript.&lt;/p&gt;
&lt;p&gt;There’s also a community project to allow you to build native apps with Svelte v3. Svelte has a beautiful and detailed tutorial that is run entirely in the browser. Be careful if you click this link: once you start the tutorial you’ll want to spend the time to get to the end.&lt;/p&gt;
&lt;h2 id=&quot;what-do-i-mean-by-persistence&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#what-do-i-mean-by-persistence&quot; aria-label=&quot;what do i mean by persistence permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;What do I mean by persistence?&lt;/h2&gt;
&lt;p&gt;Let’s assume we have a ‘to do’ app. When a new item is added, we would like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The new item to be shown on the screen, in the list of todos&lt;/li&gt;
&lt;li&gt;The new item to be stored somewhere, so it can be used by other parts of the app (e.g. maybe we have a ‘summary’ screen which shows stats about how many todos we have)&lt;/li&gt;
&lt;li&gt;Be saved on the device, so that when the app is quit and re-opened, all our todos are still intact&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;how-do-we-persist-things-now&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#how-do-we-persist-things-now&quot; aria-label=&quot;how do we persist things now permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;How do we persist things now?&lt;/h2&gt;
&lt;h3 id=&quot;in-components&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#in-components&quot; aria-label=&quot;in components permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;In components&lt;/h3&gt;
&lt;p&gt;If you’re using Vue, then your state is maintained in the component tree. You know it’s there, because otherwise the data shown on your screen would never change. Many people use Vue to add a little interactivity to specific pages/forms in a traditional web app. If that’s how you use Vue, then you probably persist your data by POSTing the results to a form or something, and you don’t need to worry about maintaining state in some clean way.&lt;/p&gt;
&lt;h3 id=&quot;using-a-global-state-store&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#using-a-global-state-store&quot; aria-label=&quot;using a global state store permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Using a global state store&lt;/h3&gt;
&lt;p&gt;If you’re developing a single-page app (SPA) or more complicated Vue application, then you’re probably using Vuex to maintain a single state across all your components. (For those new to Vue: Vuex does a similar job to Redux or MobX).&lt;/p&gt;
&lt;h2 id=&quot;so-how-do-we-keep-our-state-even-when-the-app-quits&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#so-how-do-we-keep-our-state-even-when-the-app-quits&quot; aria-label=&quot;so how do we keep our state even when the app quits permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;So how do we keep our state even when the app quits?&lt;/h2&gt;
&lt;p&gt;When you’re developing for a browser, you use the LocalStorage key-value store. That’s fine as it goes, but you probably don’t want to have calls to &lt;code class=&quot;language-text&quot;&gt;LocalStorage.setItem&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;LocalStorage.getItem&lt;/code&gt; all over your code.&lt;/p&gt;
&lt;p&gt;If the application state (stored in e.g. Vuex) isn’t too large, then you might want to persist the whole thing in LocalStorage. That’s where a couple of handy packages come in:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/championswimmer/vuex-persist&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Vuex-persist&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/robinvdvleuten/vuex-persistedstate&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;vuex-persistedstate&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Both of these packages will automatically sync your Vuex store with the browser’s LocalStorage&lt;/p&gt;
&lt;h2 id=&quot;can-we-use-the-same-approach-in-native-apps&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#can-we-use-the-same-approach-in-native-apps&quot; aria-label=&quot;can we use the same approach in native apps permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Can we use the same approach in native apps?&lt;/h2&gt;
&lt;p&gt;Almost. Native apps developed with NativeScript don’t have LocalStorage. Thankfully, there’s a package that fixes that:  &lt;a href=&quot;https://www.npmjs.com/package/nativescript-localstorage&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;nativescript-localstorage&lt;/a&gt;. After importing this package, you can do &lt;code class=&quot;language-text&quot;&gt;LocalStorage.setItem&lt;/code&gt; etc. Under the hood, it uses file system access to create and maintain a file called &lt;code class=&quot;language-text&quot;&gt;localStorage.db&lt;/code&gt; which contains a JSON string of your app’s state.&lt;/p&gt;
&lt;h2 id=&quot;what-about-svelte&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#what-about-svelte&quot; aria-label=&quot;what about svelte permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;What about Svelte?&lt;/h2&gt;
&lt;p&gt;There’s a nice example of how to do this with the previous version of svelte. The code below is from &lt;code class=&quot;language-text&quot;&gt;https://github.com/sveltejs/template-store&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useLocalStorage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;store&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; json &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; localStorage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;json&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		store&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;json&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	store&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;state&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; current &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		localStorage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;current&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This code does two things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;When it’s first imported, it checks if the old state was stored in LocalStorage. If so, it parses it adds it into the store.&lt;/li&gt;
&lt;li&gt;Whenever the state changes (&lt;code class=&quot;language-text&quot;&gt;store.on&lt;/code&gt;), it writes the entire state to a JSON string, and writes it to local storage again.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To make it work, this file needs to run once after the store is created. From main.js in the same repo as above:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;import { Store } from &amp;#39;svelte/store.js&amp;#39;;
import useLocalStorage from &amp;#39;./useLocalStorage.js&amp;#39;;

const store = new Store({
	name: &amp;#39;world&amp;#39;
});
useLocalStorage(store, &amp;#39;my-app&amp;#39;);&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;All that is needed to make the above work in a NativeScript app is to add &lt;code class=&quot;language-text&quot;&gt;import localStorage from &amp;#39;nativescript-localstorage&amp;#39;;&lt;/code&gt; before using &lt;code class=&quot;language-text&quot;&gt;localStorage&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The API for Svelte has changed a lot in the run-up to v3, and &lt;code class=&quot;language-text&quot;&gt;on&lt;/code&gt; doesn’t appear in the documentation. However, you can use &lt;code class=&quot;language-text&quot;&gt;store.subscribe&lt;/code&gt; instead of &lt;code class=&quot;language-text&quot;&gt;store.on&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Here’s a &lt;a href=&quot;https://github.com/rahimnathwani/svelte-native-counter-with-persistence&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;repo with a simple Svelte Native app with persistent state&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Quick Add for Monica CRM: A simple app I developed]]></title><description><![CDATA[I recently started using Monica CRM, and developed this app to make it easier to add new contacts from my phone.]]></description><link>https://www.encona.com/posts/monica-quick-add</link><guid isPermaLink="false">https://www.encona.com/posts/monica-quick-add</guid><pubDate>Mon, 06 May 2019 07:13:57 GMT</pubDate><content:encoded>&lt;p&gt;Monica CRM is a great open source contact manager, but at the time of writing (early 2019) there’s no official mobile client.&lt;/p&gt;
&lt;p&gt;I made a simple ‘Quick Add’ app for Android that works well for me. It might work well for you, too. &lt;a href=&quot;https://play.google.com/store/apps/details?id=com.twilam.monicacompanion&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Get it here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;why&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#why&quot; aria-label=&quot;why permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Why&lt;/h2&gt;
&lt;p&gt;Adding contacts via the web interface is a little slow for me, because:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;I live in China, and connections to servers outside China aren’t always fast or reliable.&lt;/li&gt;
&lt;li&gt;I often want to add notes for a new contact, and&lt;/li&gt;
&lt;li&gt;I sometimes want to add contacts when I have no internet connection, and this isn’t possible via the web UI.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;what-the-app-does&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#what-the-app-does&quot; aria-label=&quot;what the app does permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;What the app does&lt;/h2&gt;
&lt;p&gt;It lets you enter a person’s name (forename and surname) and some notes about that person. When you’re done, just tap ‘Save’ and you can continue adding someone else, or just do something else.&lt;/p&gt;
&lt;p&gt;There’s no waiting, because the new contact and new notes are uploaded in the background. And if you have a bad network connection (or are on a plane), the information is saved on your phone temporarily. Once you have an internet connection, it’s just one tap to upload all the pending contacts to Monica.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 360px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/ec2025311a8a167a498efcdeff933bb9/f21e7/screenshot_20190506-045633.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 205.41666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAApCAIAAAC6D54pAAAACXBIWXMAAAsTAAALEwEAmpwYAAACiUlEQVRIx+1WS08aURi9lhAV0RhDWBAWLIpFN102abtsF01/VNPaR6JoY4Lgoo9012hMNA0rEHcWqNTSFJD3Y8SBEZin48w4w/QbpqUmDRTaTReenNz5vnvumbl37uTOh8bGxmZmZqampmw228TEhMFguNYboE5PT9vtdovFMj4+jsxms8PhsFqtc3MuiFFfjIyMTE5Oulwup9NpMpmQe3nl0eOFp89fPFl45llb8/l8633h8XhWO/B6vUhV1baqKm1VbsN1OKBG4/TL4WGpVJQkURgSiGW5ahWv1eoMy3Fn/OA8B3OLpI5rRBUniEZLFCVBEAckDEY0TWMYhuM4ZBdDAlEUlUmnU6kUz/NDP7nZorCTOkWzsIjues4GXDPNsDXilGFYqQPthhI8Xxho2s1m42s8ns1mc7lcPB5PJpPQxmIxjuNAlvoC1ev1/f198BwdHYEnEo0WCgV9G6U/AREEEQmHM5l0IpH4dHAQSyUVRZFleaBp8/w5SVIUTZMUDXtOMiy8i0E/ElHHz5lAOMRWSf+AK/OV+cr8f5nlC+mviRhepHuwxQkkJ/RSwYju+Eo6b3uLwG4KfPi2cv91WZN8ReBlCXh3vYSc7rxzSeNNL+56Wbq+mNPSxfyNleKDdyf3XlVml/Kzy8X51Yo+bNZdAEmL3XlUpcTjDt9sfPicxmqcgpECzsqJMvExUSqT4glzka62wt9y0F+lpXKTz+IUBGBE+j++rSjbW5vHWAViOLShjUbC0KOrWKW8tfEeDmqIOZbNZtKapd1Gu7shnaG9vUAg2E0h3t7Z8fv9IASDu4FA4IcU0qDHvyodqJRGR0e7VQ+0tzrQU72nX5lkNBovm+c76Ka/4zsL3Qu5QBSIogAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/ec2025311a8a167a498efcdeff933bb9/8ac56/screenshot_20190506-045633.webp 240w,
/static/ec2025311a8a167a498efcdeff933bb9/a3012/screenshot_20190506-045633.webp 360w&quot;
              sizes=&quot;(max-width: 360px) 100vw, 360px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/ec2025311a8a167a498efcdeff933bb9/8ff5a/screenshot_20190506-045633.png 240w,
/static/ec2025311a8a167a498efcdeff933bb9/f21e7/screenshot_20190506-045633.png 360w&quot;
            sizes=&quot;(max-width: 360px) 100vw, 360px&quot;
            type=&quot;image/png&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/ec2025311a8a167a498efcdeff933bb9/f21e7/screenshot_20190506-045633.png&quot;
            alt=&quot;Mobile screenshot showing a form with three fields (forename, surname, notes) and a Save button&quot;
            title=&quot;Quick Add screen&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;how-you-connect-the-app-to-your-monica-account&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#how-you-connect-the-app-to-your-monica-account&quot; aria-label=&quot;how you connect the app to your monica account permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;How you connect the app to your Monica account&lt;/h2&gt;
&lt;p&gt;In order to use the app, you need a ‘Personal access token’, which you can create in the Monica web app. Just click the settings icon in the menu bar, then click ‘API’ on the left hand menu. You will see a button ‘Create New Token’ which generates a new token.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 360px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/13dc20be270e224d4689791820bb8a68/f21e7/screenshot_20190506-045652.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 205.41666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAApCAIAAAC6D54pAAAACXBIWXMAAAsTAAALEwEAmpwYAAAD+0lEQVRIx+1WS08bVxS+FCEewgghygKxYIME3VeI/pcmu/ZHRKpapV3QNkiVECkbpGZnVIcNEiBeaiulikJk4xRsnrU9b7/G87Jn5s7Y+a6vcYkxlZpuuuinozPneedxvzkzZGBgYGxsbGRkZHJycmhoqLe394P7gezo6OjU1NT4+Pjg4CAZHh6enp6emJiYm5uLRIYJIT3kXvT09EQikdnZ2ZmZGZyJfP9k6avH3yx++92jL758srS0urr6YxNP74DHl5eXf2hiZWWFBGG96vpBEIaNfwxCqf/s2U+x2M+p09Ozs7OTk5NXL1/+Fn99FI8n4olEnOHi4hzZWrXqeZ7rulDs4LrEcaqZbE4QREXVFEUtFktaPi9pmiyrsqLKsoKUqmmqljdMqyWGaRiWZdskl8tpmlZEU6lcKBRgF4pFRVULhaKm5UvlclnXVRUFJUTy+Txq4PJKAh8Fvu/TG9QD2ghpSGkYBMwIaD0MoDuAFhKGqAlgeb4fBr5quK8F+0RxoNOac6o6sBOi/SpnlSw3oKysDYJn0HawWs31dNurQBzPdj2z6pmOp0Nst3a7jzd3+LgcLN8IfFT/oThJyak4bj1gwbsgfjegEpuP0xoOtsWnfndgn2nQAuWK3Tylgl5LSPYbyZH0Wset/tVsWnZR1/WKUdIrxbJumCZ7eJ6Hm6/YrlH17JrLH6f3LlhzxTBFRVOxh8UyBEvg8dfr2C/aaNTZbtXrrS1sIrzhMSIERb+/eHF9fX15eXmWToOGqdRpMplMpVLQmUwGhAVtr66uUMODx8fHMMATUnNdcFCSZbAFBrglyzJcUJJp5ioao6eGFCJgqyCKCJqmSZCWJHCZ8U5RFPCUacZNBiyEHlEU1SaQxSrgKM6SBz0FQchmM7go9ORyWZwfl5rNZgU4NxCa4HForIVbwFMmcLAk6G0YBnzLsvQmbMsyKnpTKjyFGmQrTRdwHIdYpuXYTmu3acANKKPq265v1Zj4N1zoeDfIzRvjtwWUwPueBENk5w3T4LiHIPX9jjLyYF36NCp2yIOo+HBd+uy5/Plz+WG3AlazLpEPH190k3PIJ08zHy//OfH1+Thzu5SRX6+tX67MrnJ4weS+LBoJePbeQvDGvbcQ/1/g/+b/VnN73N3bzL84HGz63XIx8RC59VWg7Sz7VuGAgcQ/WgDGBd513oApeXR0tLW1xcclanAVGAm8GNxuYDgsLi5SNmsZ1tbW0uk0DD5lMTcxMWFgOWh0YphylxweHu7u7sZisb29vf39/YODg52dHdiIb25uRqPR7e1tRDY2Ng7uoPWPw/+g+vv7uQvAmJ+fX1hY4BFkCfnb36S+vr62Df1RE233Lt4CdWXvjzFEzHcAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/13dc20be270e224d4689791820bb8a68/8ac56/screenshot_20190506-045652.webp 240w,
/static/13dc20be270e224d4689791820bb8a68/a3012/screenshot_20190506-045652.webp 360w&quot;
              sizes=&quot;(max-width: 360px) 100vw, 360px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/13dc20be270e224d4689791820bb8a68/8ff5a/screenshot_20190506-045652.png 240w,
/static/13dc20be270e224d4689791820bb8a68/f21e7/screenshot_20190506-045652.png 360w&quot;
            sizes=&quot;(max-width: 360px) 100vw, 360px&quot;
            type=&quot;image/png&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/13dc20be270e224d4689791820bb8a68/f21e7/screenshot_20190506-045652.png&quot;
            alt=&quot;Mobile screenshot showing input fields for server URL and token&quot;
            title=&quot;Server settings configuration&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Here’s a short (4 minute) video showing installation, configuration and usage: &lt;a href=&quot;https://youtu.be/6SsJ5QSDglg&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;https://youtu.be/6SsJ5QSDglg&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;how-i-built-the-app&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#how-i-built-the-app&quot; aria-label=&quot;how i built the app permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;How I built the app&lt;/h2&gt;
&lt;p&gt;I wanted to build a cross-platform app that wasn’t just a wrapped WebView, which meant choosing between Flutter and React Native. It wasn’t an easy choice, but I decided to go with React Native as it’s been around for longer and there are lots of good resources on Udemy, Stack Overflow etc.&lt;/p&gt;
&lt;p&gt;React Native itself has many many dependencies, and I tried to add direct dependencies only when I had a real need:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;react-native-navigation: to provide a bottom-tabbed UI&lt;/li&gt;
&lt;li&gt;react-native-elements: to get some nicer default styling, and a pre-built component for list items&lt;/li&gt;
&lt;li&gt;react-native-vector-icons: easy access to icons for bottom tab navigation, and also required by react-native-elements&lt;/li&gt;
&lt;li&gt;redux: added only after I created a mess trying to pass state between two tabs that were based on two components in different files&lt;/li&gt;
&lt;li&gt;redux-persist: added to reduce the amount of code needed to store some state in both redux and local storage&lt;/li&gt;
&lt;li&gt;redux-thunk: added to make it easy to trigger network requests&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This was my first time developing a mobile app with React Native, and I took a few wrong turns. Notably, I spent a bit too much time trying to structure the code for state management and networks requests properly. Once I started using redux, everything became easier.&lt;/p&gt;
&lt;p&gt;If I were to do something similar again, I would take a look at these:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;redux-saga as an alternative to redux-think (it has more features, so maybe it’s better?)&lt;/li&gt;
&lt;li&gt;ant-design-mobile-rn as an alternative to react-native-elements (it has more components and built-in styles, so maybe it’s better?)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;BTW - This app has no relationship with Monica CRM or its creators. If it works for you, great! If not, please don’t bother Monica’s developers for support, as they likely can’t help.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[How to learn Chinese]]></title><description><![CDATA[Occasionally, people tell me they want to learn Chinese, and want some tips. Here they are.]]></description><link>https://www.encona.com/posts/how-to-learn-chinese</link><guid isPermaLink="false">https://www.encona.com/posts/how-to-learn-chinese</guid><pubDate>Fri, 26 Apr 2019 02:58:58 GMT</pubDate><content:encoded>&lt;p&gt;Chinese is not easy, but mostly success depends on:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Active study:&lt;/strong&gt; Putting in the time and effort to master basic sounds, basic vocabulary and sentence structures&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Practice:&lt;/strong&gt; Listening and speaking with native speakers. Don’t be afraid to make mistakes, or you’ll never practice, and never get better; don’t fall back to English unless absolutely necessary)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Drilling vocabulary:&lt;/strong&gt; Using flashcards to drill new vocabulary&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;getting-practice&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#getting-practice&quot; aria-label=&quot;getting practice permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Getting practice&lt;/h2&gt;
&lt;h3 id=&quot;living-in-china&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#living-in-china&quot; aria-label=&quot;living in china permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Living in China&lt;/h3&gt;
&lt;p&gt;Consider coming to China for a couple of months, after you’ve learnt the basics.  You’ll improve much more if you make the effort to hang out with Chinese people in the evenings, after spending the day studying or working with a teacher.&lt;/p&gt;
&lt;h3 id=&quot;language-exchange-over-skype&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#language-exchange-over-skype&quot; aria-label=&quot;language exchange over skype permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Language exchange over Skype:&lt;/h3&gt;
&lt;p&gt;Check out &lt;a href=&quot;http://www.italki.com&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;italki.com&lt;/a&gt; to find language partners and/or language tutors in China&lt;/p&gt;
&lt;h2 id=&quot;audio-courses&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#audio-courses&quot; aria-label=&quot;audio courses permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Audio courses&lt;/h2&gt;
&lt;p&gt;These can be good as a supplement to book learning and practice. They’re not a substitute. I found audio-only courses helpful when I started learning Chinese, as I could listen to them when on public transport or when driving. I have a friend who spent &gt;10 years in China, and he would always listen to ChinesePod when commuting, even after he’d been through each lesson &gt;10 times. His Chinese is better than mine.&lt;/p&gt;
&lt;h3 id=&quot;cd-sets&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#cd-sets&quot; aria-label=&quot;cd sets permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;CD sets&lt;/h3&gt;
&lt;p&gt;These are both good for the early stages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.pimsleur.com/learn-chinese-mandarin&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Pimsleur Mandarin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.michelthomas.com/learn-mandarin-chinese/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Learn Mandarin with Michel Thomas&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;online-audio-courses&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#online-audio-courses&quot; aria-label=&quot;online audio courses permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Online audio courses&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.chinesepod.com/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;ChinesePod.com&lt;/a&gt; (really good subscription-based service, with a free trial)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://popupchinese.com/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Pop up Chinese&lt;/a&gt; (similar to Chinesepod, but I’ve not tried it)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.yoyochinese.com/landing&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Yoyo Chinese&lt;/a&gt; (similar to Chinesepod, but I’ve not tried it)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;learning-to-write&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#learning-to-write&quot; aria-label=&quot;learning to write permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Learning to write&lt;/h2&gt;
&lt;p&gt;There are three main reasons for a foreigner to learn to write Chinese:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Because you expect writing by hand to be useful in daily life (not applicable to most people, even most Chinese people)&lt;/li&gt;
&lt;li&gt;Because writing Chinese characters helps to recognise written characters, especially to distinguish between characters that look similar&lt;/li&gt;
&lt;li&gt;Because it’s fun/interesting/cool/authentic/whatever&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You don’t need to be able to write by hand if you just want to be able to type in Chinese. You can use a Pinyin (romanised) input method on your laptop/phone/tablet.&lt;/p&gt;
&lt;p&gt;If you want to learn characters, you can use a book and copy out the characters repeatedly. But if you want to maximise efficiency, then &lt;a href=&quot;http://www.skritter.com/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Skritter&lt;/a&gt; is worth a look. I used it years ago, using a Wacom tablet. But I think they have phone/tablet versions now. It uses spaced-repetition, and very clever hinting. It’s surprisingly engaging and useful.&lt;/p&gt;
&lt;h2 id=&quot;dictionary--flashcards-essential&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#dictionary--flashcards-essential&quot; aria-label=&quot;dictionary  flashcards essential permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Dictionary / Flashcards (essential)&lt;/h2&gt;
&lt;h3 id=&quot;pleco-for-iphone-or-android&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#pleco-for-iphone-or-android&quot; aria-label=&quot;pleco for iphone or android permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Pleco for iPhone or Android&lt;/h3&gt;
&lt;p&gt;The free version is good. There are in-app purchases for additional dictionaries and flashcard functionality. Using flashcards within Pleco (vs. a standalone flashcard app) is great: whenever you look up a word in the dictionary, you can add it to your flashcard queue with a single tap.&lt;/p&gt;
&lt;h3 id=&quot;other-flash-card-programs&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#other-flash-card-programs&quot; aria-label=&quot;other flash card programs permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Other flash card programs:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Memrise (iPhone or Android)&lt;/li&gt;
&lt;li&gt;AnkiDroid (free for Android)&lt;/li&gt;
&lt;li&gt;Anki (free for desktop, but paid for iPhone/iPad).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;pronunciation&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#pronunciation&quot; aria-label=&quot;pronunciation permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Pronunciation:&lt;/h2&gt;
&lt;p&gt;The basics of pronouncing tones, You really need to get your pinyin and tone pronunciation down.  Just search google for ‘learning pinyin’ and you will find lots of free resources.  BUT you need a native Chinese speaker to listen/correct you once you think you’ve got it. If you live in a big city, go to meetup.com to find a Chinese language learners/exchange meetup.&lt;/p&gt;
&lt;h2 id=&quot;books-that-are-worth-considering&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#books-that-are-worth-considering&quot; aria-label=&quot;books that are worth considering permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Books that are worth considering&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.amazon.com/Modern-Mandarin-Chinese-Grammar-Practical/dp/041582714&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Modern Chinese Mandarin Grammar (Routledge)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Excel best practices for financial models]]></title><description><![CDATA[Simple things that will make your spreadsheets easier to understand, easier to maintain, and less likely to have errors.]]></description><link>https://www.encona.com/posts/excel-best-practices</link><guid isPermaLink="false">https://www.encona.com/posts/excel-best-practices</guid><pubDate>Fri, 12 Apr 2019 11:34:25 GMT</pubDate><content:encoded>&lt;p&gt;If you use Excel for financial modeling, you have probably had one (or more) of these things happen to you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You give your model to someone else (e.g. an investor) and they come back with many questions because they can’t understand the logic&lt;/li&gt;
&lt;li&gt;You feel stressed when you’re making changes because there is a lot of information to hold in your head&lt;/li&gt;
&lt;li&gt;You open a model you last used months/years ago, and you need a bunch of time to figure out what you were thinking&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The tips below can help. When you read through the list, your reaction to each item will likely be one of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Yup, I already do this&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Yup, I know about this, and I do it when I have enough time&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;I don’t see the point&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’ve designed and delivered training courses in accounting, financial modeling and Excel to engineers, product managers (and finance professionals!) at companies you’ve heard of. When people who’ve attended ask for help to improve a spreadsheet, or advice on how to add some feature to a complicated model, the answer almost always is to make the functioning of the model more obvious, logical and, most of all, transparent.&lt;/p&gt;
&lt;p&gt;Apply the tips below to one of your models. It will make your life easier.&lt;/p&gt;
&lt;h2 id=&quot;formulae&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#formulae&quot; aria-label=&quot;formulae permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Formulae&lt;/h2&gt;
&lt;h3 id=&quot;use-index-and-match-instead-of-vlookup&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#use-index-and-match-instead-of-vlookup&quot; aria-label=&quot;use index and match instead of vlookup permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Use &lt;code class=&quot;language-text&quot;&gt;INDEX&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;MATCH&lt;/code&gt; instead of &lt;code class=&quot;language-text&quot;&gt;VLOOKUP&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Don’t do this:&lt;/strong&gt; Use &lt;code class=&quot;language-text&quot;&gt;VLOOKUP&lt;/code&gt; to find the value in a particular column/row of a table &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do this instead:&lt;/strong&gt; Use &lt;code class=&quot;language-text&quot;&gt;MATCH&lt;/code&gt; to search in the lookup column, and &lt;code class=&quot;language-text&quot;&gt;INDEX&lt;/code&gt; to pick out the value &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why:&lt;/strong&gt; If you use &lt;code class=&quot;language-text&quot;&gt;VLOOKUP&lt;/code&gt;, then you need to reference a whole table, and specify the column by it’s sequence. But if you insert a new column anywhere to the left of that column, the column number in your &lt;code class=&quot;language-text&quot;&gt;VLOOKUP&lt;/code&gt; formula will be wrong, and your formula will return the wrong value. Using &lt;code class=&quot;language-text&quot;&gt;INDEX&lt;/code&gt; and MATCH is better because you reference only the 2 relevant columns (not the whole table), which means they are more efficient to calculate, and that the formula doesn’t break when you add new columns.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Good example:&lt;/strong&gt; &lt;a href=&quot;https://exceljet.net/index-and-match&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;https://exceljet.net/index-and-match&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;positive-and-negative-numbers&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#positive-and-negative-numbers&quot; aria-label=&quot;positive and negative numbers permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Positive and Negative numbers&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Don’t do this:&lt;/strong&gt; Make all numbers positive. Use addition/substraction as appropriate. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do this instead:&lt;/strong&gt; Use both positive and negative numbers, e.g. revenues should be positive, and costs should be negative. When making totals or subtotals, use only addition (either &lt;code class=&quot;language-text&quot;&gt;+&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;SUM&lt;/code&gt;). &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why:&lt;/strong&gt; Formulae with lots of &lt;code class=&quot;language-text&quot;&gt;+&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;-&lt;/code&gt; symbols are hard to read. Showing all numbers as positive makes it hard to understand what’s going on, without inspecting the formulae that calculate subtotals or totals. &lt;/p&gt;
&lt;h3 id=&quot;separate-inputs-from-formulae&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#separate-inputs-from-formulae&quot; aria-label=&quot;separate inputs from formulae permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Separate inputs from formulae&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Don’t do this:&lt;/strong&gt; Hard-code numbers in a formula (e.g. &lt;code class=&quot;language-text&quot;&gt;=A13/365&lt;/code&gt;) &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do this instead:&lt;/strong&gt; Put any input (hard-coded number) into its own cell, e.g.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;excel&quot;&gt;&lt;pre class=&quot;language-excel&quot;&gt;&lt;code class=&quot;language-excel&quot;&gt;A1: Number of days in the year

B1: 365

A10: Annual Revenue

A11: Daily Revenue

B11: B10/B1 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Why:&lt;/strong&gt; The model will be easier to understand, easier to audit, and easier to fix.&lt;/p&gt;
&lt;h3 id=&quot;use--to-fix-rowcolumn-within-formula&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#use--to-fix-rowcolumn-within-formula&quot; aria-label=&quot;use  to fix rowcolumn within formula permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Use &lt;code class=&quot;language-text&quot;&gt;$&lt;/code&gt; to fix row/column within formula&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Don’t do this:&lt;/strong&gt; Modify individual formulae by hand when copying them across a row, or down a column &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do this instead:&lt;/strong&gt; Use the &lt;code class=&quot;language-text&quot;&gt;$&lt;/code&gt; symbol to fix references to a particular row or column &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why:&lt;/strong&gt; If you have ‘interest rate’ in cell &lt;code class=&quot;language-text&quot;&gt;B1&lt;/code&gt; (among inputs at the top of your sheet), and you have a formula that references it:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;excel&quot;&gt;&lt;pre class=&quot;language-excel&quot;&gt;&lt;code class=&quot;language-excel&quot;&gt;=B1*B11&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When you copy that formula and paste it to the right, the pasted formula will be:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;excel&quot;&gt;&lt;pre class=&quot;language-excel&quot;&gt;&lt;code class=&quot;language-excel&quot;&gt;=C1*C11 (and C1 is probably empty!)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But what you probably wanted was:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;excel&quot;&gt;&lt;pre class=&quot;language-excel&quot;&gt;&lt;code class=&quot;language-excel&quot;&gt;=B1*C11 (i.e. apply the same interest rate, but to C11 instead of B11)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You could avoid this hassle in the first place if your first formula were instead:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;excel&quot;&gt;&lt;pre class=&quot;language-excel&quot;&gt;&lt;code class=&quot;language-excel&quot;&gt;$B$1*B11&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then, when you paste it one cell to the right, it will be:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;excel&quot;&gt;&lt;pre class=&quot;language-excel&quot;&gt;&lt;code class=&quot;language-excel&quot;&gt;$B$1*C11&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The reason we fix both the column (&lt;code class=&quot;language-text&quot;&gt;B&lt;/code&gt;) and the row (&lt;code class=&quot;language-text&quot;&gt;1&lt;/code&gt;) is because we are referring to a specific global input, not a row or column of values. In other examples, you might just fix one or the other (using just a single &lt;code class=&quot;language-text&quot;&gt;$&lt;/code&gt; symbol).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How:&lt;/strong&gt; Select the cell reference within your formula, and press &lt;code class=&quot;language-text&quot;&gt;F4&lt;/code&gt;. Press it again, and again, until the &lt;code class=&quot;language-text&quot;&gt;$&lt;/code&gt; signs are in the right places. &lt;/p&gt;
&lt;h3 id=&quot;simplify-formulae&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#simplify-formulae&quot; aria-label=&quot;simplify formulae permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Simplify formulae&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Don’t do this:&lt;/strong&gt; Use complicated formulae (e.g. containing multiple &lt;code class=&quot;language-text&quot;&gt;IF&lt;/code&gt;/&lt;code class=&quot;language-text&quot;&gt;OR&lt;/code&gt;/&lt;code class=&quot;language-text&quot;&gt;AND&lt;/code&gt; functions) &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do this instead:&lt;/strong&gt; Split complicated formulae between separate cells or separate rows. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why:&lt;/strong&gt; Complicated formulae frequently hide complicated logic, e.g.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;excel&quot;&gt;&lt;pre class=&quot;language-excel&quot;&gt;&lt;code class=&quot;language-excel&quot;&gt;=IF(AND(MONTH(A1)&amp;gt;5,MONTH(A1)&amp;lt;9),C4,D4)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;is harder to understand than two separate formula:&lt;/p&gt;
&lt;p&gt;Is summer?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;excel&quot;&gt;&lt;pre class=&quot;language-excel&quot;&gt;&lt;code class=&quot;language-excel&quot;&gt;=AND(MONTH(A1)&amp;gt;5,MONTH(A1)&amp;lt;9)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Rainfall per month:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;excel&quot;&gt;&lt;pre class=&quot;language-excel&quot;&gt;&lt;code class=&quot;language-excel&quot;&gt;=IF(B2,C4,D4)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;circular-references&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#circular-references&quot; aria-label=&quot;circular references permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Circular References&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Don’t do this:&lt;/strong&gt; Use circular references to optimise a value&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do this instead:&lt;/strong&gt; Don’t use circular reference unless you really really know what you’re doing. If you’re not sure if this applies to you, then don’t use circular references. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why:&lt;/strong&gt; There are very few cases in which circular references are the right way to solve a problem. In all other cases, circular references will make the output of your model hard to reason about, and will increase the chance that you make an error.&lt;/p&gt;
&lt;h3 id=&quot;named-cells-and-named-ranges&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#named-cells-and-named-ranges&quot; aria-label=&quot;named cells and named ranges permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Named cells and Named Ranges&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Don’t do this:&lt;/strong&gt; Use named ranges and names &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do this instead:&lt;/strong&gt; Don’t use names or named ranges. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why:&lt;/strong&gt; If a formula refers to a named cell, anyone looking at the model needs to use the ‘Trace Precedents’ command to find where that cell is, making the model harder to understand and audit.&lt;/p&gt;
&lt;h3 id=&quot;balancing-items&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#balancing-items&quot; aria-label=&quot;balancing items permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Balancing items&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Don’t do this:&lt;/strong&gt; Use ‘plugs’, i.e. formulae for balancing items &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do this instead:&lt;/strong&gt; Calculate every item directly when possible &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why:&lt;/strong&gt; If you calculate an item as a balancing item, then:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can’t do an error check on your total, and&lt;/li&gt;
&lt;li&gt;no one can reason about the components of that figure.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One of the few cases when a balancing item is acceptable is when you’re building a financial model and each period has a ‘new debt/equity funding’ line. In this case, the funding requirement is a direct result of the other items in the column, so it’s OK.&lt;/p&gt;
&lt;h2 id=&quot;formatting&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#formatting&quot; aria-label=&quot;formatting permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Formatting&lt;/h2&gt;
&lt;h3 id=&quot;colour-coding&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#colour-coding&quot; aria-label=&quot;colour coding permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Colour coding&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Don’t do this:&lt;/strong&gt; Leave all cells as black-on-white&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do this instead:&lt;/strong&gt; Colour code any cell that contains inputs (hard-coded numbers), with either (i) yellow background, blue text, or (ii) orange background, grey font &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How:&lt;/strong&gt; Use the ‘Cell styles’ section in the ‘Home’ ribbon to use the pre-defined styles. You can customise these styles if you don’t like them. Or you can just change each cell’s background colour and font colour as you normally would (not recommended, as it’s hard to stay consistent). &lt;/p&gt;
&lt;h3 id=&quot;number-precision&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#number-precision&quot; aria-label=&quot;number precision permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Number precision&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Don’t do this:&lt;/strong&gt; Display numbers with many digits of precision &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do this instead:&lt;/strong&gt; Display numbers with a maximum of 4 significant figures (but usually 3)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why:&lt;/strong&gt; The 4th or 5th significant figure is usually insignificant (do you care about less than 0.1% difference?), and every additional number on the page makes your spreadsheet harder to read, and therefore less useful.&lt;/p&gt;
&lt;h3 id=&quot;leftright-alignment&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#leftright-alignment&quot; aria-label=&quot;leftright alignment permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Left/right alignment&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Don’t do this:&lt;/strong&gt; Centre numbers&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do this instead:&lt;/strong&gt; Leave Excel to align things automatically&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why:&lt;/strong&gt; Numbers in a column are easier to compare when right-aligned. Text labels in a column are easier to scan when left-aligned. The default in Excel is to left-align text, and right-align numbers, so there’s usually no need to change anything&lt;/p&gt;
&lt;h3 id=&quot;signifying-negatives&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#signifying-negatives&quot; aria-label=&quot;signifying negatives permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Signifying negatives&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Don’t do this:&lt;/strong&gt; Use the default number formatting in Excel&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do this instead:&lt;/strong&gt; Signify negative financial values using brackets, and maybe also red font&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why:&lt;/strong&gt; Brackets are larger and much more obvious than the dash that normally signifies numbers.&lt;/p&gt;
&lt;h3 id=&quot;borders--underlining&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#borders--underlining&quot; aria-label=&quot;borders  underlining permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Borders / Underlining&lt;/h3&gt;
&lt;p&gt;Use borders consistently:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Single line at the top of a cell indicates that this cell is a subtotal&lt;/li&gt;
&lt;li&gt;Single line at top, and double line at the bottom, indicates this is a grand total &lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;model-structure&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#model-structure&quot; aria-label=&quot;model structure permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Model Structure&lt;/h2&gt;
&lt;h3 id=&quot;single-input-only&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#single-input-only&quot; aria-label=&quot;single input only permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Single input only&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Don’t do this:&lt;/strong&gt; Enter the same input (hard-coded value) in more than one cell&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do this instead:&lt;/strong&gt; Enter any input (hard-coded value) only once in the whole workbook, and reference it using a formula anywhere else it is needed&lt;/p&gt;
&lt;h3 id=&quot;calculations-across-sheets&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#calculations-across-sheets&quot; aria-label=&quot;calculations across sheets permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Calculations across sheets&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Don’t do this:&lt;/strong&gt; Reference values from another sheet in a calculation&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do this instead:&lt;/strong&gt; Use formulae to link the values from the other sheet in a separate row/column in the current sheet, and then (in a separate row) write your formulae to reference this row of values on the current sheet. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why:&lt;/strong&gt; It is easier to audit a formula when you can see the number it depends on, without flipping between sheets&lt;/p&gt;
&lt;h3 id=&quot;hidden-rowscolumns&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#hidden-rowscolumns&quot; aria-label=&quot;hidden rowscolumns permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Hidden rows/columns&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Don’t do this:&lt;/strong&gt; Hide rows to make your spreadsheet easier to read &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do this instead:&lt;/strong&gt; Don’t hide rows. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why:&lt;/strong&gt; People using your spreadsheet want to know how it works. If you hide rows, they cannot trust the calculations, because they cannot see them.&lt;/p&gt;
&lt;h3 id=&quot;multi-purpose-columnsrows&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#multi-purpose-columnsrows&quot; aria-label=&quot;multi purpose columnsrows permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Multi-purpose columns/rows&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Don’t do this:&lt;/strong&gt; Mix different types of values in a row (e.g. GAAP and non-GAAP) &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do this instead:&lt;/strong&gt; Keep different types of values in different rows (e.g. one row for GAAP, and another for non-GAAP). Even if some columns don’t include values for some rows, that is better. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why:&lt;/strong&gt; People assume things in the same column or row are comparable. Mixing different types of things means that neither the column nor the row contain the same type of value.&lt;/p&gt;
&lt;h3 id=&quot;arrange-sheets-in-a-logical-order&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#arrange-sheets-in-a-logical-order&quot; aria-label=&quot;arrange sheets in a logical order permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Arrange sheets in a logical order&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Don’t do this:&lt;/strong&gt; Arrange your sheets in the order in which you created them
&lt;strong&gt;Do this instead:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Arrange Assumptions sheets to the left of Calculations sheets&lt;/li&gt;
&lt;li&gt;Arrange Calculations sheets to the left of Output sheets&lt;/li&gt;
&lt;li&gt;If you have a cover sheet, obviously put that as the first (left-most) sheet &lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;check-for-errors&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#check-for-errors&quot; aria-label=&quot;check for errors permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Check for errors&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Don’t do this:&lt;/strong&gt; Hope that everything adds up&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do this instead:&lt;/strong&gt; Use error check rows to check that key identities hold (e.g. Capital - Assets - Liabilities = 0) &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How:&lt;/strong&gt; Make a formula that shows ‘ERROR’ if the identity doesn’t hold, but shows nothing if it does. Use a red font or red background for that cell.&lt;/p&gt;
&lt;h3 id=&quot;macros&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#macros&quot; aria-label=&quot;macros permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Macros&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Don’t use macros&lt;/strong&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do this instead:&lt;/strong&gt; Just use formulae instead. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why:&lt;/strong&gt; Macros make the logic of your spreadsheet harder to understand, both for others and for your future self.&lt;/p&gt;
&lt;h3 id=&quot;scenarios&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#scenarios&quot; aria-label=&quot;scenarios permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Scenarios&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Don’t do this:&lt;/strong&gt; Make copies of sheets for scenarios
&lt;strong&gt;Do this instead:&lt;/strong&gt; Use the same input, calculation and output sheets for all scenarios, and use a single input cell to choose which scenario you want to run&lt;/p&gt;
&lt;p&gt; &lt;strong&gt;Why&lt;/strong&gt;: Having multiple copies of the ‘same’ sheet makes it hard to make changes to your model, as you need to update structure and formulae in different places. It also makes it hard to audit, as there are more sheets to audit.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How:&lt;/strong&gt; Arrange your spreadsheet like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Column A: Input labels&lt;/li&gt;
&lt;li&gt;Columns C, D, E: Input values for scenarios 1, 2, 3&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In column B:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An input cell at the top, that contains the current selected scenario #&lt;/li&gt;
&lt;li&gt;All other cells use an INDEX() function to choose the correct current input from the cells to the right&lt;/li&gt;
&lt;li&gt;All calculation sheets refer only to column B &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;numbers&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#numbers&quot; aria-label=&quot;numbers permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Numbers&lt;/h2&gt;
&lt;h3 id=&quot;billions&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#billions&quot; aria-label=&quot;billions permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Billions&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Don’t do this:&lt;/strong&gt; Store numbers in thousands or millions&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do this instead:&lt;/strong&gt; Store numbers in units (i.e. enter 1MM as 1000000) and use number formatting to display them as 1MM or however you want &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why:&lt;/strong&gt; If you store some numbers in thousands, and some in millions, and some as units, then your formulae will be complicated. For example, if your revenue is in billions, but your number of shares is in millions, then your EPS calculation will be something like X1/Y1*1000 &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Good example:&lt;/strong&gt; &lt;a href=&quot;https://www.ablebits.com/office-addins-blog/2016/07/07/custom-excel-number-format/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;https://www.ablebits.com/office-addins-blog/2016/07/07/custom-excel-number-format/&lt;/a&gt; &lt;/p&gt;
&lt;h3 id=&quot;enter-numbers-as-numbers&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#enter-numbers-as-numbers&quot; aria-label=&quot;enter numbers as numbers permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Enter numbers as numbers&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Don’t do this:&lt;/strong&gt; Enter column headings like ‘2018 FY’ as text &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do this instead:&lt;/strong&gt; Ensure all years are entered as numbers, and use number formatting to add any extra text &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why:&lt;/strong&gt; Excel can automatically increment numbers when a range of numbers is extended, but cannot do the same for text. This reduces the risk of error.&lt;/p&gt;
&lt;h2 id=&quot;presentation&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#presentation&quot; aria-label=&quot;presentation permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Presentation&lt;/h2&gt;
&lt;h3 id=&quot;empty-columns&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#empty-columns&quot; aria-label=&quot;empty columns permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Empty columns&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Don’t do this:&lt;/strong&gt; Include empty columns to create space between columns &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do this instead:&lt;/strong&gt; User proper alignment and column width &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why:&lt;/strong&gt; The more cells a model has, the harder it is to audit and understand it properly. Adding blank columns doubles the number of cells, and anyone reading your model will need to verify that those columns are actually empty, and don’t have numbers that affect formulae.&lt;/p&gt;
&lt;h3 id=&quot;printing&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#printing&quot; aria-label=&quot;printing permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Printing&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Don’t do this:&lt;/strong&gt; Send a spreadsheet to someone without making sure it prints properly&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do this instead:&lt;/strong&gt; Set up each page to print how you want it to appear&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why:&lt;/strong&gt; Some people print spreadsheets or convert them to PDF, to share with others. If someone tries to do that with something you send them, and it looks bad, it will just make them annoyed at you.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How:&lt;/strong&gt; On &lt;em&gt;each sheet&lt;/em&gt;, use the Page Layout tab:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Margins (set to normal or narrow)&lt;/li&gt;
&lt;li&gt;Orientation (set to landscape)&lt;/li&gt;
&lt;li&gt;Size (check that it’s A4)&lt;/li&gt;
&lt;li&gt;Width (set to ‘1 page‘’)&lt;/li&gt;
&lt;li&gt;Height (set to ‘Automatic’ or a specific number of pages)&lt;/li&gt;
&lt;li&gt;Print Titles - set ‘Rows to repeat at top’ and, if applicable, header+footer (with name of file and name of sheet) &lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;comments&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#comments&quot; aria-label=&quot;comments permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Comments&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Don’t do this:&lt;/strong&gt; Let people guess where numbers came from&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do this instead:&lt;/strong&gt; Use comments to explain specific terms or the source of an input&lt;/p&gt;
&lt;h3 id=&quot;sheet-names&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#sheet-names&quot; aria-label=&quot;sheet names permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Sheet names&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Don’t do this:&lt;/strong&gt; Leave worksheets named as Sheet1, Sheet2 etc. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do this instead:&lt;/strong&gt; As soon as you add a second sheet to a workbook, rename Sheet1 and Sheet2 to sensible names&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why:&lt;/strong&gt; Make your stuff easy to use!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[How to transform capability growth into compensation]]></title><description><![CDATA[Thoughts about ensuring your compensation goes up along with your contribution.]]></description><link>https://www.encona.com/posts/negotiating-salary</link><guid isPermaLink="false">https://www.encona.com/posts/negotiating-salary</guid><pubDate>Fri, 12 Apr 2019 08:51:25 GMT</pubDate><content:encoded>&lt;p&gt;A friend of mine joined startup that later started going through rapid growth. His responsibilities went up, and he got the chance to increase his capabilities and contribution rapidly. He wanted his compensation to grow as well, whether he stayed at the same company or not. This is what I told him…&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Caveat: All of these things are easier said than done!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;As an employee, there are 3 ways to get paid more:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Negotiate a better package when you join&lt;/li&gt;
&lt;li&gt;Be awarded (or negotiate) a better package (or more equity) after you join&lt;/li&gt;
&lt;li&gt;Get a compensation bump/surprise due to your already-awarded equity (e.g. your employer’s stock goes up in price) or beating some sales compensation formula target&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;#3 is either about picking a company whose share price is going to rise (if you can reliably do this, become a full time investor!), or applies mainly to sales-related jobs &lt;em&gt;[not relevant to my friend’s situation]&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;#2 is common at large tech companies &lt;em&gt;if&lt;/em&gt; you land in a good team and are able to grow your scope and role. Obviously this doesn’t work out for everyone. But somewhere like Google, they have salary bands for each role at each level, and try to have a fair promotion process. So if you get promoted (not necessary a role change) then your salary won’t be below the lower bound for that level.&lt;/p&gt;
&lt;p&gt;#1 is the time you have most ability to influence, because:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You’re considering more than one company. So, assuming all companies don’t value you equally, one of them might value you higher. (compared with when you’re already in a job, your current employer might not happen to be the one that values you highest)&lt;/li&gt;
&lt;li&gt;You’re not fighting any internal HR policies about how much of a % raise they can give in a certain period. These are not universal, but many companies have these policies. (Some companies have a policy of how much they can offer above previous salary, but that’s much less common. Normally it’s just a data point to estimate your market value.)&lt;/li&gt;
&lt;li&gt;The company may need someone with your skill set immediately, and it may be harder to find than you think. So their alternative isn’t not giving you the right compensation, and having a risk that you leave in 6 months. It’s not hiring you now, and missing out on what you would contribute to the bottom line now.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Practically, this means your chances of a good outcome are maximised if you can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Get multiple offers&lt;/strong&gt;&lt;br&gt;
Get offers from multiple companies at around the same time. Then you can gently but confidently discuss your situation with the recruiter (or whoever is negotiating).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Find a role that fits like a glove&lt;/strong&gt;&lt;br&gt;
Find a role for which you’re the perfect fit, or at least a very close one. The fastest job offer I got was for a role where, I found out later, no other applicant came even close to meeting the requirements. To me it was an attractive role, and I really enjoyed the interview process (maybe because they were testing things I was strong on!), but I still felt they could find someone else. But it turned out it had been really hard.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use time to your advantage&lt;/strong&gt;&lt;br&gt;
If you’re in a hurry to get a new job, then that makes it harder to follow the first two pieces of advice. But It also goes the other way: if the company is in a rush, then they should be willing to pay more to close. An extra 10% salary can be a lot to an individual, but it’s much less than the cost of paying a 25% fee to an external recruiter every year or two.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Don’t forget the small things&lt;/strong&gt;&lt;br&gt;
Itemize as best you can the cash value of benefits you get from your existing employer, e.g. free food or gym membership or whatever. If moving cities, ask for relocation allowance if not already offered. See if they can give you a signing bonus or similar, to make up (partly) for the unvested equity you’re giving up.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Appeal to fairness&lt;/strong&gt;&lt;br&gt;
Give objective comparable information, and appeal to fairness. This is most useful if the company just has unrealistic ideas about compensation for certain roles/levels. Smaller companies may not do external benchmarks so might need educating.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Align incentives&lt;/strong&gt;&lt;br&gt;
At a smaller company, or for a senior role, you can also try to negotiate some very specific and challenging performance-based bonus, making it low risk for them. But that’s really tricky even if they agree, because it’s unlikely you have 100% control over the output, so you could miss it even if your performance is awesome.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The advice above doesn’t apply as much to companies that care a lot about fairness. Those companies try not to penalize you for having a low salary in the past; they will evaluate your level as best they can, and pay according to that. So going to work for a ‘fair’ company like this can be a good thing if you’ve been underpaid in the past and don’t want to fight to get what you’re worth.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;This all assumes you’ve done your best to find a role that’s a good fit, and wowed the team with what a good fit you are, got them excited to work with you etc.&lt;/strong&gt; If they really want *you* rather than just another similar person, then it makes it easier for them to pay more than they were initially expecting.&lt;/p&gt;
&lt;p&gt;Your point about new employers initially anchoring on past salary is absolutely true. But they generally look mostly at the most recent salary, so a low salary at one job doesn’t follow someone around forever, so long as they can convince one employer at some point of their value. Then the next employer will look at that one.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Teaching your toddler maths]]></title><description><![CDATA[A simple web app to help you teach your toddler to get an intuitive grasp of numbers.]]></description><link>https://www.encona.com/posts/doman-dots</link><guid isPermaLink="false">https://www.encona.com/posts/doman-dots</guid><pubDate>Thu, 11 Apr 2019 16:12:45 GMT</pubDate><content:encoded>&lt;p&gt;The book &lt;a href=&quot;https://www.amazon.com/How-Teach-Your-Baby-Math-ebook/dp/B00IAQRZ3G/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;How to Teach your Baby Math&lt;/a&gt;, by Glenn Doman, recommends teaching babies/toddlers numbers by showing them cards with dots on them, one at a time, whilst saying aloud the number of dots.&lt;/p&gt;
&lt;p&gt;Instead of making your own cards and using your own voice, you can run this web app and use your smartphone and thumb.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://doman-236804.appspot.com/5/10&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;https://doman-236804.appspot.com/5/10&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The initial screen is blank. Tap anywhere on the screen to show some dots and hear the number. After about a second, the screen will again be blank, ready for you to tap again.&lt;/p&gt;
&lt;p&gt;The URL above will show numbers from 5 to 10. Change the numbers at the end of the URL if you want a different range.&lt;/p&gt;
&lt;p&gt;If you want to host this yourself, or improve it, you can find the &lt;a href=&quot;https://github.com/rahimnathwani/doman-web&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;source code on GitHub&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Books about OKRs]]></title><description><![CDATA[Useful books for people implementing OKRs in their business, or for anyone who wants to focus on what matters]]></description><link>https://www.encona.com/posts/okrs</link><guid isPermaLink="false">https://www.encona.com/posts/okrs</guid><pubDate>Thu, 11 Apr 2019 16:02:08 GMT</pubDate><content:encoded>&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.amazon.com/Measure-What-Matters-Google-Foundation-ebook/dp/B078FZ9SYB/ref=sr_1_1?keywords=measure+what+matters&amp;#x26;qid=1554999066&amp;#x26;s=digital-text&amp;#x26;sr=1-1&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Measure what Matters&lt;/a&gt; by John Doerr&lt;br&gt;
By the guy who introducted OKRs to Google. Has lots of stories.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.amazon.com/Move-Decisive-Strategy-Obstacles-Setbacks-ebook/dp/B01N9ZVTGG/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Move&lt;/a&gt; by Patty Azzarello&lt;br&gt;
A really great book on executing strategic change, that has a section about setting ‘Control Points’, which are roughly equivalent to what Intel/Google etc. refer to as ‘Key Results’. I keep coming back to this book.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.amazon.com/Radical-Focus-Achieving-Important-Objectives-ebook/dp/B01BFKJA0Y/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Radical Focus&lt;/a&gt; by Christina Wodtke&lt;br&gt;
A light read about OKRs. Good as a first book on OKRs, but not as detailed as the two books above.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.oreilly.com/library/view/~/9781491971475/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Introduction to OKRs&lt;/a&gt; by Christina Wodtke&lt;br&gt;
A very short book on OKRs. Good as a first book on OKRs if you have a very very short attention span.&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Books for product managers]]></title><description><![CDATA[A list of things product managers should know how to do,  along with some book recommendations.]]></description><link>https://www.encona.com/posts/product-manager-resources</link><guid isPermaLink="false">https://www.encona.com/posts/product-manager-resources</guid><pubDate>Thu, 11 Apr 2019 15:27:21 GMT</pubDate><content:encoded>&lt;h2 id=&quot;overview-books&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#overview-books&quot; aria-label=&quot;overview books permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Overview books:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.amazon.com/INSPIRED-Create-Tech-Products-Customers-ebook/dp/B077NRB36N/ref=pd_sim_351_2/144-1728573-2435567?_encoding=UTF8&amp;#x26;pd_rd_i=B077NRB36N&amp;#x26;pd_rd_r=795ea91d-5c70-11e9-8fe6-ef851373c459&amp;#x26;pd_rd_w=mlF8s&amp;#x26;pd_rd_wg=mEuSz&amp;#x26;pf_rd_p=90485860-83e9-4fd9-b838-b28a9b7fda30&amp;#x26;pf_rd_r=09QF6SKRZ022V46B9F25&amp;#x26;psc=1&amp;#x26;refRID=09QF6SKRZ022V46B9F25&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Inspired&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.amazon.com/Product-Managers-Desk-Reference-2E-ebook/dp/B00KWQ1TN4/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;The Product Manager’s Desk Reference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.amazon.com/Lean-Startup-Entrepreneurs-Continuous-Innovation-ebook/dp/B004J4XGN6/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;The Lean Startup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.crackingthepmcareer.com/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Cracking the PM Career&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.amazon.com/Agile-Product-Management-Scrum-Addison-Wesley/dp/0321605780/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Agile Product Management with Scrum&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;interview-preparation-good-for-breadth-even-if-youre-not-applying-for-jobs&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#interview-preparation-good-for-breadth-even-if-youre-not-applying-for-jobs&quot; aria-label=&quot;interview preparation good for breadth even if youre not applying for jobs permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Interview preparation (good for breadth, even if you’re not applying for jobs):&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.amazon.com/Decode-Conquer-Answers-Management-Interviews/dp/0615930417/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Decode &amp;#x26; Conquer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.amazon.com/Cracking-PM-Interview-Product-Technology-ebook-dp-B00ISYMUR6/dp/B00ISYMUR6/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Cracking the PM interview&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;other-good-books-for-pms&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#other-good-books-for-pms&quot; aria-label=&quot;other good books for pms permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Other good books for PMs:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.amazon.com/Hooked-How-Build-Habit-Forming-Products/dp/1591847788/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Hooked&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.amazon.com/Design-Everyday-Things-Revised-Expanded-ebook/dp/B00E257T6C/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;The Design of Everyday Things&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.amazon.com/Zero-One-Notes-Startups-Future-ebook/dp/B00J6YBOFQ&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Zero to One&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.amazon.com/Traction-Startup-Achieve-Explosive-Customer-ebook/dp/B00TY3ZOMS/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Traction&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;all-pms-should-have-a-101-level-understanding-of-these-topics&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#all-pms-should-have-a-101-level-understanding-of-these-topics&quot; aria-label=&quot;all pms should have a 101 level understanding of these topics permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;All PMs should have a 101-level understanding of these topics:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;User research &lt;/li&gt;
&lt;li&gt;Financial Models (cash flow, NPV, payback period)&lt;/li&gt;
&lt;li&gt;Writing (how to structure documents and sentences; use something like The Pyramid Principle)&lt;/li&gt;
&lt;li&gt;Marketing/growth (different channels, CAC, LTV etc.)&lt;/li&gt;
&lt;li&gt;Presenting data (use Say it with charts by Gene Zalazny, or something by Stephen Few (Show me the numbers, or Information dashboard design)&lt;/li&gt;
&lt;li&gt;Software architecture (including how code talks to databases and APIs; concept of technical debt and how trade-offs are made)&lt;/li&gt;
&lt;li&gt;Data networking (OSI model, how it relates to TCP/IP)&lt;/li&gt;
&lt;li&gt;Scripting (bash/sed/awk or perl or python)&lt;/li&gt;
&lt;li&gt;Coding (in some high level OO or functional language; ideally Python or Java)&lt;/li&gt;
&lt;li&gt;Project Management (it’s not your job, but sometimes you have to do it)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;tools-pms-should-be-comfortable-using-in-order-to-analyse-stuff-andor-communicate-their-ideas&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#tools-pms-should-be-comfortable-using-in-order-to-analyse-stuff-andor-communicate-their-ideas&quot; aria-label=&quot;tools pms should be comfortable using in order to analyse stuff andor communicate their ideas permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Tools PMs should be comfortable using, in order to analyse stuff and/or communicate their ideas:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Something for rough mockups, e.g. Balsamiq&lt;/li&gt;
&lt;li&gt;(optional) Something for finer mockups, e.g. Sketch 3&lt;/li&gt;
&lt;li&gt;Something for quickly drawing flow charts (PowerPoint or Google Slides will do)&lt;/li&gt;
&lt;li&gt;Excel (and basic best practices like highlighting inputs, not mixing inputs and calculations, etc.)&lt;/li&gt;
&lt;li&gt;Using Powerpoint or Google Slides) to create slides to support a presentation (not just decks for people to read offline or, worse, a deck that is made for presentation, but is so wordy that people focus on the slides instead of the presenter)&lt;/li&gt;
&lt;li&gt;SQL (to help you answer your own questions)&lt;/li&gt;
&lt;li&gt;A high-level language (e.g. Python, Ruby, JavaScript, Java)&lt;/li&gt;
&lt;li&gt;Google Analytics (or MixPanel or whatever your company uses)&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item></channel></rss>