News for hackers. Stuff that matters.

CodeIsTheEnd

Re:Pareto Front on Thursday August 06, 2026 @08:34AM (#49195789)
I am training for a marathon, and, as I increase both by distance and pace, I am always excited when I have a "Pareto run": a run along the Pareto frontier of me trying to maximize distance and speed.

When explaining it to some coworkers, I stumbled on a fairly intuitive explanation: "I've run farther before, and I've run faster before, but I've never run _this_ far, _this fast."

There was some pushback about why not just call it a PR (personal record), but I would only use that term for fixed distances (1mi, 5k, 10k, etc.) or a consistent route that I've run many times before. Nobody would say "I set my 7.40 mile PR today." More importantly, it misses the comparison to all farther (and faster) runs—it's not exciting to set a 5k PR just because you've barely run that distance before, and the pace is actually slower that a 10k you've done.

(Had a Pareto run of 7.40 miles @ 6:28/mi last week!)

I watched the animated gif in the readme and let out a shout of delight when I saw the lightning strike, and on the second loop appreciated how it also lit up the surroundings. Lovely attention to detail!

I looked at the snow one and almost expected snowdrifts to start accumulating.

I initially built https://plaintextsports.com because I was annoyed with how slowly other sports websites loaded, but since then I have come to appreciate it more for the density of the information, and how few clicks it takes to get to the info you care about (usually at most two or three).
Re:Tonal.js: Functional music theory lib on Wednesday April 03, 2024 @07:42PM (#39924785)
Unsolicited feedback because I clicked: - Don't require picking a composition name before getting started - Whatever scroll settings you have broke swipe to go back, and then when I tapped the back button I got stuck in an infinite loop between the home page and the create composition page
Re:Popular Git config options on Friday February 16, 2024 @09:30PM (#39405765)
My favorite line in my .gitconfig is an alias that prints out the commit history as a tidy graph. (The default `git log --graph` uses 6 whole lines per commit!)

    [alias]
        lg = log --graph --abbrev-commit --decorate --date=relative --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)' --all -n 15
Which I took from this Stack Overflow post: https://stackoverflow.com/questions/1057564/pretty-git-branc...
Re:Text Only News Websites on Sunday March 26, 2023 @10:13AM (#35314665)
For sports, ESPN does have http://www.espn.com/nba/lite/scoreboard, but most of the links go back to the normal website. It may have been been more robust in the past, but I don't imagine anyone works on it anymore. It seems like the developer listed in the credits (http://www.espn.com/espn/lite/credits) last worked there in 2002!!

So if you're looking for a sports alternative, https://plaintextsports.com (which I made) works great! All the scores, play-by-play, box scores, standings, and schedules, but just no news stories. Blazing fast.

(No, it's not technically "Content-Type: text/plain", it uses HTML and CSS. Yes, I know it's not necessarily easier to read; it's an aesthetic. Yes, this is shameless self-promotion.)

Re:Web Push for Web Apps on iOS and iPadOS on Thursday February 16, 2023 @10:40PM (#34830440)
A personal gripe with progressive web apps: they cache the website!!

A lot of people have requested that I make a progressive web app for https://plaintextsports.com. I've looked into it, but it fundamentally doesn't work, because it caches the home page. My website doesn't load any data via JavaScript; it just relies on the HTML page updating every 30 seconds, so when the home page is cached, the website just stops working.

I don't want this service worker nonsense. In most cases offline access isn't useful; people want the live scores. (It'd be moderately useful for viewing schedules offline, but I think most people use it for live scores.) I just want the website to show up as its own app in the app switcher, and basically nothing else to change: I still want the swipe-to-go-back gesture to still work. I still want the address bar with the manual refresh button. But I can't do that.

It's frustrating that they've provided a way to make a certain style of websites into first-class apps, but it doesn't work for the most basic websites!!

Side note: this is partially a the-best-way-to-get-a-question-answered-on-the-internet-is-to-say-something-wrong post. If there's a way to make it a PWA and not have all the pages heavily cached, please let me know! I would love to be wrong on this. (Unfortunately my noprocast just triggered though, so I won't be able to edit this post or respond for the next three hours.)

I wish there were an option to export a video like the example on the homepage (with some ability to control the camera path). I'd love to be able to use it to make a promotional video for a developer tool similar to the announcement video for the Windows Terminal.

https://www.youtube.com/watch?v=8gw0rXPMMPE

The intention is to put the schedules for everything on this page:

https://plaintextsports.com/premier-league/2022-2023/clubs/l...

The challenge is that these pages are really labor intensive, because I want to show relevant information for whatever league is happening, e.g., group stage points, leg of Champions League matches, and it's really difficult to figure out how to fit everything in just 45 columns.

I complained about it in this tweet: https://twitter.com/CodeIsTheEnd/status/1569489636900347904

I run Plain Text Sports (https://plaintextsports.com/).

I got sick of waiting for ESPN to load so I made a site with the goal of providing immediate access to what people actually care about: sports scores.

It's pretty fully featured at this point, supporting the NFL, NBA, MLB, NHL, MLS, Premier League and Champions League, college basketball and college football, WNBA, NWSL, and the World Cup. And for a lot of leagues it has full schedules and standings as well.

It actually was really popular in South Africa during the World Cup when a "super-app" that points users to sites that don't use a lot of data linked to it.

The site is served off of S3 (which is cheap), but there's a job running on an AWS server that's fetching the data for all the games and republishing pages to S3. It's using Ruby and is making a lot of network requests, so it's definitely not super efficient. I need a least a couple virtual CPUs, so it ends up costing ~$60 a month. I could definitely reduce that number, but the trouble just isn't worth it to me right now.

I don't want to make money on it. It's been difficult enough to get people to use it; getting people to pay for it would be even hard. At this point I feel like I've gotten everything I've wanted from the project. (An eye-opening experience into the marketing world; a website that I use every day.)

I try to limit how much I work on it now to mostly just maintenance work. I'd rather work on other stuff. If I started making money that'd just be a number to obsess over, and, honestly, it's never going to make enough money to replace my salary as a software engineer.

You are a hero and have just cured me of a hundred daily paper cuts. My employer should give you a bonus.

It works in Chrome, but unfortunately not in the standalone Slack client. (Maybe an argument for switching to the web version?)

(Uh, does anyone know how I select all (previously C-a) or search (previously C-f) in Chrome now??)

EDIT: Looks like C-/ functions as select all, still looking for a find replacement.

EDIT #2: Oh, silly me, as long as I'm not focused on an input, C-f still works.

For anyone using a Mac, the basic cursor movement commands available in readline and emacs—C-f, C-b, C-a, C-e, C-n, C-p—are also available in virtually any text input in any program, namely web browser inputs, url bars, and textareas, as well as all system UIs.

Once you get used to using these shortcuts that means you can compose and edit text anywhere without ever moving your hands.

I recently switched to using Linux full time for my job and it KILLS me that these shortcuts aren’t available outside of the terminal. I try to navigate to a search suggestion in Chrome using C-n and accidentally open three new windows. I try to add a sentence at the start of Slack message using C-a and accidentally highlight everything and delete it. I try to move my cursor up to edit a previous line using C-p and end up brining up a print dialogue. It’s breaking the muscle memory of my most basic interactions with the computer, and it sucks.

Alright, my bike-related tally over ~6 years in SF:

- 2 stolen bike seats (one by 4th and King, one in the Mission)

- 1 entire bike stolen (left out in the Castro overnight)

- 1 rear wheel stolen (in a parking garage by the SF Symphony)

- 1 seat post clamp (literally just the clamp they had to remove the seat, take off the clamp, then put the seat back; during a 30 minute piano lesson in the Mission)

But that doesn't included the most egregious thing that I ever witnessed: I was running up to Twin Peaks on a Saturday morning, and right around noon, in the mini parking lot between the actual two peaks, with dozens of people milling about, heard someone break a car window while there was someone in the vehicle and grab a bag. A woman was seated in the passenger seat and they broke the rear driver-side window. Within seconds a car pulled up with no license plates, the guy jumped in and they sped off.

Re:PostgreSQL 15 on Thursday October 13, 2022 @09:55PM (#33198782)
The posts table also has a foreign key to the tenants table specified with ON DELETE CASCADE, so all the tenant's posts will be deleted. (I don't know if Postgres makes any effort to find some optimal ordering of the referenced tables—in this case deleting the tenant's posts firsts, then its users—to avoid updating records that will just get deleted anyway by cascading deletes.)
Re:PostgreSQL 15 on Thursday October 13, 2022 @02:05PM (#33194412)
This release includes a feature I added [1] to support partial foreign key updates in referential integrity triggers!

This is useful for schemas that use a denormalized tenant id across multiple tables, as might be common in a multi-tenant application:

    CREATE TABLE tenants (id serial PRIMARY KEY);
    CREATE TABLE users (
      tenant_id int REFERENCES tenants ON DELETE CASCADE,
      id serial,
      PRIMARY KEY (tenant_id, id),
    );
    CREATE TABLE posts (
        tenant_id int REFERENCES tenants ON DELETE CASCADE,
        id serial,
        author_id int,
        PRIMARY KEY (tenant_id, id),
        FOREIGN KEY (tenant_id, author_id)
          REFERENCES users ON DELETE SET NULL
    );
This schema has a problem. When you delete a user, it will try to set both the tenant_id and author_id columns on the posts table to NULL:

    INSERT INTO tenants VALUES (1);
    INSERT INTO users VALUES (1, 101);
    INSERT INTO posts VALUES (1, 201, 101);
    DELETE FROM users WHERE id = 101;
    ERROR:  null value in column "tenant_id" violates not-null constraint
    DETAIL:  Failing row contains (null, 201, null).
When we delete a user, we really only want to clear the author_id column in the posts table, and we want to leave the tenant_id column untouched. The feature I added is a small syntax extension to support doing exactly this. You can provide an explicit column list to the ON DELETE SET NULL / ON DELETE SET DEFAULT actions:

    CREATE TABLE posts (
        tenant_id int REFERENCES tenants ON DELETE CASCADE,
        id serial,
        author_id int,
        PRIMARY KEY (tenant_id, id),
        FOREIGN KEY (tenant_id, author_id)
          -- Clear only author_id, not tenant_id
          REFERENCES users ON DELETE SET NULL (author_id)
          --                                  ^^^^^^^^^^^
    );
I initially encountered this problem while converting a database to use composite primary keys in preparation for migrating to Citus [2], and it required adding custom triggers for every single foreign key we created. Now it can be handled entirely by Postgres!

[1]: https://www.postgresql.org/message-id/flat/CACqFVBZQyMYJV%3D...

[2]: https://www.citusdata.com/

Re:A 14kb page can load much faster than a 15kb page on Wednesday August 24, 2022 @10:48PM (#32588836)
Shameless self-promotion: the homepage of plaintextsports.com is 5.2kb today [1], an in-progress WNBA game (4th quarter) is 11.2kb [2], and an extra inning MLB game is 8.8kb [3]. I wasn't aware of this size threshold, and I'm not at this level of optimization, but I'm always pleased to find more evidence of my playful claim that it's the "fastest website in the history of the internet".

[1]: https://plaintextsports.com/all/2022-08-24/

[2]: https://plaintextsports.com/wnba/2022-08-24/conn-dal

[3]: https://plaintextsports.com/mlb/2022-08-24/laa-tb

Re:Having, a less understood SQL clause on Saturday August 06, 2022 @01:59AM (#32365313)
I had never heard of GROUP BY CUBE either! It looks like it's part of a family of special GROUP BY operators—GROUPING SETS, CUBE, and ROLLUP—that basically issue the same query multiple times with different GROUP BY expressions and UNION the results together.

Using GROUP BY CUBE(a, b, c, ...) creates GROUP BY expressions for every element in the power set of {a, b, c, ...}, so GROUP BY CUBE(a, b) does separate GROUP BYs for (a, b), (a), (b) and ().

It's like SQL's version of a pivot table, returning aggregations of data filtered along multiple dimensions, and then also the aggregations of those aggregations.

It seems like it's well supported by Postgres [1], SQL Server [2] and Oracle [3], but MySQL only has partial support for ROLLUP with a different syntax [4].

[1]: https://www.postgresql.org/docs/current/queries-table-expres...

[2]: https://docs.microsoft.com/en-us/sql/t-sql/queries/select-gr...

[3]: https://oracle-base.com/articles/misc/rollup-cube-grouping-f...

[4]: https://dev.mysql.com/doc/refman/8.0/en/group-by-modifiers.h...

The most common constraint is whether the DB as a service offerings support a given extension, since they don't support installing custom ones. Naturally choosing to support an extension across a fleet of hundreds of thousands of instances (running dozens of different minor versions) isn't a decision made lightly, so it can take a while for new extensions to be supported.

Supported extensions on AWS RDS: https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLRelea...

Supported extensions on Google Cloud SQL: https://cloud.google.com/sql/docs/postgres/extensions

Supported extensions on Azure Database: https://docs.microsoft.com/en-us/azure/postgresql/single-ser...

If anyone's looking for a great long-form article about calculating digits of Pi from the good ol' days, this 1992 New Yorker profile of the Chudnovsky brothers (creators of algorithm used by Google here!) is fantastic:

https://www.newyorker.com/magazine/1992/03/02/the-mountains-...

Very similar to a game posted a couple months ago:

https://news.ycombinator.com/item?id=30956775 (368 points, 124 comments)

Re:Apple’s hidden flight tracker app on Sunday May 29, 2022 @08:12PM (#31554184)
For college football and basketball I just use some JSON endpoints that the ncaa.com frontend hits, and they're actually very good. Literally all I had to do to support Women's basketball in addition to Men's was change "men" to "women" in the url. I haven't checked the data for baseball, but I'm sure it's more than adequate. That being said, I personally don't have any interest in college baseball, and I don't think it has a huge following, so I'm not going to invest any time into it, especially when there are higher profile leagues that I still haven't added yet (specifically, all of European football).
Re:Apple’s hidden flight tracker app on Sunday May 29, 2022 @01:37PM (#31551006)
Thank you! (I made plaintextsports!)

On my to-do list is making a personalized page where you can select exactly which teams you want to follow, something closer to what dpeck wants, but I've been having trouble finding the time...

Re:Wrong by Default on Monday May 16, 2022 @02:44PM (#31401669)
But you only need to write the destructor once.
Re:Zq: An easier and faster alternative to jq on Tuesday April 26, 2022 @11:55PM (#31176121)
You can use `yq` to copy a jq-style path to currently focused node to your clipboard! (I’m the author of jless.)

There are a couple other copy variants as well:

https://jless.io/user-guide.html#copying

Re:Please stop calling it “magic” (2017) on Wednesday April 06, 2022 @01:14PM (#30934897)
TIL: #method(:method_name) in Ruby

I'm a big fan of Ruby, and feel like I know the language pretty well, but, my goodness, I don't know how I've never come across this one before. THIS is something that feels like magic!!

    [1]> 3.method(:days).source_location
    => [".../lib/active_support/core_ext/numeric/time.rb", 37]

    [2]> puts 3.method(:days).comment
    # Returns a Duration instance matching the number of days provided.
    #
    #   2.days # => 2 days
    => nil

    [3]> puts 3.method(:days).source
      def days
        ActiveSupport::Duration.days(self)
      end
    => nil
https://ruby-doc.org/core-3.1.1/Method.html
Re:Difftastic: A diff that understands syntax on Tuesday March 29, 2022 @12:20PM (#30844584)
Oops, I think you're right! Thank you for pointing that out.

My apologies to Wilfred.

Older »