home / notes / 2022 / 2021 / 2020 / 2019 / 2018

Friday 24.06.2022

Random walks

From the Introduction to The Nature of Code by Daniel Shiffman.

Two random walk experiments. Images shrunk by scale factor of 2.

The top two frames in the linked image show the first random walk after 5 minutes and half an hour. The bottom two frames show the second random walk after roughly similar time intervals but I would not swear to that. Each step is one pixel long and can only be in one of the four cardinal points - so these images are actually from a walk on a Cartesian grid. The Processing code is below, I changed the size of the canvas to make it square.

Eyeballing the walk as the images emerged, I was impressed at the degree of clumpyness apparent using a uniform probability distribution to select the next step. Also the speed with which the walker can reach a boundary is impressive. And the 'path dependence' of the future evolution brings home the role that contingency plays in the short and medium term. The 'long term' would be when the entire frame is full of black pixels, so all walks would end up looking the same of course.

// This is very small
class Walker {
  //[full] Objects have data.
  int x;
  int y;

  //[full] Objects have a constructor where they are initialized.
  Walker() {
    x = width/2;
    y = height/2;

//[full] Objects have functions.
  void display() {

void step() {
    // 0, 1, 2, or 3
    int choice = int(random(4));
        if (choice == 0) {
    } else if (choice == 1) {
    } else if (choice == 2) {
    } else {


// A Walker object
Walker w;

void setup() {

//Create the Walker.

  w = new Walker();

void draw() {
  //[full] Call functions on the Walker.
  w.step(); //[bold]
  w.display(); //[bold]

I'm planning to read and code through the rest of the book (which I bought the pdf of) but I'm already wondering about having some kind of 'self avoidance' memory for my walker.

Eyeballing the walk indicates that the walker spends quite a lot of time crossing over the previous path. If I kept the last (say) 10 steps in an array and did not allow repeating those, how would that affect the path? Perhaps reading the current pixel colour then making that colour darker if repeating would make the self-crossing more obvious?

Thursday 23.06.2022

Turn R into a handy command line calculator

Yes, I am using R as a command line calculator with hidden features. Why not? R has a huge range of built-in functions and loads quickly in the terminal. And you have a graphing capability.

> ans
function() {
 val <- .Last.value
> 4 * atan(1)
[1] 3.141593
> ans()
[1] 3.141593
> sqrt(3^2 + 4^2)
[1] 5
> ans()
[1] 5

The ability to recall the last value calculated is useful but I'm not into typing .Last.value each time so I use a simple ans() function. Still a bit clunky but less to type.

R can deal with lists and vectors and matrices as well as scalars so I'll play with some special functions for things like creating mock data sets. For example taking a sample from a normal distribution with given mean and variance and rounding level.

R can save any functions and variables defined in the current session and a list of the commands issued in the session. By default, the workspace and history file are saved in the working directory in the files .RData and .Rhistory. I'm using the home drive level workspace as the calculator workspace. Actual statistics sessions run from directories under Documents so they stay clean.

Saturday 18.06.2022

Trying out this minimal style tag on this page just to see. Yes, it is raining today.

My only modifications are to reduce the inter-linear spacing a tad, reduce the top padding and to provide a slight tone on the background to reduce the contrast.

html {
  max-width: 70ch;
  padding: 1em 1em;
  margin: auto;
  line-height: 1.50;
  font-size: 1.25em;

Saturday 11.06.2022

Entropic Morris Minor

Triple view of the partially disassembled Morris Minor

Seen in a car park near the inner ring. Looks mostly complete, and those wheels are definitely an aftermarket addition. I can remember a neighbour in the street on which I grew up as a child driving a pristine new Wimbledon green model of the Morris Minor to work and back each day.

Friday 27.05.2022

The 'time button' [° ' "]

In a recent Maths support session via Zoom

STUDENT: "Can you explain the time button on my calculator"

ME: "Eh?"

STUDENT: "So you convert 4 hours 36 minutes to 4.6 hours"


ME: (sudden realisation) "Ah, the degrees minutes and seconds button"

I had never thought of the degrees minutes and seconds button as a short cut to time conversion to and from decimal hours before. You can also convert from decimal hours to hours minutes and seconds by pressing the very same button - the Casio calculators that are generally recommended for GCSE Maths in the uk detect the format and apply the transformation as needed. Got to thank the Babylonians for their 360 degrees and the sexagesimal (base 60) division of the degree/hour and minute.

Given the world we live in now, perhaps the [° ' "] button would be better known as the 'time button'. I mean who still uses angles in degrees, minutes and seconds?

Saturday 14.05.2022


Until about a week ago, I installed software not included in the Slackware base install manually from slackbuilds.org apart from things like OpenOffice, VLC and the Java JDK for which I used the binary distributions.

I've just started using sbotools as a result of watching the OTB's video review of the various slackware add-ons. I like the similarity with BSD ports, and, so far things have been fine.

I'm using sbotools with a slackware64 15.0 install on an old Thinkpad X60 (that is a 2006 vintage core duo laptop with 3Gb RAM and a 2T mechanical hard drive) and it basically works as advertised. You have to specify a slackbuild repository. Mine is

bash-5.1$ cat /etc/sbotools/sbotools.conf 

The first time you run a command, the slackbuild repo is cloned to

bash-5.1$ ls /usr/sbo/repo
CHECKSUMS.md5       TAGS.txt       desktop  haskell     perl
CHECKSUMS.md5.asc   TAGS.txt.gz    development  libraries   python
ChangeLog.txt       academic       games    misc        ruby
README          accessibility  gis      multimedia  system
SLACKBUILDS.TXT     audio      graphics network
SLACKBUILDS.TXT.gz  business       ham      office

and the downloaded source files are saved in

bash-5.1$ ls /usr/sbo/distfiles/
TeXmacs-2.1.1-src.tar.gz  maxima-5.44.0.tar.gz
bubblewrap-0.4.0.tar.xz   rest-0.8.1.tar.xz
geoclue-2.4.7.tar.xz      shotwell-0.24.0.tar.xz
guile-1.8.8.tar.gz    webkitgtk-2.36.1.tar.xz
ipe-7.2.13-src.tar.gz     wpebackend-fdo-1.8.3.tar.xz
libunique-1.1.6.tar.bz2   wxWidgets-3.0.5.tar.gz
libwpe-1.12.0.tar.xz      wxmaxima-Version-21.01.0.tar.gz
lua-5.3.4.tar.gz      xdg-dbus-proxy-0.1.2.tar.xz

I haven't updated any of the slackbuilds yet, but I imagine that the update script compares these versions with the versions in the updated repository and downloads and compiles the changed ones.

I'm currently compiling texmacs, which has one dependency - an older version of GNU Guile. Below are the commands...

# sbofind texmacs
# sbofind -i texmacs
# sbofind -r texmacs
# sboinstall texmacs

The sbofind -i command prints the texmacs.info file from the slackbuild so you can see the top level dependencies. The sbofind -r texmacs command prints the blurb about what the package does and what options are available. The sboinstall texmacs command sets up the queue of dependencies and compiles. The command runs a dialogue to ask you to confirm each dependency and then the whole compilation. So far, I have not set an option at compile time. I need to try that out for one of the more complex slackbuilds. Once you go ahead with the installation, sboinstall goes ahead and fetches all the source files and then runs each slackbuild script in turn from the most basic dependency up the tree.

Packages are installed progressively. Packages are built in the usual /tmp/ directory and by using an ls -1t command, you can find them all and copy them to a directory in your user space to allow installation on other machines.

The biggest compile I've tried so far was shotwell which has webkit2gtk as a dependency. So an overnight compile. If I'm in an evil mood, I might try pandoc with all the optional dependencies and see how long that takes.

Friday 29.04.2022

New starter

I had to make a new bread starter as we could not take a sample of the old one with us for a week away. The standard process adapted from an article by Hugh Fearnley-Whittingstall worked well.

First bake today was a couple of 'rustique' small loaves (150g wholemeal, 350g white, 340g water, 2 table spoons of starter, 1 table spoon of olive oil). Results very nice once shaped and baked for about 20min plus 5 min upside down to firm the bottom crust of the loaves.

The new starter is in the fridge now. It needs feeding twice a week (9°C reduction in temperature corresponds to half rate of fermentation as a rough rule of thumb so a feed every 3 to 4 days is fine for refrigerated starter).

Tuesday 19.04.2022

Fast and slow

Fast: suddenly there is a war in Europe. Scramble to support a country that has been invaded. Rapid coordination of the response by other European countries and the US. Lots of newspaper headlines about personal stories, some dreadful. Debate about the extent to which the leader of the invading country was out of touch / in a bubble / surrounded by yes-people. Urgent plans to increase North Sea oil and gas production and to build nuclear reactors.

Slow: Hospitals quoting long casualty times and some no longer testing for COVID on admission. Estimate that about a quarter of minor crimes not prosecuted because victims do not feel it is worth the hassle. Cost of living increases. Further erosion in Parliamentary behaviour norms. Still no long term planning around disposal of nuclear waste. National Health Service reveals major problems with child birth and associated drug prescription. Housing starts lower than planned. Number of children deemed to be living in poverty increases. International 'rule based' order seems to be shifting towards military or coercive processes as time goes by. The 'slow P & O' outsourcing of clerical work (aka IT) continues.

Saturday 02.04.2022

Sourdough going strong

Post Scarborough sourdough can still raise a wicked loaf. Basically the Universal Bread Recipe with sourdough and nuts.

Mix dry ingredients then add the water/sourdough/honey and mix to a rough dough. Leave to rest for half an hour. Knead for 10 min or so (can be rippy). Knead with wet hands/more water as the wholemeal can absorb more.

Rise overnight. Shape as 'Spanish country loaf': pull out to about 16 inches then fold in three and repeat four times. Place on oven tray lined with baking parchment and allow to rise for one to two hours. Slash three or four times, shake salt and sprinkle cold water on top. Then bake for half an hour in a pre-heated (225 deg min) oven. Turn over to firm up the base and bake for a further 10 minutes. Turn out onto rack and allow to cool.

Sunday 20.03.2022

Montage of 12 square images from yesterday's walk

The ImageMagick montage command line was something like

$ montage *.jpg -geometry 256x256+0+0 wall.jpg

to resize the 12 images in a directory to 256 pixels square and then montage them in 4 by 3 pattern with no borders around the images.

Saturday 12.03.2022

'Farmhouse' Veggie Soup

A cheap meal so you can donate more.

A picture of the main ingredients cut to the weights suggested in a Schwartz recipe for farmhouse vegetable soup helps visualise the required amounts without actually bothering to weigh them out in future.

A third of a stock cube in around 800ml of water worked fine. The frying of the leeks, celery and carrots for 5 minutes does make a kind of 'chef's base' with a creamy aspect. Adding the flour makes a sort of paste and it is worth mixing in the stock slowly as suggested in the recipe.

I add a (drained) tin of mixed beans towards the end of the cooking time: kidney, haricot, borlotti and black eye beans for a bit of protein. Served with cheese, apple slices and toast as a main meal for two with some leftovers to start a curry.

Sunday 06.03.2022

Algebra: not a revision guide

Just thinking aloud here after walking through GCSE Foundation algebra with some students who don't find it easy...

Positive numbers, positive quadrant

Negative number arithmetic

Pictures of formulas: graphs

That's enough to be going on with for now, but I need to find a set of practical applications or historically important applications of this lot that are simple enough to be analysed with basic algebra but rich enough to be vaguely interesting.

Wednesday 23.02.2022

Arithmetic is everywhere...

Green hand dryer

The label on the dryer proudly boasts 0.003 Kwh use for 5 to 7 seconds drying. By my mental arithmetic that is 3 watt hours used in 5 seconds. So 3600 / 5 * 3 watts heater rating = 2160 so call it a 2Kw heater.

Hands still wet after 10 seconds, tried several dries, still wet. I'm not convinced. Went and found some paper towels.

Cylinders and blocks

The 2T mechanical hard drive shows 16065 logical blocks of 512 bytes, however the physical sector size is 4096 bytes. I wanted (or so I thought) a partition to start on a sector and cylinder boundary. One cylinder is 16065*512/4096 = 2008.125 sectors, so a multiple of 8 cylinders will coincide with a physical sector boundary.

My second partition ended at 14622 cylinders. 14624 * 8225280 / 4096 is a whole number of sectors so could start next partition at 14625th cylinder. And cfdisk was quiet (no more 'partition start not on a partition boundary' errors).

Actually, the issue had nothing to do with the cylinder/sector thing, but it was nice to break out the 16 digit calculator...

Saturday 05.02.2022

Slackware 15.0

I use Slackware linux on my most often used laptops, Slackware 14.2 for 'work' and until yestderday, Slackware -current on a test laptop. I don't write about Slackware too much because it usually just works.

Patrick Volkerding pronounced Slackware 15.0 finished and released a couple of days ago. Typically, PV was playing games with the release time and with the last few entries in the ChangeLog. The whimsicality is part of the attraction of this Linux distribution along with the general 'no drama' approach (if working, not generally fixed and you get what the upstream programers released not a repackaged version with backported anything).

As one might expect the HN thread and the comment sections on articles about the Slackware release in the various IT Websites followed a pattern...

Interestingly, most of the actual articles manage to mention

Anyway, I was running the development version of Slackware (-current) on my old Thinkpad X60 with 2Gb of RAM and a newly purchased 120Gb SSD. Quite snappy but not up to running the KDE desktop environment with all of its applications and processes, so I left the KDE package set out of the original install.

In honour of the actual release, I changed my etc/slackbuilds/mirrors list to point to the mirrorservice.org's newly synchronised slackware-15.0 tree and checked that there were no actual changes.

I downloaded the official 32 bit installer iso image (3.6Gb) and dded that image to a USB stick. I decided to try simply taring up my home drive following a suggestion on StackOverflow...

$foo tar czpf /var/tmp/home.tgz .

...the trailing dot is the clever bit. Your dotfiles (and directories) will be included in the archive. The /var/tmp directory is user writable and not in your home drive so no recursive calls filling up the hard drive. Once the tar command completed, I copied the home.tgz archive to an external hard drive.

Next, booted off the USB stick, set up three partitions on the SSD using cfdisk (I find it easier to use than fdisk)

/dev/sda1    1G Linux swap
/dev/sda2   30G Linux filesystem  root (not encrypted)
/dev/sda3   80G Linux filesystem  raw device for cryptfs

Then I set up an encrypted volume on /dev/sd3 simply by following the instructions in the README_CRYPT.TXT file in the installation image. I actually printed the file out before starting the installation, and then installed everything except the KDE package set and added the /etc/crypttab file as per the README and rebooted. Then, as usual, set up my user and a few other things.

At that point, I copied the home.tgz archive back to my /home/user directory and simply expanded it...

$foo tar xvf home.tgz

...then I started up xfce4 and started Firefox and carried on reading the page I was reading before reinstalling.

Friday 28.01.2022

Starter rescue

Audrey, my sourdough starter, is smelling a bit too sour and there was a fair amount of hooch (the brown evil smelling liquid that forms on the top of a 'mature' starter which contains the alcohol produced by the fermentation). I dumped 150g of the starter (about 75% of what I keep) and refreshed with 75g water and 75g strong white bread flour. I'm keeping it at room temperature over night and then dumping half and feeding it up again tomorrow morning to see how it goes.

If all is well I'll dump half again and feed it tomorrow morning. Then in the evening I'll dump 100g and add 75g water and 75g flour. Leave that at room temperature for three hours or so and it should be jumping. I'll start a sourdough around 10pm and leave it over night. By the time I start that loaf, my starter will retain 0.25 × 0.5 × 0.5 ≈ 6% of what was in the jar tonight.

Since the Great Flour Shortage of 2020 I have been keeping around 200g of 1:1 starter fed once a week or slightly more often. I'll build that up to around 270g when I'm doing a bake and add 70g of starter to 500g flour and 350g water and the other ingredients (salt, rosemary, cinnamon, caraway seeds) and leave that to rise overnight and shape and bake. Has been working well with a reasonable rise. Not huge but not a brick either.

Tuesday 25.01.2022

Window of Truth (forever)

Window of Truth [604 by 448]

A lot of work went into this...

Monday 17.01.2022: Slackware 15.0 any time soon

I've been using Slackware since July 2014 (14.1). I'm posting this from my last remaining 32bit only computer, a ThinkPad X60 dating from December 2016. I've installed Slackware 15.0 RC3 using Alien Bob's Slackware Current Mini iso dd'ed to a USB stick.

I dd'ed the weekly Slackware iso from Slackware.no to a second USB stick. This is the only source of a 32bit iso for Slackware current/RC releases that I know of. These iso images are not hybrid (or at least they were not when I last tested one) and so won't boot if dd'ed to a USB stick. You have to burn them to a DVD (and then find a USB DVD drive that will actually boot your laptop). So my method is...

I'm using Seamonkey as the Web browser as I think that Firefox might be a little too heavy, and things seem to be working fine. With Apache OpenOffice installed from the RPM binaries (converted to Slackpkg format using rpm2tgz) I have most of what I need on this landfill machine.

The thin bezel Thinkpad X60/X61 profile - 12.1 inch 4:3 aspect ratio laptop with basically no wasted space and an old school keyboard - suits me to the ground. These are getting rare now so may need to get another one in for parts.

Saturday 15.01.2022

Install Java sdk version 11 on OpenBSD 7.0. I want this to run processing. There are several jdk packages available on OpenBSD...

foo# pkg_info -Q jdk

I went with jdk version 11 for no good reason, just that I know version 16 is quite new and has extra language features, and version 8 is very old now. Installing using pkg_add...

foo# pkg_add jdk-
quirks-4.54 signed on 2022-01-14T22:25:03Z
jdk- ok
New and changed readme(s):
--- +jdk- -------------------
You may wish to add /usr/local/jdk-11/man to /etc/man.conf

As usual the pkg-readme for jdk-11 only includes information that is special to the OpenBSD port, in this case some information about using IP addresses with Java's networking libraries. You have to research how to make java available to the user by setting some shell variables to the user's .profile...

foo$ cat .profile
# $OpenBSD: dot.profile,v 1.7 2020/01/24 02:09:51 okan Exp $
# sh/ksh initialization


PATH=$HOME/bin:/bin:/sbin:[...OTHER PATHS...]:/usr/games:$JAVA_HOME/bin

...and when you start a new log-in shell, you can see...

foo$ java -version
openjdk version "11.0.12" 2021-07-20
OpenJDK Runtime Environment (build 11.0.12+7-1)
OpenJDK 64-Bit Server VM (build 11.0.12+7-1, mixed mode)

And finally, I had to add a MANPATH line to /etc/man.conf so I can access the jdk man pages...

foo# cp /etc/examples/man.conf /etc/man.conf
foo# cat /etc/man.conf
...added this line at bottom...
# Added for Java jdk-11

manpath /usr/local/jdk-11/man

So now the java manual is available. I was supposed to read man man.conf to find out how to add the man pages to the MANPATH but I got lazy and did a Web search and came up with a Daemonforums post that explained what to do. The Java REPL called jshell works within the terminal emulator window, which is nice, so now I have yet another calculator.

Friday 14.01.2022

Lovely blue sky all today with little wind. All through our walk into town there were birds singing, by the sound of it mostly thrushes/blackbirds. Even Digbeth and Birmingham's city centre have habitat for small birds, as well as the inevitable starlings, crows and seagulls.

Re-wrote the new script for producing this notes page today. The notes are held in a markdown file that can be edited as I wish. For convenience there is a script that produces a new note at the head of the file and that script puts a heading with the date and an id=YYYYMMDD attribute in the h1 tag to match the previous years' notes pages. I'm using the original markdown's inline html format for the headings.

There is a second script that makes a Web page from the markdown file, and that will remove duplicate date headers (if I write twice on the same day) and add the header and footer. The html file itself is never edited as it is overwritten each time I generate the page.

Making sense a bit now.

Saturday 08.01.2022

Fortran as a learning language?

For numerical programs perhaps. Below is the author's example from the first Web page linked, but with some necessary information added to the source file.

[15:24]~$ cat horizon.f90
! Usage: Takes a height in metres above sea level
!        Prints distance to horizon in kilometres
! Compile: gfortran horizon.f90 -o horizon.exe
!      nb: .f90 extension indicates 'free source' format
program horizon
  real :: height, dist
  write(*,*) 'Height above sea level(m): '
  read(*,*) height
  dist = sqrt(2*6367.45*(height/1000.0))
  write(*,*) 'Distance to horizon = ', dist, 'km'
end program horizon

So you have to ensure that the fortran compiler in use is expecting files in 'free source form'. Using the Gnu Compiler Collection, you use gfortran as the compiler and make sure that the source file has extension .f90.

Use a ! at the beginning of the line as the comment character. I like to put a comment at the top of a (perhaps slightly more complex) source file with an example of use and a typical compilation command. So already some overhead and rules. But access to maths functions without importing or linking could be an advantage.

Running the example program produces output like this...

[15:24]~$ ./horizon.exe
 Height above sea level(m): 
 Distance to horizon =    22.5698032     km

...so some more reading up on formatting in the write statements might be needed to produce a neater dialogue for an astronomical program.

Friday 07.01.2022


Brian Kernighan's Home page has a link to a course that he teaches at Princeton called Computer Science 109: Computers in Our World. As the course title suggests the material is aimed at students who are not planning on a career in IT. The course attempts to explain how computers and software work, and therefore what assumptions might be made by computer programmers when asked to solve a problem by writing software. The course also covers 'machine learning' (i.e. statistical inference applied to data that has been gathered) and aspects of security.

The 'labs' section has a series of tutorials about making Web pages using HTML, spreadsheets, python, python libraries for handling natural language, machine learning (using private systems by the look of it) and a web tour of privacy and tools like Tor. This section looks especially useful.

The course textbook is Understanding the Digital World by Kernighan, a copy of the second edition of which I have just bought on Waterstones click and collect. I'll post a summary and review once I have read the work, and perhaps worked through some of the 'labs' and problem sets.

Nice to see one of the original Unix greybeards still going strong and trying to get people to look closely at how computers and algorithms work. The hope is that the students who pass through this course will know what questions to ask and how to challenge assumptions as they progress through their no doubt illustrious careers in fields unrelated to computing.


Lex Fridman Podcast #109 takes the form of a one and three-quarter hour interview with Dr Kernighan, touching on Unix, C, Awk and a new one to me, AMPL which is a proprietary domain specific language for mathematical modelling.

Wednesday 05.01.2022

#!/usr/bin/env bash

p="<h1>Some title</h1>"

s=(${r//./ })
echo "<hr><a name=${s[2]}${s[1]}${s[0]}>$p</a>"

The little script example above will split up the date in variable r into an array in s that has the day number, the month number and then the year number as separate elements. The echo line then prints them in reverse order so in yyyymmdd format inside an anchor name html tag. The title gets printed inside the anchor name tag. This all means that I can generate links to each note in this page that work the same as the links to each of the notes in the previous notes pages. The anchor name tag is depreciated in html 5 but it is easier than using an id=20220105 attribute inside the h1 tag (because I can just dump the whole heading line inside the anchor name tag and its associated closing tag), and it works for now.

Pure copy pasta from the results of a Web search. I'm going to have to learn about bash expansion and all that soon.

Monday 03.01.2022

Going back over the notes pages (2018)

Below are the mathematical notes for 2018. I need to do more maths thinking just to keep the brain from congealing.

Sunday 02.01.2022

Spanish country bread (Pan Rustico)

I'm liking the use of a 'mock starter' or biga, like in my Roman bread. I made a version of this just now and it is soft and moist (unlike much of my bread which tends towards the tasty, fibre-rich, low sodium breeze block end of the spectrum). I'm with the Staff of Life geezer in thinking that the hairys' recipe has a stupid amount of yeast in the starter. So below is my take...


Main dough

Main dough method

Shape the bread


These country bread recipes date from the days of family plots I suspect. You grew a mix of wheat, rye and barley as insurance against fungus or insect attack and the resulting grains were not easy to separate...

Version 2

A few days later: the soft and chewey nature of this loaf went down very well so I did another one. I used a quarter of a teaspoon of Alisons' quick yeast for the sponge and half a teaspoon for the main dough. Rise was just as good (in fact a little higher). A future variation will be a tablespoon of actual sourdough starter for the sponge, and then a quarter of a teaspoon of instant yeast for the main dough.

The stretch and folds during shaping seem to be a factor - will try that with other recipes. Will also need to try the recipe with ordinary strong white bread flour as opposed to the Canadian flour (15g protein) I'm working through now.

Version 3

Same recipe but with ordinary strong white bread flour (Lidl) instead of the Canadian high protein flour. More or less the same and quite moist. Not quite as good a rise but that could simply be loaf to loaf variation. This recipe is a keeper.

Saturday 01.01.2022

A New Year's day test post after the annual k58 notes page housekeeping (written while the potatoes are roasting).

I'm using a modified script to manage this not-quite-a-blog, so there will be some changes while I tweak stuff.

Keith Burnett: last modified Fri Jun 24 19:17:52 BST 2022