Digital gardening

2025-02-09

During the past few years I’ve gone through some effort to keep my digital life simpler and more orderly than my real life.

  • Migrated from Ubuntu to Debian. Been a breeze. Debian is like Ubuntu without the bad parts. I blogged about still actually being happy with Ubuntu, but am even happier with Debian. The Debian repos mostly move faster than I notice things. While I’d sometimes like to use a newer neovim, it’s not a big issue. I enjoy the stability and the feeling that my system belongs to me again.
  • Migrated from Dropbox to Syncthing. Syncthing gives me headaches, but fewer than Dropbox. Oh well…
  • Migrated from LastPass to KeePassXC. Passwords are too important to outsource to a for-profit. LastPass wasn’t the right for-profit anyway.
  • All the websites I maintain now self-host all the css/js/fonts. I try to avoid Bootstrap and other large dependencies anyway.
  • My content websites mostly use Markdown and Jekyll. Markdown might be a terrible format, but it’s good enough for me. Jekyll works for now, if it stops working, I can rewrite the parts I need in a language of choice in about an afternoon.
  • Stick with Elm for my side projects and avoid backend like the plague. I almost started learning OCaml. And Janet. And Zig. And Roc and Gleam. But for now, if I need a backend, I’ll swallow the ten thousand string types, the exorbitant size of ~/.stack/, the slow compile times, and reluctantly use Haskell ¯\_(ツ)_/¯
  • I rewrote most (all?) of my favicons into hand-crafted SVG. Inkscape output is verbose and an unreadable mess. Hand-written SVG can be beautiful.

Here’s my tsumego collections favicon, followed by its source:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 8" width="64px" height="64px">
<defs>
<filter id="blur">
	<feGaussianBlur in="SourceGraphic" stdDeviation="0.1"/>
</filter>
<radialGradient id="stripes" gradientTransform="translate(-4, -1) scale(6, 4)">
	<stop offset="40%" stop-color="#EEE"/>
	<stop offset="43%" stop-color="#CCC"/>
	<stop offset="44%" stop-color="#EEE"/>

	<stop offset="45%" stop-color="#EEE"/>
	<stop offset="48%" stop-color="#CCC"/>
	<stop offset="49%" stop-color="#EEE"/>

	<stop offset="50%" stop-color="#EEE"/>
	<stop offset="53%" stop-color="#CCC"/>
	<stop offset="54%" stop-color="#EEE"/>

	<stop offset="55%" stop-color="#EEE"/>
	<stop offset="58%" stop-color="#CCC"/>
	<stop offset="59%" stop-color="#EEE"/>

	<stop offset="60%" stop-color="#EEE"/>
	<stop offset="63%" stop-color="#CCC"/>
	<stop offset="64%" stop-color="#EEE"/>

	<stop offset="65%" stop-color="#EEE"/>
	<stop offset="68%" stop-color="#CCC"/>
	<stop offset="69%" stop-color="#EEE"/>

	<stop offset="70%" stop-color="#EEE"/>
	<stop offset="73%" stop-color="#CCC"/>
	<stop offset="74%" stop-color="#EEE"/>
</radialGradient>
<radialGradient id="edges">
	<stop offset="80%" stop-color="#FFF0"/>
	<stop offset="100%" stop-color="#0003"/>
</radialGradient>
<radialGradient id="highlight" gradientTransform="translate(-0.15 -0.15)">
	<stop offset="0%" stop-color="#FFF"/>
	<stop offset="20%" stop-color="#FFF"/>
	<stop offset="50%" stop-color="#FFF0"/>
</radialGradient>
</defs>

<circle cx="4.1" cy="4.1" r="3.8" fill="#000C" filter="url(#blur)"/>
<circle cx="4" cy="4" r="3.8" fill="url(#stripes)" />
<circle cx="4" cy="4" r="3.8" fill="url(#edges)" />
<circle cx="4" cy="4" r="3.8" fill="url(#highlight)" />
</svg>

Little wins for simplicity. They make me happy.

Diminishing returns

2025-01-25

There are many things which are vitally important to one’s overall wellbeing. Exercise, eating well, sleep, mental health, personal finance, and a few more.

There are people who concentrate a lot on one of these, eg they exercise a lot. Nothing wrong with exercise, but doing much beyond the bare minimum is high effort low payoff.

