Holiday mission

Last year, I gave my son an assignment for Christmas: help me assemble the RetroPie we got him.  He enjoyed that process and subsequently became a fan of Contra.  This year, we were a little at a loss as to what to get, and eventually decided on making the big family gift a Nintendo Switch.  Still video game themed, but not really amenable to being a DIY project.

But then, a few days before Christmas, we were talking about the vacation we took in Florida at the beginning of 2020, right before everything got locked down.  My son mentioned how much he enjoyed our trip to the science museum, which had a special exhibit on spies.  So I decided to make this year's "Christmas mission" a spy-themed scavenger hunt.  

I figured it would be nice to make it semi-educational, so I wrote a simple "encryption" program (just ROT13 in Python), commented it heavily, and e-mailed it to him.  Then I came up with four clues to lead him to, first, his stocking, and second, the Switch.  I wrote a short letter describing his mission and including the encrypted text for the first clue.  Then I encrypted the other three clues, printed them out, and hid them in the appropriate places.  I put the letter in an envelope and hid it semi-conspicuously in the Christmas tree.

Here's the program I sent him, in case anyone is interested:

# This program does a ROT13 encoding on a message to encrypt or decrypt it.
# ROT13 is a simple "substitution cipher", also called a "Caesar cipher" after
# Julius Caesar, who was one of the first people to use it.

# A substitution cipher means that you replace one character in the message with
# a different character according to certain rules.  ROT13 stands for "rotate by 13",
# because the rule is that you replace with the character that's 13 places farther in 
# the alphabet (when you get to "Z", you loop back around to "A" and keep going).

# One of the cool things about this is that, because there are 26 letters in the 
# alphabet, ROT13 can both encrypt and decrypt a message using the same method.
# You don't need to do anything different!

# Here's how the program works:

# We'll put the decryption in a function and pass it the message
def decrypt_message(message):

    # This is where we're going to store the decrypted message
    decrypted_message = ''

    # We decrypt by going through the message one character at a time.
    for character in message:
        # If the character is an upper-case or lower-case letter, let's rotate it.
        if character.islower() or character.isupper():
            # First we figure out the letter's position in the alphabet.  We can do
            # this by using it's ASCII code, which is the way we represent letters and
            # other printable characters in binary, see https://www.asciitable.com
            starting_ascii_code = ord('A') if character.isupper() else ord('a')
            # To get the position, we get the ASCII value of the letter and then subtract
            # the ASCII value for "A".  (Lower-case and upper case have different codes.)
            position_in_alphabet = ord(character) - starting_ascii_code
            # Then we add 13 and take the modulus with 26.  The "modulus" is the remainder
            # when you do division, so 30 / 26 is 1 with a remainder of 4, so the 30 % 26 is 4.
            new_position = (position_in_alphabet + 13) % 26
            # Now we add back the value we subtracted to get the position to make it
            # an ASCII code again.
            new_character = chr(new_position + starting_ascii_code)
            # Now we can add the the new letter to the decrypted message.
            decrypted_message += new_character
        else:
            # If the character isn't a letter (e.g. a space or punctuation), we'll
            # just leave it alone and add it to the decrypted message.
            decrypted_message += character

    # Now we can print out the result!
    print("The decrypted message is:")
    print(decrypted_message)
    print()


print('Ready to decrypt!  Type "exit" to quit.')
message = ''
while message != 'exit':
    print("Enter the message:")
    message = input()
    decrypt_message(message)

Zane actually found the letter on his own before I even had a chance to nudge him toward it.  He was really excited and immediately wanted to get started.  So we went and downloaded the ROT13 program and I showed him how to open it in IDLE.  He read some of the comments and then we ran it and he typed in the first message.  That led him to the second one hidden in the advent calendar, which in turn led him to his stocking in the basement.  Since we weren't doing presents until the extended family came over for lunch, the third message in his stocking told him to talk to his aunt, who I enlisted to deliver the last clue, which led to the Switch strategically hidden under the bed.

Apparently it was a good idea, because Zane was really into it and had a great time.  After finding the Switch, he even held a "debriefing" where he explained the entire mission in detail to his grandparents.  I count this as a very successful Christmas.

Back from the holidays

In the spirit of not freaking out and overdoing it for the holidays, for Christmas this year I've scheduled another "from the archives" post.  If you haven't been keeping track, that's my lazy posting series where I slap a preamble on something that's been sitting in my drafts folder forever and call it "new content".

