Highlight

2026-01-15

Climate Change

Earth has generably been warming for the past 22,025 years (+5 degrees Celsius), but about 1 degree of that was in the past 40 years. Are human activities causing climate change?

3D drawing of an oil well, city, nature, and ocean, labeled with amounts of carbon in/out
9.8 up - 5.5 down = 4.3 gigatonnes of carbon per year extra from fossil fuel & cement

That image lacks methane from melting Siberian permafrost, but fortunately smoke from wars and cars appears to reflect sunlight before the rest of Earth soaks it up. Maybe burnt sacrifices (being carbon neutral if using recently grown wood) weren't so bad after all compared to the Sun cooking us.

2026-01-09

Everything you need to know about Unicode in Perl on Windows

I've now solved the display issue by making my Perl script change the codepage to 65001 just like CMD's `dir` does:
use feature ":5.16";  # Include say and Unicode string functions.
use open ':std', ':encoding(UTF-8)';  # Print Unicode without complaining about wide chars.
use utf8;  # Unicode source code.
use strict;  # Don't ignore undefined variables.
use Win32::Console;

Win32::Console::OutputCP(65001);  # Tell Windows Terminal to render Unicode (with unclustered graphemes in 1.23.13503.0 but they copy/paste ok).

my $file_name = "emoji_🎅🎉😀💢👩🏾‍🚀.txt";

say "Writing to ${file_name}";
open( my $fh, ">", $file_name ) or die "Can't write $file_name: $!";
binmode($fh, ":encoding(UTF-8)");  # encoding() also checks UTF-8 validity, unlike ":utf8".
say $fh "My name is \"$file_name\".";
close($fh);

say "Reading ${file_name}";
open( $fh, "<", $file_name ) or die "Can't read $file_name: $!";
binmode($fh, ":encoding(UTF-8)");
read($fh, my $buf, 100);
say $buf;
close($fh);

say "Done.";
This won't affect the codepage of the terminal after, just like `dir`: And despite the female black astronaut not rendering as a single character, it copy/pastes just fine:
15:23:45 C:\apps\StrawberryPerl\perl\bin>chcp
Active code page: 850

15:23:50 C:\apps\StrawberryPerl\perl\bin>perl C:\Users\C\Documents\code\Perl\test_unicode.pm
Writing to emoji_🎅🎉😀💢👩🏾‍🚀.txt
Reading emoji_🎅🎉😀💢👩🏾‍🚀.txt
My name is "emoji_🎅🎉😀💢👩🏾‍🚀.txt".

Done.

15:23:53 C:\apps\StrawberryPerl\perl\bin>chcp
Active code page: 850
Unfortunately, writing the emoji file name only appears to work correctly inside a shell inside VS Code; not inside a shell inside Windows Terminal 1.23.13503.0: Newer languages like Python do work.
file_name = "emoji_🎅🎉😀💢👩🏾‍🚀.py.txt"

print(f"Writing to {file_name}")
with open(file_name, "w", encoding="utf8") as f:
    f.write(f"My name is \"{file_name}\".")

print(f"Reading {file_name}")
with open(file_name, "r", encoding="utf8") as f:
    print(f.read())

print("Done.")

2025-11-05

GPG - GNU Privacy Guard

GPG is an open source version of PGP - Pretty Good Privacy - which uses public-private key pairs to sign hashes or encrypt content to verify integrity and origin.