I try to do the five tibetans every morning. I only do seven repetitions of each, it takes about five minutes. The difference between doing nothing vs the five minutes of exercise is large. The difference between doing five minutes versus two hours, I won’t ever know but suspect it’s not so great.

Is the same true for blogging? This was not a high effort blog post. Just something I’d like not to forget.

Ultimate Tapan Kaikki episodes

2024-12-26

Ultimate TK is a Finnish top down shooting game. I used to play it in high school. It’s been open sourced and there’s a nicely working cross-platform fork at suomipelit.

Here’s a bit of a cheat-sheet for the episodes, listing the enemies and goodies available at each level:

BLANKET2

BLANKET2: 1 “crossroads”

  • Size/time: 32×20, 120 seconds
  • Enemies: pistol boy: 3, civilian: 2
  • Weapons: pistol: 1, flame thrower: 1
  • Bullets: 9mm: 2×50, gas: 2×50
  • Health capsules: 3

BLANKET2: 2 “containment zone”

  • Size/time: 40×36, 210 seconds
  • Enemies: pistol boy: 3, shotgun maniac: 1, civilian: 2
  • Bullets: 9mm: 1×50, 12mm: 1×50, gas: 1×50
  • Health capsules: 2

BLANKET2: 3 “entrance hall”

  • Size/time: 20×34, 90 seconds
  • Enemies: pistol boy: 2, shotgun maniac: 2, uzi rebel: 1, civilian: 1
  • Weapons: uzi: 1
  • Bullets: 9mm: 2×50, 12mm: 1×50, shotgun shells: 1×20
  • Health capsules: 2

BLANKET2: 4 “sub-station alpha”

  • Size/time: 36×30, 180 seconds
  • Enemies: pistol boy: 3, shotgun maniac: 2, uzi rebel: 2, civilian: 2
  • Bullets: shotgun shells: 2×20
  • Health capsules: 2

BLANKET2: 5 “backyard”

  • Size/time: 40×34, 120 seconds
  • Enemies: pistol boy: 2, shotgun maniac: 2, uzi rebel: 2, civilian: 1
  • Weapons: auto rifle: 1, c4 activator: 1
  • Bullets: 9mm: 1×50, 12mm: 1×50, c4: 1×5, gas: 2×50
  • Health capsules: 5

BLANKET2: 6 “hangar”

  • Size/time: 32×34, 80 seconds
  • Enemies: pistol boy: 1, shotgun maniac: 3, uzi rebel: 1, civilian: 2
  • Weapons: auto rifle: 1
  • Bullets: 12mm: 1×50, gas: 1×50
  • Health capsules: 3

BLANKET2: 7 “airstrip cc-1013”

  • Size/time: 45×20, 100 seconds
  • Enemies: shotgun maniac: 8, civilian: 2
  • Weapons: pistol: 1, grenade launcher: 1
  • Bullets: 9mm: 1×50, medium grenades: 2×10, c4: 1×5
  • Health capsules: 5

BLANKET2: 8 “guard hut”

  • Size/time: 36×24, 60 seconds
  • Enemies: pistol boy: 3, shotgun maniac: 2, uzi rebel: 1, commando: 1, civilian: 3
  • Weapons: heavy launcher: 1, c4 activator: 1
  • Bullets: 12mm: 2×50, shotgun shells: 1×20, medium grenades: 1×10, heavy grenades: 1×5, c4: 1×5, gas: 1×50
  • Health capsules: 2

BLANKET2: 9 “blood storm”

  • Size/time: 36×26, 160 seconds
  • Enemies: pistol boy: 4, shotgun maniac: 2, uzi rebel: 2, commando: 1, civilian: 10, punisher: 1
  • Weapons: auto shotgun: 1, flame thrower: 1
  • Bullets: 12mm: 2×50, shotgun shells: 1×20, medium grenades: 1×10, c4: 1×5, gas: 1×50
  • Health capsules: 4

BLANKET2: 10 “old k-mart”

  • Size/time: 42×36, 180 seconds
  • Enemies: pistol boy: 4, shotgun maniac: 2, uzi rebel: 3, commando: 1, grenade guy: 1, civilian: 5, punisher: 2
  • Weapons: auto shotgun: 2
  • Bullets: 12mm: 2×50, shotgun shells: 1×20, c4: 1×5, gas: 2×50
  • Health capsules: 4
BLANKET

