Getting some pretty strange spam emails sent to my Gmail address (which I still use). It’s the same badly formatted multi-MIME message body with different From and Subject lines. They’re trying to get… something from me? Logins, maybe? Worst phishing attempt ever!

Updates To Dynamo-Browse And CCLM
I started this week fearing that I’d have very little to write today. I actually organised some time off over the weekend where I wouldn’t be spending a lot of time on side projects. But the week started with a public holiday, which I guess acted like a bit of a time offset, so some things did get worked on.
That said, most of the work done was starting or continuing things in progress, which is not super interesting at this stage. I’ll hold off on talking about those until there’s a little more there. But there were a few things that are worth mentioning.
Dynamo-Browse
I found a bug in the query planner. It had to do with which index it chose when planning a query with only a single attribute. If a table has multiple GSIs that have that same attribute as the partition key (with different attributes for sort keys), the index the planner choose became effectively random. Because each index may have different records, running that query could give incomplete results.
I think the query planner needs to be fixed such that any ambiguity in which index to be use would result in an error. I try to avoid putting an unnecessary need for the user to know that a particular query required a particular index. But I don’t think there’s any getting around this: the user would have to specify.
But how to allow the user to specify the index to use?
The fix for the script API was reasonably simple: just allow the script author to specify the index to use in the form of an option. That’s effectively what I’ve done by adding an optional index
field to the session.query()
method. When set, the specific index would be used regardless of which index the query planner would choose.
I’m not certain how best to solve this when the user is running a query interactively. My current idea is that a menu should appear, allowing the user to select the index to use from a list. This could also include a “scan” option if no index is needed. Ideally this information will be stored alongside the query expression so that pressing R would rerun the query without throwing up the prompt again.
Another option is allowing the user to specify the index within the expression in some way. Maybe in the form of a hint, as in having the user explicitly specify the sort key in a way that does’t affect the output. This is a little hacky though — sort of like those optimisations you need to do in SQL queries to nudge the planner in a particular execution plan.
Another option is having the user specify the index specifically in the query. Maybe as an annotation:
color="blue" @index('color-item-index')
or as a suffix:
color="blue" using index('color-item-index')
Anyway, this will be an ongoing thing I’m sure.
One other thing I started working on in Dynamo-Browse is finally working on support for the between
keyword:
age between 12 and 24
This maps directly to the between
statement in DynamoDB’s query expression language, so getting scan support for this was relatively easy. I do need to make the query planner know of this though, as this operation is supported in queries if it’s used with the sort key. So this is still on a branch at the moment.
Finally, I’ve found myself using this tool a lot this last week and I desperately need something akin to what I’ve been calling a “fanout” command. This is a way to take the results of one query and use them in someway in another query — almost like sub-queries in regular SQL. What I’ve been finding myself wishing I could use this for is getting the IDs of the row from a query run over the index, and just running a query for rows with those ID over the main table. At the moment I’m left with copying the ID from the first result set, and just making a large pk in (…)
expression, which is far from ideal.
I’m not sure whether I’d like to do this as a command, or extend the query expression in some way. Both approaches have advantages and disadvantages. That’s probably why I haven’t made any movement on this front yet.
CCLM
I did spend the Monday working on CCLM. I coded up a small script which took some of the ideas from the blog post on puzzle design I mention last week that I could run to get some ideas. So far it’s only producing suggestions with two game elements, but it’s enough of a starting point for making puzzles:
leonmika@Stark cclm % go run ./cmd/puzzleidea
bear trap
directional walls
After running it on Monday I had a go at starting work on a new level. It became clear reasonably soon after I started that I needed a new game element. So I added one, which I’ve called “kindling”. By default it looks like a pile of wood, and is perfectively safe to walk on:

But if a fireball runs into it, it catches alight and spreads to any adjacent kindling tiles, turning them into fire tiles.

I had an idea for this for a while. I even went to the extend of producing the graphics for this element. But needing it for this puzzle finally bought me around to finishing the work. I actually manage to make most of the changes without any changes to the Go code at all: the existing tile definition configuration was almost powerful enough to represent this tile.
One other minor thing I fixed was the alignment of the info panels on the right side of the screen. Dealing with the unaligned numbers got a bit much eventually. The cursor position, marker position, and tag numbers are properly aligned now.

Anyway, that’s all for this week.
A better peacock photo (well, just).

One of the photos I was going to use in my last post was this photo, which was modified using Google’s Magic Eraser. You can compare this with the original photo in that post (it had two people in it). It’s far from perfect, but it’s still quite impressive.

Rode an eBike for the first time today. Can definitely recommend. Even with the assist engaged at the lowest level, it made a huge difference going up hills. Great fun.
Greetings from Cowes, Phillip Island.