This one is actually seasonal, though, as it's dated December 28, 2007.  It's also completely non-technical and yet was also tagged "Software Engineering" for some reason.  Maybe I intended to add something to it, or maybe I just fat-fingered the tag widget.  But that's neither here nor there.  The point is that my scheduled Saturday post falls on Christmas day, and this is related to Christmas.

Since this one is super-short, I'm going to add some inline commentary to it because, well, otherwise it's just boring.  But this is also purely biographical, which means that nobody else cares anyway.  So this is largely a "me" post.

The post is below the line with current-day comments in italics.  Hopefully it'll be at least modestly entertaining.  Enjoy and happy holidays!


Boy, it's been a long time since I did any blogging. (Now: Exactly a week, to be precise.)  I've been meaning to get back to it, but it seems like I just haven't been able to find the time or energy.  Hopefully that will change now that things are finally settling down.  (Now: This actually still applies, sadly.  Despite being part of the "zoomocracy" and hence managing the pandemic as well as can be expected, I've found the whole thing has been a constant slow sap on my energy.  I've tried to maintain healthy habits and schedules and have managed fairly well, but still....)

There's been a lot going on here in the last couple of months.  Of course, there was the usual holiday hubbub.  My wife always insists on making a big production for Thanksgiving and Christmas, even when she doesn't have time to.  (Now: One up-ish side of the pandemic is that this hasn't been an issue the last couple of years.  That's not precisely a "good" thing, it does put the stress of big holiday plans in perspective.  Although I do miss some of it.  For instance, I was just thinking the other day about how every year I would make and package a bunch of cookie dough for my grandmother at Christmas.  She passed in early 2020 at the age of 89, in the first wave of the pandemic.  She was never very good at making cookies - when they were kids, apparently when she mentioned to my uncles that she might make some cookies, they would tell here that maybe she should wait for my mom to come home and let her do it.  So every year I would freeze her a bunch of pre-rolled cookies that she could just pop in the oven.  She would take them to events at church and people would tell her what good cookies she made.)  We also found a buyer for our house in Corning and moved the last of stuff out.  I've been trying to unpack and organize things, but it's very slow going.  