BLANKET: 1 “we came to kill…“

  • Size/time: 32×20, 110 seconds
  • Enemies: pistol boy: 3, civilian: 2
  • Weapons: pistol: 2
  • Bullets: 9mm: 3×50, shotgun shells: 1×20
  • Health capsules: 2

BLANKET: 2 “raid the nazi base”

  • Size/time: 32×20, 190 seconds
  • Enemies: pistol boy: 3, shotgun maniac: 1, civilian: 10
  • Weapons: pistol: 2, shotgun: 1, uzi: 1
  • Bullets: 9mm: 4×50, shotgun shells: 2×20
  • Health capsules: 3

BLANKET: 3 “house number 1013”

  • Size/time: 32×20, 80 seconds
  • Enemies: pistol boy: 3, shotgun maniac: 2, civilian: 1
  • Weapons: shotgun: 1
  • Bullets: 9mm: 2×50, shotgun shells: 1×20
  • Health capsules: 2

BLANKET: 4 “deserted hospital”

  • Size/time: 50×25, 210 seconds
  • Enemies: pistol boy: 3, shotgun maniac: 1, uzi rebel: 2, civilian: 6
  • Weapons: pistol: 1, shotgun: 1
  • Bullets: 9mm: 2×50, shotgun shells: 3×20
  • Health capsules: 5

BLANKET: 5 “fallen angel”

  • Size/time: 39×33, 130 seconds
  • Enemies: pistol boy: 3, shotgun maniac: 2, uzi rebel: 1, commando: 1, civilian: 2
  • Weapons: shotgun: 1
  • Bullets: 9mm: 2×50, 12mm: 2×50, shotgun shells: 1×20, gas: 1×50
  • Health capsules: 4

BLANKET: 6 “reach the car”

  • Size/time: 18×30, 60 seconds
  • Enemies: pistol boy: 2, shotgun maniac: 2, grenade guy: 1, civilian: 1
  • Weapons: shotgun: 1, auto rifle: 1
  • Bullets: 12mm: 1×50, shotgun shells: 1×20, c4: 1×5, gas: 1×50
  • Health capsules: 3

BLANKET: 7 “command center”

  • Size/time: 40×32, 180 seconds
  • Enemies: pistol boy: 15, civilian: 20, punisher: 1
  • Weapons: auto rifle: 1, heavy launcher: 1
  • Bullets: 12mm: 2×50, shotgun shells: 1×20, heavy grenades: 1×5, c4: 1×5
  • Health capsules: 6

BLANKET: 8 “one more murder”

  • Size/time: 28×22, 110 seconds
  • Enemies: shotgun maniac: 3, uzi rebel: 1, commando: 1, civilian: 3
  • Bullets: 9mm: 1×50, 12mm: 1×50, medium grenades: 1×10, c4: 1×5
  • Health capsules: 1

BLANKET: 9 “mainframe hall”

  • Size/time: 40×36, 210 seconds
  • Enemies: pistol boy: 3, shotgun maniac: 2, uzi rebel: 2, grenade guy: 1, civilian: 1, punisher: 1
  • Weapons: auto grenadier: 2
  • Bullets: light grenades: 4×15
  • Health capsules: 5

BLANKET: 10 “hope ya had fun”

  • Size/time: 42×38, 300 seconds
  • Enemies: pistol boy: 6, shotgun maniac: 2, uzi rebel: 1, commando: 2, grenade guy: 2, civilian: 8, punisher: 2
  • Weapons: pistol: 1, shotgun: 1, uzi: 1, auto rifle: 1, grenade launcher: 1, auto grenadier: 1, heavy launcher: 1, auto shotgun: 1, c4 activator: 1
  • Bullets: 9mm: 2×50, 12mm: 2×50, shotgun shells: 2×20, light grenades: 2×15, medium grenades: 2×10, heavy grenades: 2×5, c4: 2×5
  • Health capsules: 6
FIENDIS

FIENDIS: 1 “engine damage…“

  • Size/time: 40×32, 80 seconds
  • Enemies: pistol boy: 3
  • Weapons: pistol: 1, shotgun: 1
  • Bullets: 9mm: 2×50, shotgun shells: 1×20
  • Health capsules: 3

