<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Ed Johnson-Williams</title><description>Ed Johnson-Williams&apos; website</description><link>https://edjohnsonwilliams.co.uk/</link><language>en-gb</language><item><title>A simplistic post on liberalism and Christianity</title><link>https://edjohnsonwilliams.co.uk/blog/2017-06-15-a-simplistic-post-on-liberalism-and-christianity/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2017-06-15-a-simplistic-post-on-liberalism-and-christianity/</guid><pubDate>Wed, 14 Jun 2017 23:00:00 GMT</pubDate><content:encoded>&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;I&apos;m a straight, Christian man who is liberal - both politically and theologically.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I disagree with Tim Farron&apos;s apparent view that having an abortion or gay sex is a sin&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I also disagree with Tim Farron&apos;s comments that being a liberal leader and a &quot;faithful Christian&quot; is irreconcilable. There are lots of liberal Christians.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It &lt;em&gt;helps&lt;/em&gt; to be a Christian who embraces people of all sexualities and is pro-choice if you want to be a liberal leader.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I do however think that you can hold personal views that are illiberal and still be a liberal politician so long as you don&apos;t impose your personal views on others.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;There is nothing in Tim Farron&apos;s record to suggest he has tried to impose his personal views on others.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You might say that you want to know your political leaders say what they believe in. Fair enough.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Jeremy Corbyn opposes nuclear weapons but is (now) happy to say he will promote party policy which is to renew Trident. Is there a difference between this and Farron?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;What about Theresa May? Does she personally believe everything she promotes? Does every journalist? Is this only an issue because Tim Farron is a &lt;em&gt;liberal&lt;/em&gt; politician?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I saw someone on Twitter ask...Where do you draw the line on personal views that you&apos;d be OK with so long as they didn&apos;t act on them? Would you be OK with a Holocaust denier? Answer...Don&apos;t know.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;But Tim Farron has consistently voted for liberal legislation on abortion and gay rights. This would be &lt;em&gt;a bit&lt;/em&gt; like a Holocaust denier consistently voting to fund museums about the Holocaust. Stress on &lt;em&gt;a bit like&lt;/em&gt;. It&apos;s not actually the same. Obviously.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I would probably react to this differently if I was gay and I need to think about this more.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Reading this &lt;a href=&quot;https://twitter.com/huwlemmey/status/875254164909109248&quot;&gt;Twitter thread&lt;/a&gt; by Huw Lemmey is the closest I&apos;ve got to changing my mind on this.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
</content:encoded></item><item><title>A simplistic post on Brexit utopianism</title><link>https://edjohnsonwilliams.co.uk/blog/2017-06-18-a-simplistic-post-on-brexit-utopianism/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2017-06-18-a-simplistic-post-on-brexit-utopianism/</guid><pubDate>Sun, 18 Jun 2017 09:12:00 GMT</pubDate><content:encoded>&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;This has been said many times before.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Brexit supporters on the right who complain that the socialist utopianism of Corbyn etc isn&apos;t pragmatic are ridiculous.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You can&apos;t complain about utopianism while wanting the UK to jump off the Brexit cliff hoping there will be a soft landing.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Brexit is not a pragmatic project.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Labour&apos;s position is not much better. You can&apos;t claim your manifesto is fully costed if you don&apos;t cost out the economic impact of your policy of ending freedom of movement.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
</content:encoded></item><item><title>A simplistic post on remembering your country&apos;s history</title><link>https://edjohnsonwilliams.co.uk/blog/2017-08-16-a-simplistic-post-on-remembering-your-country-s-history/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2017-08-16-a-simplistic-post-on-remembering-your-country-s-history/</guid><pubDate>Wed, 16 Aug 2017 17:27:00 GMT</pubDate><content:encoded>&lt;p&gt;Donald Trump says that removing statues to Confederate generals is &lt;a href=&quot;http://www.politico.com/story/2017/08/15/full-text-trump-comments-white-supremacists-alt-left-transcript-241662&quot;&gt;changing history&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;He&apos;s wrong.&lt;/p&gt;
&lt;p&gt;Take Germany. They don&apos;t need statues of Hitler to remember Germany&apos;s history even though Hitler is part of German history.&lt;/p&gt;
&lt;p&gt;They have memorials to the victims of Nazi Germany instead.&lt;/p&gt;
&lt;p&gt;People in Germany remember Germany&apos;s history without having monuments of the people responsible for the Holocaust.&lt;/p&gt;
&lt;p&gt;America can remember what happened before and during the Civil War without having statues of the leaders of the Confederacy.&lt;/p&gt;
&lt;p&gt;They can have memorials to victims of slavery and those who died in the Civil War instead.&lt;/p&gt;
</content:encoded></item><item><title>Female Composers in the Sacred Harp</title><link>https://edjohnsonwilliams.co.uk/blog/2018-02-07-female-composers-in-the-sacred-harp/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2018-02-07-female-composers-in-the-sacred-harp/</guid><pubDate>Thu, 08 Feb 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&amp;lt;p&amp;gt;
A couple of weeks ago, I was in a
&amp;lt;a href=&quot;https://en.wikipedia.org/wiki/Sacred_Harp&quot;&amp;gt;Sacred Harp&amp;lt;/a&amp;gt; singing
school where a new singer asked whether there are female composers in the
Sacred Harp. The singing school was in
&amp;lt;a href=&quot;https://durhamsacredharp.co.uk&quot;&amp;gt;Durham, UK&amp;lt;/a&amp;gt; (
&amp;lt;a href=&quot;https://durhamsacredharp.co.uk&quot;&amp;gt;shameless plug&amp;lt;/a&amp;gt;). I said something
like, &quot;Oh yeah there are lots of great songs in here by women.&quot; A few days
later I thought about the question again for a bit. I realised that although I
liked several songs by women, I didn&apos;t really have anything to base my answer
on.
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
To rectify that, I&apos;ve looked at the Sacred Harp and the minutes data to answer
some questions that came to mind about female composers in the Sacred Harp.
I&apos;m using the 1991 edition of the red &quot;Denson book&quot;.
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;ol&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;a href=&quot;#toc_0&quot;&amp;gt;Who are the female composers in the book?&amp;lt;/a&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;a href=&quot;#toc_0&quot;&amp;gt;Which songs in the book are by female composers?&amp;lt;/a&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;a href=&quot;#toc_1&quot;&amp;gt;
What proportion of songs in the book are by female composers?
&amp;lt;/a&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;a href=&quot;#toc_2&quot;&amp;gt;
What proportion of the composers in the book are female?
&amp;lt;/a&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;a href=&quot;#toc_3&quot;&amp;gt;
How likely are female composers to have multiple songs in the book?
&amp;lt;/a&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;a href=&quot;#toc_4&quot;&amp;gt;How popular are the songs by female composers?&amp;lt;/a&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;a href=&quot;#toc_6&quot;&amp;gt;What are the most popular songs by female composers?&amp;lt;/a&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;a href=&quot;#toc_5&quot;&amp;gt;
Has the popularity of songs by female composers changed over time?
&amp;lt;/a&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;a href=&quot;#toc_8&quot;&amp;gt;
Which songs by female composers have changed the most in the popularity
over time?
&amp;lt;/a&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
There&apos;s &amp;lt;a href=&quot;#toc_7&quot;&amp;gt;a note at the bottom of this post&amp;lt;/a&amp;gt; about how I
attributed gender to the composers. The short version is that I used the name
given in the book for the composer and didn&apos;t get into nuances.
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
The data I created and used for this is available here as
&amp;lt;a href=&quot;/files/sacred-harp-composers/sacredharpcomposers.xls&quot;&amp;gt;an Excel (.xls) spreadsheet&amp;lt;/a&amp;gt;.
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;a href=&quot;mailto:mail@edjohnsonwilliams.co.uk&quot;&amp;gt;Let me know&amp;lt;/a&amp;gt; if you see
errors, would like some more detail on an answer, or if there are other
questions you&apos;d be interested in seeing the answer to.
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;h2 id=&quot;toc_0&quot;&amp;gt;
Who are the female composers in the book? Which songs in the book are by
female composers?
&amp;lt;/h2&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
In many ways, this is the most interesting question. Here&apos;s a list of songs in
the book by female composers. Note that the first song in the book is by a
woman!
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;26&amp;lt;/strong&amp;gt; Samaria – Maggie Denson Cagle
&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;77b&amp;lt;/strong&amp;gt; Holcombe – Charlene Wallace
&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;112&amp;lt;/strong&amp;gt; The Last Words of Copernicus – Sarah Lancaster
&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;128&amp;lt;/strong&amp;gt; The Promised Land – M. Durham
&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;275b&amp;lt;/strong&amp;gt; Roll On – Cynthia Bass
&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;345b&amp;lt;/strong&amp;gt; I&apos;m On My Journey Home – Sarah Lancaster
&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;348t&amp;lt;/strong&amp;gt; Ainslie – Judy Hauff
&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;367&amp;lt;/strong&amp;gt; Consolation – Annie Denson Aaron
&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;368&amp;lt;/strong&amp;gt; Stony Point – Judy Hauff
&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;374&amp;lt;/strong&amp;gt; Oh, Sing With Me! – P. R. Lancaster
&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;378b&amp;lt;/strong&amp;gt; Never Turn Back – F. E. Parkerson
&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;406&amp;lt;/strong&amp;gt; New Harmony – M. L. A. Lancaster
&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;426t&amp;lt;/strong&amp;gt; Kelley – Amanda Burdette Denson
&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;438&amp;lt;/strong&amp;gt; The Marriage in the Skies – Sidney Burdette Denson
&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;446&amp;lt;/strong&amp;gt; Infinite Day – Ruth Denson Edwards
&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;448b&amp;lt;/strong&amp;gt; The Grieved Soul – M. A. Hendon
&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;460&amp;lt;/strong&amp;gt; Sardis – Sarah Lancaster
&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;466&amp;lt;/strong&amp;gt; Haynes Creek – Joyce Harrison
&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;491&amp;lt;/strong&amp;gt; Oh, What Love – Eula Denson Johnson
&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;504&amp;lt;/strong&amp;gt; Wood Street – Judy Hauff
&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;534&amp;lt;/strong&amp;gt; New Georgia – Ruth Denson Edwards
&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;543&amp;lt;/strong&amp;gt; Thou Art God – Ruth Denson Edwards
&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;545&amp;lt;/strong&amp;gt; The Pilgrim&apos;s Way – Irene Parker Denson
&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;547&amp;lt;/strong&amp;gt; Granville – Judy Hauff
&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;551&amp;lt;/strong&amp;gt; Jacob&apos;s Vision – Margaret Wright
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;h2 id=&quot;toc_1&quot;&amp;gt;
What proportion of songs in the book are by female composers?
&amp;lt;/h2&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
4.5% (25) of songs in the book are by female composers. 84.3% (467) of songs
are by male composers. 11.2% (62) of songs are by composers of unknown gender.
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;h2 id=&quot;toc_2&quot;&amp;gt;What proportion of the composers in the book are female?&amp;lt;/h2&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
8.7% (18) of the named composers in the book are female. 91.3% (190) of the
named composers are male. I didn&apos;t count songs in the book
&amp;lt;a href=&quot;#unknown-gender&quot;&amp;gt;where I couldn&apos;t attribute a gender&amp;lt;/a&amp;gt; to the
composer for this.
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;h2 id=&quot;toc_3&quot;&amp;gt;
How likely are female composers to have multiple songs in the book?
&amp;lt;/h2&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
Getting useful averages on how many songs female and male composer have in the
book was really hard as the data is really skewed. Small numbers of men and
women have a lot more songs than all the other composers of their gender.
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;This is the best way I could find of describing the data.&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
17% (3) of female composers and 36% (67) of male composers individually have
more than 1 song in the book.
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
Some composers who have 1 song in the 1991 edition had more songs in earlier
editions.
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;h2 id=&quot;toc_4&quot;&amp;gt;How popular are the songs by female composers?&amp;lt;/h2&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
I used
&amp;lt;a href=&quot;https://fasola.org/minutes/stats/?s=c&quot;&amp;gt;
the data from minuted Sacred Harp singings from 1995-2017
&amp;lt;/a&amp;gt;
to work out how many times each song by a female composer has been called as a
proportion of all the songs called.
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
If all 554 songs in the book were led equally, 4.15% of all songs led in
minuted singings would be by female composers. 4.28% of all songs led in
minuted singings from 1995-2017 were by female composers. 1 in every 24 songs
in the book is by a female composer. 1 in every 23 songs led at a minuted
singing from 1995-2017 is by a female composer.
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;h2 id=&quot;toc_6&quot;&amp;gt;What are the most popular songs by female composers?&amp;lt;/h2&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
If all 554 songs in the book were led equally, each song would be led 0.18% (1
in every 554) of the time. 9 of the 25 songs in the book by female composers
are more popular than that.
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
Here are the songs by female composers sorted by the percentage of all songs
led in minuted singing 1995-2017 that that particular song has been led. The
percentages are rounded to 2 decimal places. The 1 in N figure is from the
unrounded percentage which is why there&apos;s a slight discrepancy sometimes.
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
By comparison, 146 Hallelujah – the song in the book that has been led most
often – accounts for 0.8% (1 in every 125) of all songs led 1995-2017.
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;0.56% (1 in 177)&amp;lt;/strong&amp;gt; – &amp;lt;strong&amp;gt;112&amp;lt;/strong&amp;gt; The Last Words of
Copernicus – Sarah Lancaster
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;0.43% (1 in 235)&amp;lt;/strong&amp;gt; – &amp;lt;strong&amp;gt;460&amp;lt;/strong&amp;gt; Sardis – Sarah
Lancaster
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;0.34% (1 in 290)&amp;lt;/strong&amp;gt; – &amp;lt;strong&amp;gt;128&amp;lt;/strong&amp;gt; The Promised Land –
M. Durham
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;0.34% (1 in 291)&amp;lt;/strong&amp;gt; – &amp;lt;strong&amp;gt;504&amp;lt;/strong&amp;gt; Wood Street – Judy
Hauff
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;0.34% (1 in 298)&amp;lt;/strong&amp;gt; – &amp;lt;strong&amp;gt;448b&amp;lt;/strong&amp;gt; The Grieved Soul –
M. A. Hendon
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;0.29% (1 in 341)&amp;lt;/strong&amp;gt; – &amp;lt;strong&amp;gt;547&amp;lt;/strong&amp;gt; Granville – Judy
Hauff
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;0.27% (1 in 374)&amp;lt;/strong&amp;gt; – &amp;lt;strong&amp;gt;551&amp;lt;/strong&amp;gt; Jacob&apos;s Vision –
Margaret Wright
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;0.20% (1 in 489)&amp;lt;/strong&amp;gt; – &amp;lt;strong&amp;gt;426t&amp;lt;/strong&amp;gt; Kelley – Amanda
Burdette Denson
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;0.19% (1 in 522)&amp;lt;/strong&amp;gt; – &amp;lt;strong&amp;gt;378b&amp;lt;/strong&amp;gt; Never Turn Back – F.
E. Parkerson
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;0.16% (1 in 627)&amp;lt;/strong&amp;gt; – &amp;lt;strong&amp;gt;77b&amp;lt;/strong&amp;gt; Holcombe – Charlene
Wallace
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;0.12% (1 in 811)&amp;lt;/strong&amp;gt; – &amp;lt;strong&amp;gt;345b&amp;lt;/strong&amp;gt; I&apos;m On My Journey
Home – Sarah Lancaster
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;0.12% (1 in 813)&amp;lt;/strong&amp;gt; – &amp;lt;strong&amp;gt;406&amp;lt;/strong&amp;gt; New Harmony – M. L.
A. Lancaster
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;0.11% (1 in 909)&amp;lt;/strong&amp;gt; – &amp;lt;strong&amp;gt;275b&amp;lt;/strong&amp;gt; Roll On – Cynthia
Bass
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;0.09% (1 in 1059)&amp;lt;/strong&amp;gt; – &amp;lt;strong&amp;gt;368&amp;lt;/strong&amp;gt; Stony Point – Judy
Hauff
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;0.09% (1 in 1059)&amp;lt;/strong&amp;gt; – &amp;lt;strong&amp;gt;446&amp;lt;/strong&amp;gt; Infinite Day – Ruth
Denson Edwards
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;0.09% (1 in 1093)&amp;lt;/strong&amp;gt; – &amp;lt;strong&amp;gt;543&amp;lt;/strong&amp;gt; Thou Art God – Ruth
Denson Edwards
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;0.08% (1 in 1259)&amp;lt;/strong&amp;gt; – &amp;lt;strong&amp;gt;438&amp;lt;/strong&amp;gt; The Marriage in the
Skies – Sidney Burdette Denson
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;0.07% (1 in 1351)&amp;lt;/strong&amp;gt; – &amp;lt;strong&amp;gt;491&amp;lt;/strong&amp;gt; Oh, What Love – Eula
Denson Johnson
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;0.07% (1 in 1413)&amp;lt;/strong&amp;gt; – &amp;lt;strong&amp;gt;534&amp;lt;/strong&amp;gt; New Georgia – Ruth
Denson Edwards
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;0.07% (1 in 1458)&amp;lt;/strong&amp;gt; – &amp;lt;strong&amp;gt;466&amp;lt;/strong&amp;gt; Haynes Creek – Joyce
Harrison
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;0.07% (1 in 1530)&amp;lt;/strong&amp;gt; – &amp;lt;strong&amp;gt;348t&amp;lt;/strong&amp;gt; Ainslie – Judy
Hauff
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;0.05% (1 in 1912)&amp;lt;/strong&amp;gt; – &amp;lt;strong&amp;gt;26&amp;lt;/strong&amp;gt; Samaria – Maggie
Denson Cagle
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;0.04% (1 in 2685)&amp;lt;/strong&amp;gt; – &amp;lt;strong&amp;gt;367&amp;lt;/strong&amp;gt; Consolation – Annie
Denson Aaron
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;0.04% (1 in 2740)&amp;lt;/strong&amp;gt; – &amp;lt;strong&amp;gt;374&amp;lt;/strong&amp;gt; Oh, Sing With Me! –
P. R. Lancaster
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;0.03% (1 in 3095)&amp;lt;/strong&amp;gt; – &amp;lt;strong&amp;gt;545&amp;lt;/strong&amp;gt; The Pilgrim&apos;s Way –
Irene Parker Denson
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;h2 id=&quot;toc_5&quot;&amp;gt;
Has the popularity of songs by female composers changed over time?
&amp;lt;/h2&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
Songs by female composers &amp;lt;em&amp;gt;have&amp;lt;/em&amp;gt; become more popular since 1995.
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
In 1995 – the year where songs by female composers were least popular – 1 in
every 25 songs led at a minuted singing was by a female composer. By
comparison, in 2017 – when female composers&apos; songs were most popular – 1 in
every 21 songs was by a female composer.
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;h2 id=&quot;toc_8&quot;&amp;gt;
Which songs by female composers have changed the most in the popularity over
time?
&amp;lt;/h2&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
The data here compares the popularity of songs by female composers between a)
1995-1997 and b) 2015-2017 as a 3 year average % of all songs by female
composers.
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
Choosing a 3 year average seemed a bit arbitary but the same songs came out on
top whether I compared a 1 year average (1995 vs 2017) or a 2 (1995-1997 vs
2016-2017), 4, or 5 year average. The eight songs below were all in the top 10
for standard deviation in popularity of female composers&apos; song across the
full period of 1995-2017. This suggests the popularity of these songs has
varied markedly across the full period.
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
The four songs by female composers that have increased in popularity the most
are:
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;+4.52%&amp;lt;/strong&amp;gt; – &amp;lt;strong&amp;gt;547&amp;lt;/strong&amp;gt; Granville – Judy Hauff
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;+3.13%&amp;lt;/strong&amp;gt; – &amp;lt;strong&amp;gt;504&amp;lt;/strong&amp;gt; Wood Street – Judy Hauff
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;+2.93&amp;lt;/strong&amp;gt; – &amp;lt;strong&amp;gt;534&amp;lt;/strong&amp;gt; New Georgia – Ruth Denson
Edwards
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;+2.84%&amp;lt;/strong&amp;gt; – &amp;lt;strong&amp;gt;466&amp;lt;/strong&amp;gt; Haynes Creek – Joyce Harrison
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
The four songs that have decreased the most in popularity in that timeframe
are:
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;-4.8%&amp;lt;/strong&amp;gt; – &amp;lt;strong&amp;gt;460&amp;lt;/strong&amp;gt; Sardis – Sarah Lancaster
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;-4.64%&amp;lt;/strong&amp;gt; – &amp;lt;strong&amp;gt;426t&amp;lt;/strong&amp;gt; Kelley – Amanda Burdette
Denson
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;-3.22%&amp;lt;/strong&amp;gt; – &amp;lt;strong&amp;gt;275b&amp;lt;/strong&amp;gt; Roll On – Cynthia Bass
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;strong&amp;gt;-2.74%&amp;lt;/strong&amp;gt; – &amp;lt;strong&amp;gt;378b&amp;lt;/strong&amp;gt; Never Turn Back – F. E.
Parkerson
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;h2 id=&quot;toc_7&quot;&amp;gt;How I attributed gender to composers&amp;lt;/h2&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
I used the composer names as given in the book to attribute gender. In
general, if Wikipedia says a given name is predominantly used for men then I
assumed a composer with that name was male. Clearly, there are some potential
issues with that approach.
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
Some songs in the book give the name for the composer which is not the name of
the person who wrote the song. There would be arguments for assigning the song
to the original composer rather than the attributed composer but I decided not
to get into that.
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
A song which is attributed in the book to a male composer is counted as being
by a male composer even if it was written by a woman. A song which is
attributed to a female composer is counted as being by a female composer even
if it was written by a man.
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p id=&quot;unknown-gender&quot;&amp;gt;
Songs where there is no clear composer are counted as unknown, neither male
nor female. This accounts for 62 songs. This includes songs where: a) only a
surname is given (410t The Dying Californian – Ball), b) a songbook is given
as the source of the tune (28t Aylesbury – A Book of Psalmody), and c) no
source is given (43 Primrose Hill). I haven&apos;t delved into the sources of those
tunes but it is very likely that the overwhelming majority of songs in these
three groups was written by men.
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
90 of the composers in the book use their initials instead of their first
name. I assumed that they were male unless I found out that they were female.
(M. Durham, P. R. Lancaster, and M. L. A. Lancaster are female composers.) It
seems particularly likely that I&apos;ve made mistakes because of this assumption.
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
Finally, I have doubtless made mistakes in assigning a gender to some of the
composers even considering the process above. The data I used is available
here as
&amp;lt;a href=&quot;/files/sacred-harp-composers/sacredharpcomposers.xls&quot;&amp;gt;an Excel (.xls) spreadsheet&amp;lt;/a&amp;gt;.
&amp;lt;a href=&quot;mailto:mail@edjohnsonwilliams.co.uk&quot;&amp;gt;Let me know&amp;lt;/a&amp;gt; if you see any
mistakes.
&amp;lt;/p&amp;gt;&lt;/p&gt;
</content:encoded></item><item><title>Winners and Losers in the City of Durham Parish Council Election</title><link>https://edjohnsonwilliams.co.uk/blog/2018-05-04-winners-and-losers-in-the-city-of-durham-parish-council-election/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2018-05-04-winners-and-losers-in-the-city-of-durham-parish-council-election/</guid><pubDate>Fri, 04 May 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Yesterday saw the first &lt;a href=&quot;https://www.durham.gov.uk/durhamcityelection&quot;&gt;City of Durham Parish Council Election&lt;/a&gt;. Considering it was the first election of its type, it would have been handy if &lt;a href=&quot;https://twitter.com/_edjw/status/991946855562076160&quot;&gt;the council had told people&lt;/a&gt; how the electoral system would work.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://www.durham.gov.uk/media/24199/Community-Governance-Review-City-of-Durham-Parish-Boundary-and-Wards/pdf/CityOfDurhamParishBoundaryAndWards2017.pdf&quot;&gt;parish council is divided into three wards&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;Elvet and Gilesgate (six councillors) — &lt;a href=&quot;https://www.durham.gov.uk/media/24668/Declaration-of-Result-City-of-Durham-Parish-Elvet-and-Gilesgate-Ward/pdf/DeclarationOfResult-CityOfDurhamElvetAndGilesgateWard.pdf&quot;&gt;results&lt;/a&gt;
Neville&apos;s Cross (eight councillors) — &lt;a href=&quot;https://www.durham.gov.uk/media/24669/Declaration-of-Result-City-of-Durham-Parish-Nevilles-Cross-Ward/pdf/DeclarationOfResult-CityOfDurhamNevillesCrossWard1.pdf&quot;&gt;results&lt;/a&gt;
Durham South (one councillor) — &lt;a href=&quot;https://www.durham.gov.uk/media/24667/Declaration-of-Result-City-of-Durham-Parish-Durham-South-Ward/pdf/DeclarationOfResult-CityOfDurhamDurhamSouthWard.pdf&quot;&gt;results&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Nearly all the candidates stood for a party but you voted for the candidates rather than the party. If you live in a ward with six councillors, you can vote for up to six candidates and the six candidates with the most votes win. It&apos;s &lt;a href=&quot;https://en.wikipedia.org/wiki/First-past-the-post_voting&quot;&gt;first-past-the-post&lt;/a&gt; in a multi-member constituency.&lt;/p&gt;
&lt;p&gt;I ran &lt;a href=&quot;https://docs.google.com/spreadsheets/d/1Zd9AObNK9Lg9brqe4iERKLBiPNTHiYNtGNFHWOtvqRo/edit?usp=sharing&quot;&gt;some numbers on the results&lt;/a&gt;. Fun times.
(Thanks to &lt;a href=&quot;https://github.com/tabulapdf/tabula&quot;&gt;Tabula&lt;/a&gt; and specifically the &lt;a href=&quot;https://github.com/chezou/tabula-py&quot;&gt;tabula-py&lt;/a&gt; Python wrapper for Tabula that helped with exporting the table of results from Durham County Council&apos;s PDFs into CSVs.)&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.durham.gov.uk/media/24669/Declaration-of-Result-City-of-Durham-Parish-Nevilles-Cross-Ward/pdf/DeclarationOfResult-CityOfDurhamNevillesCrossWard1.pdf&quot;&gt;&lt;strong&gt;Aggregated &lt;em&gt;Neville&apos;s Cross&lt;/em&gt; Results&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The quirks of the system are clearest in the Neville&apos;s Cross ward.&lt;/p&gt;
&lt;h2&gt;&amp;lt;table class=&quot;border-collapse border-spacing-0&quot;&amp;gt;
&amp;lt;tr class=&quot;border border-black&quot;&amp;gt;
&amp;lt;th class=&quot;overflow-hidden border border-black px-1 py-3 font-semibold&quot;&amp;gt;
PARTY
&amp;lt;/th&amp;gt;
&amp;lt;th class=&quot;overflow-hidden border border-black px-1 py-3 font-semibold&quot;&amp;gt;
VOTES
&amp;lt;/th&amp;gt;
&amp;lt;th class=&quot;overflow-hidden border border-black px-1 py-3 font-semibold&quot;&amp;gt;
SEATS WON
&amp;lt;/th&amp;gt;
&amp;lt;th class=&quot;overflow-hidden border border-black px-1 py-3 font-semibold&quot;&amp;gt;
NUM OF CANDIDATES
&amp;lt;/th&amp;gt;
&amp;lt;th class=&quot;overflow-hidden border border-black px-1 py-3 font-semibold&quot;&amp;gt;
AVG VOTES PER CANDIDATE
&amp;lt;/th&amp;gt;
&amp;lt;th class=&quot;overflow-hidden border border-black px-1 py-3 font-semibold&quot;&amp;gt;
% VOTES
&amp;lt;/th&amp;gt;
&amp;lt;th class=&quot;overflow-hidden border border-black px-1 py-3 font-semibold&quot;&amp;gt;
% SEATS
&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr class=&quot;border border-black&quot;&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black&quot;&amp;gt;LD&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black&quot;&amp;gt;7098&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black&quot;&amp;gt;4&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black&quot;&amp;gt;8&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black&quot;&amp;gt;887&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black&quot;&amp;gt;41.5&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black&quot;&amp;gt;50&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr class=&quot;border border-black&quot;&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-red-600 text-white&quot;&amp;gt;
LAB
&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-red-600 text-white&quot;&amp;gt;
4031
&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-red-600 text-white&quot;&amp;gt;2&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-red-600 text-white&quot;&amp;gt;6&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-red-600 text-white&quot;&amp;gt;
672
&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-red-600 text-white&quot;&amp;gt;
23.5
&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-red-600 text-white&quot;&amp;gt;
25
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr class=&quot;border border-black&quot;&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-lime-600 text-white&quot;&amp;gt;
GREEN
&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-lime-600 text-white&quot;&amp;gt;
3012
&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-lime-600 text-white&quot;&amp;gt;
1
&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-lime-600 text-white&quot;&amp;gt;
4
&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-lime-600 text-white&quot;&amp;gt;
753
&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-lime-600 text-white&quot;&amp;gt;
17.6
&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-lime-600 text-white&quot;&amp;gt;
12.5
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr class=&quot;border border-black&quot;&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-sky-700 text-white&quot;&amp;gt;
CON
&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-sky-700 text-white&quot;&amp;gt;
1241
&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-sky-700 text-white&quot;&amp;gt;0&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-sky-700 text-white&quot;&amp;gt;3&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-sky-700 text-white&quot;&amp;gt;
414
&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-sky-700 text-white&quot;&amp;gt;
7.2
&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-sky-700 text-white&quot;&amp;gt;0&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr class=&quot;border border-black&quot;&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-stone-300&quot;&amp;gt;IND 2&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-stone-300&quot;&amp;gt;823&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-stone-300&quot;&amp;gt;1&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-stone-300&quot;&amp;gt;1&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-stone-300&quot;&amp;gt;823&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-stone-300&quot;&amp;gt;4.8&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-stone-300&quot;&amp;gt;12.5&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr class=&quot;border border-black&quot;&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-stone-300&quot;&amp;gt;IND 1&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-stone-300&quot;&amp;gt;566&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-stone-300&quot;&amp;gt;0&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-stone-300&quot;&amp;gt;1&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-stone-300&quot;&amp;gt;566&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-stone-300&quot;&amp;gt;3.3&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-stone-300&quot;&amp;gt;0&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr class=&quot;border border-black&quot;&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-stone-300&quot;&amp;gt;IND 3&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-stone-300&quot;&amp;gt;353&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-stone-300&quot;&amp;gt;0&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-stone-300&quot;&amp;gt;1&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-stone-300&quot;&amp;gt;353&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-stone-300&quot;&amp;gt;2.1&amp;lt;/td&amp;gt;
&amp;lt;td class=&quot;overflow-hidden border border-black bg-stone-300&quot;&amp;gt;0&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Three Green candidates in Neville&apos;s Cross got more votes than the average Labour candidate. But only one Green candidate was elected whereas two Labour candidates were elected.&lt;/li&gt;
&lt;li&gt;Green candidates got more votes on average than Labour candidates but two Labour candidates were elected and only one Green candidate was elected.&lt;/li&gt;
&lt;li&gt;One Lib Dem candidate got more votes than the average Labour and Green candidate. But she didn&apos;t get elected even though Labour and the Greens won two seats and one seat respectively.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It looks like Green voters ran out of Green candidates to vote for. With their remaining votes it seems likely that they voted for Labour candidates with the effect of boosting Labour candidates above Green candidates.&lt;/p&gt;
&lt;p&gt;It&apos;s important to note that two Labour candidates who won seats got significantly more support than the other Labour candidates. I&apos;m not sure but lots of voters could know them personally.&lt;/p&gt;
&lt;p&gt;So key takeaways are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;If you support a single party, vote for all the candidates from that party and don&apos;t vote for any others. Just don&apos;t use all your votes. If you do, you risk boosting them above the candidates from your most-preferred party.&lt;/li&gt;
&lt;li&gt;If you&apos;re a political party in one of these elections, do everything you can to field the maximum number of candidates. It ensures that supporters of your party just vote for your candidates and don&apos;t boost other parties&apos; candidates above your most popular candidate(s).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Despite the quirks, for a first-past-the-post election, these results were &lt;em&gt;relatively&lt;/em&gt; proportional. In general, the Greens suffered the most. I &lt;a href=&quot;http://www.dhondt.eu/js/&quot;&gt;used this website&lt;/a&gt; to project what the results would have been under one type of proportional representation where voters voted for a party rather than individual candidates. The Greens would have won two extra seats overall across the city.&lt;/p&gt;
</content:encoded></item><item><title>How often is 1st January a Monday?</title><link>https://edjohnsonwilliams.co.uk/blog/2018-01-02-how-often-is-1st-january-a-monday/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2018-01-02-how-often-is-1st-january-a-monday/</guid><pubDate>Tue, 02 Jan 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Answer...less often than every other day except Saturday. I have no idea why.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Yesterday, 1st January 2018 was a Monday. Monday is the first day of the week. Some people think Sunday is the first day of the week. I don&apos;t understand those people.&lt;/p&gt;
&lt;p&gt;Anyway, it made me wonder...How often has the first day of the week been the first day of the year? And how many years will we have to wait until the first day of the year is a Monday again?&lt;/p&gt;
&lt;p&gt;I wrote some &lt;a href=&quot;#that-bad-repetitive-python&quot;&gt;bad, repetitive Python code&lt;/a&gt; (also &lt;a href=&quot;https://github.com/edjw/how-often-is-1st-january-a-monday/&quot;&gt;on Github)&lt;/a&gt; to work this out. I also made some bad, repetitive use of the &lt;a href=&quot;https://plot.ly/python/&quot;&gt;Plotly Python Library&lt;/a&gt; to make some bar charts.&lt;/p&gt;
&lt;p&gt;For some reason, 1st January doesn&apos;t spread evenly among all the days of the week. One in 7 is 14.29%. 1st January is a Monday or Saturday 14% of the time; Wednesday or Thursday 14.25% of the time; and Tuesday, Friday or Sunday 14.5% of the time.&lt;/p&gt;
&lt;h1&gt;From the year 1 AD to 2018&lt;/h1&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Day of week&lt;/th&gt;
&lt;th&gt;Times 1st Jan has been X day&lt;/th&gt;
&lt;th&gt;Avg years to wait&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Monday&lt;/td&gt;
&lt;td&gt;283&lt;/td&gt;
&lt;td&gt;7.15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tuesday&lt;/td&gt;
&lt;td&gt;293&lt;/td&gt;
&lt;td&gt;6.89&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wednesday&lt;/td&gt;
&lt;td&gt;287&lt;/td&gt;
&lt;td&gt;7.03&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Thursday&lt;/td&gt;
&lt;td&gt;288&lt;/td&gt;
&lt;td&gt;7.01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Friday&lt;/td&gt;
&lt;td&gt;292&lt;/td&gt;
&lt;td&gt;6.89&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Saturday&lt;/td&gt;
&lt;td&gt;282&lt;/td&gt;
&lt;td&gt;7.14&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sunday&lt;/td&gt;
&lt;td&gt;293&lt;/td&gt;
&lt;td&gt;6.89&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;These are the number of times 1st January has fallen on X day of the week since the year 1 AD (the earliest year Python can work with in its standard library). It also shows the mean average number of years we have to wait from 1st January being X day of the week until the next time it happens.&lt;/p&gt;
&lt;p&gt;There are three groupings of frequency of 1st January being X day of the week.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Tuesdays (293 since the year 1 AD), Fridays (292) and Sundays (293) -- 14.51%&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Wednesdays (287) and Thursdays (288)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mondays (283) and Saturdays (282)&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Somebody (else) probably has an explanation for why this happens.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The next time 1st January is a Monday is 2024 (in 6 years). The previous time was 2007 (11 years ago).&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;]&lt;/p&gt;
&lt;p&gt;]&lt;/p&gt;
&lt;h1&gt;From the year 1 AD to 9999&lt;/h1&gt;
&lt;p&gt;To test that a bit further I tried it from 1AD to the year 9999 as well. (9999 is the maximum year Python can work with in its standard library.) The results are as good as exactly the same.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Day of week&lt;/th&gt;
&lt;th&gt;Times 1st Jan has been X day&lt;/th&gt;
&lt;th&gt;Avg years to wait&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Monday&lt;/td&gt;
&lt;td&gt;1400&lt;/td&gt;
&lt;td&gt;7.14&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tuesday&lt;/td&gt;
&lt;td&gt;1450&lt;/td&gt;
&lt;td&gt;6.89&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wednesday&lt;/td&gt;
&lt;td&gt;1425&lt;/td&gt;
&lt;td&gt;7.02&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Thursday&lt;/td&gt;
&lt;td&gt;1425&lt;/td&gt;
&lt;td&gt;7.02&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Friday&lt;/td&gt;
&lt;td&gt;1450&lt;/td&gt;
&lt;td&gt;6.89&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Saturday&lt;/td&gt;
&lt;td&gt;1399&lt;/td&gt;
&lt;td&gt;7.15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sunday&lt;/td&gt;
&lt;td&gt;1450&lt;/td&gt;
&lt;td&gt;6.89&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;And just to check that there&apos;s no change over time in how often a 1st January is X day of the week...&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;There&apos;s no change over time in the rate of X day of the week being 1st January. (The days in the original three groupings overlap.)&lt;/p&gt;
&lt;h1&gt;That bad, repetitive Python&lt;/h1&gt;
&lt;p&gt;In case you want to work with this here&apos;s that bad, repetitive code I used. It&apos;s &lt;a href=&quot;https://github.com/edjw/how-often-is-1st-january-a-monday/&quot;&gt;also on Github&lt;/a&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
    from datetime import datetime
    from statistics import mean
    import plotly
    import plotly.graph_objs as go

    # year = int(datetime.today().strftime(&quot;%Y&quot;))  # 2018 at the moment
    year = 9999  # the latest year you can use


    def get_first_jan_weekdays(year):
        mondays = []  # &quot;2018, 2007, 2001&quot;
        tuesdays = []
        wednesdays = []
        thursdays = []
        fridays = []
        saturdays = []
        sundays = []

        while year &amp;gt;= 1:
            day_of_week_first_jan = datetime(year, 1, 1).strftime(&quot;%A&quot;)

            if day_of_week_first_jan == &apos;Monday&apos;:
                mondays.append(year)
            elif day_of_week_first_jan == &apos;Tuesday&apos;:
                tuesdays.append(year)
            elif day_of_week_first_jan == &apos;Wednesday&apos;:
                wednesdays.append(year)
            elif day_of_week_first_jan == &apos;Thursday&apos;:
                thursdays.append(year)
            elif day_of_week_first_jan == &apos;Friday&apos;:
                fridays.append(year)
            elif day_of_week_first_jan == &apos;Saturday&apos;:
                saturdays.append(year)
            elif day_of_week_first_jan == &apos;Sunday&apos;:
                sundays.append(year)

            year -= 1

        return mondays, tuesdays, wednesdays, thursdays, fridays, saturdays, sundays


    def first_jans_over_time(mondays, tuesdays, wednesdays, thursdays, fridays,
                                saturdays, sundays):
        mondays_over_time = sorted(mondays)
        tuesdays_over_time = sorted(tuesdays)
        wednesdays_over_time = sorted(wednesdays)
        thursdays_over_time = sorted(thursdays)
        fridays_over_time = sorted(fridays)
        saturdays_over_time = sorted(saturdays)
        sundays_over_time = sorted(sundays)

        return mondays_over_time, tuesdays_over_time, wednesdays_over_time, thursdays_over_time, fridays_over_time, saturdays_over_time, sundays_over_time


    def get_number_of_first_jan_weekdays(mondays, tuesdays, wednesdays, thursdays,
                                            fridays, saturdays, sundays):
        total_mondays = len(mondays)
        total_tuesdays = len(tuesdays)
        total_wednesdays = len(wednesdays)
        total_thursdays = len(thursdays)
        total_fridays = len(fridays)
        total_saturdays = len(saturdays)
        total_sundays = len(sundays)

        return total_mondays, total_tuesdays, total_wednesdays, total_thursdays, total_fridays, total_saturdays, total_sundays


    def get_avg_wait_between_years(mondays, tuesdays, wednesdays, thursdays,
                                    fridays, saturdays, sundays):
        # 1st num minus 2nd num
        mon_waits = [s - t for s, t in zip(mondays, mondays[1:])]
        # mean difference rounded to 2 decimal places
        mon_avg_wait = round(mean(mon_waits), 2)

        tues_waits = [s - t for s, t in zip(tuesdays, tuesdays[1:])]
        tues_avg_wait = round(mean(tues_waits), 2)

        wed_waits = [s - t for s, t in zip(wednesdays, wednesdays[1:])]
        wed_avg_wait = round(mean(wed_waits), 2)

        thurs_waits = [s - t for s, t in zip(thursdays, thursdays[1:])]
        thurs_avg_wait = round(mean(thurs_waits), 2)

        fri_waits = [s - t for s, t in zip(fridays, fridays[1:])]
        fri_avg_wait = round(mean(fri_waits), 2)

        sat_waits = [s - t for s, t in zip(saturdays, saturdays[1:])]
        sat_avg_wait = round(mean(sat_waits), 2)

        sun_waits = [s - t for s, t in zip(sundays, sundays[1:])]
        sun_avg_wait = round(mean(sun_waits), 2)

        return mon_avg_wait, tues_avg_wait, wed_avg_wait, thurs_avg_wait, fri_avg_wait, sat_avg_wait, sun_avg_wait


    def generate_first_jan_over_time_line_chart(*args):

        trace0 = go.Scatter(
            x=mondays_over_time, name=&apos;Mondays&apos;, line=dict(color=(&apos;red&apos;), width=3))

        trace1 = go.Scatter(
            x=tuesdays_over_time,
            name=&apos;Tuesdays&apos;,
            line=dict(color=(&apos;blue&apos;), width=3))

        trace2 = go.Scatter(
            x=wednesdays_over_time,
            name=&apos;Wednesdays&apos;,
            line=dict(color=(&apos;yellow&apos;), width=3))

        trace3 = go.Scatter(
            x=thursdays_over_time,
            name=&apos;Thursdays&apos;,
            line=dict(color=(&apos;green&apos;), width=3))

        trace4 = go.Scatter(
            x=fridays_over_time,
            name=&apos;Fridays&apos;,
            line=dict(color=(&apos;black&apos;), width=3))

        trace5 = go.Scatter(
            x=saturdays_over_time,
            name=&apos;Saturdays&apos;,
            line=dict(color=(&apos;pink&apos;), width=3))

        trace6 = go.Scatter(
            x=sundays_over_time,
            name=&apos;Sundays&apos;,
            line=dict(color=(&apos;orange&apos;), width=3))

        data = [trace0, trace1, trace2, trace3, trace4, trace5, trace6]

        layout = go.Layout(
            title=&quot;Number of times 1st Jan is X day over time&quot;,
            xaxis=dict(title=&quot;Instance of X day as 1st January&quot;, range=[0, 10001]),
            yaxis=dict(title=&quot;Year from 1 AD to 9999&quot;, range=[0, 1400]),
        )

        plotly.offline.plot({&quot;data&quot;: data, &quot;layout&quot;: layout})


    def generate_totals_bar_chart(*args):
        y_axis_data = []
        for arg in args:
            y_axis_data.append(arg)

        data = [
            go.Bar(
                x=[
                    &quot;Mondays&quot;, &quot;Tuesdays&quot;, &quot;Wednesdays&quot;, &quot;Thursday&quot;, &quot;Fridays&quot;,
                    &quot;Saturdays&quot;, &quot;Sundays&quot;
                ],
                y=y_axis_data)
        ]

        layout = go.Layout(
            title=&quot;How often is 1st January a Monday? From the year 1 to 9999&quot;,
            xaxis=dict(title=&quot;Days of the week&quot;),
            yaxis=dict(
                title=&quot;Number of times 1st January has been X day&quot;,
                range=[1350, 1460]),
        )

        plotly.offline.plot({&quot;data&quot;: data, &quot;layout&quot;: layout})


    def generate_avgs_barchart(*args):
        y_axis_data = []
        for arg in args:
            y_axis_data.append(arg)

        data = [
            go.Bar(
                x=[
                    &quot;Mondays&quot;, &quot;Tuesdays&quot;, &quot;Wednesdays&quot;, &quot;Thursday&quot;, &quot;Fridays&quot;,
                    &quot;Saturdays&quot;, &quot;Sundays&quot;
                ],
                y=y_axis_data)
        ]

        layout = go.Layout(
            title=
            &quot;How many years until it&apos;s a Monday again? From the year 1 to 9999&quot;,
            xaxis=dict(title=&quot;Days of the week&quot;),
            yaxis=dict(title=&quot;Average (mean) years to wait&quot;, range=[6.5, 7.5]),
        )

        plotly.offline.plot({&quot;data&quot;: data, &quot;layout&quot;: layout})


    mondays, tuesdays, wednesdays, thursdays, fridays, saturdays, sundays = get_first_jan_weekdays(
        year)

    total_mondays, total_tuesdays, total_wednesdays, total_thursdays, total_fridays, total_saturdays, total_sundays = get_number_of_first_jan_weekdays(
        mondays, tuesdays, wednesdays, thursdays, fridays, saturdays, sundays)

    mon_avg_wait, tues_avg_wait, wed_avg_wait, thurs_avg_wait, fri_avg_wait, sat_avg_wait, sun_avg_wait = get_avg_wait_between_years(
        mondays, tuesdays, wednesdays, thursdays, fridays, saturdays, sundays)

    mondays_over_time, tuesdays_over_time, wednesdays_over_time, thursdays_over_time, fridays_over_time, saturdays_over_time, sundays_over_time = first_jans_over_time(
        mondays, tuesdays, wednesdays, thursdays, fridays, saturdays, sundays)

    # generate_totals_bar_chart(total_mondays, total_tuesdays, total_wednesdays, total_thursdays, total_fridays, total_saturdays, total_sundays)

    # generate_avgs_barchart(mon_avg_wait, tues_avg_wait, wed_avg_wait, thurs_avg_wait, fri_avg_wait, sat_avg_wait, sun_avg_wait)

    # generate_first_jan_over_time_line_chart(mondays_over_time, tuesdays_over_time, wednesdays_over_time, thursdays_over_time, fridays_over_time, saturdays_over_time, sundays_over_time)