In the moving process, we also acquired a piano.  It's actually my mom's piano, which she doesn't play and has been wanting to get out of the house for some time.  I, however, do play and I've been immensely enjoying trying to get back in practice.  (Now: This is also still relevant.  I don't play that much anymore, but I still find it relaxing to do every now and then.  The last few weeks I've broken out the old Christmas carol sheet music in honor of the holidays.  Even though things are better than last Christmas, we're still not really back to normal.  So in these weird times, I find playing the piano a nice way to decompress, put aside the worries, and think about better days.)

Using your tablet as a monitor

The other week I was wondering: can I use my tablet as an external monitor?  I mean, it would be nice to have a portable monitor so I can do dual-display on my laptop wherever I go.  And I usually have my tablet with me.  And it's got a nice 10" display with decent definition.  So why not use it as an extra monitor where I can toss my Slack window or something like that?

Unfortunately, it doesn't seem like there's an out-of-the-box way to do this with my Windows laptop and Galaxy S6 Lite tablet.  But the good news is that there's software that will make it work pretty painlessly.

The solution I ended up going with was Duet.  It's a combination of a desktop app and mobile app working in tandem that works for Windows, Mac, Android, and iOS.  There is a service you can create an account for, but it's not necessary - you can use the apps locally without signing up for anything.  (In fact, I haven't even tried creating an account yet.)  By default Duet connects via a USB connection to your device, but you can also enable an option to connect wirelessly over WiFi.  The WiFi connection is fine, but at least on my network there was a lot of mouse lag when trying to use apps on the tablet.  It's not unusable, but it is unpleasant.  The USB connection is super-responsive, though, so I normally just use that.  As a nice extra, Duet even allows you to use the touchscreen of the tablet, so if your laptop has a touchscreen (which mine does), your secondary screen will work just the same.  Very slick!

IMG_20211214_154055-small.jpg

The only down side of Duet I've seen so far is that it's not free and there doesn't seem to be a demo version.  There's no cost for the desktop component, but the Android app is about $10.  That's not exactly a fortune, but it's enough to be annoying if you try it and it doesn't work.  Thus my first attempt was with Spacedesk, which is completely free.  However, I didn't actually get a chance to try it out, as the desktop driver install experience was...not great.  For some reason, it took an uncomfortably long to for the installer to run.  Like, after half an hour it was still working.  So I clicked "cancel".  And then, after another hour, the rollback finally completed and I closed the installer.  I have no idea what it was doing, but that was enough to make me not trust it.

Duet, on the other hand, installed fast and worked the first time.  The settings are pretty minimal.  For the connection, you can change the framerate, performance setting, and resolution.  System-wide, you can toggle notifications and "Duet Air", which is what they call the WiFi connection.  To connect the tablet, you pretty much just plug it in.  Duet on the tablet will prompt you to connect the screen and Duet on the laptop will also detect the connection and add the display.  (Of course, if you're using a WiFi connection, it's not that simple.  But it's still pretty simple.)  After that, the tablet just behaves like a regular touchscreen display.  Unfortunately, it only supports one device at a time, so you can't plug in two tablets, or your tablet and your phone, but that's not a huge deal.

So far I'm pretty happy with Duet.  It's a nicely done little utility that "just works" and does a useful thing.  Definitely worth checking out if you have a device that would make a good extra monitor.

Non-standard project setup with CoC and Pyright

Here's a quick little thing that I'll probably need to remember and might be useful to other.

At work, we have a PHP project that has automated integration tests written in Python.  The top-level directory of the Git repo is the normal PHP stuff, but the tests/integration/ directory is a Python sub-project that uses Poetry and Pytest.

Now, I use Vim as my editor and CoC with Intelliphense and Pyright for my PHp and Pythong language servers.  Since the main repo is PHP, Intelliphense works just fine.  Hwoever, Pyright needs a little help.  In particular, it didn't find the third-party dependencies or the integration test framework packages because it didn't know where to look.

Fortunately, this is easily fixed by creating a pyrightconfig.json file.  I was able to create one of those in the top-level directory of the project and add an "execution environment" to tell Pyright where to find the root of the Python project.  I set it to the "tests" directory because, while the main dir is tests/integration/,  that directory is also a Python module, so using "tests" lets Pyright find the "integration" module.

My particular file looks like this:

{
    "venvPath": "tests/integration",
    "venv": ".venv",
    "executionEnvironments": [
        {
            "root": "tests
        }
    ]
}

Windows 11 is fine

A couple of weeks ago I got the notification on my laptop that I could now upgrade to Windows 11.  And since I was feeling optimistic that day, I clicked "yes".

I'm not going to do a "review of Windows 11" post, though.  Not because I'm lazy or pressed for time (though I don't deny those charges), but really just because I don't have that much to say.  I mean, so far Windows 11 is fine.  And I don't mean that in the sarcastic, room-on-fire-this-is-fine meme sort of way.  My experience has been genuinely fine.  It's not a phenomenal, life-changing upgrade, but I haven't had any problems either.

For the most part, I haven't really noticed much of a change from Windows 10.  Yeah, now windows have more rounded corners and the UI in general got kind of a face lift, but those are mostly cosmetic changes.  They added some handy window management features that I use on occasion, but I haven't discovered any major features that strike me as must-have's.  

The one change I did immediately notice was the start menu.  I really don't like the new start menu.  I think it's much less useful than the one from Windows 10.  For one, the default position is in the middle of the screen, which seems like a pointless change.  However, there's a setting to easily change that.  But beyond that, it doesn't allow much customization and seems much more focused on being a glorified search box than a menu.  You can still pin items to the start menu, but the option to arrange them into groups is gone.  Also, the pinned area is now smaller and paginated, which is kind of annoying.

2021-11-27T14-22-18-212Z-small.png

Fortunately, that can be changed too.  There are a few options out there for start menu replacement in Windows 11.  I went with Stardock's Start11, which give you quite a few options in terms of customizing the start menu experience, including versions of the Windows 10 menu and the "classic" Windows 7 style menu.  On top of this, it gives you a number of other settings to manipulate the look and behavior of the start menu and taskbar, such as controlling transparency and texture, swapping out the start button image, and controlling click behavior.  It's actually quite well done, and with a $6 price tag, it's kind of a no-brainer if you don't like the new menu.

2021-11-27T14-10-15-829Z-small.png