Parking this info here for my future-self to reference.
Create a vim file, mine is at ~/gitcommithighlight.vim
:highlight OverLength ctermbg=red ctermfg=white guibg=red
" First line must be 50 characters or less
:let w:m1=matchadd('OverLength', '\%1l\%>50v.\+', -1)
" Second line must be blank
:let w:m1=matchadd('OverLength', '\%2l\%>0v.\+', -1)
" All other lines must be be 72 characters or less
:let w:m2=matchadd('OverLength', '\%>2l\%>72v.\+', -1)
Set git’s editor to vim and make it source the above file: git config --global core.editor "$(which vim) -S ~/gitcommithighlight.vim"
So I’ve been thinking for a while, “wifi control of these lamps is all well and good, but I’d really rather push data over a serial connection so that I can avoid having to set up wifi networks. Also, serial just makes more sense for high throughput usecases, eg sending a continuous stream of updates”
“…Too bad WLED doesn’t have a serial API”
You know what they say about when you assume things? I don’t know why I never really looked it up, but I just figured that WLED didn’t have serial support. Turns out it actually supports multiple protocols, and as of 0.13.0 it can receive the same JSON commands via serial as it does via wifi.
So here’s a little video of a proof of concept I put together, to learn a couple of things. It’s my first time playing around with web serial – I lifted heavily from this Codelab to get things working.
Oh boy, let me take you down the rabbit hole that keeps sneakily stealing hours of my life from me.
We’ll start with a topic I’ve covered a few times before:
Seals
I’ve written before about my mock sinograph signature – a pseudo Chinese-character sequence that I use to sign my artwork with.
I have also signed my work in the past with a signature stamp that I picked up at a dollar store in Japan, that simply contained the character of my surname.
In the intervening times, I’ve experimented with laser engraving seals of my sinograph, and modifying its design. I briefly hit on a design I absolutely adored that incorporated “Alethea” into the character 鴨 (duck), which when put together with my surname 林 would have correspondingly given me “forest duck” as my signature. This would allude to the name of the chenonetta jubata in Chinese, nicely tying all of my identities together.
Unfortunately, a Mandarin-speaking coworker cautioned me against using 鴨 as a pseudonym. They informed me that when referring to people, “duck” is sometimes used as a euphemism for a male prostitute. So with that knowledge, I decided to fall back to my made-up characters.
When I made the most recent revision to my signature, I decided to get it professionally carved into soapstone, and had the company confirm that I wasn’t going to run into any similar embarrassing misunderstandings with the design. The actual seal carving ended up being very expensive (considering I could have just laser engraved it myself), but I valued the peace of mind that came with having someone knowledgable vetting it. Experiencing how the seal design transferred so cleanly with good quality seal paste (the ink used to stamp the blocks with) also unlocked the next step in my journey.
QArt Codes
Some time ago, I read this blog post about embedding images into QR codes. As a tl;dr, QR codes are made to be tolerant to damage. Most QR codes that contain logos in them just cover the data contained in the code and take advantage of the error-correcting algorithm to ensure the right values are read out. “QArt Codes”, on the other hand, use a provided image to generate a URL that naturally encodes to something that resembles the source image.
I can’t remember what led me to the article initially, it was a looooong time ago. I may have been working on a puzzle hunt for AVCon that used QR codes to log people’s progress and I wanted to embed the AVCon Invader logo into it (so some time around 2014). But the puzzle hunt, and QR codes in Aus generally didn’t catch on so the idea just got relegated to the back of my mind.
Still, QArt codes are super neat and I’m surprised I haven’t seen them in the wild more. Actually, I think the page that generated the codes was down during the rise of QR codes in the pandemic, so there was a bit of a missed window. But the page is back now, and you can play with making your own! Or if you want to play with the code there’s a standalone version you can run locally.
(Side note, when I was researching game-parsing screen readers to work on Ikalog stuff, I ran into this blog post by Up Banking. That’s the only QArt code that I’ve recognised in the wild to date)
Adding 2+2…
This is the post that lit the lightbulb in my head.
I mean, having hit this point in my post it’s pretty obvious what we’re gonna do, right?
QArt Chopping and Changing
“So how did you lose hours of your life to this? There’s a page that generates them, you just put your picture in there and you’re done, right?”
Well, to start off with, as I mentioned above the page that generates them was actually not available for some time, so I had to mess around with the original QArt source code (with a few headaches) and then later had the fortune of running into the standalone version.
After that… I lost time to the search of perfection.
Here’s my first draft of a painterly QArt signature. The output of the QArt generator still had a lot of noise, so I used painterly brushstrokes to make the noise look more appealing. At this point I still only superficially appreciated the stuff in the article and while I knew about some areas that were more important to preserve than others I was mostly just drawing willy-nilly with the understanding that “QR codes can repair damaged data”.
It’s neat but it’s off-centre, it contains only my surname and it probably won’t scan properly when scaled down for overlaying on art.
I was satisfied for a while with the proof of concept, but later I started thinking about laser cutting myself a new signature chop anyway, as the soapstone one I’d purchased was too large to use on A4 and smaller art (the majority of my pieces!)
So I looked at the QR codes and realised that I should provide a source image that wouldn’t need to scale. I want to control the pixels of the code so I should provide a pixel art version of my signature.
This provides an okayish output – it’s a good basis on which to paint over parts to arrive at a more aesthetically pleasing version.
I did do some test runs with this kind of “corrected” design and to my delight they did scan when stamped.
However, I anticipate that the stamping process can be error prone and therefore it will be impossible to perfectly transfer the design. So I keep returning to these QArt codes to try to minimise the errors. First by lowering the amount of modifications that I make to the generated code…
Then, by changing the generation of the code itself.
One strategy was to reduce the area of the QR code that must be dedicated to my URL. I chose not to use a URL shortener. I intend to keep the chenonetta.com domain into the forseeable future but I can’t control what happens with any URL forwarding services.
I also opted to include the full http:// prefix in the URL. I did some playing around with readers and some automatically open pages if the URL starts with www. or ends with a .com but I didn’t want to rely on that behaviour. I kept the ale subdomain but that’s the least defensible decision and I might change my mind on it in the future.
So how to save space if I’m not shortening the input data? The original QArt coder uses byte encoding for the main part of the URL. This uses 8 bits per character. I modified the generator to create the URL in two parts – an alphanum encoded section for the main URL and then byte encoding just for the # that joins the URL and its throwaway anchor. Alphanumeric encoding uses 11 bits for every two characters. Overall I did still save a little space, even with the extra stuff needed to define the single-character byte encoded section.
I also played with manually specifying the masking strategy (the mask is a pattern that gets XOR’d over the generated QR code – read the original QArt code article for details).
After a lot of iterating, this is probably the closest I’ll get for now. I think this is technically still a damaged code but the areas that I drew through are part of the instructions about how to read the code, not the data. Like the data itself, there are some redundancies for the instructions so the codes still scan ok. Most of the time I’ve spent on these codes has been spent in the cleanup and tweaking stages – what can I get away with without introducing errors?
This is supposedly an error free code according this debugging website – though the scale of the source image definitely affects its assessment of whether the code is error free or not. The site also doesn’t recognise flipped QR codes (even though other readers seem to be fine with them)
Being forced to make compromises on the final outcome always keeps me coming back to tweak things again and again – can I change the orientation so that I don’t have to use a flipped code? Can I rebalance the density of noise around the main design so that it doesn’t distract from the centre as much? Can I smooth the curves in the image more? I’ll just keep searching and searching for the ideal version of this design…
To wrap up, here’s the current setup I use for transferring the print to paper. I’ve been experimenting with moving to block printing ink instead of seal paste, because the latter is oil based and takes days to dry. So far I haven’t had a high success rate with the new ink but I think I’m learning. Sometimes a dodgy print can be recovered with a little bit of hand editing, though it requires some deft brushwork!
Follow these steps to set up WLED colour changes as channel point rewards using Kruiz Control. These instructions are written specifically for my Squid Lamps but can be modified for use with any WLED project.
Example video of this setup in action:
EDIT updated 2022-12-21
Check out Riekelt’s project, KrakenCommand for an alternative setup!
Click the above link to generate a token. You’ll be prompted to authorize permissions as a Twitch account.
Do not share this token with anyone else! It has permissions to manage your channel redemptions, to send messages in chat as the Twitch account that you choose and to see the email associated with the account. (I dunno why email address is needed but Comfy.js won’t work without that permission)
Open settings/chat/oauth.txt and replace the “token” part of the file with the generated token. Remove any spaces.
Channel Name
In settings/twitch/user.txt set the name of the channel that you want to watch for channel point redemptions. (Usually, your channel)
Chat User (Optional – not currently used)
Set settings/chat/user.txt to a Twitch channel. Setting this would allow Kruiz Control to send messages on your behalf to that channel.
Replace the contents of triggers.txt with the following. Note that the OnChannelPoint triggers need to match the names of the rewards from the step above.
Replace the IP address on line 2 (http://192.168.0.113) with the IP of the lamp.
Your lamp needs to be connected to the same network as your streaming PC.
OnInit
API Url SquidBeakon "http://192.168.0.113/json/state"
API Method SquidBeakon POST
API Header SquidBeakon "Content-Type" "application/json"
OnChannelPoint "Rainbow Lamp"
API RawData SquidBeakon "{\"seg\": [{\"of\": 4, \"fx\": 110, \"sx\": 128, \"ix\": 128, \"pal\": 11}]}"
API Send SquidBeakon
OnChannelPoint "Blue Lamp"
API RawData SquidBeakon "{\"seg\": [{\"fx\": 0, \"col\": [[0, 0, 255]]}]}"
API Send SquidBeakon
OnChannelPoint "Cyan Lamp"
API RawData SquidBeakon "{\"seg\": [{\"fx\": 0, \"col\": [[0, 255, 200]]}]}"
API Send SquidBeakon
OnChannelPoint "Green Lamp"
API RawData SquidBeakon "{\"seg\": [{\"fx\": 0, \"col\": [[8, 255, 0]]}]}"
API Send SquidBeakon
OnChannelPoint "Yellow Lamp"
API RawData SquidBeakon "{\"seg\": [{\"fx\": 0, \"col\": [[255, 200, 0]]}]}"
API Send SquidBeakon
OnChannelPoint "Orange Lamp"
API RawData SquidBeakon "{\"seg\": [{\"fx\": 0, \"col\": [[255, 160, 0]]}]}"
API Send SquidBeakon
OnChannelPoint "Red Lamp"
API RawData SquidBeakon "{\"seg\": [{\"fx\": 0, \"col\": [[255, 0, 0]]}]}"
API Send SquidBeakon
OnChannelPoint "Magenta Lamp"
API RawData SquidBeakon "{\"seg\": [{\"fx\": 0, \"col\": [[255, 0, 255]]}]}"
API Send SquidBeakon
Once this is implemented, we can update the trigger code to refund channel points if the lamp failed to update, and clear items out of the queue if it’s successful.
Alternatively, we could write our own code using Comfy.js!
Add a new browser source. Select “Local File” and pick the index.html file from the Kruiz Control directory that you extracted in step 1. Keeping this browser source active will listen for Channel Point redemptions.
Select a reward in Twitch and if everything has been set up correctly, the lamp colours will change!
If you make any changes to the files inside the Kruiz Control directory, including the settings or triggers.txt files, you must refresh your browser source in OBS for the changes to take effect.
Appendix: A single reward with user-provided colour
If you don’t want to crowd your rewards with the lamp options, you can create one reward and allow it to control the lamp colours with the redemption message from your viewers.
Using a single reward also allows for the Twitch cooldowns to be used. This means that a viewer can’t override the colours set by another viewer until the cooldown ends.
Replace triggers.txt with the text from the code block below. Create a single reward named “Set Lamp Color” and turn on the “Require Viewer to Enter Text” checkbox.
This trigger will search the text of the message that was attached to the points redemption and if one of the color keywords is found then the lamp colour will change. It’s worth suggesting to the user what to enter in their message in the reward description, eg:
Set my squid lamp to rainbow, blue, cyan, green, yellow, orange, red or magenta by including one of these words in your message!
OnInit
API Url SquidBeakon "http://192.168.0.113/json/state"
API Method SquidBeakon POST
API Header SquidBeakon "Content-Type" "application/json"
OnChannelPoint "Set Lamp Color"
Param Lower message
Param Keyword message "rainbow"
If 3 {matched} == true
API RawData SquidBeakon "{\"seg\": [{\"of\": 4, \"fx\": 110, \"sx\": 128, \"ix\": 128, \"pal\": 11}]}"
API Send SquidBeakon
Exit
Param Keyword message "blue"
If 3 {matched} == true
API RawData SquidBeakon "{\"seg\": [{\"fx\": 0, \"col\": [[0, 0, 255]]}]}"
API Send SquidBeakon
Exit
Param Keyword message "cyan"
If 3 {matched} == true
API RawData SquidBeakon "{\"seg\": [{\"fx\": 0, \"col\": [[0, 255, 200]]}]}"
API Send SquidBeakon
Exit
Param Keyword message "green"
If 3 {matched} == true
API RawData SquidBeakon "{\"seg\": [{\"fx\": 0, \"col\": [[8, 255, 0]]}]}"
API Send SquidBeakon
Exit
Param Keyword message "yellow"
If 3 {matched} == true
API RawData SquidBeakon "{\"seg\": [{\"fx\": 0, \"col\": [[255, 200, 0]]}]}"
API Send SquidBeakon
Exit
Param Keyword message "orange"
If 3 {matched} == true
API RawData SquidBeakon "{\"seg\": [{\"fx\": 0, \"col\": [[255, 160, 0]]}]}"
API Send SquidBeakon
Exit
Param Keyword message "red"
If 3 {matched} == true
API RawData SquidBeakon "{\"seg\": [{\"fx\": 0, \"col\": [[255, 0, 0]]}]}"
API Send SquidBeakon
Exit
Param Keyword message "magenta"
If 3 {matched} == true
API RawData SquidBeakon "{\"seg\": [{\"fx\": 0, \"col\": [[255, 0, 255]]}]}"
API Send SquidBeakon
Exit
Appendix: Customising Eye colours
Add the following trigger commands to triggers.txt. Make sure to create the corresponding rewards in the Twitch dashboard!
OnChannelPoint "Red Eyes"
API RawData SquidBeakon "{\"seg\": [{},{\"col\": [[255, 0, 0]]}]}"
API Send SquidBeakon
OnChannelPoint "Lime Eyes"
API RawData SquidBeakon "{\"seg\": [{},{\"col\": [[255, 255, 0]]}]}"
API Send SquidBeakon
OnChannelPoint "White Eyes"
API RawData SquidBeakon "{\"seg\": [{},{\"col\": [[255, 255, 255]]}]}"
API Send SquidBeakon
Appendix: Multiple Lamps
This sample sets up SquidBeakon1 and SquidBeakon2 with their own URLs so that they can be driven by separate rewards. Full support for multiple channel point settings is left as an exercise for the reader.
OnInit
API Url SquidBeakon1 "http://192.168.0.113/json/state"
API Method SquidBeakon1 POST
API Header SquidBeakon1 "Content-Type" "application/json"
API Url SquidBeakon2 "http://192.168.0.114/json/state"
API Method SquidBeakon2 POST
API Header SquidBeakon2 "Content-Type" "application/json"
OnChannelPoint "Rainbow Lamp 1"
API RawData SquidBeakon1 "{\"seg\": [{\"of\": 4, \"fx\": 110, \"sx\": 128, \"ix\": 128, \"pal\": 11}]}"
API Send SquidBeakon1
OnChannelPoint "Rainbow Lamp 2"
API RawData SquidBeakon2 "{\"seg\": [{\"of\": 4, \"fx\": 110, \"sx\": 128, \"ix\": 128, \"pal\": 11}]}"
API Send SquidBeakon2
Appendix: Tips for displaying your lamps on stream
The lamps are emitting light, which can be difficult to capture on camera. Some tips to improve the appearance of the lights:
Reflected surfaces
Nearby white or other reflective surfaces will convey the colours of the light
Ambient lighting
The lights will be washed out by bright ambient lighting. The frequencies of sunlight can be especially effective at washing out the lamp colours. Indoor lighting or a dimmed room are best!
Diffusion
A piece of printer paper or baking paper in front of the lights can be used to diffuse the colours. This file contains templates for paper cutouts that can be placed in or on the lamp.
WLED JSON API
The commands in this document send JSON data via the WLED JSON API.
Lately we’ve been streaming our board game misadventures.
With the webcam set up over our table, we can capture a reasonable amount of the play area, but things are quite hard to read. So I’ve been experimenting with some overlays to convey pertinent game information.
Here’s a demo of the overlay in action – the popup in the top left only appears for a little while when I change the “last tile visited” variable, and the player information allows us to track all of the different resources and upgrades that the players pick up along the way.
I think keeping the overlays updated is quite the distraction though – I guess that’s my excuse for John going 3-0 undefeated tonight!
Anyhow, I needed extra content to hit the once-per-day blog target for the month, plus it seemed like an interesting project to learn HTML 5’s fancy new flex boxes so I made a voting form. It kind of bloated out in size from what I’d originally intended so the coding is kind of awful but it seemed a waste to not share it with the world and see what results we can collate.
It’s a preferential voting form where you can either decide on a “party” of ties that you like best and vote party-by-party, or you can decide to number every tie as you like. We know you might want to be a bit lazy though so you can vote “below the line” and have a valid vote as long as you fill in at least six candidates.
This past weekend I helped run AVCon, Adelaide’s local Anime and Video Games convention. For the first time since 2010 I also took charge of running the Smash Bros tournament at the event.
Although I like writing tournament management systems, this year I didn’t really have the time for it. Fortunately for me, Smash Bros. has been running as a 1v1 format for the last few years so I was able to fall back on trusty ol’ Challonge.
Challonge has bracketing and result reporting down-pat, but I’ve always felt that it lacks a crucial tool – indicating which station a match should be played on. After running tournaments in 2013 I was tempted to write a database to sit between Challonge and my players and create an interface where I could associate matches with console stations.
Fortunately for me in June of this year Challonge rolled out a change that allowed users to set match locations… even if it’s buried away in the interface a little. It wasn’t ideal, but with a little JavaScript hax I was able to very easily turn it into what I wanted. I wrote some JavaScript that modifies the Challonge tournament management screen to do two things.
1) Display a set of numbers representing the stations on which games should be played on.
2) Allow highlighting of matches to indicate that they are up “now†or “nextâ€.
Consistent with my trend of naming projects after disasters, this script has been dubbed “Landslide”.
Installation Instructions
You need to find a way to run User Scripts in your browser. This script was tested and run with Greasemonkey on Firefox, so instructions will be for Greasemonkey.
Grab this script – it’s where all the magic happens. Copy it to your clipboard.
Now in Firefox, navigate to the Greasemonkey dropdown and select “New User Script…”.
A few options come up – ignore them and click on “Use Script From Clipboard”. A window will appear with the script in it – save and close it and the script should be installed! You may need to refresh pages for the changes to take effect.
You can verify that script installation works correctly by checking out one of my tournaments and verifying that each game loads up an @[number] underneath its lettered match-name.
Usage Instructions
Mouse over match IDs to bring up a modified menu. The menu will display a few new things: “Toggle Highlightâ€, “Clear Station†and a series of station IDs. The IDs are by default set from 1-8. I haven’t really put time into customising the numbers but you could edit the script to make the station IDs appear differently if you wish.
Selecting a number will set the match location as an @[number] indicator, underneath the letter-name that Challonge assigns for the match.
Toggle highlight will set a match from no highlight, to yellow, which means there is a match on next.
Toggling a yellow highlight will turn it red. Toggling a red highlight will clear the match highlight AND will also automatically upgrade a match that is set up as being “next” (yellow) on the same station to be the new “now” (red) match.
Finally the script will attempt to stop you from setting two matches on the same station to both be on “now” or “next”.
How does it work?
I push the data into the “location” field of the match. You’ll see locations for matches set as something like 3|next
Because Challonge stores this data, match locations can be reloaded when you refresh the page!
Warnings
Do not modify location manually – this will probably cause the script to desync.
If you have any problems with the “state” of the script – it might get confused about which stations are active if a certain sequence of data entry occurs – just refresh the page and it should reload your data.
Closing thoughts – how did it go for MY tournaments?
Having the Station IDs accessible for matches was invaluable. As I was calling up players for their games, many would hear their names but wanted to confirm where they needed to play. Last year, I’d flail around counting down the bracket or call out “uh, is [opponent name] here?†then send the player asking me where they needed to go to whoever had their hand up. This year, I was able to immediately tell them “You’re on Station 5â€. I feel it saved a lot of time and confusion.
The “now†and “next†highlighting wasn’t really as useful due to the speed at which games were being completed, and please note it is buggy due to its last-minute inclusion. But it wasn’t totally useless – when I forgot to input results the script would tell me that I had matches already active and I could then ask “Hey could [player] and [player] who played on [station number] confirm who won their match?â€.
There is of course room for improvement – for example, matches don’t automatically toggle out of being on “now†when results are recorded. But it was hugely useful for me this last weekend and I think worth sharing. If you use this for nothing other than the Station number then I think you’ll still find it amazing.
Feedback and forks are welcomed. I hope you find this script useful.
Just something to prove I’m not completely out of the blogging game yet.
I’ve been working on a program to generate knot work. The idea initially was as a helper for human-generated knots but could also eventually extend into automation of patterns.
These knots are made using a font that contains characters that resemble common intersections and crossing overs. The font is quite cleverly designed and allows for a lot of different ideas to be expressed and also has all the rotations worked out in such a way that the generated knotwork tends to have the right crossing over and under effect appear.
This method of generation works very different from the traditional knotting which usually requires a lot of forethought and preparation. With this font a more stream-of-thought way of creating knotwork is enabled. It’s definitely quite fun and exciting to see a knot come to life in unexpected ways!
[Edit 8th May 2015: I’ve been alerted to the fact that in Windows the audio sounds decidedly piano-like. This is not intentional! I will see if I can fix this at a later date.]
Well March Blog Badness Madness begins today! This challenge, having snuck up on me, has left me racking my brain for ideas of what to post. This time I have no weekly classes to guarantee me at least something to post each week (not that I did take advantage of said classes in order to put together posting material…) so I need to come up with ideas. Ideas of March.
Anyhoo, let’s start by discussing a coding thing I worked on last year. A prototype Accordion emulator written in Java
Screenshot below, you can download the program here. (Requires Java).
This program started as a simple attempt to generate a Stradella button map that I could refer to while playing the piano accordion. I wanted to draw up my own as a bit of fun in remembering my music theory (each row is a perfect fifth interval from the one below it). After some annoying attempts to draw the thing up by hand, then some fiddling around in Photoshop, I concluded that it’d be faster to write a program to generate the thing for me.
Once I’d done that, I decided it’d be fun to make the buttons play notes when they were pressed. Things snowballed from there.
Inspired by a program I’d spotted a few years ago I realised that I could use a keyboard with the program and could map a number of keyboard keys quite easily to the bass button keys as both key layouts contain diagonal rows. Quite fortunately, a standard keyboard should offer 12 rows and four columns of keys allowing for every note in a scale to be represented in my emulator. Although the focus of the program is on the bass keys, I added in a section of the piano keyboard as well to allow for a bit of experimentation with melody and bass.
Finally, I flipped the keyboards so that they correspond more intuitively to what a player would expect to see while playing, as the buttons face away from the player. This also became handy for when I wanted to practice accordion and didn’t have a mirror handy to check my hand placements 🙂
As you can tell I’ve had a few changes of heart in naming this program – it started as AccordionIng which naturally became Accordin’. I’ve started thinking of it as In Accord lately, not that I’ve been really thinking about it lately. Other people tend to just call it Accordion Hero. One day I’d like to turn this into something like an “Accordion Hero” type game or a music tutor. That would probably call for a rewrite. For now, I’m quite pleased that it allows me to practice with my headphones in and not bothering other people.