My first experience with a distributed SCM systems was Mercurial. Running hg branch
created a new branch and automatically switched you over to it.
When I moved to Git, I occasionally fell into the trap of typing git branch
and expecting to change over to the new branch. I fell for this quite often for a long time, for several years at least. It was happening frequently enough that I actually hacked Git to tell me that I haven’t actually changed branches yet:
$ git branch xyz-123
Branch 'xyz-123' created, but you're still on 'develop'
I’m using OhMyZSH now, which shows the current branch in the prompt. This has helped a great deal, and I fall for this much less often than I used to.
And yes, I know about git checkout -b
, but typing checkout
to create branches was a bigger change to me than simply learning that git branch
doesn’t change branches.
Using tools I’ve built to help me at work and all I see are features not implemented. Never-mind that the tool didn’t even exist a year ago. It exists now, so why doesn’t it do the thing I need it to do at this exact time? A person’s expectation is just insatiable, I guess. 😏
It’s amazing what a difference going to the gym can make. This afternoon I was feeling so lethargic, like all I wanted to do was crawl into bed. But I decided to crawl to the gym instead. I really didn’t want to, and I usually don’t go Mondays so I had an excuse not to. But I’m so glad I did because afterwards I got my energy back and I was eager to just do stuff.
Partial credit goes to coffee. It also helped with getting over the slump.
Photos of Fitzroy Gardens, while we play our bocce comp. grand final. Perfect weather for it. Also lots of weddings going on.



Dev Log - 2023-03-12
Preamble
When I moved Working Set over to Micro.blog, I’d thought I’d be constantly writing micro-posts about what I’m working on, as a form of working in public. I found that didn’t really work for me, for a few reasons.
I’ve got a strange relationship with this blog. I wanted a place online to write about the projects I’ve been working on, but every time I publish something here, I always get the feeling that I’m “showing off” in some way: ooh, look what I’ve done, aren’t I cleaver? And okay, I’d be lying if there’s not a part of me that wants others to see how I spend my time. If I didn’t want that, I’d be content with these posts existing in a private journal.
And maybe this is a form of self-justification but I’d like to think that there’s a bit of that feeling in every developer that keeps a public blog on what they do. Maybe not exactly “showing off”, but I’m sure they feel proud on what they work on and they want to talk about it. And there’s really nothing wrong with that. In fact, the posts I tend to enjoy the most are those from other devs talking about the projects they’re working on.
So yeah, I admit that having others see what I’m working on would be nice. They say write what you want to read, and this is my attempt at doing just that.
But that only explains why I write about it on a public blog instead of a private journal. Why I should want to write these posts at all is that I’d like to keep a record of the the projects I work on. Nostalgia is one reason: seeing a project progress over time or remembering projects long since abandoned. But another might be a way to track where I’m spending my time. This is theoretical at the moment, but if there ever came a time when I wanted to find this out, I have to have the record written somewhere.
But not as micro-posts. I think a fixed weekly cadence is more appropriate. I tried this a couple of years ago, and although it worked for a while, I fell out of the habit. But after seeing the weekly entries by Jonathan Hays, I’ve been inspired to try it again.
So that’s why I’m trying these weekly update. They’ll be frequent enough to be useful to act like diary entries, but not so frequent that they will bother people who aren’t interested. They’ll be long enough to warrant a title, making it easy for people to skip it. And they’ll be any anything related to a side project I’m working on: either current or abandoned, public or completely private. And I’m giving myself permission not to feel bad about it.
Anyway, we’ll see how we go.
Update 6th July: I’ve gone back to just making posts when I have something to write about.
Dynamo-Browse
Big week for Dynamo-Browse: I finally got v0.2.0 out the door. This is the release with scripting support (yes, it finally shipped). The scripting implementation has been finished for a while. The thing that was blocking it’s release was all the documentation I had to write: both the section in the manual and the API reference.
The build was also a bit of an issue. The release builds are built using GitHub actions. To get them published as Homebrew casks, the actions need to push them to another repository. The secret token used to access this repository expired, and I had to create another one. Not difficult, but the fact that I had to create a whole new secret instead of rotate the existing one was a little annoying. Getting the permissions right, and being forced to choose a different name (“Deploy Homebrew formulas v2”) didn’t help matters either.
But got there in the end. The v0.2.0 release is now available on dynamobrowse.app and GitHub.
I’ll reduce the time I spend on this for a little while. We’ll see how long that lasts. I use this tool for work so often and I’ve got a whole list of features I’d like to see added to it.
CCLM