&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>When does Easter Sunday fall on April Fools&apos; Day?</title><link>https://edjohnsonwilliams.co.uk/blog/2018-04-01-how-often-does-easter-sunday-fall-on-april-fools-day/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2018-04-01-how-often-does-easter-sunday-fall-on-april-fools-day/</guid><pubDate>Sun, 01 Apr 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Today is both &lt;a href=&quot;https://en.wikipedia.org/wiki/April_Fools&apos;_Day&quot;&gt;April Fools&apos; Day&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Easter&quot;&gt;Easter Sunday&lt;/a&gt; (in &lt;a href=&quot;https://en.wikipedia.org/wiki/Western_Christianity&quot;&gt;Western Christianity&lt;/a&gt;).&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When did this last happen and when will it happen again?&lt;/p&gt;
&lt;p&gt;This is relatively straightforward to find out thanks to &lt;a href=&quot;https://en.wikipedia.org/wiki/Python_(programming_language)&quot;&gt;Python&lt;/a&gt; and specifically the &lt;a href=&quot;https://github.com/dateutil/dateutil&quot;&gt;dateutil&lt;/a&gt; module. Dateutil makes it easy to find out the date of Easter Sunday for any given year between 1583 and 4099. The code I used for this is right at the bottom of this post.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The last time April Fools&apos; Day was on Easter Sunday was 1956 – 62 years ago. And the next time will be in 2029 – only 11 more years!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Here&apos;s a full list of years where Western Easter Sunday is on April Fools&apos; Day.&lt;/p&gt;
&lt;p&gt;1584
1646
1657
1668
1714
1725
1736
1804
1866
1877
1888
1923
1934
1945
1956
2018
2029
2040
2108
2170
2181
2192
2238
2249
2260
2306
2317
2328
2401
2412
2485
2496
2553
2564
2610
2621
2632
2700
2762
2773
2784
2857
2863
2868
2925
2936
3004
3077
3088
3145
3156
3235
3240
3308
3387
3392
3449
3455
3460
3517
3528
3601
3607
3612
3691
3696
3759
3764
3821
3827
3832
3900
3973
3979
3984
4063
4068
4074&lt;/p&gt;
&lt;h2&gt;The Code&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;
from dateutil.easter import easter