FIENDIS: 2 “an underground lab”

  • Size/time: 50×20, 120 seconds
  • Enemies: shotgun maniac: 4
  • Weapons: uzi: 1
  • Bullets: 9mm: 2×50, shotgun shells: 1×20, c4: 1×5
  • Health capsules: 5

FIENDIS: 3 “they aren’t human”

  • Size/time: 42×34, 110 seconds
  • Enemies: pistol boy: 3, shotgun maniac: 2, uzi rebel: 1, civilian: 3
  • Weapons: uzi: 1
  • Bullets: 9mm: 1×50, shotgun shells: 1×20
  • Health capsules: 2

FIENDIS: 4 “elevator ambushed”

  • Size/time: 24×16, 20 seconds
  • Enemies: commando: 1, flamer: 1
  • Weapons: auto rifle: 1
  • Bullets: 9mm: 1×50, 12mm: 2×50, mines: 1×5
  • Health capsules: 2

FIENDIS: 5 “maintainance tunnel”

  • Size/time: 16×38, 80 seconds
  • Enemies: pistol boy: 1, shotgun maniac: 2, commando: 2, civilian: 1, flamer: 1
  • Bullets: 12mm: 2×50, gas: 1×50
  • Health capsules: 3

FIENDIS: 6 “storage room”

  • Size/time: 40×38, 150 seconds
  • Enemies: pistol boy: 1, shotgun maniac: 2, uzi rebel: 3, commando: 2, grenade guy: 1, civilian: 4
  • Weapons: grenade launcher: 1
  • Bullets: 12mm: 2×50, medium grenades: 1×10, c4: 2×5
  • Health capsules: 6

FIENDIS: 7 “cloned mutants”

  • Size/time: 40×38, 170 seconds
  • Enemies: pistol boy: 3, shotgun maniac: 1, uzi rebel: 2, commando: 1, civilian: 8, punisher: 2, flamer: 1
  • Weapons: auto rifle: 1
  • Bullets: 12mm: 2×50, gas: 2×50
  • Health capsules: 6

FIENDIS: 8 “garage inc.”

  • Size/time: 40×20, 120 seconds
  • Enemies: pistol boy: 4, shotgun maniac: 2, uzi rebel: 1, commando: 1, grenade guy: 1, civilian: 6, flamer: 2
  • Weapons: flame thrower: 1
  • Bullets: 12mm: 1×50, light grenades: 1×15, gas: 4×50
  • Health capsules: 3

FIENDIS: 9 “the way out”

  • Size/time: 32×24, 80 seconds
  • Enemies: pistol boy: 1, commando: 3, civilian: 2, punisher: 3, flamer: 1
  • Weapons: auto grenadier: 1, c4 activator: 1
  • Bullets: 12mm: 2×50, shotgun shells: 1×20, light grenades: 1×15, c4: 1×5
  • Health capsules: 6

FIENDIS: 10 “final escape”

  • Size/time: 40×30, 80 seconds
  • Enemies: shotgun maniac: 4, uzi rebel: 1, commando: 3, grenade guy: 1, civilian: 6, punisher: 1, flamer: 4
  • Weapons: heavy launcher: 1
  • Bullets: 12mm: 2×50, shotgun shells: 1×20, heavy grenades: 2×5, gas: 1×50
  • Health capsules: 4
MOTHAFUX

MOTHAFUX: 1 “chiseled stone”

  • Size/time: 40×30, 120 seconds
  • Enemies: pistol boy: 1, shotgun maniac: 1, civilian: 3
  • Weapons: pistol: 2, flame thrower: 1
  • Bullets: 9mm: 2×50, gas: 2×50
  • Health capsules: 3

MOTHAFUX: 2 “the sewage”

  • Size/time: 70×20, 180 seconds
  • Enemies: pistol boy: 2, shotgun maniac: 2, civilian: 4
  • Weapons: shotgun: 1, c4 activator: 1
  • Bullets: 9mm: 2×50, 12mm: 1×50, shotgun shells: 2×20, c4: 2×5, gas: 1×50
  • Health capsules: 3

MOTHAFUX: 3 “confrontation”

  • Size/time: 34×25, 120 seconds
  • Enemies: pistol boy: 1, uzi rebel: 2, civilian: 2
  • Weapons: uzi: 1, flame thrower: 1
  • Bullets: 9mm: 2×50, 12mm: 1×50, shotgun shells: 1×20, c4: 1×5, gas: 1×50
  • Health capsules: 2

