compost.party 88x31

the why

as evidenced by my homepage, I like 88x31 buttons! I think they're a fun sort of internet art.

when compost.party came back up, it occurred to me it would be fun for it to have some sort of 88x31. of course, it would be even more fun if it was functional in some way, and it would be even more fun if I brought in some bespoke programming tools.

...

so I made a functional 88x31 for compost.party with bespoke programming tools!


the what

this is the 88x31! it's a bit dense, but that's because it contains all the battery statistics present on the homepage.

if you want to embed it, please hotlink! the image is updated by a cronjob, so the button will change over time on reload.

the original tga is available at /88x31.tga, and the machine-readable data (see below) is available at /88x31.txt.


the how

recently, I've been playing with uxn. it's a similar sort of idea to PICO-8 or other fantasy consoles, but instead of using a conventional programming language, it's based around this 16-bit stack-based assembly language, which is intended to be comfortably handwritten. it's very cool, and very fun.

I thought the design ethos of "doing a lot within extreme constraints" that uxn has fit well with compost.party's whole vibe, so I decided to write the button generation code in it. the resulting rom (uxn programs are binary rom files) is 1.5kb, generated from 480 lines of uxntal code.

input data

the uxn code works by stepping through an internal state machine, and reading in numbers as it goes. it ignores any character not in the digits 0-9, treating any such sequence as a delimiter between numbers. input numbers are not capped, and overflows are not checked, because it's not necessary for the sort of input data.

the actual format, then, is just a list of numbers. the first 3 are for the current statistics, followed by 168 numbers composing the weekly statistics. here's what that looks like:

current:     99
recent low:  00
recent high: 00

past week:
  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

output

GIF compression is absolutely implementable in uxn. at some point, I will probably do compression in-rom! unfortunately, I am lazy, so currently the script outputs a .TGA file. TGA is an image format with support for a frankly astonishing number of modes, one of which is uncompressed, with a palette. this makes it easy to have the internal buffer that the button gets generated in be the same format as the TGA output. the rom basically just updates a buffer where 1 byte = 1 pixel, and then spits it out to stdout. that can then be converted to a more conventional format, like GIF.

plumbing

getting the input data isn't too hard. the history is already aggregated for the purposes of the compost.party homepage, and GIF compression can be easily handled with a tool like imagemagick. orchestrating all of this is accomplished in bit of bash:

#!/bin/bash

# convert the data into a list of hourly numbers
# this code is needed to fill in gaps where the phone was dead
node <<EOF >/tmp/buttonstats.txt
  let start = Date.now();
  let powerdata = Object.fromEntries(
    require('/home/ursula/git/compost.party/src/_data/power-history')
      .filter(val =>
        val.timestamp.includes(':00:'))
      .map(val =>
        [val.timestamp.substr(0,13), val['qcom-battery'].capacity.value]));

  for(i = 0; i < 168; i++) {
    key = (new Date(start - (i * 3600000))).toJSON().substr(0,13);
    charge = powerdata[key] ?? 0;
    console.log(String(100 + charge).substr(1));
  }
EOF

# parse out the main readings
current=`cat /sys/class/power_supply/qcom-battery/capacity`
low=`tail -n 24 /tmp/buttonstats.txt | sort -n | head -n 1`
high=`tail -n 24 /tmp/buttonstats.txt | sort -nr | head -n 1`

# generate input for the rom
{ echo "current:     $current"
  echo "recent low:  $low"
  echo "recent high: $high"
  echo
  echo "past week:"
  echo `cat /tmp/buttonstats.txt` | fold -sw72 | sed 's/^/  /'; } | tee ~/html/88x31.txt |

# generate and store the image
  uxncli ~/88x31.rom | tee ~/html/88x31.tga | magick tga:- ~/html/88x31.gif

# template the webpage
sed 's![0-9].*$!<b>\0</b>!g' ~/html/88x31.txt |
  cat ~/html/button.head.html - ~/html/button.tail.html >~/html/button.html

rm /tmp/buttonstats.txt

can I see the code?

of course! it's free to read and modify on the compost.party git!