for year in range(1583, 4100):
    easter_full_date = easter(year)
    easter_full_date = str(easter_full_date)
    year, month, date = easter_full_date.split(&quot;-&quot;)

    if date == &quot;01&quot; and month == &quot;04&quot;:
        print(year)
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>Football formations in Sacred Harp numbers</title><link>https://edjohnsonwilliams.co.uk/blog/2018-06-10-football-formations-in-sacred-harp-numbers/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2018-06-10-football-formations-in-sacred-harp-numbers/</guid><pubDate>Sun, 10 Jun 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This is a very silly post.&lt;/p&gt;
&lt;p&gt;I took all &lt;a href=&quot;https://fasola.org/indexes/1991/?v=pagenum&quot;&gt;the song numbers&lt;/a&gt; from &lt;a href=&quot;https://en.wikipedia.org/wiki/Sacred_Harp&quot;&gt;the Sacred Harp&lt;/a&gt; and asked the question, &quot;Which song numbers in the Sacred Harp are football/soccer formations?&quot;&lt;/p&gt;
&lt;p&gt;The answer (if you only count modern, &lt;strong&gt;proper&lt;/strong&gt; formations with a forward) is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;343&lt;/em&gt;, &lt;em&gt;352&lt;/em&gt;, &lt;em&gt;361&lt;/em&gt;, &lt;em&gt;424&lt;/em&gt;, &lt;em&gt;433&lt;/em&gt;, &lt;em&gt;442&lt;/em&gt;, &lt;em&gt;451&lt;/em&gt;, &lt;em&gt;532&lt;/em&gt;, and &lt;em&gt;541&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;There&apos;s a great book called &lt;a href=&quot;https://www.orionbooks.co.uk/books/detail.page?isbn=9781409176824&quot;&gt;Inverting the Pyramid&lt;/a&gt; that&apos;s about the history of football formations. A really popular formation in the 1880s was &lt;em&gt;2-3-5&lt;/em&gt;. Some teams in recent years have also experimented with playing without a forward.&lt;/p&gt;
&lt;p&gt;So, if you count all possible formations with 10 outfield players and at least 1 player in defence and midfield (but not necessarily &lt;a href=&quot;https://en.wikipedia.org/wiki/Forward_(association_football)#False_9&quot;&gt;at least 1 forward&lt;/a&gt;) then the full list is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;118&lt;/em&gt;, &lt;em&gt;127&lt;/em&gt;, &lt;em&gt;136&lt;/em&gt;, &lt;em&gt;145t&lt;/em&gt;, &lt;em&gt;145b&lt;/em&gt;, &lt;em&gt;154&lt;/em&gt;, &lt;em&gt;163t&lt;/em&gt;, &lt;em&gt;163b&lt;/em&gt;, &lt;em&gt;172&lt;/em&gt;, &lt;em&gt;181&lt;/em&gt;, &lt;em&gt;217&lt;/em&gt;, &lt;em&gt;235&lt;/em&gt;, &lt;em&gt;271t&lt;/em&gt;, &lt;em&gt;271b,&lt;/em&gt; &lt;em&gt;280&lt;/em&gt;, &lt;em&gt;316&lt;/em&gt;, &lt;em&gt;325&lt;/em&gt;, &lt;em&gt;334&lt;/em&gt;, &lt;em&gt;343&lt;/em&gt;, &lt;em&gt;352&lt;/em&gt;, &lt;em&gt;361&lt;/em&gt;, &lt;em&gt;370&lt;/em&gt;, &lt;em&gt;415&lt;/em&gt;, &lt;em&gt;424&lt;/em&gt;, &lt;em&gt;433&lt;/em&gt;, &lt;em&gt;442&lt;/em&gt;, &lt;em&gt;451&lt;/em&gt;, &lt;em&gt;460&lt;/em&gt;, &lt;em&gt;532&lt;/em&gt;, &lt;em&gt;541&lt;/em&gt;, and &lt;em&gt;550&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And the Python code I used to get the answers to this very silly question…&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
# All song numbers with the t (top) or b (bottom) taken off
song_numbers = [26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 191, 192, 193, 195, 196, 197, 198, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 220, 222, 223, 224, 225, 227, 228, 229, 230, 231, 232, 234, 235, 236, 240, 242, 245, 250, 254, 260, 263, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 306, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 358, 359, 360, 361, 362, 365, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 510, 511, 512, 513, 515, 516, 517, 518, 521, 522, 524, 527, 528, 530, 531, 532, 534, 535, 536, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 553, 556, 558, 560, 562, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573]

total_is_ten = []

for number in song_numbers:
    number_of_digits = len(str(number))

    # Remove numbers from the list that are only 2 digits.
    # Football formations have at least 3 digits in
    if number_of_digits != 3:
        continue

    # Remove numbers from the list with a zero for the middle number
    # No-one plays 0 in defence or midfield. Some teams like Barcelona occasionally play 0 up front
    list_of_digits = [int(digit) for digit in str(number)]
    if min(list_of_digits[1:2]) == 0:
        continue

    # From the remaining numbers in the list, keep it if the sum of the digits in the number is 10
    sum_of_digits = sum(int(digit) for digit in str(number))
    if sum_of_digits == 10:
        total_is_ten.append(number)

print(total_is_ten)

# All results
# 118, 127, 136, 145, 154, 163, 172, 181, 217, 235, 271, 280, 316, 325, 334, 343, 352, 361, 370, 415, 424, 433, 442, 451, 460, 523, 532, 541, 550

# All results where it&apos;s a proper formation nowadays
# 343, 352, 361, 424, 433, 442, 451, 523, 532, 541

&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>Square numbers in Sacred Harp song numbers</title><link>https://edjohnsonwilliams.co.uk/blog/2018-06-10-square-numbers-in-sacred-harp-song-numbers/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2018-06-10-square-numbers-in-sacred-harp-song-numbers/</guid><pubDate>Sun, 10 Jun 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;A singer at the &lt;a href=&quot;https://durhamsacredharp.co.uk/&quot;&gt;Sacred Harp singing in Durham&lt;/a&gt; yesterday was calling only &lt;a href=&quot;https://en.wikipedia.org/wiki/Square_number&quot;&gt;square numbers&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I went and made a list of those numbers.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Square root&lt;/th&gt;
&lt;th&gt;Song number&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;36t&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;36b&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;49t&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;49b&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;64&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;81t&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;81b&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;121&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;144&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;169&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;14&lt;/td&gt;
&lt;td&gt;196&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;225t&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;225b&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;td&gt;289&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;18&lt;/td&gt;
&lt;td&gt;324&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;19&lt;/td&gt;
&lt;td&gt;361&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;400&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;21&lt;/td&gt;
&lt;td&gt;441&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;484&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;And the Python code I used to find this…&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
import math

# All song numbers with the t (top) or b (bottom) taken off
song_numbers = [26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 191, 192, 193, 195, 196, 197, 198, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 220, 222, 223, 224, 225, 227, 228, 229, 230, 231, 232, 234, 235, 236, 240, 242, 245, 250, 254, 260, 263, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 306, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 358, 359, 360, 361, 362, 365, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 510, 511, 512, 513, 515, 516, 517, 518, 521, 522, 523, 524, 527, 528, 530, 531, 532, 534, 535, 536, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 553, 556, 558, 560, 562, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573]

square_numbers = []

for number in song_numbers:

    # find the square root of the song number
    square_root = math.sqrt(number)

    # if the sqrt of the song number is an integer
    if int(square_root) == square_root:

        # add the song number to the list of square numbers
        square_numbers.append(number)

print(square_numbers)
# 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 289, 324, 361, 400, 441, 484

# 36t, 36b, 49t, 49b, 64, 81t, 81b, 100, 121, 144, 169, 196, 225t, 225b, 289, 324, 361, 400, 441, 484

&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>A better way of removing punctuation from a string in Python</title><link>https://edjohnsonwilliams.co.uk/blog/2018-07-06-a-better-way-of-removing-punctuation-from-a-string-in-python/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2018-07-06-a-better-way-of-removing-punctuation-from-a-string-in-python/</guid><pubDate>Fri, 06 Jul 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This post is as a future reminder for me as much as anything.&lt;/p&gt;
&lt;p&gt;I made &lt;a href=&quot;https://github.com/edjw/game-image-resizer&quot;&gt;a Python program&lt;/a&gt; called game-image-resizer a few months ago. It takes a list of board games, finds each board game on &lt;a href=&quot;http://boardgamegeek.com/&quot;&gt;BoardGameGeek&lt;/a&gt;&apos;s API, downloads the best image for each game, does some resizing and editing of the image, and then saves it using a useful filename.&lt;/p&gt;
&lt;p&gt;That final stage of saving as a useful filename meant taking the board game name, making it lower case, removing punctuation, and replacing spaces with underscores.&lt;/p&gt;
&lt;p&gt;I did it like this – roughly using the information in &lt;a href=&quot;https://stackoverflow.com/questions/265960/best-way-to-strip-punctuation-from-a-string-in-python&quot;&gt;this StackOverflow discussion&lt;/a&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
from string import punctuation

# making string lower case
working_string = working_string.lower()

# removing punctuation
remove_punctuation = str.maketrans(&apos;&apos;, &apos;&apos;, punctuation)
working_string = working_string.translate(remove_punctuation)

# replacing spaces and double-spaces with an underscore
working_string = working_string.replace(&quot;  &quot;, &quot;_&quot;)
working_string = working_string.replace(&quot; &quot;, &quot;_&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I found a better, easier-to-use way of doing this earlier this morning on &lt;a href=&quot;https://www.reddit.com/r/Python/comments/8wc2vi/5_rarely_mentioned_but_super_useful_packages_you/&quot;&gt;a Reddit post&lt;/a&gt; in &lt;a href=&quot;https://www.reddit.com/r/Python&quot;&gt;/r/Python&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It uses &lt;a href=&quot;https://inflection.readthedocs.io/en/latest/&quot;&gt;Inflection&lt;/a&gt; – a &quot;string transformation library&quot;. Inflection does all sorts of things including &lt;code&gt;inflection.parameterize().&lt;/code&gt; &lt;a href=&quot;https://inflection.readthedocs.io/en/latest/index.html#inflection.parameterize&quot;&gt;Parameterize&lt;/a&gt; &quot;replace[s] special characters in a string so that it may be used as part of a &apos;pretty&apos; URL.&quot;&lt;/p&gt;
&lt;p&gt;This means I can now do the following which is a much nicer-to-read and nicer-to-write solution.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
from inflection import parameterize

# Example board game names with upper case, punctuation, and non-ASCII characters
board_game_names = [
    &quot;Dawn of the Zeds (Third edition)&quot;,
    &quot;Flash Point: Fire Rescue – Honor &amp;amp; Duty&quot;,
    &quot;Orléans&quot;,
    &quot;Mechs vs. Minions&quot;,
    &quot;Tzolk&apos;in: The Mayan Calendar&quot;,
    &quot;T.I.M.E Stories&quot;,
    &quot;Aeon&apos;s End&quot;,
]

for name in board_game_names:
    parameterized_name = parameterize(name, separator=&quot;_&quot;) # Default is `separator=&apos;-&apos;`
    print(parameterized_name) # Or whatever I want to do with it


Output

dawn_of_the_zeds_third_edition
flash_point_fire_rescue_honor_duty
orleans
mechs_vs_minions
tzolk_in_the_mayan_calendar
t_i_m_e_stories
aeon_s_end

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Parameterize mostly just uses some regular expressions but it&apos;s very useful. It has the effect of:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://inflection.readthedocs.io/en/latest/_modules/inflection.html#transliterate&quot;&gt;Replacing non-ASCII characters&lt;/a&gt; with an ASCII approximation – using &lt;code&gt;inflection.transliterate()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://inflection.readthedocs.io/en/latest/_modules/inflection.html#parameterize&quot;&gt;Replacing any character&lt;/a&gt; with the separator if it isn&apos;t one of:
&lt;ul&gt;
&lt;li&gt;a-z&lt;/li&gt;
&lt;li&gt;A-Z&lt;/li&gt;
&lt;li&gt;0-9&lt;/li&gt;
&lt;li&gt;a hyphen (-)&lt;/li&gt;
&lt;li&gt;an underscore(_)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Ensuring there is never more than one separator in a row&lt;/li&gt;
&lt;li&gt;Removing separators from the start or end of the string&lt;/li&gt;
&lt;li&gt;Making the string lower case&lt;/li&gt;
&lt;/ol&gt;
</content:encoded></item><item><title>New website: Making it easy to get thumbnails of YouTube videos</title><link>https://edjohnsonwilliams.co.uk/blog/2018-08-26-new-website-making-it-easy-to-get-thumbnails-of-youtube-videos/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2018-08-26-new-website-making-it-easy-to-get-thumbnails-of-youtube-videos/</guid><pubDate>Sun, 26 Aug 2018 14:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I made a web app that makes it easy to download thumbnails for YouTube videos. It’s called &lt;a href=&quot;https://youtubethumbnails.pythonanywhere.com&quot;&gt;Get YouTube Thumbnails&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Update 12 Jan 2021: This broke and I forgot how it worked so I couldn’t fix it. I’ve rebuilt it here: &amp;lt;a href=&quot;https://getyoutubethumbnails.netlify.app&quot;&amp;gt;getyoutubethumbnails.netlify.app&amp;lt;/a&amp;gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;When you submit a YouTube URL, you get back the image, a link to that image, and the original height and width of that image (even if it&apos;s scaled down on your screen size).&lt;/p&gt;
&lt;p&gt;You can also download the image with a YouTube play logo overlaid on the top.&lt;/p&gt;
&lt;p&gt;This is useful when you want to link to a YouTube video and you can&apos;t or don&apos;t want to embed a video. This might be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;in emails&lt;/li&gt;
&lt;li&gt;in presentation slides (PowerPoint etc)&lt;/li&gt;
&lt;li&gt;in websites where you don&apos;t want any Javascript&lt;/li&gt;
&lt;li&gt;in websites where you want to minimise data transfers&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let me know if you find it useful!&lt;/p&gt;
</content:encoded></item><item><title>Publishing my Pocket reading list on this website</title><link>https://edjohnsonwilliams.co.uk/blog/2019-04-25-publishing-my-pocket-reading-list-on-this-website/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2019-04-25-publishing-my-pocket-reading-list-on-this-website/</guid><pubDate>Fri, 26 Apr 2019 08:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I&apos;ve recently added &lt;a href=&quot;/reading-list&quot;&gt;a page called Reading List to this website&lt;/a&gt;. It&apos;s a page that shows the unread articles in my &lt;a href=&quot;https://getpocket.com/&quot;&gt;Pocket account&lt;/a&gt; that I haven&apos;t tagged as &apos;private&apos;.&lt;/p&gt;
&lt;p&gt;This post details how this works using Eleventy Javascript data files, the Pocket API, IFTT webhooks, and Netlify build webhooks.&lt;/p&gt;
&lt;p&gt;In case you don&apos;t know, Pocket is a service that lets you save links to read/watch later. It&apos;s really &lt;a href=&quot;https://support.mozilla.org/en-US/kb/save-web-pages-later-pocket-firefox&quot;&gt;well-integrated into Firefox&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I recently switched this blog from &lt;a href=&quot;https://jekyllrb.com&quot;&gt;Jekyll&lt;/a&gt; to &lt;a href=&quot;https://www.11ty.io&quot;&gt;Eleventy&lt;/a&gt;. Eleventy is a &lt;a href=&quot;https://indieweb.org/static_site_generator&quot;&gt;static-site generator&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Eleventy lets you &lt;a href=&quot;https://www.11ty.io/docs/data-js/&quot;&gt;make any data returned by a Javascript file&lt;/a&gt; available to your website. This means you can pull in data from an external API and feed it to your templates to display on your website as static HTML. So the only time a call to the Pocket API is made is when the site is being built on the server.&lt;/p&gt;
&lt;p&gt;For my site, I use a Javascript file called &lt;a href=&quot;https://github.com/edjw/edjw-blog/blob/master/_data/readingList.js&quot;&gt;&lt;code&gt;readingList.js&lt;/code&gt;&lt;/a&gt; that 1) pulls in all my items saved in Pocket, 2) reverses the order so they&apos;re roughly in descending publication date order, and 3) excludes any items I&apos;ve tagged in Pocket as &apos;private&apos;.&lt;/p&gt;
&lt;p&gt;The data from &lt;a href=&quot;https://getpocket.com/developer/docs/v3/retrieve&quot;&gt;Pocket&apos;s API&lt;/a&gt; is then available to my &lt;a href=&quot;https://github.com/edjw/edjw-blog/blob/master/_includes/layouts/reading-list.njk&quot;&gt;templates&lt;/a&gt; – written in Nunjucks in my case.&lt;/p&gt;
&lt;p&gt;I host this website on &lt;a href=&quot;https://www.netlify.com&quot;&gt;Netlify&lt;/a&gt;. Netlify runs a build of your site when you make a change to the git repository it&apos;s linked to. Usually these changes would be things like adding a new blogpost or changing some CSS. But when I add an article to Pocket, no changes are made to the files in the git repository. The readingList.js file stays the same.&lt;/p&gt;
&lt;p&gt;So, for automated updating of the Reading List page, I need to trigger a build whenever something changes in my Pocket account.&lt;/p&gt;
&lt;p&gt;I&apos;m doing this using &lt;a href=&quot;https://ifttt.com&quot;&gt;IFTT &apos;Applets&apos;&lt;/a&gt;. I&apos;ve set up triggers to run whenever 1) a new item is added to my Pocket account, 2) if an item is archived, or 3) if an item is tagged as &apos;private&apos;.&lt;/p&gt;
&lt;p&gt;And because IFTT can&apos;t detect if a tag is removed from a Pocket item, I&apos;ve also added a trigger that runs once a day at midnight. This one makes sure any items are displayed which I&apos;d previously tagged as &apos;private&apos; but then had that tag removed.&lt;/p&gt;
&lt;p&gt;When these &apos;applets&apos; above run, they send a webhook to Netlify to start a new build - using a &apos;Build hook&apos; from the &apos;Build &amp;amp; Deploy&apos; settings in Netlify. In IFTT, you set a POST request to a URL generated by Netlify that looks like this: &amp;lt;code&amp;gt;https://api.netlify.com/build_hooks/6rbs0k5tmi3ipx7s8g82k9fm?trigger_title=Midnight+build&amp;lt;/code&amp;gt;&lt;/p&gt;
&lt;p&gt;Notice you can include a &lt;code&gt;trigger_title&lt;/code&gt; parameter which can be unique to each IFTT applet. This shows up in the Netlify build logs so you can check back on what happened.&lt;/p&gt;
&lt;p&gt;When these applets start a new build, the site pulls in the updated Pocket data and then rebuilds the HTML using the new Pocket data. I don&apos;t have to do anything other than manage my Pocket account for the changes to be replicated on my site.&lt;/p&gt;
&lt;p&gt;That&apos;s it. I&apos;ve possibly missed something. &lt;a href=&quot;https://twitter.com/_edjw&quot;&gt;Let me know&lt;/a&gt; if you have any questions :-)&lt;/p&gt;
&lt;p&gt;--&lt;/p&gt;
&lt;p&gt;Thanks to &lt;a href=&quot;https://bryanlrobinson.com/blog/2019/04/02/using-eleventys-javascript-data-files&quot;&gt;Bryan L. Robinson for his blog&lt;/a&gt; explaining how to get Eleventy&apos;s Javascript data files working with the Meetup API. I&apos;ve adapted his work for my purposes here.&lt;/p&gt;
&lt;p&gt;Thanks also for &lt;a href=&quot;https://reader.fxneumann.de/plugins/oneclickpocket/auth.php&quot;&gt;Felix Neumann&apos;s tool&lt;/a&gt; that lets you easily generate a Pocket Access Token.&lt;/p&gt;
</content:encoded></item><item><title>A dataset for Sacred Harp songs</title><link>https://edjohnsonwilliams.co.uk/blog/2018-10-08-a-dataset-for-sacred-harp-songs/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2018-10-08-a-dataset-for-sacred-harp-songs/</guid><pubDate>Mon, 08 Oct 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I&apos;ve previously done some analysis involving songs from the Sacred Harp. Some &lt;a href=&quot;/blog/2018-02-07-female-composers-in-the-sacred-harp&quot;&gt;have been serious&lt;/a&gt;; some &lt;a href=&quot;/blog/2018-06-10-football-formations-in-sacred-harp-numbers&quot;&gt;less&lt;/a&gt;{&apos; &apos;}&lt;a href=&quot;/blog/2018-06-10-square-numbers-in-sacred-harp-song-numbers&quot;&gt;so&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;One challenge in doing this analysis is having a machine-readable dataset of all songs to work with. The excellent &lt;a href=&quot;https://fasola.org/indexes/1991/&quot;&gt;indexes on fasola.org&lt;/a&gt; present the information for each individual song on a different page which is great but you can&apos;t easily analyse all the songs at once.&lt;/p&gt;
&lt;p&gt;To make future analysis easiser, I&apos;ve prepared a single dataset of all the songs in &lt;em&gt;The Sacred Harp, 1991 Edition&lt;/em&gt; (Denson Revision) in both a &lt;code&gt;.CSV&lt;/code&gt; spreadsheet and also in a &lt;code&gt;.JSON&lt;/code&gt; file.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;Download the &lt;a href=&quot;https://raw.githubusercontent.com/edjw/Sacred-Harp-datasets/master/sacred_harp_songs_data.csv&quot;&gt;.CSV spreadsheet&lt;/a&gt;&lt;/strong&gt; (Right click on this link and click Save or Download)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Download the &lt;a href=&quot;https://raw.githubusercontent.com/edjw/Sacred-Harp-datasets/master/sacred_harp_songs_data.json&quot;&gt;.JSON file&lt;/a&gt;&lt;/strong&gt; (Right click on this link and click Save or Download)&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;The files are &lt;a href=&quot;https://github.com/edjw/Sacred-Harp-datasets&quot;&gt;stored in a Github repository here&lt;/a&gt;. (Don&apos;t worry if that bit doesn&apos;t make sense. You can still use the CSV and JSON files above.)&lt;/p&gt;
&lt;p&gt;Where the data exists, these data are available:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;song number&lt;/li&gt;
&lt;li&gt;bare song number (ie. without the &apos;t&apos; or &apos;b&apos; after the song number for top or bottom)&lt;/li&gt;
&lt;li&gt;song title&lt;/li&gt;
&lt;li&gt;composer/source&lt;/li&gt;
&lt;li&gt;composition date&lt;/li&gt;
&lt;li&gt;poet/source&lt;/li&gt;
&lt;li&gt;poetry date&lt;/li&gt;
&lt;li&gt;poetic meter&lt;/li&gt;
&lt;li&gt;lyrics&lt;/li&gt;
&lt;li&gt;time signature&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;s&gt;I&apos;m planning to add time signature data for all the songs.&lt;/s&gt; Time signatures are also included.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;mailto:mail@edjohnsonwilliams.co.uk&quot;&gt;&lt;strong&gt;Let me know&lt;/strong&gt;&lt;/a&gt; if you find mistakes in the data or if you have any ideas about how to make it better.&lt;/p&gt;
</content:encoded></item><item><title>Sacred Harp songs that are also HTTP Status Codes</title><link>https://edjohnsonwilliams.co.uk/blog/2018-10-09-sacred-harp-songs-that-are-also-http-status-codes/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2018-10-09-sacred-harp-songs-that-are-also-http-status-codes/</guid><pubDate>Tue, 09 Oct 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This is another &lt;em&gt;really&lt;/em&gt; silly Sacred Harp one. Someone called &quot;&lt;em&gt;404&quot; (&lt;/em&gt;&lt;a href=&quot;https://fasola.org/indexes/1991/?p=404&quot;&gt;&lt;em&gt;Youth Will Soon Be Gone&lt;/em&gt;&lt;/a&gt;&lt;em&gt;)&lt;/em&gt; at a &lt;a href=&quot;https://web.archive.org/web/20170918140510/http://newcastleshapenote.co.uk/&quot;&gt;Newcastle singing&lt;/a&gt; recently and someone immediately said &lt;a href=&quot;https://en.wikipedia.org/wiki/HTTP_404&quot;&gt;Error Not Found&lt;/a&gt;. As a result, this is a list of Sacred Harp songs that are also &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP/Status&quot;&gt;HTTP Status Codes&lt;/a&gt;. 404 is probably the most famous status code but &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP/Status&quot;&gt;there are lots&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;My wife estimated that this will be funny to about three people. That might be pushing it.&lt;/p&gt;
&lt;p&gt;NB. I used &lt;a href=&quot;/blog/2018-10-08-a-dataset-for-sacred-harp-songs&quot;&gt;the Sacred Harp dataset&lt;/a&gt; I just published to work this out.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;100&lt;/strong&gt; – The Bower of Prayer&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;100&lt;/strong&gt; Continue&lt;/p&gt;
&lt;p&gt;This interim response indicates that everything so far is OK and that the client should continue with the request or ignore it if it is already finished.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;101b&lt;/strong&gt; – Holy City&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;101&lt;/strong&gt; Switching Protocol&lt;/p&gt;
&lt;p&gt;This code is sent in response to an Upgrade request header by the client, and indicates the protocol the server is switching to.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;101t&lt;/strong&gt; – Canaan’s Land&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;101&lt;/strong&gt; Switching Protocol&lt;/p&gt;
&lt;p&gt;This code is sent in response to an Upgrade request header by the client, and indicates the protocol the server is switching to.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;102&lt;/strong&gt; – Fulfillment&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;102&lt;/strong&gt; Processing&lt;/p&gt;
&lt;p&gt;This code indicates that the server has received and is processing the request, but no response is available yet.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;200&lt;/strong&gt; – Edom&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;200&lt;/strong&gt; OK&lt;/p&gt;
&lt;p&gt;The request has succeeded. The meaning of a success varies depending on the HTTP method:
GET: The resource has been fetched and is transmitted in the message body.
HEAD: The entity headers are in the message body.
PUT or POST: The resource describing the result of the action is transmitted in the message body.
TRACE: The message body contains the request message as received by the server&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;201&lt;/strong&gt; – Pilgrim&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;201&lt;/strong&gt; Created&lt;/p&gt;
&lt;p&gt;The request has succeeded and a new resource has been created as a result of it. This is typically the response sent after a POST request, or after some PUT requests.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;202&lt;/strong&gt; – New Lebanon&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;202&lt;/strong&gt; Accepted&lt;/p&gt;
&lt;p&gt;The request has been received but not yet acted upon. It is non-committal, meaning that there is no way in HTTP to later send an asynchronous response indicating the outcome of processing the request. It is intended for cases where another process or server handles the request, or for batch processing.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;203&lt;/strong&gt; – Florida&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;203&lt;/strong&gt; Non-Authoritative Information&lt;/p&gt;
&lt;p&gt;This response code means returned meta-information set is not exact set as available from the origin server, but collected from a local or a third party copy. Except this condition, 200 OK response should be preferred instead of this response.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;204&lt;/strong&gt; – Mission&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;204&lt;/strong&gt; No Content&lt;/p&gt;
&lt;p&gt;There is no content to send for this request, but the headers may be useful. The user-agent may update its cached headers for this resource with the new ones.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;205&lt;/strong&gt; – Pleasant Hill&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;205&lt;/strong&gt; Reset Content&lt;/p&gt;
&lt;p&gt;This response code is sent after accomplishing request to tell user agent reset document view which sent this request.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;206&lt;/strong&gt; – Christian’s Hope&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;206&lt;/strong&gt; Partial Content&lt;/p&gt;
&lt;p&gt;This response code is used because of range header sent by the client to separate download into multiple streams.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;207&lt;/strong&gt; – Louisiana&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;207&lt;/strong&gt; Multi-Status&lt;/p&gt;
&lt;p&gt;A Multi-Status response conveys information about multiple resources in situations where multiple status codes might be appropriate.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;208&lt;/strong&gt; – Traveling On&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;208&lt;/strong&gt; Multi-Status&lt;/p&gt;
&lt;p&gt;Used inside a DAV: propstat response element to avoid enumerating the internal members of multiple bindings to the same collection repeatedly.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;300&lt;/strong&gt; – Calvary&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;300&lt;/strong&gt; Multiple Choice&lt;/p&gt;
&lt;p&gt;The request has more than one possible response. The user-agent or user should choose one of them. There is no standardized way of choosing one of the responses.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;301&lt;/strong&gt; – Greenland&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;301&lt;/strong&gt; Moved Permanently&lt;/p&gt;
&lt;p&gt;This response code means that the URI of the requested resource has been changed. Probably, the new URI would be given in the response.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;302&lt;/strong&gt; – Logan&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;302&lt;/strong&gt; Found&lt;/p&gt;
&lt;p&gt;This response code means that the URI of requested resource has been changed temporarily. New changes in the URI might be made in the future. Therefore, this same URI should be used by the client in future requests.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;303&lt;/strong&gt; – Heavenly Land&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;303&lt;/strong&gt; See Other&lt;/p&gt;
&lt;p&gt;The server sent this response to direct the client to get the requested resource at another URI with a GET request.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;304&lt;/strong&gt; – Morgan&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;304&lt;/strong&gt; Not Modified&lt;/p&gt;
&lt;p&gt;This is used for caching purposes. It tells the client that the response has not been modified, so the client can continue to use the same cached version of the response.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;306&lt;/strong&gt; – Oxford&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;306&lt;/strong&gt; unused&lt;/p&gt;
&lt;p&gt;This response code is no longer used, it is just reserved currently. It was used in a previous version of the HTTP 1.1 specification.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;308&lt;/strong&gt; – Parting Friends&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;308&lt;/strong&gt; Permanent Redirect&lt;/p&gt;
&lt;p&gt;This means that the resource is now permanently located at another URI, specified by the Location: HTTP Response header. This has the same semantics as the 301 Moved Permanently HTTP response code, with the exception that the user agent must not change the HTTP method used: If a POST was used in the first request, a POST must be used in the second request.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;400&lt;/strong&gt; – Struggle On&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;400&lt;/strong&gt; Bad Request&lt;/p&gt;
&lt;p&gt;This response means that server could not understand the request due to invalid syntax.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;401&lt;/strong&gt; – Cuba&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;401&lt;/strong&gt; Unauthorized&lt;/p&gt;
&lt;p&gt;&apos;Although the HTTP standard specifies unauthorized, semantically this response means unauthenticated. That is, the client must authenticate itself to get the requested response.&apos;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;402&lt;/strong&gt; – Protection&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;402&lt;/strong&gt; Payment Required&lt;/p&gt;
&lt;p&gt;This response code is reserved for future use. Initial aim for creating this code was using it for digital payment systems however this is not used currently.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;403&lt;/strong&gt; – Heavenly Rest&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;403&lt;/strong&gt; Forbidden&lt;/p&gt;
&lt;p&gt;The client does not have access rights to the content, i.e. they are unauthorized, so server is rejecting to give proper response. Unlike 401, the client&apos;s identity is known to the server.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;404&lt;/strong&gt; – Youth Will Soon Be Gone&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;404&lt;/strong&gt; Not Found&lt;/p&gt;
&lt;p&gt;The server can not find requested resource. In the browser, this means the URL is not recognized. In an API, this can also mean that the endpoint is valid but the resource itself does not exist. Servers may also send this response instead of 403 to hide the existence of a resource from an unauthorized client. This response code is probably the most famous one due to its frequent occurence on the web.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;405&lt;/strong&gt; – The Marcellas&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;405&lt;/strong&gt; Method Not Allowed&lt;/p&gt;
&lt;p&gt;The request method is known by the server but has been disabled and cannot be used. For example, an API may forbid DELETE-ing a resource. The two mandatory methods, GET and HEAD, must never be disabled and should not return this error code.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;406&lt;/strong&gt; – New Harmony&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;406&lt;/strong&gt; Not Acceptable&lt;/p&gt;
&lt;p&gt;This response is sent when the web server, after performing server-driven content negotiation, doesn&apos;t find any content following the criteria given by the user agent.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;407&lt;/strong&gt; – Charlton&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;407&lt;/strong&gt; Proxy Authentication Required&lt;/p&gt;
&lt;p&gt;This is similar to 401 but authentication is needed to be done by a proxy.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;408&lt;/strong&gt; – Weeping Mary&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;408&lt;/strong&gt; Request Timeout&lt;/p&gt;
&lt;p&gt;This response is sent on an idle connection by some servers, even without any previous request by the client. It means that the server would like to shut down this unused connection. This response is used much more since some browsers, like Chrome, Firefox 27+, or IE9, use HTTP pre-connection mechanisms to speed up surfing. Also note that some servers merely shut down the connection without sending this message.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;409&lt;/strong&gt; – Promised Day&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;409&lt;/strong&gt; Conflict&lt;/p&gt;
&lt;p&gt;This response is sent when a request conflicts with the current state of the server.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;410b&lt;/strong&gt; – Mutual Love&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;410&lt;/strong&gt; Gone&lt;/p&gt;
&lt;p&gt;&apos;This response would be sent when the requested content has been permanently deleted from server, with no forwarding address. Clients are expected to remove their caches and links to the resource. The HTTP specification intends this status code to be used for limited-time, promotional services. APIs should not feel compelled to indicate resources that have been deleted with this status code.&apos;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;410t&lt;/strong&gt; – The Dying Californian&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;410&lt;/strong&gt; Gone&lt;/p&gt;
&lt;p&gt;&apos;This response would be sent when the requested content has been permanently deleted from server, with no forwarding address. Clients are expected to remove their caches and links to the resource. The HTTP specification intends this status code to be used for limited-time, promotional services. APIs should not feel compelled to indicate resources that have been deleted with this status code.&apos;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;411&lt;/strong&gt; – Morning Prayer&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;411&lt;/strong&gt; Length Required&lt;/p&gt;
&lt;p&gt;Server rejected the request because the Content-Length header field is not defined and the server requires it.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;412&lt;/strong&gt; – New Hosanna&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;412&lt;/strong&gt; Precondition Failed&lt;/p&gt;
&lt;p&gt;The client has indicated preconditions in its headers which the server does not meet.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;413&lt;/strong&gt; – The Loved Ones&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;413&lt;/strong&gt; Payload Too Large&lt;/p&gt;
&lt;p&gt;Request entity is larger than limits defined by server; the server might close the connection or return an Retry-After header field.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;414&lt;/strong&gt; – Parting Friend&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;414&lt;/strong&gt; URI Too Long&lt;/p&gt;
&lt;p&gt;The URI requested by the client is longer than the server is willing to interpret.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;415&lt;/strong&gt; – Easter Morn&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;415&lt;/strong&gt; Unsupported Media Type&lt;/p&gt;
&lt;p&gt;The media format of the requested data is not supported by the server, so the server is rejecting the request.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;416&lt;/strong&gt; – The Christian’s Nightly Song&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;416&lt;/strong&gt; Requested Range Not Satisfiable&lt;/p&gt;
&lt;p&gt;The range specified by the Range header field in the request can&apos;t be fulfilled; it&apos;s possible that the range is outside the size of the target URI&apos;s data.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;417&lt;/strong&gt; – Weeping Pilgrim&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;417&lt;/strong&gt; Expectation Failed&lt;/p&gt;
&lt;p&gt;This response code means the expectation indicated by the Expect request header field can&apos;t be met by the server.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;418&lt;/strong&gt; – Reese&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;418&lt;/strong&gt; I&apos;m a teapot&lt;/p&gt;
&lt;p&gt;The server refuses the attempt to brew coffee with a teapot.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;421&lt;/strong&gt; – Sweet Morning&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;421&lt;/strong&gt; Misdirected Request&lt;/p&gt;
&lt;p&gt;The request was directed at a server that is not able to produce a response. This can be sent by a server that is not configured to produce responses for the combination of scheme and authority that are included in the request URI.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;422&lt;/strong&gt; – Burdette&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;422&lt;/strong&gt; Unprocessable Entity&lt;/p&gt;
&lt;p&gt;The request was well-formed but was unable to be followed due to semantic errors.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;423&lt;/strong&gt; – Grantville&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;423&lt;/strong&gt; Locked&lt;/p&gt;
&lt;p&gt;The resource that is being accessed is locked.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;424&lt;/strong&gt; – Sweet Union&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;424&lt;/strong&gt; Failed Dependency&lt;/p&gt;
&lt;p&gt;The request failed due to failure of a previous request.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;425&lt;/strong&gt; – Golden Streets&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;425&lt;/strong&gt; Too Early&lt;/p&gt;
&lt;p&gt;Indicates that the server is unwilling to risk processing a request that might be replayed.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;426b&lt;/strong&gt; – Jasper&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;426&lt;/strong&gt; Upgrade Required&lt;/p&gt;
&lt;p&gt;The server refuses to perform the request using the current protocol but might be willing to do so after the client upgrades to a different protocol. The server sends an Upgrade header in a 426 response to indicate the required protocol[s].&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;426t&lt;/strong&gt; – Kelley&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;426&lt;/strong&gt; Upgrade Required&lt;/p&gt;
&lt;p&gt;The server refuses to perform the request using the current protocol but might be willing to do so after the client upgrades to a different protocol. The server sends an Upgrade header in a 426 response to indicate the required protocol[s].&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;428&lt;/strong&gt; – World Unknown&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;428&lt;/strong&gt; Precondition Required&lt;/p&gt;
&lt;p&gt;The origin server requires the request to be conditional. Intended to prevent the &apos;lost update&apos; problem, where a client GETs a resource&apos;s state, modifies it, and PUTs it back to the server, when meanwhile a third party has modified the state on the server, leading to a conflict.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;429&lt;/strong&gt; – Christian’s Delight&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;429&lt;/strong&gt; Too Many Requests&lt;/p&gt;
&lt;p&gt;The user has sent too many requests in a given amount of time (rate limiting).&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;431&lt;/strong&gt; – New Bethany&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;431&lt;/strong&gt; Request Header Fields Too Large&lt;/p&gt;
&lt;p&gt;The server is unwilling to process the request because its header fields are too large. The request MAY be resubmitted after reducing the size of the request header fields.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;451&lt;/strong&gt; – Mary’s Grief and Joy&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;451&lt;/strong&gt; Unavailable For Legal Reasons&lt;/p&gt;
&lt;p&gt;The user requests an illegal resource, such as a web page censored by a government.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;500&lt;/strong&gt; – Living Hope&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;500&lt;/strong&gt; Internal Server Error&lt;/p&gt;
&lt;p&gt;The server has encountered a situation it doesn&apos;t know how to handle.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;501&lt;/strong&gt; – O’Leary&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;501&lt;/strong&gt; Not Implemented&lt;/p&gt;
&lt;p&gt;The request method is not supported by the server and cannot be handled. The only methods that servers are required to support [and therefore that must not return this code] are GET and HEAD.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;502&lt;/strong&gt; – A Charge to Keep&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;502&lt;/strong&gt; Bad Gateway&lt;/p&gt;
&lt;p&gt;This error response means that the server, while working as a gateway to get a response needed to handle the request, got an invalid response.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;503&lt;/strong&gt; – Lloyd&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;503&lt;/strong&gt; Service Unavailable&lt;/p&gt;
&lt;p&gt;The server is not ready to handle the request. Common causes are a server that is down for maintenance or that is overloaded. Note that together with this response, a user-friendly page explaining the problem should be sent. This responses should be used for temporary conditions and the Retry-After: HTTP header should, if possible, contain the estimated time before the recovery of the service. The webmaster must also take care about the caching-related headers that are sent along with this response, as these temporary condition responses should usually not be cached.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;504&lt;/strong&gt; – Wood Street&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;504&lt;/strong&gt; Gateway Timeout&lt;/p&gt;
&lt;p&gt;This error response is given when the server is acting as a gateway and cannot get a response in time.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;505&lt;/strong&gt; – Where Ceaseless Ages Roll&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;505&lt;/strong&gt; HTTP Version Not Supported&lt;/p&gt;
&lt;p&gt;The HTTP version used in the request is not supported by the server.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;506&lt;/strong&gt; – The Ark&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;506&lt;/strong&gt; Variant Also Negotiates&lt;/p&gt;
&lt;p&gt;The server has an internal configuration error: transparent content negotiation for the request results in a circular reference.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;507&lt;/strong&gt; – Sermon on the Mount&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;507&lt;/strong&gt; Insufficient Storage&lt;/p&gt;
&lt;p&gt;The server has an internal configuration error: the chosen variant resource is configured to engage in transparent content negotiation itself, and is therefore not a proper end point in the negotiation process.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;510&lt;/strong&gt; – Corley&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;510&lt;/strong&gt; Not Extended&lt;/p&gt;
&lt;p&gt;Further extensions to the request are required for the server to fulfill it.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;511&lt;/strong&gt; – The Great Redeemer&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;511&lt;/strong&gt; Network Authentication Required&lt;/p&gt;
&lt;p&gt;The 511 status code indicates that the client needs to authenticate to gain network access.&lt;/p&gt;
</content:encoded></item><item><title>New website: Durham Sacred Harp</title><link>https://edjohnsonwilliams.co.uk/blog/2019-05-02-new-website-durham-sacred-harp/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2019-05-02-new-website-durham-sacred-harp/</guid><pubDate>Mon, 22 Jan 2018 18:55:00 GMT</pubDate><content:encoded>&lt;p&gt;I made a website for the Durham Sacred Harp singing group. It&apos;s at &lt;a href=&quot;https://durhamsacredharp.co.uk&quot;&gt;https://durhamsacredharp.co.uk&lt;/a&gt;.&lt;/p&gt;
</content:encoded></item><item><title>New website: Turning off targeted ads</title><link>https://edjohnsonwilliams.co.uk/blog/2019-03-29-new-website-turning-off-targeted-ads/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2019-03-29-new-website-turning-off-targeted-ads/</guid><pubDate>Fri, 29 Mar 2019 20:24:00 GMT</pubDate><content:encoded>&lt;p&gt;I’ve made a website. It’s called &lt;a href=&quot;https://stoptargetingads.me&quot;&gt;Stop Targeting Ads at Me&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It’s a collection of links and instructions to turn off targeting of ads and/or data collection that helps advertisers target ads on all sorts of websites, apps, and devices.&lt;/p&gt;
&lt;p&gt;Some people would prefer that data about who they are and what they do isn’t used to advertise things to them. This website is for those people.&lt;/p&gt;
&lt;p&gt;I’ve described what the site’s about on &lt;a href=&quot;https://stoptargetingads.me/about&quot;&gt;the About page&lt;/a&gt; so take a look there if you’re interested.&lt;/p&gt;
&lt;p&gt;This is a personal project and I’ve just started telling people about it. If you visit the site AT ALL (even if it’s just for a few seconds and then you close the tab), let me know. I’d love to talk to you about it. Either &lt;a href=&quot;mailto:hello@stoptargetingads.me&quot;&gt;email me at hello@stoptargetingads.me&lt;/a&gt; or &lt;a href=&quot;https://twitter.com/_edjw&quot;&gt;contact me on Twitter at @_edjw&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Much bigger questions are out there about ad targeting.&lt;/p&gt;
&lt;p&gt;For example, is it reasonable to expect people to spend their time and energy doing these things below just to avoid having data about them used to target ads at them?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Find out/realise ad targeting is going on&lt;/li&gt;
&lt;li&gt;Find out that they can opt out of targeting at all&lt;/li&gt;
&lt;li&gt;Find the way to opt out on each individual website, app, and service they use&lt;/li&gt;
&lt;li&gt;Actually opt out on every individual website, app, and service they use&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;These are a lot of steps to take. The website helps but it still takes ordinary people way too much of their limited time and energy to do all this.&lt;/p&gt;
&lt;p&gt;And that’s before we even get in to the worst offenders on user interface dark patterns that dissuade people from turning off the ad targeting (Yahoo/Oath, Facebook, and Twitter ...looking at you). I’ll write those up at some point.&lt;/p&gt;
</content:encoded></item><item><title>New website: Newcastle Sacred Harp</title><link>https://edjohnsonwilliams.co.uk/blog/2019-05-02-new-website-newcastle-sacred-harp/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2019-05-02-new-website-newcastle-sacred-harp/</guid><pubDate>Thu, 02 May 2019 19:38:00 GMT</pubDate><content:encoded>&lt;p&gt;I made a website for the Newcastle Sacred Harp singing group. It&apos;s available at &lt;a href=&quot;https://newcastlesacredharp.co.uk&quot;&gt;https://newcastlesacredharp.co.uk&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The site is built with Jekyll and &lt;a href=&quot;https://github.com/newcastle-shapenote/newcastle-shapenote-website&quot;&gt;the code is on Github&lt;/a&gt;. I learnt to set up Netlify CMS for the site. Which was nice.&lt;/p&gt;
</content:encoded></item><item><title>Rebuilt website: Durham Sacred Harp</title><link>https://edjohnsonwilliams.co.uk/blog/2019-05-04-rebuilt-website-durham-sacred-harp/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2019-05-04-rebuilt-website-durham-sacred-harp/</guid><pubDate>Sat, 04 May 2019 20:40:00 GMT</pubDate><content:encoded>&lt;p&gt;I&apos;ve rebuilt the &lt;a href=&quot;https://durhamsacredharp.co.uk&quot;&gt;Durham Sacred Harp site&lt;/a&gt; in &lt;a href=&quot;https://www.11ty.io&quot;&gt;Eleventy&lt;/a&gt;. The &lt;a href=&quot;https://github.com/durhamsacredharp/durham-sacred-harp&quot;&gt;source is on Github here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This let me add in Netlify CMS which will make managing the content a lot easier as it was just one big HTML file before. The site should look the same.&lt;/p&gt;
&lt;p&gt;On the old site, I was using client-side Javascript to work out the dates of the next three singings. This was always a hack that I wasn&apos;t that happy with. If someone had the date and time wrong on their computer it wouldn&apos;t show the correct dates.&lt;/p&gt;
&lt;p&gt;I&apos;ve put the script into an Eleventy Javascript Data files to get those dates at build time. Then I use the IFTT and Netlify build webhook technique I wrote about &lt;a href=&quot;/blog/2019-04-25-publishing-my-pocket-reading-list-on-this-website&quot;&gt;in this blogpost&lt;/a&gt; to rebuild the site every Sunday at midnight.&lt;/p&gt;
</content:encoded></item><item><title>Replicating Jekyll&apos;s `markdownify` filter in Nunjucks with Eleventy</title><link>https://edjohnsonwilliams.co.uk/blog/2019-05-04-replicating-jekylls-markdownify-filter-in-nunjucks-with-eleventy/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2019-05-04-replicating-jekylls-markdownify-filter-in-nunjucks-with-eleventy/</guid><pubDate>Sat, 04 May 2019 20:11:00 GMT</pubDate><content:encoded>&lt;p&gt;Jekyll has a useful filter called &lt;code&gt;markdownify&lt;/code&gt; that converts a Markdown string into HTML. Nunjucks doesn&apos;t have this filter.&lt;/p&gt;
&lt;p&gt;I&apos;ve replicated this in &lt;a href=&quot;https://www.11ty.io&quot;&gt;Eleventy&lt;/a&gt; by adding this into my &lt;code&gt;.eleventy.js&lt;/code&gt; file.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;module.exports = function (eleventyConfig) {
  const md = require(&quot;markdown-it&quot;)({
    html: false,
    breaks: true,
    linkify: true,
  });

  eleventyConfig.addNunjucksFilter(&quot;markdownify&quot;, (markdownString) =&amp;gt;
    md.render(markdownString),
  );
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In a Nunjucks template, you can now use &lt;code&gt;{{ someMarkdownString | markdownify | safe }}&lt;/code&gt; to convert any Markdown string to HTML.&lt;/p&gt;
&lt;p&gt;I&apos;m not 100% sure about the &lt;code&gt;| safe&lt;/code&gt; bit, but it&apos;s working for me like this.&lt;/p&gt;
</content:encoded></item><item><title>New website: I made a test site to learn about fetching data from APIs and turning it into HTML using vanilla JS and accidentally made my main Hacker News reader</title><link>https://edjohnsonwilliams.co.uk/blog/2019-10-01-new-website-i-made-a-test-site-to-fetch-data-from-apis-and-turn-it-into-html-using-vanilla-js-and-accidentally-made-my-main-hacker-news-reader/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2019-10-01-new-website-i-made-a-test-site-to-fetch-data-from-apis-and-turn-it-into-html-using-vanilla-js-and-accidentally-made-my-main-hacker-news-reader/</guid><pubDate>Tue, 01 Oct 2019 19:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Title says it all. &lt;a href=&quot;https://doughnut-reader.netlify.com&quot;&gt;Doughnut Reader is my main Hacker News reader&lt;/a&gt; now. It&apos;s got a dark theme, works nicely on mobile, and is really fast. No tracking.&lt;/p&gt;
&lt;p&gt;Have a look and let me know what you think.&lt;/p&gt;
&lt;p&gt;If you have a look at the code (&lt;a href=&quot;https://github.com/edjw/hacker_news_reader&quot;&gt;source on Github is here&lt;/a&gt;), you can see that I played for a long time with getting comments to appear on the site in a popup. It kind of worked but I couldn&apos;t get the multi-level comments to work well. It means you have to go onto the main HN site if you want to read the comments — which, as we all known, is a big if.&lt;/p&gt;
</content:encoded></item><item><title>Twitter&apos;s political ads ban has an accurate definition of political but campaign groups won&apos;t like it (eventually)</title><link>https://edjohnsonwilliams.co.uk/blog/2019-11-02-twitters-political-ads-ban/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2019-11-02-twitters-political-ads-ban/</guid><pubDate>Sat, 02 Nov 2019 11:02:00 GMT</pubDate><content:encoded>&lt;p&gt;Twitter&apos;s decision to ban political ads by the end of November &lt;a href=&quot;%5Bhttps://threadreaderapp.com/thread/1189634360472829952.html%5D(https://threadreaderapp.com/thread/1189634360472829952.html)&quot;&gt;^1&lt;/a&gt; could lead to some bad situations for campaign groups, charities, and NGOs.&lt;/p&gt;
&lt;p&gt;As well as ads run by politicians, candidates, or ads in support of politicians, Twitter is also banning &quot;issue ads&quot;.&lt;/p&gt;
&lt;p&gt;They&apos;re defining issue ads as &quot;ads that advocate for or against legislative issues of national importance (such as: climate change, healthcare, immigration, national security, taxes)&quot;. &lt;a href=&quot;%5Bhttps://business.twitter.com/en/help/ads-policies/restricted-content-policies/political-content/global-political-content.html%5D(https://business.twitter.com/en/help/ads-policies/restricted-content-policies/political-content/global-political-content.html)&quot;&gt;^2&lt;/a&gt; &lt;a href=&quot;%5Bhttps://twitter.com/vijaya/status/1189664481263046656%5D(https://twitter.com/vijaya/status/1189664481263046656)&quot;&gt;^3&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It remains to be seen how totally and equally Twitter will enforce the policy. Twitter does have a track record of announcing content policies and failing to enforce them.&lt;/p&gt;
&lt;p&gt;But in case it&apos;s not obvious, this ban will cover ads by small campaigns, campaigns we like, and ads about issues that we think are not politically contentious. It won&apos;t just cover misinformation in ads by politicians or campaigns that we don&apos;t like!&lt;/p&gt;
&lt;p&gt;Twitter has a broad definition of &quot;political&quot;. They don&apos;t just mean politicians and political parties. And that&apos;s right. Politics and political outcomes are affected by all sorts of actors, not just politicians.&lt;/p&gt;
&lt;p&gt;As an aside, my definition is even broader — the content of &lt;em&gt;every&lt;/em&gt; tweet and the practice of tweeting itself is &quot;political&quot;. &lt;a href=&quot;%5Bhttps://culturalstudiesnow.blogspot.com/2017/03/foucault-on-power-and-knowledge-summary.html%5D(https://culturalstudiesnow.blogspot.com/2017/03/foucault-on-power-and-knowledge-summary.html)&quot;&gt;^4&lt;/a&gt; But that&apos;s not the popular definition of &quot;political&quot; and Twitter obviously doesn&apos;t want to ban every tweet!&lt;/p&gt;
&lt;p&gt;Twitter probably thinks it&apos;s making life easier for itself by saying no &quot;political&quot; ads and they probably think they&apos;ve already defined &quot;political&quot;. That might be true but this will still get really complicated.&lt;/p&gt;
&lt;p&gt;A climate campaign group will try to run an ad and will be told they can&apos;t. There will be uproar because climate campaigners will say that the science isn&apos;t political. This has already happened with registering to run &quot;political&quot; Facebook ads.&lt;/p&gt;
&lt;p&gt;And other groups will just be upset that they can&apos;t use Twitter ads to push back against messages they don&apos;t like that get free advertising on TV/Radio etc.&lt;/p&gt;
&lt;p&gt;A few other questions…&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;How does a campaign group know when their issue has reached national importance and should expect their ads not to be allowed?&lt;/li&gt;
&lt;li&gt;How does Twitter know when an issue has crossed that threshold? How nationally important is too nationally important?&lt;/li&gt;
&lt;li&gt;How broadly is Twitter defining &apos;national security&apos; and &apos;taxes&apos;?&lt;/li&gt;
&lt;/ol&gt;
</content:encoded></item><item><title>New website: Save Your Indie High Street</title><link>https://edjohnsonwilliams.co.uk/blog/2020-03-30-new-website-save-your-indie-high-street/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2020-03-30-new-website-save-your-indie-high-street/</guid><pubDate>Mon, 30 Mar 2020 21:23:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://saveyourindiehighstreet.uk&quot;&gt;Save Your Indie High Street&lt;/a&gt; is a response to coronavirus.&lt;/p&gt;
&lt;p&gt;Local pubs, cafes, restaurants and cinemas have had to close. Even with help from the government, they&apos;re under huge financial strain.&lt;/p&gt;
&lt;p&gt;Many small businesses sell vouchers or deliver their goods.&lt;/p&gt;
&lt;p&gt;Save Your Indie High Street lets anyone submit details about how to order delivery or buy vouchers from small local businesses.&lt;/p&gt;
&lt;p&gt;People can then use this information to support their local businesses get through coronavirus.&lt;/p&gt;
&lt;p&gt;Nearly 60 businesses are on the site so far. &lt;a href=&quot;https://saveyourindiehighstreet.uk/save&quot;&gt;You can add a business&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The site is open source. Have a &lt;a href=&quot;https://github.com/edjw/Save-Your-Indie-High-Street&quot;&gt;look at the code&lt;/a&gt;.&lt;/p&gt;
</content:encoded></item><item><title>Bernie Sanders&apos; healthcare plan isn&apos;t necessarily the best way to universal American healthcare</title><link>https://edjohnsonwilliams.co.uk/blog/2020-02-15-bernie-sanders-healthcare-plan-isnt-necessarily-the-best-way-to-universal-american-healthcare/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2020-02-15-bernie-sanders-healthcare-plan-isnt-necessarily-the-best-way-to-universal-american-healthcare/</guid><pubDate>Sat, 15 Feb 2020 21:32:00 GMT</pubDate><content:encoded>&lt;p&gt;In the UK, the NHS is taxpayer-funded and free at the point of access. [^1] It is great. And it sounds a lot like Bernie Sanders&apos; plan for &lt;a href=&quot;https://berniesanders.com/issues/medicare-for-all&quot;&gt;Medicare for All&lt;/a&gt; with a government-provided healthcare program providing all Americans with healthcare coverage.&lt;/p&gt;
&lt;p&gt;One difference between the British system and Medicare for All is that Bernie Sanders&apos; plan is to completely dismantle America&apos;s private healthcare insurance system in less than four years. In Britain, there&apos;s a private sector that you can use if you can afford it and want to pay for it. I don&apos;t personally know anyone who does this though.&lt;/p&gt;
&lt;p&gt;Unlike Britain, private health insurance is common in America. Over half of Americans have private health insurance of some sort. It&apos;s a big ask to get rid of it so quickly.&lt;/p&gt;
&lt;p&gt;Something like Pete Buttigieg&apos;s plan for &lt;a href=&quot;https://peteforamerica.com/policies/health-care&quot;&gt;Medicare for All Who Want It&lt;/a&gt; is actually much closer to the UK system. (Other candidates have plans similar to this but Buttigieg&apos;s plan has a name I can remember.)&lt;/p&gt;
&lt;p&gt;Buttigieg&apos;s plan gives everyone access to government-funded healthcare, but doesn&apos;t abolish the private system straightaway. He costs it at $1.5 trillion over 10 years. That&apos;s a lot less than the $52 trillion over 10 years that &lt;a href=&quot;https://elizabethwarren.com/plans/paying-for-m4a&quot;&gt;Elizabeth Warren says her plan&lt;/a&gt; – very similar to Sanders&apos; – would cost. $50.5 trillion pays for a lot of other progressive things that you want a Democratic president to do!&lt;/p&gt;
&lt;p&gt;Buttigieg thinks the lower costs to the individuals and families as well as the more efficient service you&apos;d get in a government-backed programme would probably lead to lots of people switching away from private insurance. But he&apos;d rather give people the choice.&lt;/p&gt;
&lt;p&gt;There&apos;s a good reason that people might want the choice. Trade unions in America have spent decades securing high quality healthcare for their members through generous employee-funded insurance. Many of them are understandably nervous about giving that up.&lt;/p&gt;
&lt;p&gt;I&apos;ve noticed British people seem to assume Bernie Sanders&apos; plan is to bring the NHS to America and don&apos;t realise the bit about abolishing the private sector completely. And British people who&apos;re on the (broadly-defined) left seem to assume the candidates who&apos;re labelled as moderates or centrists are opposite to Sanders and therefore probably oppose healthcare for everyone.&lt;/p&gt;
&lt;p&gt;But I&apos;m not sure there&apos;s a Democratic candidate who doesn&apos;t support healthcare for everyone. Sanders, Buttigieg, Klobuchar, Warren, Biden. They all support it. (Maybe Bloomberg doesn&apos;t. I haven&apos;t looked into him.)&lt;/p&gt;
&lt;p&gt;Part of this confusion is probably down to British progressives not realising quite how successful Sanders has been in the 2016 primaries against Clinton and since then. He&apos;s moved the common ground of healthcare policy in the Democratic party towards him. Another reason is that the candidates are exaggerating their differences for political gain.&lt;/p&gt;
&lt;p&gt;Basically everyone in the Democratic party agrees on universal healthcare. There&apos;s just disagreement on how to get it done, whether you should force people to lose their existing private insurance, how to get the legislation passed, how quickly to do it, how much is a reasonable amount for the state/tax-payers to pay for it.&lt;/p&gt;
&lt;p&gt;Sanders&apos; healthcare plan is one way to get universal healthcare in America. It could do a lot of good and make America a much better place to live in. It&apos;s not really the British system. And there are alternatives that would have the same impact on people who can&apos;t currently afford healthcare for a lot less money without disrupting people who are happy with their current situation. Other candidates exist and they are good. Let&apos;s not make this a purity test.&lt;/p&gt;
&lt;p&gt;[^1]: You have to pay an expensive surcharge if you&apos;re in the UK on a visa. Most people have to pay about £10 for each prescription. Dentistry is subsidised but not free. There are probably other exceptions that I&apos;m not thinking of.&lt;/p&gt;
</content:encoded></item><item><title>Development and Production favicons in Eleventy</title><link>https://edjohnsonwilliams.co.uk/blog/2020-03-24-development-production-favicons-eleventy/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2020-03-24-development-production-favicons-eleventy/</guid><pubDate>Tue, 24 Mar 2020 14:45:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;CSS Tricks&lt;/em&gt; has an article up about &lt;a href=&quot;https://css-tricks.com/different-favicon-for-development&quot;&gt;using a different favicon for local development and production&lt;/a&gt;. That way, when you&apos;ve got both open in tabs, you can easily tell which tab is which.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Here&apos;s a way to have different production and development favicons in &lt;a href=&quot;https://www.11ty.dev&quot;&gt;Eleventy&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Have two folders for your site&apos;s favicons.&lt;/strong&gt; Keep your favicons for production in one folder. And keep your favicons for development in the other folder.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Set the &lt;code&gt;ELEVENTY_ENV&lt;/code&gt; environment variable in the scripts section of your &lt;code&gt;package.json&lt;/code&gt;.&lt;/strong&gt; Set &lt;code&gt;ELEVENTY_ENV&lt;/code&gt; to &quot;dev&quot; when you&apos;re in development and using &lt;code&gt;eleventy --serve&lt;/code&gt;. Set it to &quot;prod&quot; for the build script.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;// package.json

&quot;scripts&quot;: {
    &quot;dev&quot;: &quot;ELEVENTY_ENV=dev eleventy --serve&quot;,
    &quot;build&quot;: &quot;ELEVENTY_ENV=prod eleventy&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Pass through the relevant favicons directory.&lt;/strong&gt; In your &lt;code&gt;eleventy.js&lt;/code&gt; file, get the &lt;code&gt;ELEVENTY_ENV&lt;/code&gt; variable. Then, if it&apos;s &quot;prod&quot;, pass through your production favicons. If it&apos;s &quot;dev&quot;, pass through your development icons.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;//.eleventy.js

module.exports = function (eleventyConfig) {
  let env = process.env.ELEVENTY_ENV;

  if (env === &quot;prod&quot;) {
    eleventyConfig.addPassthroughCopy({
      &quot;./src/site/assets/images/favicons_prod&quot;: &quot;/&quot;,
    });
  } else if (env === &quot;dev&quot;) {
    eleventyConfig.addPassthroughCopy({
      &quot;./src/site/assets/images/favicons_dev&quot;: &quot;/&quot;,
    });
  }
};
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>On the whataboutery around the Saudi takeover of Newcastle United</title><link>https://edjohnsonwilliams.co.uk/blog/2020-04-18-on-the-whataboutery-around-the-takeover-of-newcastle-united/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2020-04-18-on-the-whataboutery-around-the-takeover-of-newcastle-united/</guid><pubDate>Sat, 18 Apr 2020 21:15:00 GMT</pubDate><content:encoded>&lt;p&gt;Saudi Arabia wants to buy 80% of Newcastle United Football Club to make itself look good.&lt;/p&gt;
&lt;p&gt;I&apos;m a Newcastle fan. I&apos;m appalled by the idea of Saudi Arabia buying the club. Saudi Arabia is using the club to improve its terrible and well-deserved image. Saudi Arabia has a disgraceful human rights record. It also plays a leading role in the world&apos;s addiction to oil.&lt;/p&gt;
&lt;p&gt;Countries should not buy football clubs. Especially countries that abuse people like Saudi Arabia does.&lt;/p&gt;
&lt;p&gt;We&apos;re unlikely to get to the point that football&apos;s authorities deal with this properly. They should. It’s their responsibility.&lt;/p&gt;
&lt;p&gt;But as fans, let&apos;s not try to make ourselves feel better about Saudi Arabia buying Newcastle United. Pointing out other bad things does not stop Saudi Arabia&apos;s actions being worse.&lt;/p&gt;
&lt;p&gt;People are understandably desperate to get rid of Mike Ashley and move on to a different owner. I am too.&lt;/p&gt;
&lt;p&gt;But the reasons, the whataboutery, some people are using to make it seem like it&apos;s fine for Saudi Arabia to own the club are getting ridiculous.&lt;/p&gt;
&lt;p&gt;Here is some of the whataboutery I&apos;ve seen people engaging in over the last few days.&lt;/p&gt;
&lt;h3&gt;1. Whatabout Mike Ashley?&lt;/h3&gt;
&lt;p&gt;Yes. Mike Ashley is a bad boss. His company Sports Direct treats its workers terribly. Mike Ashley has treated the club terribly. But, unlike Saudi Arabia, Mike Ashley does not:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;murder journalists &lt;a href=&quot;%5Bhttps://www.bbc.co.uk/news/world-middle-east-49826905%5D(https://www.bbc.co.uk/news/world-middle-east-49826905)&quot;&gt;^1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;behead people &lt;a href=&quot;%5Bhttps://www.theguardian.com/world/2018/apr/26/saudi-arabia-criticised-over-executions-for-drug-offences%5D(https://www.theguardian.com/world/2018/apr/26/saudi-arabia-criticised-over-executions-for-drug-offences)&quot;&gt;^2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;lead wars that kill civilians &lt;a href=&quot;%5Bhttps://www.amnesty.org.uk/exposed-british-made-bombs-used-civilian-targets-yemen%5D(https://www.amnesty.org.uk/exposed-british-made-bombs-used-civilian-targets-yemen)&quot;&gt;^3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;put people in prison for saying that men and women are equal &lt;a href=&quot;%5Bhttps://www.bbc.co.uk/news/world-middle-east-47553416%5D(https://www.bbc.co.uk/news/world-middle-east-47553416)&quot;&gt;^4&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. Whatabout Saudi Arabia investing in other clubs?&lt;/h3&gt;
&lt;p&gt;This one is often followed up with something about how the media didn&apos;t cover Saudi Arabia having interest in other clubs.&lt;/p&gt;
&lt;p&gt;Yes. It is bad that Saudi Arabia has invested indirectly in other clubs to try to improve its image.&lt;/p&gt;
&lt;p&gt;And while we&apos;re here…Yes, it is also bad that Saudi Arabia paid social media influencers to go to a music festival in Saudi Arabia and &lt;a href=&quot;https://www.theguardian.com/world/2019/dec/23/shameless-influencers-face-backlash-for-promoting-saudi-arabia-music-festival&quot;&gt;post about a &apos;cultural revolution&apos;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Some people seem to think that anyone who criticises the Saudi takeover is holding Newcastle to a higher moral standard than other clubs. I don&apos;t fully understand why some people think this.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.theguardian.com/football/2019/feb/15/sportswashing-europes-biggest-clubs-champions-league-owners-sponsors-uefa&quot;&gt;Journalists have covered Saudi Arabia investing in&lt;/a&gt; or being interested in buying other clubs in the past. How else would any of us have heard about it happening if journalists had not covered it?&lt;/p&gt;
&lt;h3&gt;3. Whatabout the UK&apos;s arms sales to Saudi Arabia?&lt;/h3&gt;
&lt;p&gt;Yes. This is also very bad. The UK should not sell arms to Saudi Arabia. That Saudi Arabia buys so many arms for its war in Yemen is a reason why Newcastle United should not be involved with them.&lt;/p&gt;
&lt;h3&gt;4. Whatabout the fans? Don’t they deserve some success?&lt;/h3&gt;
&lt;p&gt;It would be great for Newcastle to have success. Supporting Newcastle under Mike Ashley has often been rubbish. But if Newcastle does have success using Saudi Arabia&apos;s money, it will be hollow.&lt;/p&gt;
&lt;p&gt;Sidenote: Does any team actually &lt;em&gt;deserve&lt;/em&gt; success more or less than other teams?&lt;/p&gt;
&lt;h3&gt;5. Whatabout you? Don’t criticise the deal if you do unethical things too&lt;/h3&gt;
&lt;p&gt;This is the worst one.&lt;/p&gt;
&lt;p&gt;The thinking goes like this. If you use oil to drive or pay money to a company like Uber (another Saudi investment), then it’s hypocritical to criticise the Saudi takeover of Newcastle.&lt;/p&gt;
&lt;p&gt;You’ve got to wonder whether people saying this have been criticising Mike Ashley over the last few years while paying money to Newcastle United, Sports Direct, House of Fraser or any of his other businesses.&lt;/p&gt;
&lt;p&gt;I suspect some people find this argument effective though. The sort of person who criticises a country for committing torture probably also feels a bit guilty about using oil for transport. But any guilt we feel for that should not stop us criticising the Saudi state.&lt;/p&gt;
&lt;p&gt;Another way of making this odd argument is,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Hey! How dare you condemn that person for murdering their kids? Yesterday you parked with half a wheel in the next parking space along!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It’s clearly ridiculous.&lt;/p&gt;
&lt;p&gt;It’d be quite dangerous if everyone stopped criticising extremely unethical things (like torture) just because they also made individual choices that might be unethical but are incredibly difficult to avoid in the modern world.&lt;/p&gt;
&lt;p&gt;We can still criticise unspeakable actions by a country even if we make (much less consequential) unethical actions in our day-to-day lives.&lt;/p&gt;
&lt;p&gt;When I used an Uber to take my baby to the hospital at 3am, did it immediately become hypocritical to criticise Uber or their Saudi investors? Obviously not.&lt;/p&gt;
&lt;p&gt;Ethical purity is impossible. No-one meets that test. No-one is asking for ethical purity. Torture is wrong. It is infinitely worse than taking an Uber.&lt;/p&gt;
&lt;p&gt;Newcastle should not be involved with a prospective owner who commits torture.&lt;/p&gt;
&lt;h3&gt;6. Whatabout the Queen/Prince William/Prince Charles/Donald Trump/Boris Johnson?&lt;/h3&gt;
&lt;p&gt;If Mohammad bin Salman is good enough for them to meet him, he’s good enough for Newcastle&lt;/p&gt;
&lt;p&gt;Maybe they should not have met him. Maybe they took him to task on human rights? A photo of someone meeting someone is not a good reason why it’s ok for a club to accept someone like that as their owner.&lt;/p&gt;
&lt;h3&gt;7. Whatabout other owners?&lt;/h3&gt;
&lt;p&gt;All owners are bad men with a bad past (apparently). Hardly any (no?) other owner has abused people in the way Saudi Arabia has.&lt;/p&gt;
&lt;h3&gt;8. Whatabout what journalists did/did not say in the past?&lt;/h3&gt;
&lt;p&gt;A whole thread of this whataboutery is finding previous articles or tweets by journalists who criticise the Saudi takeover of Newcastle. People then say that these journalists were less critical of potential Saudi investment in other clubs and therefore it&apos;s hypocritical for journalists to criticise this deal.&lt;/p&gt;
&lt;p&gt;It does not matter what journalists did or did not say in the past.&lt;/p&gt;
&lt;p&gt;We are either happy for Saudi Arabia to use Newcastle United to persuade more people to look favourably on it or not.&lt;/p&gt;
&lt;p&gt;What a journalist said or did not say in the past has no effect on how horrific it is for Saudi Arabia to beheading people.&lt;/p&gt;
</content:encoded></item><item><title>New website: Hammer keys. Get trains.</title><link>https://edjohnsonwilliams.co.uk/blog/2020-04-30-new-website-hammer-keys-get-trains/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2020-04-30-new-website-hammer-keys-get-trains/</guid><pubDate>Thu, 30 Apr 2020 14:29:00 GMT</pubDate><content:encoded>&lt;h3&gt;User story&lt;/h3&gt;
&lt;p&gt;As a 3-year old,&lt;/p&gt;
&lt;p&gt;I want to press any and all the keys on my dad&apos;s keyboard,&lt;/p&gt;
&lt;p&gt;So I can see trains.&lt;/p&gt;
&lt;h3&gt;Acceptance criteria&lt;/h3&gt;
&lt;p&gt;It&apos;s done when my son can press any key on a keyboard and see a new train.&lt;/p&gt;
&lt;h3&gt;Resulting website&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://hammer-keys-get-trains.netlify.app&quot;&gt;Hammer keys. Get trains.&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/edjw/hammer-keys-get-trains&quot;&gt;See the code for the site on Github&lt;/a&gt;. I used &lt;a href=&quot;https://github.com/alpinejs/alpine/&quot;&gt;Alpine.js&lt;/a&gt; to learn a bit about that and declarative approaches Javascript.&lt;/p&gt;
</content:encoded></item><item><title>Websites and allotments: why do I write code?</title><link>https://edjohnsonwilliams.co.uk/blog/2020-05-17-websites-and-allotments-why-do-i-write-code/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2020-05-17-websites-and-allotments-why-do-i-write-code/</guid><pubDate>Sun, 17 May 2020 12:42:00 GMT</pubDate><content:encoded>&lt;p&gt;I am not a professional web developer. Why do I write code?&lt;/p&gt;
&lt;p&gt;My answer is, farmers don&apos;t have allotments. Let me explain.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Aside (21-5-20): Since I published this, I&apos;ve come across people talking about digital gardening. This seems to mean publishing open iterations of your learning on your website and not worrying about being judged. It&apos;s not quite what I mean here despite the metaphor of allotment as website being similar.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Making my personal website and &lt;a href=&quot;/tags/new-website&quot;&gt;my sideprojects&lt;/a&gt; are a hobby.&lt;/p&gt;
&lt;p&gt;It&apos;s taken me a long time to understand this. My wife was very surprised when I said the other day that I had only just realised this.&lt;/p&gt;
&lt;p&gt;It&apos;s nice to have your own website. It&apos;s good to have an online space where you can put your stuff on your own terms.&lt;/p&gt;
&lt;p&gt;As with most hobbies, having the free time to put a website together is a privilege. Lots of people who might want to do this just don&apos;t have that free time. Fortunately for me, I have had the time to learn how to make a website for myself.&lt;/p&gt;
&lt;p&gt;Writing blogposts is a great way to work out what you think. Sometimes people read what you write and thank you for it. Sometimes, it&apos;s just &lt;a href=&quot;/blog/2020-04-18-on-the-whataboutery-around-the-takeover-of-newcastle-united&quot;&gt;a good way of getting something out of your system&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;But if all I wanted was a place to publish writing that wasn&apos;t Facebook, I could use a blogging platform like &amp;lt;span&amp;gt;Wordpress.com&amp;lt;/span&amp;gt;. If I didn&apos;t mind using a social media platform, I could publish writing on Facebook Posts or do threads on Twitter. I would spend much less time fitting the pieces of a website together, adjusting the layout, and adding new pages.&lt;/p&gt;
&lt;p&gt;I could write blogposts without writing code. It is not necessary to build a personal website with &lt;a href=&quot;https://11ty.dev&quot;&gt;Eleventy&lt;/a&gt;, host it on &lt;a href=&quot;https://www.netlify.com&quot;&gt;Netlify&lt;/a&gt;, and keep the code on &lt;a href=&quot;https://github.com&quot;&gt;Github&lt;/a&gt; to have an online place to put my stuff.&lt;/p&gt;
&lt;p&gt;Clearly, I enjoy making the platform as much as the content.&lt;/p&gt;
&lt;p&gt;When you make your own website, you can also try out new things like publishing the articles I&apos;ve got in &lt;a href=&quot;/reading-list&quot;&gt;my reading list&lt;/a&gt;. &amp;lt;span&amp;gt;Wordpress.com&amp;lt;/span&amp;gt; or Facebook Posts aren&apos;t flexible enough to let you do that.&lt;/p&gt;
&lt;p&gt;Making your own personal website in this way is a bit like keeping &lt;a href=&quot;https://en.wikipedia.org/wiki/Allotment_(gardening)&quot;&gt;an allotment&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Most people with an allotment don&apos;t need to grow fruit and vegetables for survival. Mostly, they don&apos;t sell what they grow and can afford to buy food.&lt;/p&gt;
&lt;p&gt;But like me and my website, people with allotments enjoy tending to the plot, making it look nice, deciding what to plant, borrowing ideas from other people, and trying new things.&lt;/p&gt;
&lt;p&gt;Farmers and professional web developers have different priorities and pressures to people who keep an allotment or a personal website as a hobby. And that&apos;s ok.&lt;/p&gt;
</content:encoded></item><item><title>New website: First Draft – Don&apos;t let editing slow down your first draft</title><link>https://edjohnsonwilliams.co.uk/blog/2020-10-01-new-website-first-draft-dont-let-editing-slow-down-your-first-draft/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2020-10-01-new-website-first-draft-dont-let-editing-slow-down-your-first-draft/</guid><pubDate>Thu, 01 Oct 2020 16:09:00 GMT</pubDate><content:encoded>&lt;p&gt;Update: I&apos;ve rewritten First Draft from scratch and re-worked it into a totally offline desktop app. It&apos;s now called &lt;a href=&quot;https://draft-one.com&quot;&gt;&lt;strong&gt;Draft One&lt;/strong&gt;&lt;/a&gt;. It&apos;s available on &lt;a href=&quot;https://apps.apple.com/gb/app/draft-one/id1660388186&quot;&gt;&lt;strong&gt;macOS&lt;/strong&gt;&lt;/a&gt; so far with Windows to come.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Do you ever find yourself writing a first draft of something but you keep getting bogged down by making little edits?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://first-draft.netlify.app/&quot;&gt;First Draft&lt;/a&gt;&lt;/strong&gt; is a text editor I&apos;ve created that stops editing from slowing you down. It&apos;s at &lt;strong&gt;&lt;a href=&quot;https://first-draft.netlify.app/&quot;&gt;first-draft.netlify.app&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;With &lt;em&gt;First Draft&lt;/em&gt;, you can type text. But you can&apos;t remove any characters you type.&lt;/p&gt;
&lt;p&gt;No deleting. No backspace. No selecting text to overwrite it. No cutting. No replacing text with spellcheck.&lt;/p&gt;
&lt;p&gt;It takes a tiny bit of getting used to. But it really helps you get over writer&apos;s block and procrastination.&lt;/p&gt;
&lt;p&gt;When you&apos;ve got your typo-ridden first draft out of your brain and onto your computer, copy your text over into another text editor to clean it up.&lt;/p&gt;
</content:encoded></item><item><title>New website: Find the nearest Tailwind Colour</title><link>https://edjohnsonwilliams.co.uk/blog/2021-01-02-new-website-find-the-nearest-tailwind-colour/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2021-01-02-new-website-find-the-nearest-tailwind-colour/</guid><pubDate>Sat, 02 Jan 2021 10:02:00 GMT</pubDate><content:encoded>&lt;p&gt;I&apos;ve made a new tool called &lt;strong&gt;&lt;a href=&quot;https://find-nearest-tailwind-colour.netlify.app/&quot;&gt;Find the nearest Tailwind colour&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Enter any hex colour code like #FFFFFF and it willl find the nearest colour in &lt;a href=&quot;https://tailwindcss.com/&quot;&gt;Tailwind CSS&lt;/a&gt;&apos;s full colour palette for you.&lt;/p&gt;
&lt;p&gt;It&apos;s useful when you want to quickly use a colour that&apos;s close to another (similar) colour but you don&apos;t want to &lt;a href=&quot;https://tailwindcss.com/docs/customizing-colors#extending-the-defaults&quot;&gt;extend Tailwind&apos;s colour palette&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;(&lt;a href=&quot;https://svelte.dev/&quot;&gt;Svelte&lt;/a&gt; was handy again here.)&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://find-nearest-tailwind-colour.netlify.app/&quot;&gt;Take a look at the tool&lt;/a&gt;.&lt;/p&gt;
</content:encoded></item><item><title>New website: Coffee recipes app to learn Svelte</title><link>https://edjohnsonwilliams.co.uk/blog/2020-09-07-new-website-coffee-recipes-app-to-learn-svelte/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2020-09-07-new-website-coffee-recipes-app-to-learn-svelte/</guid><pubDate>Mon, 07 Sep 2020 17:52:00 GMT</pubDate><content:encoded>&lt;p&gt;I&apos;ve made a very small website of coffee recipes. To be clear, there is &lt;a href=&quot;https://coffee-coach.netlify.app/v60-by-james-hoffman&quot;&gt;one recipe&lt;/a&gt; on there.&lt;/p&gt;
&lt;p&gt;I&apos;ve called it &lt;a href=&quot;https://coffee-coach.netlify.app/&quot;&gt;Coffee Coach&lt;/a&gt; – which is way too grandiose.&lt;/p&gt;
&lt;p&gt;Basically it just does the calculations for how much coffee or water I need and how much water to pour when I&apos;m making my pourover coffee. There are other bits to a coffee recipe. I haven&apos;t mentioned those. This just stops me needing to open my calculator app.&lt;/p&gt;
&lt;p&gt;It&apos;s been a good way of learning a bit about what &lt;a href=&quot;https://svelte.dev/&quot;&gt;Svelte&lt;/a&gt; and &lt;a href=&quot;https://sapper.svelte.dev/&quot;&gt;Sapper&lt;/a&gt; can do as reactive UI and app tools.&lt;/p&gt;
</content:encoded></item><item><title>Re-written website: Get YouTube Thumbnails</title><link>https://edjohnsonwilliams.co.uk/blog/2021-01-13-re-written-website-get-youtube-thumbnails/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2021-01-13-re-written-website-get-youtube-thumbnails/</guid><pubDate>Wed, 13 Jan 2021 19:01:00 GMT</pubDate><content:encoded>&lt;p&gt;A few years ago, I made a tool called Get YouTube Thumbnails. &lt;a href=&quot;/blog/2018-08-26-new-website-making-it-easy-to-get-thumbnails-of-youtube-videos&quot;&gt;See my original blog post about it&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This is what it did.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;When you submit a YouTube URL, you get back the image, a link to that image, and the original height and width of that image (even if it&apos;s scaled down on your screen size).&lt;/p&gt;
&lt;p&gt;You can also download the image with a YouTube play logo overlaid on the top.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Anyway, that site broke and I didn&apos;t remember enough about how it worked to fix it. So I rebuilt &lt;a href=&quot;https://getyoutubethumbnails.netlify.app&quot;&gt;Get YouTube Thumbnails&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It does exactly the same thing. It&apos;s possibly a bit rough around the edges but it works.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/edjw/get-youtube-thumbnails-svelte&quot;&gt;See the code for the site&lt;/a&gt;. It uses Svelte and Netlify functions this time around and still uses Cloudinary for the image processing.&lt;/p&gt;
</content:encoded></item><item><title>Announcing &quot;Draft One&quot; – a new text editor</title><link>https://edjohnsonwilliams.co.uk/blog/2023-02-02-announcing-draft-one/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2023-02-02-announcing-draft-one/</guid><pubDate>Thu, 02 Feb 2023 20:19:00 GMT</pubDate><content:encoded>&lt;p&gt;Update (19.12.2023): I&apos;ve allowed my Apple developer certificate lapse and the domain expired so this isn&apos;t available any more :-(&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;a href=&quot;https://draft-one.com&quot;&gt;&lt;strong&gt;Draft One&lt;/strong&gt;&lt;/a&gt; is a new app I&apos;ve built. I&apos;m calling it &lt;em&gt;a text editor for focused first drafts&lt;/em&gt;. It&apos;s a simple app, but I think it&apos;s going to be really useful for people.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://draft-one.com&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you ever find yourself double-guessing yourself when you&apos;re writing – and therefore slowing down – this app might be for you.&lt;/p&gt;
&lt;p&gt;Or maybe you spend ages fixing your typos – when what you really want to be doing is just getting a first draft down?&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://draft-one.com&quot;&gt;Draft One&lt;/a&gt; is &lt;strong&gt;a text editor that won’t let you edit, delete or undo text&lt;/strong&gt;. This helps you to get out of the habit of double-guessing yourself and cleaning up your typos on your first draft.&lt;/p&gt;
&lt;p&gt;The thinking is that &lt;strong&gt;you can’t write freely and edit at the same time.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Editing flips your brain out of the flow state you need for good first drafts. Editing gets you into a critical – not a creative – mindset.&lt;/p&gt;
&lt;p&gt;Draft One&apos;s &lt;a href=&quot;https://apps.apple.com/gb/app/draft-one/id1660388186&quot;&gt;&lt;strong&gt;available on macOS already&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;And I&apos;m working on getting a Windows version out soon.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Here&apos;re some more marketing screenshots&lt;/strong&gt; that I uploaded to the &lt;a href=&quot;https://apps.apple.com/gb/app/draft-one/id1660388186&quot;&gt;&lt;strong&gt;Mac App Store&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;There&apos;s loads more to say about the technical side.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I built it with &lt;a href=&quot;https://tauri.studio&quot;&gt;Tauri&lt;/a&gt;, which is a fairly new framework for building desktop apps with web technologies. There are some really good things about it, but definitely some rough edges too.&lt;/p&gt;
&lt;p&gt;Speaking of rough edges…building an app for the Mac App Store is a whole new world of pain.&lt;/p&gt;
&lt;p&gt;Draft One&apos;s built with &lt;a href=&quot;https://draft-one.com/credits&quot;&gt;a bunch of other amazing open source projects too&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&apos;ll write more about the technical stuff and the Mac App Store stuff soon.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://draft-one.com/contact&quot;&gt;&lt;strong&gt;Let me know&lt;/strong&gt;&lt;/a&gt; if you find it useful or have feedback or ideas!&lt;/p&gt;
</content:encoded></item><item><title>I&apos;ve set up a microblog that uses Github Issues as a CMS</title><link>https://edjohnsonwilliams.co.uk/blog/2023-02-16-ive-set-up-a-microblog-that-uses-github-issues-as-a-cms/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2023-02-16-ive-set-up-a-microblog-that-uses-github-issues-as-a-cms/</guid><pubDate>Thu, 16 Feb 2023 10:11:00 GMT</pubDate><content:encoded>&lt;p&gt;I&apos;ve made a &lt;a href=&quot;https://microblog.edjohnsonwilliams.co.uk&quot;&gt;microblog&lt;/a&gt;. It&apos;s a blog but the idea is that I can put short posts there without too much thought or effort.&lt;/p&gt;
&lt;p&gt;The key thing here is the posting experience. If it&apos;s not easy, I won&apos;t do it.&lt;/p&gt;
&lt;p&gt;Writing a markdown file on my phone is just not going to happen. I &lt;em&gt;can&lt;/em&gt; – but usually don&apos;t – use Netlify CMS for this blog and it&apos;s not good on mobile – like it&apos;s really bad.&lt;/p&gt;
&lt;p&gt;Github&apos;s interface for creating issues is pretty good for this though, including on the mobile app. You get a really good markdown editor for free including the ability to add images, videos, all markdown stuff and a formatting bar.&lt;/p&gt;
&lt;p&gt;The microblog uses &lt;a href=&quot;https://astro.build&quot;&gt;Astro&lt;/a&gt; for the framework, same as this blog. But the microblog renders dynamically on the server using Vercel&apos;s serverless functions to fetch the content from Github&apos;s API for Issues and build the pages. Github has a limit of 5,000 API requests an hour. Seems unlikely the microblog will get enough visitors to hit that.&lt;/p&gt;
&lt;p&gt;I also pieced together an API route which dynamically builds share (Open Graph) images for all of the pages. That uses &lt;a href=&quot;https://github.com/vercel/satori&quot;&gt;Vercel&apos;s &apos;satori&apos;&lt;/a&gt; library.&lt;/p&gt;
&lt;p&gt;It&apos;s got &lt;a href=&quot;https://microblog.edjohnsonwilliams.co.uk/rss.xml&quot;&gt;an RSS feed if you&apos;re into that sort of thing&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&apos;ll switch the site repostitory to public in a few days. I&apos;ll probably leave the Issues/CMS repository private.&lt;/p&gt;
</content:encoded></item><item><title>Big UK mountains</title><link>https://edjohnsonwilliams.co.uk/blog/2022-11-02-big-uk-mountains/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2022-11-02-big-uk-mountains/</guid><pubDate>Wed, 02 Nov 2022 20:11:00 GMT</pubDate><content:encoded>&lt;p&gt;There&apos;s a very high mountain in the Cairngorms in Scotland called &lt;a href=&quot;https://www.google.com/maps/d/viewer?mid=1iOCGBdsMcbORzRdTSw7klktqU_5OlKI&amp;amp;ll=57.05826366073055%2C-3.725758513285524&amp;amp;z=18&quot;&gt;&quot;Sgor an Lochain Uaine&quot;&lt;/a&gt;. It&apos;s 1,258m above sea level. That makes it the &lt;a href=&quot;https://en.wikipedia.org/wiki/Sg%C3%B2r_an_Lochain_Uaine&quot;&gt;5th highest mountain in the UK&lt;/a&gt;. But as the whole of the Cairngorms is pretty high, it&apos;s not much higher than the surrounding area.&lt;/p&gt;
&lt;p&gt;And mountains that are higher than everything else around it are theoretically more likely to have better views at the top.[^1]&lt;/p&gt;
&lt;p&gt;Prominence is a word in geography that means the vertical distance you&apos;d have to climb down from one summit before you could start climbing up another higher summit.&lt;/p&gt;
&lt;p&gt;Peaks with high prominence are higher than everything else in the area. Peaks with low prominence are usually a similar height to everything else in the area.[^2]&lt;/p&gt;
&lt;p&gt;As an example, Sgor an Lochain Uaine has quite a low prominence (118m) – especially for its height (1,258m). On the other hand, Ben More on the Isle of Mull in Scotland has a height and a prominence of 966m. It&apos;s the highest mountain on an island. So you&apos;d have to go down to sea level before you could climb anything higher. I haven&apos;t climbed Ben More, but &lt;a href=&quot;https://www.walkhighlands.co.uk/mull/ben-more-mull.shtml#Step6&quot;&gt;the view looks pretty good to me&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;So how can you get a list of mountains that are likely to have a good view from the top? The &lt;a href=&quot;https://prominentpeaks.org.uk/index.php&quot;&gt;UK Prominent Peak Database&lt;/a&gt; is a list of the 1,530 mountains[^3] in the UK that are a) at least 500m above sea level, and b) have a prominence of at least 100m. They think this criteria makes it easier to find the UK mountains that are probably interesting to climb with a good view at the top.&lt;/p&gt;
&lt;p&gt;They categorise all the UK&apos;s mountains by prominence. P1000 means a prominence of 1000m+, P500 is 500m+, P200 is 200m, and P100 is 100m+. The UK has 3 P1000s, 155 P500s, 577 P200s and 829 P100s.&lt;/p&gt;
&lt;p&gt;I&apos;ve taken &lt;a href=&quot;https://prominentpeaks.org.uk/downloads.php&quot;&gt;the UK Prominent Peak Database&lt;/a&gt; and added latitude/longitude, a Google Map link, and a Open Street Map link for each mountain.&lt;/p&gt;
&lt;p&gt;Here&apos;s &lt;a href=&quot;https://www.google.com/maps/d/viewer?mid=1iOCGBdsMcbORzRdTSw7klktqU_5OlKI&quot;&gt;a map I made using the reworked data&lt;/a&gt;. It&apos;s a nice way to visualise the locations of these higher and prominent mountains and find mountains in a specific area. It looks like the website may have had a map in the past but it&apos;s not working any more.&lt;/p&gt;
&lt;p&gt;Here are links to the datasets I&apos;ve adapted from the UK Prominent Peak data.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;All GB: &lt;a href=&quot;/files/big-uk-mountains/All_GB_Peaks_P100+_H500+.csv&quot;&gt;CSV&lt;/a&gt; / &lt;a href=&quot;/files/big-uk-mountains/All_GB_Peaks_P100+_H500+.xlsx&quot;&gt;XLSX&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;P1000 (prominence of 1000m+): &lt;a href=&quot;/files/big-uk-mountains/P1000_GB_Peaks.csv&quot;&gt;CSV&lt;/a&gt; / &lt;a href=&quot;/files/big-uk-mountains/P1000_GB_Peaks.xlsx&quot;&gt;XLSX&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;P500: &lt;a href=&quot;/files/big-uk-mountains/P500_GB_Peaks.csv&quot;&gt;CSV&lt;/a&gt; / &lt;a href=&quot;/files/big-uk-mountains/P500_GB_Peaks.xlsx&quot;&gt;XLSX&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;P200: &lt;a href=&quot;/files/big-uk-mountains/P200_GB_Peaks.csv&quot;&gt;CSV&lt;/a&gt; / &lt;a href=&quot;/files/big-uk-mountains/P200_GB_Peaks.xlsx&quot;&gt;XLSX&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;P100: &lt;a href=&quot;/files/big-uk-mountains/P100_GB_Peaks.csv&quot;&gt;CSV&lt;/a&gt; / &lt;a href=&quot;/files/big-uk-mountains/P100_GB_Peaks.xlsx&quot;&gt;XLSX&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I removed mountains in Northern Ireland. Unfortunately I couldn&apos;t get my program to convert the OS map references for Northern Irish peaks into latitude/longitude which is needed for making the map above. I also removed a few columns from the dataset that weren&apos;t working any more.&lt;/p&gt;
&lt;p&gt;There is another database called &lt;a href=&quot;http://www.hills-database.co.uk/downloads.html&quot;&gt;&quot;Database of British and Irish hills&quot;&lt;/a&gt; that seems to be updated regularly. It is extremely thorough (21,291 hills!) with data about peaks as low as just 2m above sea level! The website recommends &lt;a href=&quot;https://apps.apple.com/app/id315200683&quot;&gt;an iOS app called Hill Lists&lt;/a&gt; and &lt;a href=&quot;https://play.google.com/store/apps/details?id=uk.colessoft.android.hilllist&amp;amp;hl=en_GB&quot;&gt;an Android app called British Hills&lt;/a&gt; as app-based ways of accessing and filtering this database.&lt;/p&gt;
&lt;p&gt;[^1]: Although &lt;a href=&quot;https://www.geograph.org.uk/photo/3067669&quot;&gt;this photo from the top of Sgor an Lochain Uaine&lt;/a&gt; makes the view seem well worth it in this case.&lt;/p&gt;
&lt;p&gt;[^2]: I&apos;ve also seen the word &quot;drop&quot; used instead of prominence.&lt;/p&gt;
&lt;p&gt;[^3]: In the UK, &lt;a href=&quot;https://en.wikipedia.org/wiki/Mountain#Definition&quot;&gt;a mountain is 610m (2,000ft) above sea level&lt;/a&gt;. But I&apos;m just going to say mountain even though some of the peaks in the UK Prominent Peak Database are only 500m.&lt;/p&gt;
</content:encoded></item><item><title>I attended a funeral on Youtube</title><link>https://edjohnsonwilliams.co.uk/blog/2022-09-08-i-attended-a-funeral-on-youtube/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2022-09-08-i-attended-a-funeral-on-youtube/</guid><pubDate>Thu, 08 Sep 2022 20:11:00 GMT</pubDate><content:encoded>&lt;p&gt;I watched a funeral of a former colleague on Youtube today. I was at home all by myself. It was one of the hardest experiences I&apos;ve ever gone through.&lt;/p&gt;
&lt;p&gt;My colleague was Mary Milne. She managed me at &lt;em&gt;&lt;a href=&quot;https://traidcraftexchange.org&quot;&gt;Traidcraft Exchange&lt;/a&gt;&lt;/em&gt; – soon to be &lt;em&gt;Transform Trade&lt;/em&gt;. Mary was an incredibly supportive and inspirational colleague and manager. She was a remarkable person. She lived in Hampshire and worked in London. I worked in Newcastle. I only worked at Traidcraft Exchange for 18 months or so. Although we spoke most days but probably saw each other in person fewer than 5 times. It would have been more without Covid of course.&lt;/p&gt;
&lt;p&gt;Lot of people have gone through this experience of live-streaming somebody&apos;s funeral over the last few years. I found it so intense. It&apos;s impossible to know, but I&apos;m sure it affected me more than if I&apos;d been in the church. I wasn&apos;t ready for this.&lt;/p&gt;
&lt;p&gt;I sort of assumed it would be less affecting to watch it on a computer. But then I was missing the companionship of other people. I had a view the whole time of Mary&apos;s coffin. I also didn&apos;t sing the hymns by myself. It kind of makes sense that it would be a lot.&lt;/p&gt;
&lt;p&gt;Another former colleague who was there in person said the service was great and so many people were there. You couldn&apos;t see how many people were in the church on the stream. Just the number of other accounts watching it on Youtube.&lt;/p&gt;
&lt;p&gt;Mary wrote &lt;a href=&quot;https://walking-through-fire.blogspot.com/&quot;&gt;a fantastic blog&lt;/a&gt; over the last couple of years since she was diagnosed with cancer. It was not always an easy read. I still haven&apos;t been able to read her last post which is about her thoughts on death. I&apos;m still too sad.&lt;/p&gt;
</content:encoded></item><item><title>I’m making a React Native phone app and omg I miss Svelte stores</title><link>https://edjohnsonwilliams.co.uk/blog/2022-09-11-im-making-a-react-native-phone-app-and-omg-i-miss-svelte-stores/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2022-09-11-im-making-a-react-native-phone-app-and-omg-i-miss-svelte-stores/</guid><pubDate>Sun, 11 Sep 2022 23:01:00 GMT</pubDate><content:encoded>&lt;p&gt;That’s it. That’s the title.&lt;/p&gt;
</content:encoded></item><item><title>Announcing Nearest Color</title><link>https://edjohnsonwilliams.co.uk/blog/2024-06-03-announcing-nearest-color/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2024-06-03-announcing-nearest-color/</guid><pubDate>Mon, 03 Jun 2024 21:49:00 GMT</pubDate><content:encoded>&lt;p&gt;I&apos;m making &lt;a href=&quot;https://nearest-color.com&quot;&gt;a new tool called Nearest Color&lt;/a&gt; to help you find the nearest colour from your palette. It&apos;s still a work in progress but I&apos;m sharing progress. It&apos;ll be an app for macOS and Windows.&lt;/p&gt;
&lt;p&gt;You enter &amp;lt;code&amp;gt;#d58400&amp;lt;/code&amp;gt; and select your palette. Say you select Tailwind, it tells you &amp;lt;code&amp;gt;yellow-600&amp;lt;/code&amp;gt;. You enter &amp;lt;code&amp;gt;lab(80.5% -40 79)&amp;lt;/code&amp;gt;, it tells you &amp;lt;code&amp;gt;lime-400&amp;lt;/code&amp;gt;.&lt;/p&gt;
&lt;p&gt;I &lt;a href=&quot;https://nearest-color.com/best-color-science&quot;&gt;made a page&lt;/a&gt; showing how the underlying colour algorithm for Nearest Color finds matches that correspond with human perception unlike other tools that just use the mathematically closest colour.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://nearest-color.com&quot;&gt;Find out more about Nearest Color&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://testflight.apple.com/join/XSTycxqX&quot;&gt;Test it out on MacOS for free with TestFlight&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title>Svelte Unstyled Tags Input</title><link>https://edjohnsonwilliams.co.uk/blog/2023-12-10-svelte-unstyled-tags-input/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2023-12-10-svelte-unstyled-tags-input/</guid><pubDate>Sun, 10 Dec 2023 22:33:00 GMT</pubDate><content:encoded>&lt;p&gt;I&apos;ve made a tags input component for Svelte. It comes completely unstyled but with lots of classes, ids and data attributes for hooking in with your own styles. And same for passing in your own classes to specific parts of the components too. There are plenty of configuration options for things like showing the input label, customising button text, placeholders etc.&lt;/p&gt;
&lt;p&gt;This is how the tags input component looks &apos;out-of-the-box&apos;. &lt;/p&gt;
&lt;p&gt;You can make it look however you want. This is an example. &lt;/p&gt;
&lt;p&gt;Source for the package here: &lt;a href=&quot;https://github.com/edjw/svelte-unstyled-tags&quot;&gt;https://github.com/edjw/svelte-unstyled-tags&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;NPM page here: &lt;a href=&quot;https://www.npmjs.com/package/svelte-unstyled-tags&quot;&gt;https://www.npmjs.com/package/svelte-unstyled-tags&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is the first time I&apos;ve published a node package to npm. It was actually fine!&lt;/p&gt;
</content:encoded></item><item><title>Chess Variants</title><link>https://edjohnsonwilliams.co.uk/blog/2023-11-20-chess-variants/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2023-11-20-chess-variants/</guid><pubDate>Mon, 20 Nov 2023 19:32:00 GMT</pubDate><content:encoded>&lt;p&gt;Shut Up &amp;amp; Sit Down – the board game reviewers – have a fun video called &lt;a href=&quot;https://www.youtube.com/watch?v=8yrfLDsEcQ4&quot;&gt;&lt;em&gt;Nine Easy Ways to Make Chess Fun&lt;/em&gt;&lt;/a&gt; that looks at 9 variants on the rules of chess.&lt;/p&gt;
&lt;p&gt;I&apos;ve been playing normal chess a bit recently and I like it. Just going to write down notes on some of the variants that seem like they&apos;d be fun to try out.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#atomic-chess&quot;&gt;Atomic Chess&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#horde&quot;&gt;Horde&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#monster-chess&quot;&gt;Monster chess&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#rifle-chess&quot;&gt;Rifle chess&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#demi-chess&quot;&gt;Demi chess&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#synchronistic-chess&quot;&gt;Synchronistic chess&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#get-the-king-to-the-other-side&quot;&gt;Get the King to the other side&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Atomic Chess&lt;/h2&gt;
&lt;p&gt;Standard chess rules and…&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Every capture causes an explosion which destroys the captured piece, the piece used to capture, and all pieces except pawns in a 3x3 square surrounding the capture piece.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You can&apos;t capture a piece that would destroy your king.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Your king can&apos;t capture any piece because it would be destroyed in the explosion.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Any move that blows up the opponent&apos;s king means an immediate victory, overriding all checks and checkmates.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Normal checkmate can happen.&lt;/p&gt;
&lt;p&gt;The two kings can touch. When the kings are touching, checks don&apos;t count because you can&apos;t capture something that would blow up your own king. To win in this situation, you have to force the king to move by zugzwang or explode a piece of the opposite colour while their king is next to it without exploding your own king&lt;/p&gt;
&lt;p&gt;This &lt;a href=&quot;https://lichess.org/study/uf9GpQyI&quot;&gt;Lichess tutorial for Atomic chess is good&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Horde&lt;/h2&gt;
&lt;p&gt;White has 36 pawns. White wins by checkmating Black&apos;s king. Black wins by capturing all White&apos;s pawns – including pawns promoted to other pieces&lt;/p&gt;
&lt;p&gt;White&apos;s pawns on the first and second rows can move forward 2 squares. Black&apos;s pawns can&apos;t capture White&apos;s first row pawns have moved two squares by en passant.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Read some &lt;a href=&quot;https://docs.google.com/document/d/136BCRPzm1QH_OBK3qjKwlmK3MIji7ZmLZPMYgDpmOCU&quot;&gt;very in-depth strategy advice on Horde chess&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Monster chess&lt;/h2&gt;
&lt;p&gt;White has a king and four pawns – but can move twice each turn. Black plays as usual.&lt;/p&gt;
&lt;p&gt;Normal rules of chess but…&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;White only has to escape check on the second move. It can stay in check or move into check on its first move.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;White wins by checkmating Black&apos;s king, or being able to capture Black&apos;s king on its second move.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Black wins if the White king cannot escape check in two moves. To do that, Black has to control a 5x5 square around White&apos;s king, not just the 3x3 square as in normal chess.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;Rifle chess&lt;/h2&gt;
&lt;p&gt;Rules are the same as normal chess. But after capturing a piece, the attacker stays still. Protecting pieces is useless. I think this is going to be a brain burner.&lt;/p&gt;
&lt;h2&gt;Demi chess&lt;/h2&gt;
&lt;p&gt;All rules the same but only four columns wide and you start with a king, bishop, knight, and rook. You castle by moving the King 2 spaces as usual.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;Synchronistic chess&lt;/h2&gt;
&lt;p&gt;Both players write down their moves and then announce them. They move pieces using these rules for resolving things.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;If both players choose to move to the same square, White captures the Black piece if it&apos;s on Black&apos;s side of the board. Black captures the White piece if it&apos;s on White&apos;s side. So you&apos;re weaker when you&apos;re closer to your home?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If players chose to capture each other, both pieces are captured.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If a player moves to a square that the opponent&apos;s piece moved away from in that turn, it is captured if it&apos;s of lower value (King &amp;gt; Queen &amp;gt; Castle &amp;gt; Bishop &amp;gt; Knight &amp;gt; Pawn). If it&apos;s the same or higher value, then pieces aren&apos;t taken.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You could both get checkmate at the same time.&lt;/p&gt;
&lt;h2&gt;Get the King to the other side&lt;/h2&gt;
&lt;p&gt;Not sure of the name for this one but I saw it talked about in the comments. Normal rules but you can also win by getting your King into the opponent&apos;s half of the board (5th rank). You can still win by checkmate too. This probably incentivises bringing the King out earlier. Risky but could win you the game if you take the risk.&lt;/p&gt;
</content:encoded></item><item><title>Deploy Laravel 11 for free on Vercel in 2024</title><link>https://edjohnsonwilliams.co.uk/blog/2024-06-04-deploy-laravel-11-for-free-on-vercel-in-2024/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2024-06-04-deploy-laravel-11-for-free-on-vercel-in-2024/</guid><pubDate>Tue, 04 Jun 2024 21:31:00 GMT</pubDate><content:encoded>&lt;p&gt;You can deploy Laravel on Vercel. For free!&lt;/p&gt;
&lt;p&gt;This is nice if you&apos;re coming to Laravel from Javascript land like me. In Javascript, Netlify and Vercel make it really easy to deploy something you&apos;re just trying out for free without needing to worry about running a server.&lt;/p&gt;
&lt;p&gt;Deploying Laravel on Vercel is more work compared to hosting Astro, SvelteKit etc on Vercel or Netlify. But Laravel does more stuff so it&apos;s a tradeoff like everything else.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://ploi.io/register?referrer=H1A1JZd9zNVLJ4EimK4I&quot;&gt;Tools like Ploi&lt;/a&gt; (referral) and &lt;a href=&quot;https://forge.laravel.com&quot;&gt;Laravel Forge&lt;/a&gt; are probably the way forward for more substantial sites.&lt;/p&gt;
&lt;p&gt;I&apos;m going to assume you know a bit about Vercel and how to use its CLI and web interface.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/edjw/edjw-blog-astro/issues/18&quot;&gt;&lt;strong&gt;Provide feedback to this post on Github&lt;/strong&gt;&lt;/a&gt;. I will make changes to this post if you can point out the ways it can be improved.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;1. Make a Laravel app&lt;/h2&gt;
&lt;p&gt;I&apos;m going to assume you can do this or can find out how to do it.&lt;/p&gt;
&lt;h2&gt;2. Add these files to your Laravel project&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;api/index.php&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;vercel.json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.vercelignore&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;api/index.php&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;?php

require __DIR__ . &apos;/../public/index.php&apos;;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;vercel.json&lt;/h3&gt;
&lt;p&gt;This config uses Frankfurt for the region but choose one near your likely users.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;/build/(.*)&lt;/code&gt; route rule has to be before the &lt;code&gt;/(.*)&lt;/code&gt; route rule. The &lt;code&gt;/build/(.*)&lt;/code&gt; route is for your Vite-generated assets like CSS and images. The &lt;code&gt;/(.*)&lt;/code&gt; route is for your Laravel app.&lt;/p&gt;
&lt;p&gt;The runtime is a &lt;a href=&quot;https://github.com/vercel-community/php&quot;&gt;PHP Runtime for Vercel Serverless Functions&lt;/a&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;version&quot;: 2,
  &quot;regions&quot;: [&quot;fra1&quot;],
  &quot;functions&quot;: {
    &quot;api/index.php&quot;: {
      &quot;runtime&quot;: &quot;vercel-php@0.7.1&quot;
    }
  },
  &quot;routes&quot;: [
    {
      &quot;src&quot;: &quot;/build/(.*)&quot;,
      &quot;dest&quot;: &quot;/build/$1&quot;
    },
    {
      &quot;src&quot;: &quot;/(.*)&quot;,
      &quot;dest&quot;: &quot;/api/index.php&quot;
    }
  ],
  &quot;outputDirectory&quot;: &quot;public&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;.vercelignore&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;/vendor
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3. Edit &lt;code&gt;.package.json&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;As of 4th July 2024, you need to add this to your &lt;code&gt;package.json&lt;/code&gt;. Otherwise you&apos;ll get a buildtime error of &lt;code&gt;php: error while loading shared libraries: libssl.so.10: cannot open shared object file: No such file or directory&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&quot;engines&quot;: { &quot;node&quot;: &quot;18.x&quot; },
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;4. Edit &lt;code&gt;.gitignore&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Add &lt;code&gt;.vercel&lt;/code&gt; to your &lt;code&gt;.gitignore&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;5. Trust proxies&lt;/h2&gt;
&lt;p&gt;Go to &lt;code&gt;bootstrap/app.php&lt;/code&gt;. Add &lt;code&gt;$middleware-&amp;gt;trustProxies(at: &apos;*&apos;);&lt;/code&gt; to the &lt;code&gt;withMiddleware&lt;/code&gt; method so it looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;-&amp;gt;withMiddleware(function (Middleware $middleware) {
    $middleware-&amp;gt;trustProxies(at: &apos;*&apos;);
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This step is new in Laravel 11 and needed if you want to host on Vercel which uses AWS. &lt;a href=&quot;https://laravel.com/docs/11.x/requests#trusting-all-proxies&quot;&gt;See more here&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;6. Run &lt;code&gt;vercel&lt;/code&gt; to deploy&lt;/h2&gt;
&lt;p&gt;It&apos;ll error because of missing environment variables.&lt;/p&gt;
&lt;h2&gt;7. Set the &lt;code&gt;APP_KEY&lt;/code&gt; environment variable&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;php artisan key:generate --show # in a Laravel project
# or
php -r &quot;echo &apos;base64:&apos; . base64_encode(random_bytes(32)) . PHP_EOL;&quot; # elsewhere
vercel env add APP_KEY
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;8. Set the other environment variables&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;APP_URL=https://your-app-url.vercel.app
APP_ENV=production
APP_DEBUG=false
APP_CONFIG_CACHE=/tmp/config.php
APP_EVENTS_CACHE=/tmp/events.php
APP_PACKAGES_CACHE=/tmp/packages.php
APP_ROUTES_CACHE=/tmp/routes.php
APP_SERVICES_CACHE=/tmp/services.php
VIEW_COMPILED_PATH=/tmp
LOG_CHANNEL=stderr
SESSION_DRIVER=cookie
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;9. Set up a database (optional)&lt;/h2&gt;
&lt;p&gt;I&apos;ve had a look around for database options that will work with a Laravel deployed on Vercel.&lt;/p&gt;
&lt;h3&gt;Turso&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://turso.tech&quot;&gt;Turso&lt;/a&gt; is &lt;em&gt;basically&lt;/em&gt; SQLite. To use Turso with Laravel, the best approach I can find is to add Turso as a database driver and &lt;a href=&quot;https://github.com/tursodatabase/turso-driver-laravel?tab=readme-ov-file&quot;&gt;follow Turso&apos;s LibSQL Driver for Laravel installation instructions here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This post used to mention &lt;a href=&quot;https://github.com/richan-fongdasen/turso-laravel?tab=readme-ov-file#installation&quot;&gt;this package&lt;/a&gt; and advised to se &lt;code&gt;https&lt;/code&gt; not &lt;code&gt;libsql&lt;/code&gt; in the &lt;code&gt;DB_URL&lt;/code&gt; variable and to add these environment variables&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;DB_CONNECTION=turso
DB_URL=https://***.turso.io
DB_ACCESS_TOKEN=your_turso_access_token
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I think it&apos;s probably better to use the Turso-approved driver.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://turso.tech/pricing&quot;&gt;You have to go a long way&lt;/a&gt; to absolutely need to start paying for Turso.&lt;/p&gt;
&lt;h3&gt;Neon&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://neon.tech&quot;&gt;Neon&lt;/a&gt; is Postgres. Neon lets you have a 500MB project for free. You can make multiple databases in Neon and use them as you like.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;DB_CONNECTION=&quot;psql&quot;
DB_URL=&quot;postgres://default:*****db_user*****@***db_password**.neon.tech:5432/****database_name****?sslmode=require&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Don&apos;t use a pooled connection from Neon.&lt;/p&gt;
&lt;h3&gt;Cloudflare D1&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://developers.cloudflare.com/d1&quot;&gt;Cloudflare D1&lt;/a&gt; is also &lt;em&gt;basically&lt;/em&gt; SQLite. To add it as a database driver for Laravel, &lt;a href=&quot;https://github.com/renoki-co/l1?tab=readme-ov-file#d1-with-laravel&quot;&gt;follow these instructions&lt;/a&gt;. It looks like they would like to offer Cloudflare KV as a cache driver and Cloudflare Queues as a queue driver too but that&apos;s not available as of 4th June 2024.&lt;/p&gt;
&lt;p&gt;Aaron Francis did a good video on &lt;a href=&quot;https://www.youtube.com/watch?v=htAOyy3-E9c&quot;&gt;using Cloudflare D1 with Laravel&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Cache&lt;/h2&gt;
&lt;p&gt;You don&apos;t have to set up Redis for a cache and session driver. You could use your database. But you can &lt;a href=&quot;https://upstash.com&quot;&gt;use Upstash for this if you want&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Add these environment variables.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;CACHE_STORE=&quot;redis&quot;
QUEUE_CONNECTION=&quot;redis&quot;
REDIS_HOST=***********.upstash.io
REDIS_PASSWORD=&quot;your-upstash-password&quot;
REDIS_PORT=&quot;your-upstash-port-eg-40682&quot;
SESSION_DRIVER=&quot;redis&quot;
REDIS_CACHE_DB=&quot;0&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Also add &lt;code&gt;&apos;scheme&apos; =&amp;gt; &apos;tls&apos;&lt;/code&gt; to both &lt;code&gt;default&lt;/code&gt; and &lt;code&gt;cache&lt;/code&gt; in the &lt;code&gt;redis&lt;/code&gt; section of &lt;code&gt;config/database.php&lt;/code&gt;. Otherwise, you&apos;ll get an error: &quot;Error while reading line from the server&quot;.&lt;/p&gt;
&lt;h2&gt;Other things&lt;/h2&gt;
&lt;p&gt;When you install a new module using composer, you&apos;ll probably get a build failure in Vercel such as &lt;code&gt;Required package &quot;predis/predis&quot; is not present in the lock file.&lt;/code&gt; You need to redeploy and clear the Build Cache.&lt;/p&gt;
&lt;p&gt;I had a look at the Vercel database and cache options. They look far more expensive than the other options I&apos;ve looked at and are actually whitelabelled versions of Neon and Upstash anyway!&lt;/p&gt;
&lt;h2&gt;Disclaimer&lt;/h2&gt;
&lt;p&gt;I haven&apos;t pushed this approach very hard. There might be limits that I haven&apos;t reached yet. To help you deploy Laravel on a conventional server with a database, Redis, web server etc on Hetzner, Digital Ocean, AWS EC2 etc, you might want to &lt;a href=&quot;https://ploi.io/register?referrer=H1A1JZd9zNVLJ4EimK4I&quot;&gt;use something like Ploi&lt;/a&gt; (referral).&lt;/p&gt;
&lt;h2&gt;Prior art&lt;/h2&gt;
&lt;p&gt;There&apos;s some prior art from others which helped get to this point. I found some things in Laravel and Vercel have changed since these posts/project were made which is why I pieced together the instructions above. I couldn&apos;t have done any of this without this work by Caleb Porzio and Luca Pacitto (Nembie).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://calebporzio.com/easy-free-serverless-laravel-with-vercel&quot;&gt;https://calebporzio.com/easy-free-serverless-laravel-with-vercel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Nembie/vercelit-laravel&quot;&gt;https://github.com/Nembie/vercelit-laravel&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;An example of a new thing in my instructions would be that Vercel doesn&apos;t support environment variables in &lt;code&gt;vercel.json&lt;/code&gt; any more. The &lt;code&gt;/build/(.*)&lt;/code&gt; route is another new thing here.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/edjw/edjw-blog-astro/issues/18&quot;&gt;&lt;strong&gt;Provide feedback to this post&lt;/strong&gt;&lt;/a&gt;. I will make changes to this post if you can point out the ways it can be improved.&lt;/p&gt;
</content:encoded></item><item><title>Launching Nearest Color</title><link>https://edjohnsonwilliams.co.uk/blog/2024-07-19-launching-nearest-color/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2024-07-19-launching-nearest-color/</guid><pubDate>Fri, 19 Jul 2024 20:29:00 GMT</pubDate><content:encoded>&lt;p&gt;I&apos;ve launched an app that matches any colour to popular colour palettes. It&apos;s called &lt;a href=&quot;https://nearest-color.com&quot;&gt;Nearest Color&lt;/a&gt;. That site&apos;s got demos and videos etc. In short, you give it a colour in any format and it tells you the closest colours to it from your selected palette.&lt;/p&gt;
&lt;p&gt;You can &lt;a href=&quot;https://apps.apple.com/gb/app/nearest-color/id6504228400&quot;&gt;buy it on the Mac App Store&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It was made with &lt;a href=&quot;https://tauri.app&quot;&gt;Tauri&lt;/a&gt; and &lt;a href=&quot;https://svelte.dev&quot;&gt;Svelte&lt;/a&gt;.&lt;/p&gt;
</content:encoded></item><item><title>When vendor lock-in might be worth it: RedwoodSDK&apos;s Cloudflare-only approach</title><link>https://edjohnsonwilliams.co.uk/blog/2025-06-09-when-vendor-lock-in-might-be-worth-it-redwoodsdks-cloudflare-only-approach/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2025-06-09-when-vendor-lock-in-might-be-worth-it-redwoodsdks-cloudflare-only-approach/</guid><pubDate>Mon, 09 Jun 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I&apos;ve been looking at &lt;a href=&quot;https://rwsdk.com/&quot;&gt;RedwoodSDK&lt;/a&gt; recently. It&apos;s a React framework that&apos;s making a technology and communication decision I find quite interesting. Instead of trying to be platform-agnostic, they&apos;re building exclusively for Cloudflare and just accepting the vendor lock-in criticism in exchange for being able to quickly create a batteries-included JS framework.&lt;/p&gt;
&lt;h2&gt;Most frameworks try to work everywhere&lt;/h2&gt;
&lt;p&gt;The usual approach is to build abstraction layers so your code can run anywhere – Vercel, Netlify, AWS, your own servers.&lt;/p&gt;
&lt;p&gt;But RedwoodSDK is saying: &quot;We&apos;re building for Cloudflare and we&apos;re happy to compromise on portability and the risks that come with vendor lock-in.&quot;&lt;/p&gt;
&lt;h2&gt;Most JS frameworks are not batteries-included&lt;/h2&gt;
&lt;p&gt;It&apos;s not that platform-agnostic frameworks can&apos;t have batteries included – &lt;a href=&quot;https://laravel.com/&quot;&gt;Laravel&lt;/a&gt; and &lt;a href=&quot;https://rubyonrails.org/&quot;&gt;Rails&lt;/a&gt; obviously do this. &lt;a href=&quot;https://adonisjs.com/&quot;&gt;Adonis.js&lt;/a&gt; shows it&apos;s possible in JavaScript.&lt;/p&gt;
&lt;p&gt;But it is definitely rare to offer database, queues, storage, auth, realtime etc in a convention-based way within the JS ecosystem.&lt;/p&gt;
&lt;p&gt;By accepting vendor lock-in, RedwoodSDK – a very new project – has added many of the things you get from a batteries-included framework like Laravel at launch.&lt;/p&gt;
&lt;p&gt;You get little bits of this with the &lt;a href=&quot;https://svelte.dev/blog/sv-the-svelte-cli&quot;&gt;new Svelte CLI&lt;/a&gt; which offers simple scaffolding for a database ORM and auth. Rich Harris (the maker of Svelte) &lt;a href=&quot;https://www.smashingmagazine.com/2025/01/svelte-5-future-frameworks-chat-rich-harris&quot;&gt;has talked about JS frameworks needing to offer more things like Laravel and Rails&lt;/a&gt;: &quot;There are too many things that you need to learn in order to build a full stack application today using JavaScript.&quot;&lt;/p&gt;
&lt;h2&gt;The criticism they&apos;re accepting&lt;/h2&gt;
&lt;p&gt;Vendor lock-in is the obvious concern. If Cloudflare changes pricing or direction, you might be stuck paying higher prices.&lt;/p&gt;
&lt;p&gt;When you listen to Peter Pistorius, the co-creator of RedwoodSDK, he&apos;s pretty upfront about how he&apos;s accepting this. For example on the &lt;a href=&quot;https://syntax.fm/show/902/fullstack-cloudflare-with-react-and-vite-redwood-sdk&quot;&gt;Syntax podcast&lt;/a&gt;, he says: &quot;Certainly, there is lock in there, and we have to own that...I&apos;m unashamedly in love with Cloudflare.&quot;&lt;/p&gt;
&lt;p&gt;Are they maybe positioning themselves to be acquired by Cloudflare? I don&apos;t know, maybe.&lt;/p&gt;
&lt;h2&gt;Why this might work&lt;/h2&gt;
&lt;p&gt;How many web projects actually need to be portable? Platform lock-in isn&apos;t the main worry for anything I build – side projects, tools for me and friends. Getting it built and keeping it running is the main thing.&lt;/p&gt;
&lt;p&gt;There&apos;s also something to be said for consistency. I use Tailwind in every personal project, so I never have to relearn CSS frameworks. You get that consistency to some extent in Vue, where &lt;a href=&quot;https://router.vuejs.org/&quot;&gt;Vue Router&lt;/a&gt; and &lt;a href=&quot;https://pinia.vuejs.org/&quot;&gt;Pinia&lt;/a&gt; are such standards that in every project you do, you&apos;d see the same stuff each time.&lt;/p&gt;
&lt;p&gt;RedwoodSDK is opinionated on infrastructure so it removes decisions you have to make on each individual project.&lt;/p&gt;
&lt;h2&gt;Early days&lt;/h2&gt;
&lt;p&gt;I haven&apos;t built anything proper with RedwoodSDK yet. Maybe I&apos;ll find limits I haven&apos;t seen. But I thought it was interesting that they were making this clear choice rather than trying to be principled and pure about avoiding vendor lock-in.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Edit (10.06.2025 aka the very next day): I have literally just seen that Peter Pistorius &lt;a href=&quot;https://rwsdk.com/blog/saas-is-just-vendor-lock-in-with-better-branding&quot;&gt;wrote basically exactly&lt;/a&gt; what I&apos;m saying in this post on a blogpost a few days ago 🤦‍♂️&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The pitch of modern SaaS is &quot;don&apos;t reinvent the wheel.&quot; But every wheel you bolt on comes with some friction. It&apos;s not just a service: It&apos;s a contract. It&apos;s a dependency. It&apos;s a subtle architectural shift, and it comes with taxes.&lt;/p&gt;
&lt;p&gt;No matter what choice you make, it&apos;s always going to be vendor-locked in. Switching out something, even if it&apos;s open source and self-hosted, means that you&apos;re rewriting a lot of code.&lt;/p&gt;
&lt;p&gt;So, my argument is, don&apos;t make those decisions. Just pick a platform. The thing that matters is the software that you want to write, not the framework or the services that it runs on.&lt;/p&gt;
&lt;p&gt;Platforms like Cloudflare or Supabase shine. Where your database, queue, image service, and storage all live within the same platform and speak the same language. You avoid paying these taxes repeatedly. You simply pick the product that&apos;s already there.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;No context switching between vendors.&lt;/li&gt;
&lt;li&gt;No API key wrangling.&lt;/li&gt;
&lt;li&gt;No compatibility hacks or configuration forks.&lt;/li&gt;
&lt;li&gt;Just fast, local feeling integrations that work the same in dev and production.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It feels like everything is running on the same machine, and in a way it kind of is. That&apos;s the hidden superpower of integrated platforms. They collapse the distance between your code and your services. And in doing so, they give you back the one thing no SaaS vendor can sell you: &quot;Flow.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded></item><item><title>Making music</title><link>https://edjohnsonwilliams.co.uk/blog/2025-11-06-making-music/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2025-11-06-making-music/</guid><pubDate>Thu, 06 Nov 2025 23:12:59 GMT</pubDate><content:encoded>&lt;p&gt;I&apos;ve been writing &lt;a href=&quot;/shapenote-compositions&quot;&gt;shapenote tunes&lt;/a&gt; in the Sacred Harp/Christian Harmony style. I&apos;ve also been making electronic music (&lt;a href=&quot;https://edjw.bandcamp.com/album/-&quot;&gt;Bandcamp&lt;/a&gt;, &lt;a href=&quot;https://soundcloud.com/edjw/sets/bmgh9wrn3cjt&quot;&gt;Soundcloud&lt;/a&gt;) – mostly techno things but I also tried making some drum-and-bass. It&apos;s been great.&lt;/p&gt;
&lt;p&gt;This is quite new for me to compose music. It does take quite a lot of time and effort to build confidence in doing it. I can tell it&apos;s one of those you never finish learning kind of things.&lt;/p&gt;
&lt;p&gt;With shapenote composition, it really helped to have a list of common chords to use and rare chords to avoid to fit within the idioms and expectations of the genre. With electronic music, there&apos;s a much, much wider range of sounds and styles within the genre and you can do your own thing. But also there&apos;s so much more to learn. I didn&apos;t really think before about how people who make music using laptop using programs like Ableton are composing drums, melody, bass, maybe vocals, and doing the whole arrangement with the structure, changing dynamics, changing effects to make different parts change their feel all the time, designing sounds from scratch, finding and manipulating sounds. I&apos;m definitely missing stuff here. There is &lt;em&gt;so&lt;/em&gt; much to it.&lt;/p&gt;
&lt;p&gt;It&apos;s really rewarding to hear something you made and enjoy it. This is almost instant with Ableton. You export your track and listen to it. You need a group of singers to hear what a shapenote composition really sounds like. I&apos;ve done 4-track versions myself where you sing the bass, tenor, alto, treble in your own voice on top of each other. That sounds weird because it&apos;s just one person and I can&apos;t sing alto! But it&apos;s the best way I&apos;ve found to get quicker feedback on what feels intuitive and not intuitive to sing.&lt;/p&gt;
&lt;p&gt;I&apos;d love to find a group of people who like sharing their electronic music productions with each other. I have that with shapenote compositions and it&apos;s really nice.&lt;/p&gt;
</content:encoded></item><item><title>Use LLMs to use chess engines, not to play chess</title><link>https://edjohnsonwilliams.co.uk/blog/2025-06-11-use-llms-to-use-chess-engines-not-to-play-chess/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2025-06-11-use-llms-to-use-chess-engines-not-to-play-chess/</guid><pubDate>Wed, 11 Jun 2025 20:57:05 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Use LLMs to build systems that solve problems. Don&apos;t use LLMs to solve problems directly.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://machinelearning.apple.com/research/illusion-of-thinking&quot;&gt;Apple published some research recently&lt;/a&gt; saying LLMs fail at &quot;reasoning&quot; when problems get even fairly complicated. They asked LLM models from Anthropic and OpenAI to solve Tower of Hanoi and they couldn&apos;t handle it.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Tower_of_Hanoi&quot;&gt;Tower of Hanoi&lt;/a&gt; is a puzzle with three rods and multiple discs of different sizes, where you have to move all the discs from one rod to another while never placing a larger disc on top of a smaller one.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p class=&quot;text-sm -mt-8&quot;&amp;gt;Image: &amp;lt;a href=&quot;https://commons.wikimedia.org/wiki/File:Tower_of_Hanoi.jpeg&quot;&amp;gt;Tower of Hanoi&amp;lt;/a&amp;gt; by &amp;lt;a href=&quot;https://commons.wikimedia.org/wiki/User:Evanherk&quot;&amp;gt;User:Evanherk&amp;lt;/a&amp;gt; is licensed under &amp;lt;a href=&quot;https://creativecommons.org/licenses/by-sa/3.0/&quot;&amp;gt;CC BY-SA 3.0&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;The LLMs didn&apos;t do any better when researchers provided the complete solution for Tower of Hanoi. The models still couldn&apos;t solve the puzzle reliably.&lt;/p&gt;
&lt;p&gt;Gary Marcus – a critic of AI hype – &lt;a href=&quot;https://garymarcus.substack.com/p/a-knockout-blow-for-llms&quot;&gt;writes this up as &quot;truly embarrassing&quot; and a &quot;knockout blow&quot; for LLMs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&apos;m not an AI expert. I can&apos;t explain why LLMs are bad at chess or Tower of Hanoi. And I get why you might want to be sceptical of the AI model companies&apos; marketing around &quot;reasoning&quot;.&lt;/p&gt;
&lt;p&gt;But for practical purposes for people who&apos;re trying to use the models, there&apos;s a thing that&apos;s being missed here I think.&lt;/p&gt;
&lt;h2&gt;Use LLMs to write the code that solves problems&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;There&apos;s a difference between asking an LLM to run an algorithm step-by-step in chat versus asking it to build code that runs that algorithm.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We should avoid using LLMs as the runtime – the system that solves problems. We should use them to build systems that solve problems.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Use LLMs to build the runtime. Don&apos;t use LLMs as a runtime.&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;I built a working Tower of Hanoi solver with Claude in 20 minutes&lt;/h2&gt;
&lt;p&gt;I haven&apos;t used &lt;a href=&quot;https://www.anthropic.com/claude-code&quot;&gt;Claude Code&lt;/a&gt; for very many projects yet. But I spent 20 minutes building a Tower of Hanoi solver to see what would happen if I treated Claude as a builder rather than asking it to reason through the puzzle directly.&lt;/p&gt;
&lt;p&gt;You don&apos;t need to watch this, but this is what it looks like.&lt;/p&gt;
&lt;p&gt;&amp;lt;div class=&quot;w-9/12 mx-auto&quot;&amp;gt;
&amp;lt;video controls width=&quot;100%&quot; muted&amp;gt;
&amp;lt;source src=&quot;/files/tower-of-hanoi/tower-of-hanoi-screenrecording.mp4&quot; type=&quot;video/mp4&quot;&amp;gt;
&amp;lt;p&amp;gt;Screen recording of an app solving Tower of Hanoi with 3 starting pieces then with 8 starting pieces&amp;lt;/p&amp;gt;
&amp;lt;/video&amp;gt;
&amp;lt;/div&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Apple researchers were asking Claude to execute moves directly – to be the runtime. I asked Claude to create code that would execute moves correctly – to be the builder.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The result was a complete, working application that handles puzzles more complex than what the Apple research shows these models can solve when reasoning through text.&lt;/p&gt;
&lt;p&gt;You can see the &lt;a href=&quot;https://github.com/edjw/tower-of-hanoi-py-claude&quot;&gt;complete Tower of Hanoi code and documentation&lt;/a&gt; including a &lt;a href=&quot;https://github.com/edjw/tower-of-hanoi-py-claude/blob/main/docs/prd-tower-of-hanoi-visual-solver.md&quot;&gt;project requirements document&lt;/a&gt; and a &lt;a href=&quot;https://github.com/edjw/tower-of-hanoi-py-claude/blob/main/docs/tasks-prd-tower-of-hanoi-visual-solver.md&quot;&gt;task breakdown&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I gave the whole thing quite strict guidelines to follow. I repurposed &lt;a href=&quot;https://github.com/snarktank/ai-dev-tasks&quot;&gt;Ryan Carson&apos;s Cursor commands&lt;/a&gt; that try to set up an LLM coding tool like Claude Code or Cursor with the context, starting point, requirements, and goals to give it the best chance of doing the thing you want it to. It worked. Claude recognised this as a well-known algorithmic problem, understood what I wanted, and generated deterministic code to solve it.&lt;/p&gt;
&lt;p&gt;Clearly this is a limited example and LLMs might struggle to come up with code to solve genuinely novel problems that haven&apos;t been well documented before and that aren&apos;t in its training data. Claude will have recognised the Tower of Hanoi problem from its training data, so it didn&apos;t need to reason to work out what rules it had to put in place in the code to solve it.&lt;/p&gt;
&lt;h2&gt;LLMs should use chess engines, not play chess&lt;/h2&gt;
&lt;p&gt;I&apos;ve tried playing chess against LLMs before – using an LLM as a chess-playing runtime. They&apos;ve always been terrible at it and forget where the pieces are whenever I&apos;ve played (&lt;a href=&quot;https://maxim-saplin.github.io/llm_chess&quot;&gt;though recent OpenAI models seem to be getting good&lt;/a&gt;). I suspect Claude would be quite good at building a chess application that uses an existing chess engine like &lt;a href=&quot;https://en.wikipedia.org/wiki/Stockfish_(chess)&quot;&gt;Stockfish&lt;/a&gt;. &lt;strong&gt;The LLM wouldn&apos;t be making chess moves or creating the engine itself. It would be building the interface and integration code to use an existing chess engine.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Maybe this clarifies some of the languageness of large language models. LLMs have language skills but can&apos;t actually do things outside of language. They can use their language skills to write instructions for moving chess pieces accurately, but they can&apos;t work out how to move chess pieces accurately themselves. This probably also applies to other areas like data analysis and maths where you might want LLMs to write code to analyse data but not to analyse data itself.&lt;/p&gt;
&lt;p&gt;Maybe LLMs don&apos;t have to be brilliant reasoners for low stakes projects like puzzles and some coding. I do think the criticisms of reasoning by Apple make a lot of sense for high stakes things like processing visa applications, making complex financial decisions and novel problems that don&apos;t have well established solutions.&lt;/p&gt;
&lt;p&gt;But for many use-cases, we should use LLMs for the things they&apos;re good for – &lt;strong&gt;creating deterministic code rather than asking them to solve problems directly&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Sidenote: I&apos;m also finding that asking LLMs to use command line tools is more reliable than MCP versions of those tools. &lt;a href=&quot;https://docs.netlify.com/welcome/build-with-ai/netlify-mcp-server/&quot;&gt;Netlify&apos;s MCP&lt;/a&gt; seems to fail a lot for me. Using &lt;a href=&quot;https://claude.ai/download&quot;&gt;Claude Desktop&lt;/a&gt; with &lt;a href=&quot;https://github.com/wonderwhy-er/DesktopCommanderMCP&quot;&gt;Desktop Commander&lt;/a&gt; to run commands from &lt;a href=&quot;https://docs.netlify.com/cli/get-started/&quot;&gt;Netlify&apos;s CLI&lt;/a&gt; works very reliably. This feels like something that&apos;s related to this point above.&lt;/p&gt;
</content:encoded></item><item><title>UK Mountains Update</title><link>https://edjohnsonwilliams.co.uk/blog/2025-11-06-uk-mountains-update/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2025-11-06-uk-mountains-update/</guid><pubDate>Thu, 06 Nov 2025 22:31:30 GMT</pubDate><content:encoded>&lt;p&gt;3 year ago, I made &lt;a href=&quot;https://www.google.com/maps/d/viewer?mid=1iOCGBdsMcbORzRdTSw7klktqU_5OlKI&quot;&gt;a map of British mountains&lt;/a&gt;. The map showed high and &lt;em&gt;prominent&lt;/em&gt; mountains. Prominence is about how far you have to climb down from the top of the mountain to climb a higher mountain. More prominent mountains are likely to have a better view from the top. The map was meant to make it easier to find those.&lt;/p&gt;
&lt;p&gt;Anyway, I made great use of the map on holiday in the Lake District a couple of weeks ago to find good mountains to climb near Keswick. My family and I climbed &lt;a href=&quot;https://en.wikipedia.org/wiki/Dodd_(Lake_District)&quot;&gt;Dodd&lt;/a&gt; (1,410th most prominent peak in Britain) and &lt;a href=&quot;https://en.wikipedia.org/wiki/Great_Mell_Fell&quot;&gt;Great Mell Fell&lt;/a&gt; (great name, 740th most prominent peak). They both had great views from the top – it works!&lt;/p&gt;
&lt;p&gt;We also climbed &lt;a href=&quot;https://en.wikipedia.org/wiki/Latrigg&quot;&gt;Latrigg&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Cat_Bells&quot;&gt;Cat Bells&lt;/a&gt;. Those aren&apos;t particularly prominent peaks, but are also great walks and views.&lt;/p&gt;
&lt;p&gt;Next time we&apos;ll have to try &lt;a href=&quot;https://en.wikipedia.org/wiki/Skiddaw&quot;&gt;Skiddaw&lt;/a&gt; (50th most prominent peak) and &lt;a href=&quot;https://en.wikipedia.org/wiki/Blencathra&quot;&gt;Blencathra&lt;/a&gt; (200th).&lt;/p&gt;
</content:encoded></item><item><title>Very slightly smaller UK mountains</title><link>https://edjohnsonwilliams.co.uk/blog/2022-11-05-very-slightly-smaller-uk-mountains/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2022-11-05-very-slightly-smaller-uk-mountains/</guid><pubDate>Sat, 05 Nov 2022 17:11:00 GMT</pubDate><content:encoded>&lt;p&gt;Earlier this week, I wrote about &lt;a href=&quot;https://edjohnsonwilliams.co.uk/blog/2022-11-02-big-uk-mountains&quot;&gt;the UK Prominent Peaks database&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;That database has all UK peaks that are at least 500m above sea level and have a prominence of at least 100m. See the post for an explanation of prominence but – long story short – the higher a mountain&apos;s prominence, the more it stands out from the surrounding area.)&lt;/p&gt;
&lt;p&gt;You&apos;ve got to draw the line somewhere. But there are 427 peaks that are between 400-499m high and have a prominence of at least 100m.[^1] 38 miss the cut by a height of 10m or less!&lt;/p&gt;
&lt;p&gt;Extending the list to H400+ means areas including Manchester, Leeds-Bradford, Middlesbrough, Cornwall, Shetland, Orkney and Worcester-Gloucester have a high and prominent peak reasonably near to them.&lt;/p&gt;
&lt;p&gt;So I&apos;ve added the options of P100 / H400-H499 and P200 / H400-H499 to &lt;a href=&quot;https://www.google.com/maps/d/viewer?mid=1iOCGBdsMcbORzRdTSw7klktqU_5OlKI&quot;&gt;the map I made using the UK Prominent Peaks data&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;[^1]: See the full &lt;a href=&quot;http://www.hills-database.co.uk/downloads.html&quot;&gt;&quot;Database of British and Irish hills&quot;&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title>A simplistic post on quick trade agreements</title><link>https://edjohnsonwilliams.co.uk/blog/2017-07-10-a-simplistic-post-on-quick-trade-agreements/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2017-07-10-a-simplistic-post-on-quick-trade-agreements/</guid><pubDate>Mon, 10 Jul 2017 14:14:00 GMT</pubDate><content:encoded>&lt;p&gt;A quick trade deal means the country with the smaller economy being forced to accept the demands of the larger economy in return for the speed of the deal.&lt;/p&gt;
&lt;p&gt;You don&apos;t want a quick deal if you&apos;re &lt;a href=&quot;http://www.bbc.co.uk/news/uk-politics-40540340&quot;&gt;negotiating with the US&lt;/a&gt;. Unless you&apos;re not bothered about food safety, environmental standards, rules on procurement of public services (this means NHS).&lt;/p&gt;
&lt;p&gt;One example. &lt;a href=&quot;http://www.salon.com/2014/05/26/chlorine_in_your_chicken_why_poultry_is_more_dangerous_than_ever_partner/&quot;&gt;Chicken in America&lt;/a&gt; is usually &lt;a href=&quot;https://www.washingtonpost.com/world/europe/free-trade-with-us-europe-balks-at-chlorine-chicken-hormone-beef/2014/12/04/e9aa131c-6c3f-11e4-bafd-6598192a448d_story.html&quot;&gt;washed with chlorine&lt;/a&gt;. You can&apos;t sell chlorine-washed chicken in the EU. The US chicken industry wants to sell its chicken internationally without having a separate chlorine-free production line. So the US puts something into a trade agreement with the UK that says chlorine-washed chicken is OK. The UK wants a quick agreement so says yes to that so it can improve the deal on a bigger priority like financial services.&lt;/p&gt;
&lt;p&gt;Apply the chicken example to basically every category of goods or services.&lt;/p&gt;
&lt;p&gt;If you&apos;re a single bloc negotiating on behalf of 28 countries you&apos;re more likely to be able to say no to stuff you really don&apos;t want and other countries are more likely to say yes to the things you do want. That&apos;s because other countries have much stronger incentives to get a deal with you so they can do more trade with you than if you&apos;re a single country alone.&lt;/p&gt;
&lt;p&gt;File this one under things I never thought about before the referendum&lt;/p&gt;
</content:encoded></item><item><title>Some of my Sacred Harp poster designs</title><link>https://edjohnsonwilliams.co.uk/blog/2019-07-08-some-of-my-sacred-harp-posters/</link><guid isPermaLink="true">https://edjohnsonwilliams.co.uk/blog/2019-07-08-some-of-my-sacred-harp-posters/</guid><pubDate>Mon, 08 Jul 2019 09:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Over the last year, I&apos;ve been designing posters for the &lt;a href=&quot;https://durhamsacredharp.co.uk&quot;&gt;Durham Sacred Harp&lt;/a&gt; singing. These are a few that I&apos;ve made.&lt;/p&gt;
&lt;h2&gt;Main poster&lt;/h2&gt;
&lt;p&gt;This one is very close to the one that I printed up and put around town. There are a couple of small differences. If you haven&apos;t sung Sacred Harp before, then the logo at the top is alluding to &lt;a href=&quot;https://en.wikipedia.org/wiki/Sacred_Harp#Singing_Sacred_Harp_music&quot;&gt;the hollow square arrangement&lt;/a&gt; that Sacred Harp singers sit in. I&apos;ve tried to prioritise a modern look and legibility of the copy.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;Bookwrap&lt;/h2&gt;
&lt;p&gt;This is a bookwrap with a similar design made landscape. It wraps around the loaner books we give out to new singers.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;Funky ones&lt;/h2&gt;
&lt;p&gt;These are a couple of designs that I kind of wimped out of getting printed and sticking up around town. I particularly like the first one. The shapes at the top are from &lt;a href=&quot;https://en.wikipedia.org/wiki/Sacred_Harp#The_music_and_its_notation&quot;&gt;the shapenote notation system&lt;/a&gt; that Sacred Harp uses.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
</content:encoded></item></channel></rss>