MOTHAFUX: 4 “biohazard”

  • Size/time: 60×15, 160 seconds
  • Enemies: pistol boy: 3, shotgun maniac: 3, commando: 1, civilian: 2
  • Weapons: auto rifle: 1, grenade launcher: 1
  • Bullets: 12mm: 2×50, shotgun shells: 1×20, medium grenades: 1×10, gas: 2×50
  • Health capsules: 3

MOTHAFUX: 5 “hotel room”

  • Size/time: 34×24, 60 seconds
  • Enemies: pistol boy: 1, uzi rebel: 3, civilian: 7, flamer: 1
  • Weapons: c4 activator: 1
  • Bullets: 12mm: 1×50, medium grenades: 1×10, c4: 1×5, gas: 1×50
  • Health capsules: 1

MOTHAFUX: 6 “sub-urban life”

  • Size/time: 50×34, 220 seconds
  • Enemies: pistol boy: 3, uzi rebel: 1, commando: 2, civilian: 8
  • Weapons: flame thrower: 1
  • Bullets: 9mm: 1×50, 12mm: 1×50, gas: 1×50
  • Health capsules: 3

MOTHAFUX: 7 “main street”

  • Size/time: 70×40, 210 seconds
  • Enemies: pistol boy: 5, shotgun maniac: 6, uzi rebel: 2, commando: 3, civilian: 12, punisher: 1
  • Weapons: auto rifle: 1, auto grenadier: 1
  • Bullets: 12mm: 2×50, light grenades: 1×15, medium grenades: 1×10, c4: 1×5
  • Health capsules: 6

MOTHAFUX: 8 “south park”

  • Size/time: 42×34, 140 seconds
  • Enemies: pistol boy: 1, shotgun maniac: 3, uzi rebel: 3, grenade guy: 1, civilian: 12
  • Weapons: c4 activator: 1
  • Bullets: 12mm: 3×50, shotgun shells: 1×20, medium grenades: 1×10, c4: 1×5, gas: 2×50
  • Health capsules: 5

MOTHAFUX: 9 “hell on earth”

  • Size/time: 50×40, 210 seconds
  • Enemies: pistol boy: 4, uzi rebel: 4, commando: 2, civilian: 2, punisher: 2, flamer: 1
  • Weapons: auto grenadier: 1
  • Bullets: 12mm: 1×50, light grenades: 1×15, gas: 2×50
  • Health capsules: 5

MOTHAFUX: 10 “dawn of the dead”

  • Size/time: 30×50, 180 seconds
  • Enemies: pistol boy: 1, commando: 4, civilian: 3, punisher: 3, flamer: 2
  • Weapons: heavy launcher: 1
  • Bullets: 12mm: 1×50, shotgun shells: 1×20, heavy grenades: 1×5, gas: 1×50
  • Health capsules: 2
DEFAULT

DEFAULT: 1 “pay back time”

  • Size/time: 32×20, 60 seconds
  • Enemies: pistol boy: 3, civilian: 1
  • Weapons: pistol: 2
  • Bullets: 9mm: 2×50, shotgun shells: 1×20
  • Health capsules: 1

DEFAULT: 2 “plutonium store”

  • Size/time: 40×30, 100 seconds
  • Enemies: pistol boy: 3, shotgun maniac: 1
  • Bullets: 12mm: 1×50
  • Health capsules: 1

DEFAULT: 3 “nice day to die”

  • Size/time: 45×30, 150 seconds
  • Enemies: pistol boy: 2, shotgun maniac: 2, uzi rebel: 1
  • Weapons: shotgun: 1
  • Bullets: 9mm: 1×50, shotgun shells: 1×20
  • Health capsules: 2

DEFAULT: 4 “jungle george”

  • Size/time: 50×40, 160 seconds
  • Enemies: pistol boy: 1, shotgun maniac: 2, uzi rebel: 2
  • Weapons: pistol: 1, shotgun: 1
  • Bullets: 9mm: 2×50, shotgun shells: 1×20, c4: 2×5
  • Health capsules: 2

DEFAULT: 5 “the aliens”

  • Size/time: 80×60, 240 seconds
  • Enemies: pistol boy: 2, uzi rebel: 3, commando: 1, civilian: 10
  • Weapons: grenade launcher: 1
  • Bullets: 9mm: 2×50, shotgun shells: 1×20, medium grenades: 1×10, c4: 1×5
  • Health capsules: 3