Today with help from ChatGPT I finally used it in Git Bash on Windows 11 to verify the Cygwin installer in order to install GCC to compile the backend for Grafana to test a patch for a label regression in 1.6. (Update: I'll just make run in GNU/Linux.)

First inspect and remember the public keys, lest you get "gpg: Can't check signature: No public key":

C@MSI MINGW64 ~/Documents/code/GitHub/grafana (main)
$ gpg --show-keys "C:\Users\C\Downloads\cygwin_pubring.asc.txt"
pub   dsa1024 2008-06-13 [SC] [expired: 2022-09-03]
      1169DF9F22734F743AA59232A9A262FF676041BA
uid                      Cygwin <cygwin@cygwin.com>
sub   elg1024 2008-06-13 [E] [expired: 2022-09-03]

gpg: WARNING: No valid encryption subkey left over.
pub   rsa4096 2020-02-27 [SC] [expires: 2027-02-27]
      56405CF6FCC81574682A5D561A698DE9E2E56300
uid                      Cygwin <cygwin@cygwin.com>


C@MSI MINGW64 ~/Documents/code/GitHub/grafana (main)
$ gpg --import "C:\Users\C\Downloads\cygwin_pubring.asc.txt"
gpg: /c/Users/C/.gnupg/trustdb.gpg: trustdb created
gpg: key A9A262FF676041BA: public key "Cygwin <cygwin@cygwin.com>" imported
gpg: key 1A698DE9E2E56300: public key "Cygwin <cygwin@cygwin.com>" imported
gpg: Total number processed: 2
gpg:               imported: 2
gpg: no ultimately trusted keys found
GPG is just noting that the encryption subkey [E] has expired. Key capabilities:
LetterMeaningDescription
SSignUsed to create digital signatures — for signing messages or files (like the .sig file from Cygwin).
CCertifyUsed to sign other keys — e.g. when one key "certifies" that another key belongs to someone (building the “web of trust”). Usually part of the primary key’s role.
EEncryptUsed to encrypt data so only the matching private key can decrypt it. Typically found on a subkey.
AAuthenticateUsed to prove identity in secure communication (e.g. SSH or email authentication). Not common on signing keys for software releases.

Then verify the signature of the executable:

C@MSI MINGW64 ~/Documents/code/GitHub/grafana (main)
$ gpg --keyid-format=long --with-fingerprint --verify /C/Users/C/Downloads/setup-x86_64.exe.sig /C/Users/C/Downloads/setup-x86_64.exe
gpg: Signature made Thu, May 22, 2025  4:49:21 PM WEDT
gpg:                using RSA key 56405CF6FCC81574682A5D561A698DE9E2E56300
gpg: Good signature from "Cygwin <cygwin@cygwin.com>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: 5640 5CF6 FCC8 1574 682A  5D56 1A69 8DE9 E2E5 6300

2025-10-13

Is the USA ok?

YouTube and/or some people who don't like serious conversations tends to disappear comments, so here's a copy of one with links to sources:
It appears that not a day goes by in the USA without somebody shooting multiple people, hence my question since people seem tired of talking about them.

According to a 2012 Guardian article on gun homicides, the average per 100k people gun homicide rate was 4.9 globally, 3.0 for the US, and 0.4 for Europe (not counting Kosovo, Montenegro, and Russia due to missing data).

In for example 1956 when US schools had gun safety classes, Wikipedia only lists a page for Asia. 1954 had one mass shooting in the US Capitol though. The total US population, including Armed Forces overseas, was about 162,414,000 on July 1, 1954, based on the 1950 Census.
1/162,414,000*100,000 = 0.0006 mass shootings (which includes school shootings) per 100k people.

In 2024 however, with only 340.1 million people, there were 586 mass shootings according to Wikipedia, so 586 / 340.1e6 * 100000 = 0.1723 per 100k people. A 280 times increase.
Meanwhile, less kinetically energetic pollution is causing about one human megadeath per year.

2024-11-20

Popping speakers instead of expected audio

If your speakers pop (#NotAllSpeakers do, like my 1990s Target ones that unfortunately fell to their death.) like my Logitech that spent more money on excessive bass than buffering input power or whatever, make sure it doesn't sleep (D3) in Windows 11.
By setting the right \HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class key descendant's PerformanceIdleTime value to data 00 00 00 00, and perhaps value IdlePowerState as well, preventing power toggles and cut audio. Credit to TenForums.

Start regedit, paste the key, Ctrl+F, paste value, find next value, confirm DriverDesc description in parent key, and modify PowerSettings data, or save and execute this audio_pop_fix.reg:
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4d36e96c-e325-11ce-bfc1-08002be10318}\0005\PowerSettings]
"ConservationIdleTime"=hex:04,00,00,00
"IdlePowerState"=hex:00,00,00,00
"PerformanceIdleTime"=hex:00,00,00,00

2024-04-05

SVG to WebP converter in JS

2024-03-18

Don't forget to check your integer type!

"""PIL/Pillow Image.fromarray() doesn't check your array value types!"""

from PIL import Image
import numpy as np


im = Image.new("RGB", (2, 1))
im.putpixel((0, 0), (255, 0, 0))
im.putpixel((1, 0), (0, 255, 0))

a = np.array(im)
print("Good shape:", a.shape, a)
print("See?")
Image.fromarray(a, "RGB").show()

a = np.array([[[255, 0, 0], [0, 255, 0]]])
print("Bad shape:", a.shape, a)
print("Where'd the green pixel go?")
Image.fromarray(a, "RGB").show()

a = np.uint8(a)
print("Fixed shape:", a.shape, a)
print("If the green pixel disappeared, you forgot to cast to uint8.")
Image.fromarray(a, "RGB").show()