I got the editor up and running again last week and I spent Saturday designing a level with the working name “The Beach”. I’m a huge fan of the Developing series on the Game Makers Toolkit YouTube channel, and the latest video was about how difficult it was for Mark to design levels for his video game. I found I had the exact same problem for designing levels for mine (although I think the lack of effort I put into it doesn’t help). He pointed to a blog post by an indie game designer that had some useful tips to help with puzzle design. The one about using two elements that interact with it.
The one I worked on was for a custom element that will change boxes with a square indicator to blank tiles when pressing the yellow button. I’ve had this element around for a while but I haven’t actually used it in a level yet. I’d thought I’ll be time to do so, but the level I came up with seems a little simple. Not sure what I’d do about it. I could either rearrange it so that it appears earlier in the level set, or I can make it a little more difficult in some way.
Client Project
One thing that releasing Dynamo-Browse has given me is the opportunity to do a small client project. I’ve talked about this on lmika.org and the latest update is that I think I’ve convinced him to consider a static site, seeing that it would be easier for him to run (don’t need to worry about plugins) and would be easier for me to build (I don’t know how to use Wordpress, especially not their new block editor).
This week was basically coming up with a site layout. I had the opportunity to use Figma for the first time. Works reasonably well, but I’m wondering if Balsamiq Mockups was probably a better choice for a rough outline of what the site is to look like. But that’s all moot: a layout was put together and sent to the client for him to get some feedback.
Anyway, still early days here. I’m looking at possible Hugo templates to build the site in and possible hosting solutions that would work with the client. I’m not aware of options for static hosting other than the AWS, Cloudflare or Azures of the world. Not sure it will work for the client, although it’s totally possible that I’m just not looking in the right places.
So that’s it. Update one done. Although next week I’ll be taking some leave so update two might be slightly shorter (at least there’ll be no preamble) so it may be less about current updates. I guess we’ll find out together.
It took me a while to get use to it but I’ve grown to like The Verge homepage redesign. Having the micro-posts there seems to work well, especially considering that certain microblogging services have effectively cut off API access.
I know UI designers like using either Sketch or Figma — and after signing up to Figma this week, I can see why. But I’m going to give a shout-out to Balsamiq Wireframes (nee Balsamiq Mockups). I’ve found it to be a great tool for demonstrating a proposed layout for a UI without worrying too much about the details. It’s so quick to put together and the hand-drawn motif makes it clear that the drawn UI is just a concept.
I also love how they use text to represent visual content. An example is items in a table-view: instead of using the mouse to draw each row by hand, you configured it by effectively typing out a CSV with some Markdown. Use commas to separate the columns, use [ ]
to indicate a column should have checkboxes. Such a great idea.
Do sites that just load their articles with (video) ads, pop-overs, requests for emails, etc. see any improvements in their metrics after doing this (more clicks, longer visit times, more ad revenue)? Or are the just in a cycle of diminishing returns and think that adding more crap will help?
🔗 After 6 long months, an Android phone finally cloned the iPhone 14
The screen-shots of this “mini capsule” are hillarous. The animated waves that appear when the capsule is expanded; the fact that the only thing it can display is the battery level since there’s nothing like Live Actions. The capper is the “90%” on the right side of the capsule, right next to the 90 in the battery indicator. You know, just in case you need reminding that the battery is at 90%. Champions indeed!
Hilarity aside, it’s a little sad seeing these Android OEMs doing everything they can to rip off Apple’s design. And it’s not just those in the long tail of OEMs either. Seeing Samsung half-arse features months after they debut on the iPhone, just to abandon them months later is really cringeworthy (anyone remember “AR Emoji”, their rip-off of Animoji). It’s past time they developed some taste on their own.
Hiding Your Attachment Folder In Obsidian's Outline
A useful little CSS snippet for anyone using Obsidian that wants to hide their attachment folder from their outline.
.nav-folder.mod-root>.nav-folder-children .nav-folder>.nav-folder-title[data-path^="Attachments"],
.nav-folder.mod-root>.nav-folder-children .nav-folder>.nav-folder-title[data-path^="Attachments"] + .nav-folder-children {
display: none;
}
To use:
- Go to the directory
$VAULT/.obsidian/snippets
where$VAULT
is the directory of you vault. If thesnippets
directory doesn’t exist, create it. - Copy the CSS snippet into a new CSS file.
- Open you vault settings and go to Appearance.
- Scroll to the bottom to where you see CSS snippets.
- Click the reload button. You should see the CSS file you’ve just created appear in the list. Turn it on to apply it.
This’ll work if you’ve configured Obsidian to store attachments in a folder called “Attachments” located at the root of your vault, like I do. But I suspect the data-path
attribute holds the folder’s path so you could use whatever CSS attribute selector you need based on how you’ve configured attachments. For example, [data-path*="/Files"]
selector will probably work if you’ve configured attachments to be in folders called “Files” that sits alongside your notes (I haven’t tested this so YMMV).
Working with some GitHub access tokens last night left me wondering why there’s no way to just renew an expired token. Dealing with the secret is not as tedious as dealing with the token permissions. Get that wrong and you’ve wasted several minutes of work.