DEFAULT: 6 “the wc”

  • Size/time: 32×20, 80 seconds
  • Enemies: commando: 2, grenade guy: 1, civilian: 3
  • Bullets: medium grenades: 1×10
  • Health capsules: 1

DEFAULT: 7 “wolfenstein”

  • Size/time: 40×30, 100 seconds
  • Enemies: uzi rebel: 5, punisher: 1
  • Weapons: auto rifle: 1, c4 activator: 1
  • Bullets: 12mm: 2×50
  • Health capsules: 2

DEFAULT: 8 “wolfenstein 2”

  • Size/time: 45×40, 130 seconds
  • Enemies: shotgun maniac: 4, civilian: 10, punisher: 3
  • Bullets: shotgun shells: 2×20, c4: 1×5
  • Health capsules: 2

DEFAULT: 9 “parkinghall 2”

  • Size/time: 50×50, 150 seconds
  • Enemies: shotgun maniac: 2, grenade guy: 2, civilian: 10, punisher: 1
  • Bullets: 9mm: 1×50, shotgun shells: 1×20, light grenades: 1×15, medium grenades: 1×10, c4: 1×5
  • Health capsules: 2

DEFAULT: 10 “final battle”

  • Size/time: 80×60, 300 seconds
  • Enemies: pistol boy: 1, shotgun maniac: 1, uzi rebel: 1, commando: 5, grenade guy: 1, civilian: 10, punisher: 8
  • Weapons: auto rifle: 1
  • Bullets: 12mm: 1×50, shotgun shells: 2×20, light grenades: 1×15, medium grenades: 1×10
  • Health capsules: 5

For your (in?)convenience, I ordered the episodes by difficulty (from easiest to hardest) rather than alphabetically.

[Edit:] I managed to find more episodes on archive.org! Some of them might suck or crash the game, I don’t have the time to check.

[Edit 2:] I created a fork. It includes the following changes:

  • Faster fade-in/out for less wait time.
  • Larger (and easily configurable) in-game viewport, so you can see more around you!

Solar

2024-07-12

Original solarized colours:

#002b36;
#073642;
#586e75;
#657b83;
#839496;
#93a1a1;
#eee8d5;
#fdf6e3;
#b58900;
#cb4b16;
#dc322f;
#d33682;
#6c71c4;
#268bd2;
#2aa198;
#859900;

The grayish pairs are almost indistinguishable to my old eyes. In L*A*B, these are: 15 -12 -12, 20 -12 -12, 45 -7 -7, 50 -7 -7, 60 -6 -3, 65 -5 -2, 92 0 10, 97 0 10

I tried more regular spacing as per OKLCH interpolation between the two extremes, and quickly found out it’s actually useful to have a colour which is right next to the extreme, to be able to get a slightly different background.

So, here’s an attempt to take the most extreme two colours from both sides and interpolate the four in the middle, giving a better range of usable shades:

#002b36;
#073642;
#37565e;
#62797a;
#8f9c98;
#bec2b6;
#eee8d5;
#fdf6e3;

It’s a small improvement, no?


Continuing, the orig solarized colours:

#b58900;
#cb4b16;
#dc322f;
#d33682;
#6c71c4;
#268bd2;
#2aa198;
#859900;

And my tweaked version:

#a80
#c60
#d24
#c39
#77d
#28c
#2a9
#890

Tweaks mainly to better separate the red from its neighbors. Also shorthand notation, because who needs more than 4096 colours? Limiting the number of available colours lets one focus on things that matter rather than focusing on things that don’t. (The irony being that improving a colour scheme is a thing that doesn’t matter.)


Here’s a screenshot from my terminal. Left is original Solarized, right is after the changes:

solarized comparison
Interested in exploring the colours in OKLCH?

Here are the base colours in the format to paste to Huetone:

{
  "name": "solar base",
  "hues": [
    {
      "name": "color",
      "colors": [
        "#002b36",
        "#073642",
        "#37565e",
        "#62797a",
        "#8f9c98",
        "#bec2b6",
        "#eee8d5",
        "#fdf6e3"
      ]
    }
  ]
}

And the colour wheel:

{
  "name": "solar colours",
  "hues": [
    {
      "name": "color",
      "colors": [
        "#aa8800",
        "#cc6600",
        "#dd2244",
        "#cc3399",
        "#7777dd",
        "#2288cc",
        "#22aa99",
        "#889900"
      ]
    }
  ]
}

Consumption vs creation

2024-05-25

Some people think screen-time = bad. Or that smart phones = bad. I think it’s mostly creation vs consumption, no matter the medium.

Creation = good.
Comsumption = bad.

Scrolling Instagram (TikTok? whatever people use these days…) is consumption (bad). Posting on Instagram: creation (good). Checking instagram followers: consumptive (bad).

Of course it’s a spectrum. Playing computer games is more consumptive than creating them, but probably more creative than scrolling Instagram. It also depends on the particular game, playing Factorio being more creative than playing Farmville.

I’ve been doing ok recently wrt consumption vs creation, I don’t consume much and mostly spend my little free time creating. See, even now I’m creating this blog post (good). While you’re reading it (bad). Stop and go create something!

Notes on OKLCH and rainbows

2024-04-30

Colours are tricky! OKLCH is a colour space. OKLCH is better than most colour spaces in that changing the values leads to natural sensible results. But sometimes, those sensible results are not achievable because of physics, biology (eyes), and technology (display devices).

Evil Martians have a very good blog post on OKLCH. In case that goes down, MDN has a somewhat drier explanation.

The problem with the other colour spaces is that changing one of the values a certain amount leads to strange results. In HSV, changing the hue by 30 sometimes shows almost the same colour, other times an entirely different one.

In OKLCH, changing one of the values gives you nice results. Also, sometimes it gives you an inexistent colour, or a colour which is theoretically displayable, but not by your device. Oops.

Here’s an OKLCH Color Picker & Converter, go play around with it! In case it goes down, source.

I like cyclical rainbow colour palettes. I like having them consist of existing and displayable colours.

Here’s a somewhat dark one. OKLCH with Lightness 50%, Chroma 0.08 and all them hues. Anything darker, and the chroma can’t go up because of the missing cyans (and yellows). The maximum chroma that has all the colours for Lightness 50% is 0.08 – all the chromas in this post will be the maximal possible ones for the given lightness so that all the hues are still available in rgb.

Increasing Lightness to 60%, Chroma can go up to 0.1, again hitting the cyans.

The maximum chroma (for preserving all the hues) is 0.12 for Lightness 71–76%.

At lightness 85%, the purples are becoming a problem, allowing chroma of only up to 0.07 – a light saturated purple doesn’t exist. I’m so sorry.

Choosing a programming language in 2024

2024-02-22

Welp. I want to write a simple backend service and have it low maintenance for the upcoming decade. I will probably want to write other simple backend services in the upcoming decade and I’m getting old so I’d rather stick to fewer than more languages. But also I’d rather the languages to be tidy. This is a stream-of-thought for my own reference, but I might end up pushing the “publish” button anyway.

Without further ado, the contenders:

Haskell

I already wrote 30 lines of Haskell to do very simple API call forwarding, so I’m not starting from scratch here. The ergonomics just aren’t there:

  • Stack downloads a lot of things and uses exorbitant amounts of disk space. I’m running on a $5 DigitalOcean droplet!
  • With such strong typing I want an amazing IDEs but mostly end up typing things in vim.
  • Haskell is not a beautiful language. Yes it maintains backwards compatibility. Why fmap on functors and map only on lists?
  • I count six different string types and I’m trying very hard to count as few as possible. If one wanted to count as many as possible, I shudder to think what the number would be. Ideal number of string types is one.

On the plus side, stack is in my distro’s repos

PHP

Hey, I have three-ish things running PHP on the aforementioned $5 DigitalOcean droplet. Less beautiful language than Haskell, very low maintenance, just works. But hey it’s not 2004 anymore…

Python

It’s everywhere and there’s no hope of it ever going away. Its library ecosystem is amazing, its package management story is atrocious. Reads like pseudocode, but all bugs are runtime. Probably a practical choice, but is it really that much better than PHP? If I’m getting invested in another language apart from PHP, I’d like it to be nicer.

Scala

Maybe. Having worked with Scala professionally for 7 years, I know it well and like it enough. It seems to be losing a lot of steam recently, as in its cake eaten completely by the inferior Kotlin. But it’s not disappearing completely, is it? And the ecosystem of Java (and Kotlin!) libraries is there.

