My Sister’s Computer Hates Me!

Good Morning from my Robotics Lab! This is Shadow_8472, and today I am starting a series on installing Linux on my sister’s desktop. Let’s get started!

The Plan

My sister has expressed an interest in digital privacy and switching to Linux. She showed interest in installing Linux on her computer this week, and I just got a pair of new SSD’s on sale while shopping for my Arch installation, so I’m using one of those for this installation.

To the best of my experience, PopOS has been the distro of choice to use in terms of compatibility and privacy – by that I mean it has access to the Ubuntu library while System76, the company that makes it, advertises itself as being more privacy aware. While I’ve had problems with it in the past, they weren’t too difficult to sort out. It has a straightforward installer, and then their website has a selection of commands to install a preferred desktop environment. In short: it’s my favorite distro for beginners.

Hardware Installation 1

My sister left me a note inviting me to start work at my convenience, only for a Windows update to pop up while her system was unattended. I got her message before it was obscured, but I still found the irony funny.

For reference, I am working with a 1TB SATA SSD. About as soon as I had the case open, I was scavenging the technology pile for a SATA cable and a power connector from the supply I replaced a while back. The computer screws I found gave me too much trouble attaching it to her computer’s bracket, so I left it loose, later securing it with electrical tape several hours and “learning moments” later.

PopOS Install 1

Computer motherboards have what’s known as firmware, often referred to as BIOS, though recently replaced by UEFI. For the rest of this post, BIOS refers to the old, limited firmware exclusively. My sister’s computer boots with UEFI, and it was displaying on her WACOM graphical tablet where I missed it for playing around with HDMI connections on the graphics card so I could override boot to a USB drive with the latest PopOS install media.

I forget how, but the tablet-monitor went unnoticed until it was the sole output with the installer. I took special care to make sure I was installing to the blank drive, and not over her Windows installation. This was especially important because the system already had a 1 TB hard drive. After that, I put on the KDE desktop environment.

A minor, still-unresolved nuisance was the main monitors constantly being swapped. You can swap cables, or physical devices. Somehow, they always end up swapped. I also noticed some sort of U/I ghosting and horizontal line flickering I solved by removing the WACOM tablet entirely (it was mirrored to one screen – possibly both directions).

I finished up my first day arguing Minecraft into working (barely). I installed MultiMC and GraalVM, only for her modded world to require Java 8 (not an option at present for GraalVM). I was able to link up OpenJDK 8, which came preinstalled. I had to duck back into Windows to disable fastboot so Linux could mount the Windows drive and she can play the same world in either operating system using a symbolic link (shortcut) there. Despite Minecraft only launching around 1 in every 30-50 attempts, we were able to leave her world running “overnight” – which turned out to be only a few minutes after walking away. We found Linux in a mess in the morning. Very little worked, but it all pointed to hard drive failure. It wouldn’t even boot after requiring a forced shutdown. We ended up trying a SATA cable from an old church office computer in our stock – praise God, it cleared up the issue! It still didn’t solve Minecraft from arguing with video drivers:

java: ../nouveau/pushbuf.c:730: nouveau_pushbuf_data: Assertion `kref' failed.

or throwing SIGSEGV errors I haven’t begun to investigate yet.

All this time, I was thinking about how GRUB (Grand Universal Boot Loader) was never able to see Windows, like in the other systems I’ve dual booted. To my dismay, I found PopOS was running in legacy BIOS mode, where Windows was in UEFI mode. The two will never be able to see each other. A reinstall was in order.

PopOS Install 2

Dual booting is no joke if you don’t know what you’re doing. If it were my system, I’d have just taken the hit and accepted the need to select an operating system at the firmware-level. But no, I want an intuitive menu my sister can use. Unfortunately, this meant reinstalling in UEFI mode. To help with that, the folks at r/TechSupport pointed me to Ventoy and instructions on how to set it up with a GPT (General Partition Table for UEFI) instead of an MBR (Master Boot Record for BIOS).

I used my new Ventoy USB to reinstall PopOS, being sure to select the NVIDIA drivers version of the install disk image and choosing the more KDE-native display manager sddm over GDM3 when prompted.

UEFI is a pain to dual boot.

GRUB did not come installed this time. I tried installing grub-efi, but was never able to get it to work correctly, even after installing something for it to /dev/sdX. After much reading, I concluded that a simpler alternative to GRUB may be more suited to this application as the last of my stamina for the week depleted.

Takeaway

I thought this would be a nice, little side project done in a couple hours with a tough issue here or there. WRONG!

Final Question

Have you ever had a project fight you every. step. of. the. way?

I Don’t Want to Use Manjaro Anymore

Good Morning from my Robotics Lab! This is Shadow_8472, and today, I am scoping out Arch Linux for install on a daily driver. Let’s get started.

Majaro done did it this time. With every bad update I get, I’m more keen to listen to the people calling out its mistakes. Recently, an update broke around three pieces of software I use – including one I need for an upcoming project. Let’s spend a week or few installing Arch!

Arch Linux: Pre-Install Impressions

Arch is a major Linux distribution heading a branch of other distributions, similar to Debian or Fedora (of the Red Hat branch). Its userbase has an elitist reputation like the ability to install Arch makes them smarter or something, but I’m sure it’s just for the memes. My understanding going into this project is that Arch Linux is less a “Here is an operating system to install” and more “Here are the components, install what you need. If you don’t know what you need, check the wiki [1]. It’s one of the best.” Thus: people who use arch [by the way] have only proved they know how to follow instructions.

Arch Linux has two primary resources: archlinux.org [2] and wiki.archlinux.org [1]. Additionally, I’m following a tutorial by Learn Linux TV on Arch installation [3]. One afternoon on the Arch Wiki, and I can tell this is looking like a longer project. I’ll be lucky to have my installation media and basic install.

The Arch community is smaller than other distributions, and therefore places a heavier emphasis on users contributing back. Given the more technically inclined user base Arch caters to, it’s a more reasonable of an expectation than it sounds like at first glance.

Choices Before Install

As noted above, Arch is a distribution that highly values customizability. Browsing the wiki turns up a slew of names I’ve seen while troubleshooting. Every little part that can go into an operating system one never thinks of until it’s not working properly is on display here. While I intend to go for a complete desktop environment at this time, I could totally spend months building something truly unique if I had the patience to learn each piece – perhaps starting with a window manager as different from what you typically find on phones and desktops as they are from each other, maybe something that doesn’t use the mouse outside a program. I’m not ready for that though.

One major choice made before even download is if you want to install for a BIOS vs UEFI (or on an encrypted drive). BIOS almost needs no introduction – almost. Some version of the Basic Input Output System can be found on most desktop computers made since around 1980 and on into the new millennium. BIOS runs directly on a computer’s motherboard the moment power turns on. Its job is to start the boot loader, and manage system I/O until shutdown. It has become so ubiquitous that even having grown up around computers, I only recently realized the word is a proper name like “Linux” as opposed to describing its purpose per the term “operating system.”

It’s taken fifty-some-odd years, but BIOS replacement UEFI is the de-facto successor that addresses these limitations. UEFI boots drives beyond 2.2 terabytes, with its limitations on the 2022 scale of the Internet in exabytes. Unconfined to 16 bit operations, UEFI can afford things like a nicer interface with mouse support. Like it for its additional utilities or hate it for being closed source and Internet capable, it’s what most people are stuck with going forward.

Takeaway

Installing Arch is a much larger task than I originally gave it credit for. From what I have seen, it is the distribution I would recommend for people looking to learn how to assemble a Linux system once they are familiar with the command line. I expect this project to take my Linux problem solving skills to the next level.

Final Question

What is the deepest you have gone into your favorite operating system?

Works Cited

[1] wiki.archlinux.org, [Online]. Available: https://wiki.archlinux.org/. [Accessed Oct. 17, 2022].

[2] J. Vinet, A. Griffin, and L. Polyák. archlinux.org, 2002-2022. [Online]. Available: https://archlinux.org/. [Accessed Oct. 17, 2022].

[3] Learn Linux TV, “Arch Linux: Full Installation Guide – A complete tutorial/walkthrough in one video!,” youtube.com,March 31, 2021. [Online]. Available: https://youtu.be/DPLnBPM4DhI. [Accessed Oct. 17, 2022].

I Went From Command Line to Discord Voice on Raspberry Pi

Good Morning from my Robotics Lab! This is Shadow_8472 with a side project of the week. Let’s get started!

Starting From the Basics

I found myself in need of a separate Discord account connected to a voice server this past week. With one account on my main computer and myself unable to use Discord mobile, I chose to work with my Raspberry Pi 400. I downloaded a build of Debian 12 for the Pi, flashed it with balenaEtcher, and it booted to the command line with no Internet access.

I was challenging myself by trying to maintain a conversation while setting things up. As I lacked a free Ethernet connection, that meant working with Wi-Fi. I only got as far as failing to get wpa_supplicant up while only using far fewer tools than were assumed by the tutorials I was using. In the end, I moved a connection over from my main computer temporarily.

Desktop Environment

The MATE desktop environment has been good to me for my old laptop. Once I got it installed on the Pi, even it felt a bit heavy – a note for next time, I suppose. I was able to easily connect to Wi-Fi and restore my desktop’s Ethernet.

Firefox went on next because Discord doesn’t have a client for ARM processors outside the same Android app I cannot use, but the browser version loaded. It didn’t see my USB microphone, and neither did Firefox even after bumbling around with allowing web pages to see my mic. Only then did I find and enable the PulseAudio daemon so Firefox could see my mic and pass it to Discord.

pulseaudio --start

Since I was working quick and sloppy as root, I had to use the following instead:

pulseaudio --system

Takeaway

I can tell my skills are improving. I believe a full Arch install may be in my future.

Note

An interesting problem I keep running into is the system clock. Extreme low-end computers frequently don’t include the circuitry to measure time while power is otherwise off because of monetary cost and circuit board real estate. This week, it meant I had to reboot after connecting to Ethernet, though I could probably have found a way to manually set it.

Final Question

What is the craziest project you’ve ever done starting with a command line?

I look forward hearing your answers on in the comments below or on my Discord server.

I Want to Power On Without the Power Button

Good Morning from my Robotics Lab! This is Shadow_8472 with a side project of the week. Let’s get started!

Booting Without the Power Button

I retired my laptop as a server primarily over a broken load-bearing clip on the screen’s bezel. As I now have to be more careful than I can be in regular use, I want to minimize how often I open or close the lid. The power button is under the lid. A month or so ago, I told it to reboot over Cockpit, a web admin interface, and the web interface remained down. Only this week did I open the lid to the background of my login screen.

Without considering the actual problem, I marched along research for booting with lid closed. Options for this kind of thing are either limited or use different keywords than I think of. My options consolidated into the following: “Wake on LAN,” “Wake on USB,” “Wake on AC.” Wake on LAN allows other computers to power on a device with a special packet. Wake on USB was an option I found for the look-see in my BIOS under a similar name, but its help description implied it was only for when the computer was asleep and would work for a cold boot or perhaps even with Linux.

Wake on AC is an option I have witnessed before and even used without understanding it for a fair booth I once helped with long ago when it was defaulted on for a system. I reached out to multiple places for help with this one, and am still to hear back. No option appears in my BIOS menu, but rumors exist about hidden options or recovery modes. I have been unsuccessful in accessing any such modes so far.

Open Source BIOS Replacements

While it’s easy to think of BIOS as essentially part of the hardware, it’s actually a category of software called firmware, and it can be swapped out like an operating system. On the other hand, open source BIOS alternatives suffer from the same challenges as replacement operating systems for smartphones: every model of motherboard potentially has a tailored BIOS to run it, meaning it can take a while reverse engineer and get working properly.

My I focused my attention on two projects called Coreboot and Libreboot (Libre-boot, not Lib-reboot). Both are open source projects. Coreboot is willing to grab proprietary, closed-source blobs of binary data to increase their availability to enthusiasts. Libreboot’s mission is 100% open source booting at the cost of more extensive work to communicate with different chipsets. Neither project lists my laptop model as supported. On the other hand, I recognized System76 on Coreboot’s list of vendors.

All I wanted was to boot without my power button. Is that too much to ask?

Takeaway

In the end, I worked on the wrong problem this week. I misdiagnosed my symptoms with a valid concern, but even if I pulled it off this week, Cockpit still does not start until I’m logged in, and that’s kind of important when physical access is less than immediate.

Final Question

Have you ever gone off working on an issue you hadn’t actually run into yet?

I look forward hearing your answers on in the comments below or on my Discord server.

I Upgraded My Python Discord Bot (Week5)

Good Morning from my Robotics Lab! This is Shadow_8472 and today, the month of bot development concludes. Be sure to catch the previous posts before reading this one. Let’s get started!

Measures of Progress

Progress this week towards the bot while substantial, wasn’t anything special. In fact, the last day I had to work on it was mostly a flop of me goofing off on other pursuits instead of focusing. Instead, I’d like to focus on what I’ve accomplished over the month.

This longer push on the bot built upon a dice bot I programmed up several months ago that understood how to roll X dice with N sides. Over the month, I achieved multiple personal firsts and worked on my coding style. It was always satisfying when I came up with a new or clever trick to reduce code complexity for a given job. I learned a thing or two about coding the “right” way and practiced with Git version control software.

Memorable Milestones and Personal Firsts

The first big milestone that sticks out in retrospect was rewriting the dice rolling engine from scratch. I will likely want to make another dice bot geared for another game in the future. By splitting out related functions of a larger project into separate files, I can almost trivially re-use the code in another project or re-implement the whole thing. Shorter source files are also much easier to navigate and maintain.

Code condensation is fun. It hurts to see a piece of code you spent all day hacking together (successfully) to be replaced in five minutes by a stupidly more efficient approach, but simpler is easier to maintain. I found myself going through my code more than a few times as I learned about the likes of fstrings and the enumerate function to make sure they were being used when they made more sense than old standards or contextually strayed code, respectively.

This week in particular, I noticed how my relationship with exceptions has changed over the long term. As a beginning programmer in high school, exceptions and tracebacks always meant the existence of a bug. As I became more experienced (one of my early blog projects), I encountered a programming problem where the only way I could solve it was to try/catch an exception. On this project, I have a few places where I reached for try/except almost as though it were an if/else statement. I’ve even made use of Python’s ability to manage different kinds of exceptions with different code blocks in a new feature I worked on this week (but haven’t finished as of writing).

Saving and Loading Data

I have next to zero practical knowledge of writing programs with save data. I was able to bodge a webcam subtitle program involving a second webcam and writing text to a file, but that’s it from before this week.

Fancy dice bots have the ability to store information about players and characters involved in a game. My group don’t strictly need this feature to play, but it is high up on the nice-to-have list. Plus this is a skill I am after; it was just so intimidatingly long to research! Modules like Pickle and Shelve that dump data directly into a file warn in their documentation that clever users can inject arbitrary code through clever wording if the programmer isn’t careful. I started with a module called “configParser,” before realizing this wasn’t exactly its intended use case. It’s close enough though, but it still took a while to gain a mental model of how it operates internally – with an object in RAM, and not directly on the disk. Write the object to essentially a plaintext file, and it can be read back fairly simply. As an important bonus, the saved files are human readable.

Again, saving data to files is perfectly safe. It’s important though to be careful when loading naively stored user-generated data. While researching, I learned about a 15 year-old, trivially exploited vulnerability in the tarfile module that circulated in the news last week. The moral: know what you’re loading, and sanitize incoming data from users or directly from the Internet before saving it.

Takeaway

Sometimes, you need to look at something ten or more times before things start making more sense than not. Programming takes time to learn. One new technique I tried out this week (but wasn’t able to use) is called Ternary Operators. These look like if/else statements nestled into a single line, but they’re more for when you have multiple variations on a single command. My to-do list on this project is quite lengthy as I still need to diagnose why my newest feature collapsed on me. I wish I could end the month with everything in a working state, but such as it is, I have other things I need to work on too.

Final Question

What is your most ambitious personal project to date?

I Upgraded My Python Discord Bot (Week4)

Good Morning from my Robotics Lab! This is Shadow_8472 and today, the month of bot development continues. Be sure to catch the previous posts before reading this one. Let’s get started!

Iteration vs. Recursion

My first major milestone this week was coding a recursive dice tally function to replace the iterative one. Iteration and recursion are two approaches to solving the same types of problems.

The experience of iteration is the more native one to think in. Your program has a path to walk that loops back in on itself as needed. Its downside is that this path can grow beyond the comprehension of the programmer fairly quickly when using in loops within loops within loops if need be. From experience, I found myself guessing more often than not when I was finishing the iterative tally function, and even then I had to teach myself to indent debug text.

To get the idea of recursion, imagine having an army of clones. Each recursion clone has a tiny job, but half that job is working out what it’s supposed to do, and most of the time, that it’s subdividing the problem and summoning one or more clones to work on each one. Recursion has a higher learning curve, but it’s a lot simpler to maintain. I was able to identify and squash a bug involving my pip tally missing secondary pips within seconds to a minute as opposed to fixing the same bug in minutes to an hour and a lot print() statements.

Code Polishing

The more time I spend on this project, the more I discover or rediscover tidier ways to code. It’s not always a hundred lines crunched down into two or three, but it can still feel validating to get a whole chunk of debug code onto a single line I can easily comment out.

In terms of memorable condensations this week, I had two functions –cleanInput() and tokenizeInput() (the later of which underwent around an eighteen:three line reduction last week)– in my dice engine file used for turning raw input into a format my roller can understand. Upon closer inspection, they combined neatly. Later, I solved a bug introduced when adding support for counting dice sets against the total [subtraction] by re-arranging lines of code from tokenizeInput in before lines from cleanInput.

Another thing that’s been bothering me has been the inability to pass off the context from Discord messages to other functions. As far back as the first stint on this bot, I wanted a function so I wouldn’t have to repeat myself in-code when sending a copy of returned messages to the command line. I achieved this with a function that logs, then returns strings I pass it.

print(“Hello World!”)
await ctx.send(“Hello World!”)

becomes

await ctx.send(broadcast(“Hello World!”))

Furthermore, I also played around with the ‘or’ operator. As I began work on implementing more features, of a trio of lines used for grabbing a user’s server nickname – or baring one, a user’s global account name. The way Python works, I was able to use

(ctx.message.author.nick or ctx.message.author.name)

straight in my broadcast liner function.

My general philosophy for this project has been to come up with a creative approach instead of just patching problems as they pop up. The readability of code will go down sharply as efforts to limit the amount of guesswork patching are neglected. As it stands right now with the next section’s features unfinished, I’d say this should be something I can come back to in a few months and make sense of faster than recoding it from scratch.

The Pythonic Way

Change of plan: implementing a save system can wait. While researching save file systems, I happened across an article on askpython.com about so-called “pythonic coding” [1]. Conventions change over time. I’ve noticed this first hand over this project as my style has noticeably drifted as I’ve consulted resources from over the past decade. Looks like I’ll be going through my code again and bringing my code up to standard where I can.

My first task was converting to using fstrings (f-strings – I cannot find anyone saying for sure what the f stands for, but I will be thinking of it as “format” until someone corrects me) when putting variables into strings. It went pretty smoothly, though I did have to be careful about using single vs double quotes when dealing with string data, such as keys in a dictionary. I’m not going for total conversion. If a print statement contains just one string and one variable, I can separate them with a comma. Anything more, and it’s time for fstrings.

The enumerate() function for getting loop indexes was one I’ve read about before, but didn’t appreciate until now. Similar to fstrings, enumerate has its place – specifically anywhere I used pointer variables. Now that I look at my code, my most annoying use of pointers was in that ugly function I’ve already replaced. Nevertheless, I was able to combine a pointer and its supporting code into for-loop statements. Similarly, I employed range() in a while-loop being used for a similar indexing job.

The AskPython article also brought up naming conventions, but I’m putting a hard pass on that one for this project. Variable names are fragile, and only work if they’re all converted at once. I’m not up to that level of potential breakage right now.

Takeaway

Code takes a lot of work to maintain and ensure readability. Add a seemingly innocent feature or consolidate chunks of code that belonged together all along, and you’re liable for something breaking and going unnoticed. I’ve lost track of all the bugs I’ve squashed, but I try to commit it to Git whenever I have a stable version, documenting my progress since my last commit. I still haven’t looked into using its other features yet, but it’s good practice making improved quality commits, and I know that’s worth something, even if it doesn’t feel like it yet.

Final Question

Have you ever taken up [part of] a set of standards for projects, even mid-project?

I look forward hearing your answers on in the comments below or on my Discord server.

Work Cited

[1] pankaj, “Pythonic Way of Writing Code,” [Online]. Available: https://www.askpython.com/python/examples/pythonic-way-of-coding. [Accessed Sept. 19, 2022].

I Upgraded My Python Discord Bot (Week3)

Good Morning from my Robotics Lab! This is Shadow_8472 and today, the development cycle continues on my Discord dice bot. Be sure to catch the last two weeks’ posts before reading this one. Let’s get started!

The Development Cycle

My bot will never truly be “done.” In the past, once software was released, it was typically tied to physical media. New features and bug fixes were either integrated into fresh copies or sold as expansion packs. In more recent times, your license to run a piece of proprietary software is tracked by an online service like Steam, and updates are usually free of charge. When you’re developing a piece of software internally, versions mean less and less until some deadline is reached or it’s “good enough” to stop work for a while.

When I stopped work last week, I was not “good enough.” It was pointed out to me that challenge dice for Star Trek Adventures, the game I’ll be playing, count their challenge pips as normal pips as well. My dice engine actually already supported multiple pip types on the same side naively, so I adjusted the challenge die definition instead of bodging a solution.

Various other improvements behind the scenes included matching the double space from the engine file over in the bot’s main file, making the challenge dice roll command use an icon picture, and implementing the RegEx OR operator for screening input. And then I went to adding or subtracting constants. I must have spent an hour or two trying to shove it through the engine side of things. I lost count at four places they needed special handling along the way from parsing to tallying. Just as I was about to finish, I had the brilliant, but tardy idea to code constants as single-sided, single-valued dice. Another good chunk of coding time summed up in one critical line of code. I was sure to leave a comment.

As part of my little constant episode, I made several changes to the code in lots of hard-to-remember places. Fortunately for me, most or all of my unrelated work was on the bot side of things. Because I split the file between bot and dice engine, I was able to pull up an old copy of the engine from the “production” branch and make the relatively few needed changes.

Takeaway

At this point, I need to plan on finishing the month with this bot. The engine’s code is messy, and I’d rather put it away clean so I don’t have to start over or feel the need to black box it next time I need dice.

Final Question

RegEx gave me a bit of trouble working on it. I used https://regex101.com/ to design my expression, but some of the statements they used threw exceptions in Python. Have you ever had a version mismatch give you a bit of grief?

I Upgraded My Python Discord Bot (Week2)

Good Morning from my Robotics Lab! This is Shadow_8472 and today, I am adding some features to my Discord dice bot. Be sure to catch last week’s post before reading this one. Let’s get started!

My Golden Standard

Dice come in many forms. Outside of specialty die collecting, the hobby of role play games will tend to land you with the widest variety to determine success/failure of fictional characters as their real-world players throw them into the hands of the equally fictional Random Number God (RNG*). Most people are familiar with cubic dice with faces valued one to six, but both the shape (read: number of sides) and the faces can be changed.

The role play system Gensys and its Star Wars themed ancestors go so far as to use as many as three types of pips on their narrative dice – it’s even possible to get both a “success” and “advantage” from the same face! There exists a dice roller by SkyJedi on GitHub for this system, but I would like a bot I can look at and understand. It serves as my gold standard, but I can settle for bronze.

*(officially RNG means Random Number Generator)

About My Bot

This bot constitutes my first major project where I have a discrete engine I will likely re-use later, so I’ve done my best to keep the engine clean at the expense of no time to redo the main bot’s .py file. The biggest question I had to ask myself over and over again was this: Engine or implementation? Is this feature specific to this function, or does it belong in the engine? I defined my engine’s role to begin after input has been screened, and lasting until it’s returned the structured results. I also included a separate tally function for summing the results.

Part way through testing, one of my friends tried subtracting one term from another. I had to re-write a good chunk of the otherwise mostly working engine, but I came out with a product that can pass common mathematical operators without choking.

I finished this week with a presentable bot. I didn’t get all the features I was after, but it will work for my upcoming Star Trek themed game. My main must-have feature is a set of “challenge dice” with the faces 1, 2, 0, 0, C, C. Multiple pip types was an important feature on this engine

Tricks Learned Along the Way

In no particular order, I taught myself a trick or two.

Space-indented comments:
Debugging is all about wall of text. At one point, I had a function with a triple for-loop to split input strings into tokens another function could evaluate one at a time. Six hours I bickered with it until success. That victory is in part thanks to my idea to indent debug messages based on how many nested loops each one was in. On my way to a break, inspiration hit and within five minutes, I had replaced the whole thing with only three lines of code.

When to Spaghetti Code:
Programming is an art form. Just as sketch work is drawn/painted over, so too are new features written quickly and sloppily, made to work, added to, tweaked, extended, and eventually depreciated as early code is replaced by a more elegant solution. Messy code is hard to develop, but a little more isn’t going to ruin your day if it’s that little bit more to round off a major version before a deadline. As you code, you will pick up better ways to do things, and you will want to go over your old code as you are able.

Clean Your Code Regularly:
I don’t know why I need to remind myself this, but I have a hard time deleting massive code blocks once a functional replacement has been coded. It feels good being able to revert quickly, but I’m working over SSH in a terminal window, and scrolling through uncollapsible blocks of code all the time isn’t fun. My advice is to comment out the old code being removed and make sure your program still works before removing it all together and verifying that it still works. The same goes for massive chunks of debug code built up over a long debugging session. If a whole file needs a major quality bump, I found it helpful to make a big block of comment I can move functions above as I perfect them.

Git Is a Tool to Practice:
I am using Git locally on this project. Right now, my skill level is git add and git commit. Meaningful comments will come with time as will checking out a previous version will come with time. I’m not working with an online repository, so I don’t need to worry about push or pull, though I am aware of them. In the meantime, I keep a special place for my most recent stable version.

The Development Cycle Loops:
The development cycle doesn’t end with release. Early versions will be flawed. Even now, I’m considering using those picture icons to the dice output. Always a new feature. Support code can take even longer to wrestle into existence if the clean implementation re-writes half the engine.

Takeaway

I would like to stress that I’m finding it difficult to write about writing code. Tangible progress is often non-linear. There are a lot more options than when you’re working with someone else’s program. In some ways, writing a program is more like writing a story than wrestling a Windows game into working on Linux. Once you’ve figured out the interface to set up your canvass, you are in full command of the ideas you express.

Final Question

What do you think of this “Lessons Learned” format?

I Upgraded My Python Discord Bot

Good Morning from my Robotics Lab! This is Shadow_8472 and today, I am tailoring my simple Discord dice bot for an upcoming role play. Let’s get started!

Project History

A while back, I built a very simple dice bot for Discord [1]. In its current form, it can be used for rolling an integer number of dice with another integer number of sides (3d6, for example) provided at runtime. A lot of effort also went into learning the Buildah/Podman OCI container implementation so I could clean up afterwords if something got messy. In the end, I managed a container with a mounted volume I could reprogram on the fly without entering the container.

Containerization with Podman/Cockpit has been treating me very kindly. This week, I was able to add environment variables on container creation, allowing me to work a bot token and branch label into the container itself. I also created separate development/production branches for short-term testing and long-term operation respectively, though in effect, I’ll also be keeping an old version around to act as a “stable” branch which will have its code integrated into the container itself instead of relying on an attached volume.

During this week’s work, I figured out how to test code segments directly in the interpreter. I also played around with separating core functions out of the main .py program file, and found they imported cleanly into the live interpreter. As a result, my debugging efficiency improved quite a bit.

Total Rewrite

There is a meme out there where a programmer can write a program such that only he and God know how it works – after a time, only God will know. A good programmer will return to such a problem with ideas for a more elegant solution, though it usually means rewriting from scratch. The core dice rolling functions for my first dice bot were hacked together and barely able to roll an arbitrary set of XdN dice where X in the number of dice and N is the number of sides.

This time, however, I’m programming for a game with non-standard dice faces. No way was I going to shove that into my old bot core. Instead, I spent around eight to ten hours crafting a new monstrosity I can reuse for other bots in the future and handles multiple types of die pips on a side at once. I focused on hacking it into my existing bot code (which I have yet to fully decipher), but it wasn’t so bad. What I do know is that I obsoleted several bits of code and about half as many comments intended for future work on that ugly line of development.

My new functions begin with the assumption that N can be defined as a list of sides, which in-turn list their respective kinds/counts of pips. For when N is int type (integer), I have some code to build a die face-by-face in that format. All the dice are loaded into a list, and that list is passed off to another function to actually roll the dice and tally up the results.

Worth noting is that I’m starting to make git commits to savestate my progress. I’m not worrying about proper form right now, but I’m counting on improving over time.

Settings Files

The ability to save/load data –while not strictly needed for a simple dice bot– is an important skill to develop. My brief research showed that while there’s any number of ways a Python programmer may implement settings, a somewhat standardized and end-user friendly method is using .ini files. While I may not use them this week in this project, I will want to remember this side goal. I’ve invented my own scheme before, and it wasn’t fun.

Takeaway

It’s really difficult to communicate all the little challenges that come up without looking/feeling like an idiot half the time because I missed something and another half because of the jargon. I’d have to say most of the time I spend coding is trying to understand what I just wrote. I still haven’t completed all the features I need, so the plan is to cover the rest of this revamp in next week’s post.

Final Question

What were you working on the first time you successfully extracted a part of your program into a separate document?

Works Cited

[1] Shadow_8472, “My Discord Bot Understands Strange Dice,” Feb. 28, 2022. letsbuildroboticswithshadow8472, [Online]. Available: https://letsbuildroboticswithshadow8472.com/index.php/2022/02/28/my-discord-bot-understands-strange-dice/ [Accessed Aug. 29, 2022].

I Archived Two Old Hard Disks

Good Morning from my Robotics Lab! This is Shadow_8472 with a side project of the week. Let’s get started!

Who doesn’t have a few hard drives from previous computers laying around? Not my family anyway. The first one I dealt with is a Quantum Fireball KX with my father’s name written on it. More importantly: it uses a legacy PATA connection for data, and with the transition away from SATA to M.2 well underway, the time for preservation is now.

My early attempts revolved around a PCI card for a PATA adapter. Long story short: I was never able to boot with the Fireball hooked into my system. I tried different combinations on the jumper pins along with position on the cable. I was never able to access the BIOS. All I got was a freeze mid-power-on-beep or a failed attempt to boot to the hard disk after hearing it spinning up. I verified the card and cable by testing them with CD/DVD reader/burners also from the PATA era.

Aware that the Fireball might be burned out, we ordered a multi-adapter so I could connect it over USB – without having to fight for the BIOS. It mounted right up. I used rsync to dump the contents to GoldenOakLibry, my family’s network storage. Along the way, I came across devhints.io [1]. It looks like an amazing resource. It helped me out wrangling rsync quickly. It has one of the highly exclusive places in my bookmarks list. My only complaint is how interesting Mr. Cruz made his site to cite. Most importantly, I wrote out a sticky note about when and where I dumped the drive.

The second drive (branded Deskstar, SATA connector) took way too long. I was the fool for putting it over Wi-Fi, and I paid for it. Several times, rsync would appear to stall as it got to a larger file. A couple such times, I figured the drive was overheating due to no circulation so I stopped rsync, powered it off, and let it cool down. The breakthrough was pulling up a utility to show my network data.

There was a rather important incident I feel inclined to report before wrapping up. At one point, I accidentally caught a cord connected to the adapter. The drive tumbled off my desk, but I barely managed to catch it after a fumble or two. My worst fear was that of a “head crash,” where the read-write head contacts the spinning platter, leaving a scratch and destroying the data on it. If anything, the slow Wi-Fi speed worked in my favor, because the head was off where it won’t do any harm during an impact.

Takeaway

Data preservation is a chore. In retrospect, I should have performed this procedure exclusively over a wired connection – I should have investigated the possibility of mounting it to GoldenOakLibry directly.

Final Question

What kinds of “digital chores” turned out more memorable than you’d have cared for?

I look forward hearing your answers on in the comments below or on my Discord server.

Work Cited

[1] R. Cruz “Rsync cheatsheet”devhints.io, [Online]. Available:https://devhints.io/rsync [Accessed: Aug 22, 2022].