F#

F# is a nicer language than Scala. But it’s not that much nicer and reportedly the .NET ecosystem is worse. It’s also an ecosystem I don’t know at all. There’s ASP.NET and .NET and .NET core and .NET framework and perhaps they’re complementary or one replaces the other and the naming is confusing…

Idris and PureScript and Roc

Idris is Haskell without the warts, but no one uses Idris and it has no libraries. Nor even a package manager really.

PureScript requires a lot of imports and seems to be more of a frontend language, but perhaps I’m just being uncharitable to it. And uh JavaScript as its main compile target. It makes sense for a frontend language, of course. I use Elm and don’t complain about JavaScript being the compile target. PureScript looks real nice!

ROC is not even a thing yet.

All three a bit too much bleeding edge.

Conclusion

There is no conclusion! The only conclusion I can possibly come up with is that the nicer the language, the worse its ecosystem. The worse the language, the nicer its ecosystem. Here’s, uh, an infographic:

objective ranking of programming languages

Tiling gradients

2024-02-08

Here’s a test. A simple diagonal gradient from white to black, first full size, then four tiles of the same, and lastly sixteen tiles:

It does not tile very nicely. Neither does one which has white-black-white:

And neither white-black-white-black one:

But the following one does! White-black-white-black-white:

Then for 6, 7, and 8 it again does not tile (showing just the four tile versions):

For sequence of 9 it tiles! And sequence of 13 too! And… umm, 17 again?

Proof by induction!


I’m sure this is like some very trivial mathematics. But I do not know it. And the grayscale is a little dreary, make it pop! Let’s have three colours:

Call them purple, teal, yellow. Unsurprisingly, the three colours don’t tile when it’s purple-teal-yellow (sequence of 3), neither purple-teal-yellow-purple (sequence of 4), neither purple-teal-yellow-purple-teal (sequence of 5), neither sequence of 6:

But for sequence of 7 (purple-teal-yellow-purple-teal-yellow-purple) it tiles! Then for 13 and 19 and 25 it does too.


Uh oh, let us take four colours now. Purple, blue, green, yellow.

Green green, green green. Yellow? Yellow!

For sequence of 4 the tiling doesn’t work, but for sequence of 9 it does! And for 17 too, and 25.

This looks very much like 2n + 1


Five colours!

That’ll be 11, 21, 31, 41, 51, …

And lastly ten colours, with sequence of 21:


Why 2n + 1 ?

This is perhaps too embarassingly simple to write a blog post about, but I found none and found a lot of people on the internet confused by their gradients not aligning.

The n here is the number of different colours in your gradient. The 2n + 1 is how many colours you need to include in your code.

The +1 is simple: the last colour of the palette needs to be the same as the first, as they “touch” in the corner.

The 2n is not that difficult either: when it was n, the corners touch just fine, but the sides are shifted by half against each other, not lining up. 2n makes the sides line up, too.

Bonus time?

Here, have an animated one:

Valmorel

2024-01-21

In the nineties, when I was about ten, my parents took me to Valmorel, a ski resort in French Alps. It was my first time skiing in the Alps and I enjoyed the trip a lot. After a week of skiing, when we were leaving, I cried in the bus. My mother said don’t worry, we’d go again. But I knew this was it, there would be no other experience that could compare to going to Valmorel for the first time in my life.

Looking back, I’m surprised how correct and prescient my reaction was. There was no other Valmorel. I’d gone skiing in the Alps many times since, almost every year. It is fun. But the magic of the first time is long gone.

There will be other experiences, good and bad, repeated and unique. There will never be another Valmorel.

Pure.css

2023-01-27

I’ve been using Pure.css whenever I need to use CSS, and love it:

  • It’s tiny (about 1/10th the size of Bootstrap).
  • It’s simple. Go-read-the-code simple.
  • It gets out of the way.
  • They release about twice a year, usually adding a single feature or so. Why move fast when slow is enough?

Back in the day, I used Twitter Bootstrap for the Tsumego Collections. It’s very heavy, there’s an infinite number of classes, one has to fit in within the framework very precisely for it to work, and it requires JavaScript for the menus (???).

The main drawback of Pure.css is its ungooglability and multitude of names. The web address is purecss.io, the logo says “Pure.css”, the page title says “Pure”, the left menu shows “PURE”. I honestly have no idea what the project name actually is.