<?xml version="1.0" encoding="UTF-8" ?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Felix' Ramblings</title>
<subtitle>Somewhat random ramblings and personal updates.</subtitle>
<link href="https://p4m.dev/atom.xml" rel="self" />
<link href="https://p4m.dev" />
<updated>2026-04-26T12:31:48Z</updated>
<id>https://p4m.dev</id>
<author>
<name>Felix</name>
</author>
<entry>
<title>Another Quick Update &amp; Vent</title>
<link rel="alternate" href="https://p4m.dev/posts/34/" />
<updated>2026-03-24T00:00:00Z</updated>
<id>https://p4m.dev/posts/34/</id>
<content type="html">
<![CDATA[<p>
It's only Tuesday evening, but boy this is already a busy week! 
I am in the progress of making some (minor) changes to the site:
</p>
<p>
First of all, I have added separate "Other" page to the top-bar, which contains a contact mail (hopefully in a format which will not flood my inbox with bot messages). When I first created this website, I just wanted to have my own little corner of the Internet where I can upload stuff. 
It sounds weird, but I didn't actually expect anyone to actually read any of my stuff "proactively". This is my way of getting things "out of my system", doing some reflection and having a place I can point my friends to if they are asking about some of the stuff I did.
</p>
<p>
I didn't expect anyone to randomly stumble on this website on their own. 
So I thought if I had my mail listed I would, at most, get spam messages by crawling bots.
To my surprise, not only do people in-fact (somehow) stumble on my website(s), but some also
go out of their way to write me a nice message, even if I don't have any contact information listed anywhere.
Now I'm starting to feel bad that people spend unnecessary effort to reach me, so hopefully that will make things a little bit easier.
</p>
<p>
All that being said, imagine my surprise when I saw that my 10 month old schizo-rant got posted on <a href="https://news.ycombinator.com/item?id=47478298">Hackernews</a> and <a href="https://lobste.rs/s/gwp3b9/i_hate_programming_wayland_applications">Lobste.rs</a>, which resulted in a total of <b>>200 comments</b>. I have no idea who posted my shit to these platforms and how they stumbled upon it in the first place.
I certainly didn't expect anyone to seriously engage with a wall of text written by me.
From what I can tell, I managed to basically get responses covering a wide range from "I agree" to "you are part of the problem" <a href="#note-0" id="back-0">[0]</a>. I still stand by what I said, but it's very interesting to see the various takes and responses nonetheless.
</p>
<p>
This made me wonder whether I should have an "about me" section on my site as well. 
To be clear, I don't think I'm a particularly interesting person (I'm interesting in the same way that car crashes are interesting), but I feel like I mislead some of these commenters. 
Or to put it differently: I'm not sure people would spend the same amount of effort responding to my ramblings if they knew that the author is some 25 year old dumb fuck with barely any professional experience (which, of course, doesn't stop me from having strong opinions) <a href="#note-1" id="back-1">[1]</a>. 
Funnily enough, when I initially created this website (not sure if it was already "public" or just during the prototype stage), I already had an "about" page, which I decided to remove later (because if I point my friends to the website, they don't need an about page). 
At least that made it easy to add a page like that back, so maybe I will extend that page in the future.
</p>
<p>
I did get a request about supporting Atom / RSS feeds (again, did not expect that, blah blah) - I will work on that and place it in the "Other"-page later.
Today I got sidetracked by my system first crashing, and then completely refusing to boot.
To keep a long story short (I did not want to spend my freetime with this, but here we are): 
<ul style="list-style-type:'- '"><li> The mainboard had a debugging "CPU"-LED lit up (next to "RAM", "VGA", etc).</li><li> I got scared that I somehow fried my CPU (really not a good time to buy PC parts right now)</li><li> Cleared CMOS </li><li> Same problem</li><li> Flashed my BIOS (which my mainboard supports even without a working CPU)</li><li> Same problem</li><li> Turns out one of my RAM-sticks is fucked, the other three sticks are working fine (I upgraded from 2x8GB to 4x8GB)</li><li> Obviously my BIOS settings are gone, including the EFI-entry pointing to my partition, meaning I still cannot boot</li><li> Looking shit up, apparently you can open an EFI Shell from the BIOS and load the bootloader manually</li><li> Entering my decryption key errors out because I still had to disable secure boot</li>
</ul>
</p>
<p>
I could have saved myself a bunch of time if the RAM-LED lit up instead of the CPU-LED. Unlucky.
A faulty RAM-stick in this economy is also unfortunate (especially because I have to drop a second stick to get 
dual channel memory to work now), but at least I still have full performance with 16GB of RAM. 
</p>
<p>
It's getting way too late, so I will end this post here. 
</p>
<p>
<img src="./meme.png" style="width:500px;height:432px;" />
</p>
]]></content>
</entry>
<entry>
<title>Fuck Every Single Microsoft Product</title>
<link rel="alternate" href="https://p4m.dev/posts/33/" />
<updated>2026-03-08T00:00:00Z</updated>
<id>https://p4m.dev/posts/33/</id>
<content type="html">
<![CDATA[<p>
Theme Song for my day (taken from <a href="https://www.youtube.com/watch?v=QYnAGzzRKeI">here</a>):
<audio controls="controls" preload="none">
<source src="./LifeIsBeautiful.mp3" type="audio/mp3" />
</audio></p>
<p>
<ul style="list-style-type:'- '"><li> Family uses outlook calendar for events</li><li> Fix phone not syncing the events properly (phone setting randomly turned itself off 5 menus deep, very cool)</li><li> Problem: I'm not using my phone much, but it's my primary source for these events / schedule</li><li> I can check the outlook web view, but the website is so clunky and slow that I want to keep this to a minimum (and therefore am still using my phone)</li><li> Idea: I bet there's a calendar API. Doing a piss-simple calendar viewer for these events could be a fun small project, doesn't have to be anything fancy.</li><li> "Hardest part is probably doing the event querying from the account, but it can't be that annoying"</li><li> If only you knew</li><li> Search for "outlook calendar API" </li><li> Get large microsoft article</li><li> "Here's 5 reasons why you should integrate the calendar into your app"</li><li> ??? Just give me the API</li><li> "API reference"<ul style="list-style-type:'- '"><li> "Outlook calendar API in Microsoft Graph v1.0"</li><li> "Outlook calendar API in Microsoft Graph beta"</li>
</ul>
</li><li> What the fuck is Microsoft Graph</li><li> "Microsoft Graph is a Microsoft API developer platform that connects multiple services and devices."</li><li> ??? I don't care, just give me the endpoints</li><li> Endpoint "List calendars"</li><li> Requires authentication (duh), "Here's the basics:"</li><li> "Microsoft Graph is a protected API gateway for accessing data in Microsoft cloud services like Microsoft Entra ID and Microsoft 365"</li><li> ??? </li><li> More searching</li><li> Need to go to Microsoft Azure and add a Entra ID project</li><li> "Login using Microsoft Account"</li><li> Enter E-Mail</li><li> Asks me to either enter my password or some secondary mail to get a login code</li><li> Secondary mail is a very old one of mine which is full of spam mail</li><li> I should probably change this</li><li> Login</li><li> Go into microsoft accounts</li><li> Go into settings</li><li> I cannot find shit</li><li> I can find a place to add secondary mails,</li><li> I can find a place to adjust my phone number,</li><li> but it's still using my very old mail account for the code thingy</li><li> go to search engine</li><li> It's in some weird submenu </li><li> okay fixed that, back to the azure thing</li><li> Now logged in using Microsoft Account</li><li> Get Error Popup</li><li> Something about my account not being authenticated properly, recommending to re-login</li><li> ???</li><li> Close</li><li> Get same Error Popup</li><li> Okay, logout</li><li> Now on azure homepage</li><li> Press login</li><li> Use microsoft credentials</li><li> Can't login, get some error with JSON IDs and other bullshit</li><li> did I just brick my account</li><li> change page</li><li> go to outlook</li><li> try to login</li><li> login works fine, legacy mail is no longer used, everything good</li><li> ???</li><li> go to azure site</li><li> Now logged in </li><li> bruh</li><li> Get same fucking error popup on the page I mentioned before</li><li> close popup</li><li> get the same popup</li><li> close popup</li><li> repeat to a total of five times</li><li> click on button to create Entra ID project (do you remember I was trying to do a thing)</li><li> new page</li><li> same five popups</li><li> my brother in christ</li><li> Confirm creation</li><li> Get another error, could not be created, looks similar to error popups</li><li> Back to the search engine</li><li> Apparently it's a common issue</li><li> fun fact: this is a multi-billion dollar company</li><li> Solution is to create a proper azure billing plan, even if you just use the free version</li><li> back to azure</li><li> error popup</li><li> this is not good for my health</li><li> logout</li><li> Start billing plan</li><li> Do some reading, free plan / "pay as you use" is fine, the API I use should be free anyways</li><li> Login using microsoft account</li><li> Actually works this time</li><li> Asks me for my credit card</li><li> okay maybe reasonable due to API abuse and whatnot, fine</li><li> enter my credentials</li><li> I am back at the azure page</li><li> Create Entra ID project (do you remember this)</li><li> Do the usual setup shit:<ul style="list-style-type:'- '"><li> Create app</li><li> Create secret</li><li> Add permissions</li><li> yada yada</li>
</ul>
</li><li> Okay, go back to the old browser tabs, where was the endpoint I needed</li><li> Not quite sure I'm setting up everything correctly, try to find some examples instead</li><li> Microsoft provides example code, good</li><li> It's a Visual Studio solution, unlucky</li><li> scrap that, back to search engine, looking for basic ass curl commands</li><li> Find examples</li><li> Need to create token first, blah blah blah</li><li> Run example curl request</li><li> get token</li><li> Use token to run another example request</li><li> Permission denied</li><li> deep breaths</li><li> more experiments and more googling</li><li> turns out my permissions were wrong</li><li> they were only valid for user authenticated requests, and not my token requests</li><li> ??? okay I guess</li><li> try again</li><li> new token, new me</li><li> example request also works now</li><li> cool</li><li> change to calendar end-point, make request</li><li> no response</li><li> ???</li><li> look at verbose output of curl</li><li> request sent successfully, literally no json response from server</li><li> ????????</li><li> more googling</li><li> To get access to the calendar end-point, you need to have a 365 subscription</li><li> This is the account which uses that calendar, I am part of the 365 subscription</li><li> Look at azure subscriptions</li><li> It's not listed</li><li> ??????????????</li><li> Something something my azure shit needs authentication from the subscription admin</li>
</ul>
</p>
<p>
<img src="./DogRagebait.png" />
</p>
<p>
I think I'm good.
</p>
]]></content>
</entry>
<entry>
<title>Failing To Structure My Thoughts On The Game "Life Tastes Like Cardboard"</title>
<link rel="alternate" href="https://p4m.dev/posts/32/" />
<updated>2025-11-21T00:00:00Z</updated>
<id>https://p4m.dev/posts/32/</id>
<content type="html">
<![CDATA[<p>
Quick warnings/notes upfront:
<ul style="list-style-type:'- '"><li> Heavy spoilers. The game is <b>entirely free</b> on either <a href="https://store.steampowered.com/app/1114090/Life_Tastes_Like_Cardboard/">Steam</a> or <a href="https://demensa.itch.io/life-tastes-like-cardboard">Itch</a>.</li><li> The game (and thus this post) contains unfun themes such as depression and suicide.</li><li> All of my notes &amp; thoughts are mostly unstructured. I have been thinking about this game for a bit and just need to get things out of my system.</li><li> I have extended my website generator to embed some music tracks from the game onto this page.
You can find the entire soundtrack of the game <a href="https://demensa.bandcamp.com/album/life-tastes-like-cardboard-soundtrack">on BandCamp</a>, for free.</li>
</ul>
</p>
<h1>
 Before The Game</h1>
<p>
<audio controls="controls" preload="none">
<source src="./00_ClassII.ogg" type="audio/ogg" />
</audio></p>
<p>
I don't know where to start. 
Since playing the game, I have a bunch of thoughts loosely flying around in my head. 
I'm sitting in my room, at the beginning of a small vacation from work, trying to process this game I finished a a few days ago.
Let me start with some harmless stuff.
</p>
<p>
The game has been on my list of games to play for over 5 years. 
The only reason why I didn't play it earlier was because I had troubles getting the game to run on linux.
I was browsing my Steam library, saw the game, looked up if anyone got it to working since then, and yeah - nowadays 
the game runs okay-ish on linux out-of-box, and with some tweaks, it supposedly "fully works"; or rather
it doesn't run any worse than on windows.
</p>
<p>
I don't even remember where I initially heard of game at this point.
I only vaguely recall reading some high praise for this niche game. 
The steam page doesn't exactly scream "high quality":
<ul style="list-style-type:'- '"><li> You have a pretty bland game banner on the top right</li><li> the game trailer looks like it's made in windows movie maker</li><li> the screenshots look like scribblings done in paint, matching the game description "This is my first game."</li>
</ul>
</p>
<p>
<img src="./00.png" style="width:500px;height:462px;" />
</p>
<p>
The description "I'm sorry for making this" as well as the combination of 
"deals with topics such as suicide, self-harm and mental illness" with "It's about myself mostly" did peak my interest though.
And given that it's free, I added it to my account.
</p>
<p>
In hindsight after finishing the game, I feel kind of lucky that I only played it now, and not 5 years ago.
I'm sure the game would have hit differently, but life changed a lot since then, and right now, this seems like
quite the fitting point in my life (although I'm wondering how I would have reacted to the game back then).
</p>
<h1>
 A Horrible Introduction To The Game</h1>
<p>
<audio controls="controls" preload="none">
<source src="./01_Jon.ogg" type="audio/ogg" />
</audio></p>
<p>
It's not really a "game" in the traditional sense / this game falls into the category of 
"walking simulators". 
The game is a 2D game where you (mostly) control the character "Jon". 
The developer's description of the game is quite fitting:
<figure>
 "You walk around and press the 'interact' button."
</figure>
</p>
<p>
You get a lot of text. You can easily spend 3-5 hours on your playthrough.
As such (and probably even more so than elsewhere), from a game mechanics 
point of view, this game is not very interesting, or even "good" for that matter.
Some sections feel way too long, stretched out, a chore to complete. 
</p>
<p>
Let me show you some parts of the beginning of the game. 
You wake up, and you can scroll through two small screens of Jon's apartment. 
The "dialogue" at this point consists of Jon's thoughts. 
You leave your apartment, take the bus to the university, sit down for the lecture without being able to interact with anyone.
Then you take another bus home. And the cycle repeats the next day.
So far, it's very easy to believe that this is Jon's life, and by extension, the life of the developer.
</p>
<p>
<img src="./01.png" style="width:500px;height:134px;" />
</p>
<p>
This is a very gentle introduction, and it quickly transitions to becoming abstract for the entirety of the game.
As the cycle continues, the few environments of Jon's life merge together, with your only choice being to navigate
a weird, broken, combined space of various things.
After Jon refusing to leave the apartment, we get the title card "Life Tastes Like Cardboard".
</p>
<p>
We enter room containing a cardboard cutout. We get to revisit this room a lot of times throughout the game:
We can find (entirely optional) objects, which remind Jon of some random memory.
In that room after finding such an object, you can sit down and "talk" to the cardboard cutout 
(or rather: Jon will sit down and talk to himself about his memory regarding the object you found).
The cardboard cutout only ever says "Hello, my name is Rem. I am very good at listening.". 
</p>
<p>
Shortly after, Jon gets to know the only other re-occuring character in the game: Ollie.
From there on out, we will walk through various abstract places, occasionally meeting up with Ollie and talking about 
random things.
</p>
<p>
<img src="./02.png" style="width:500px;height:120px;" />
</p>
<p>
I'm not a good game reviewer. I cannot do this game justice by just listing the various scenarios which occur throughout the game.
However, I do want to show you a random selection of environments in the game. 
It really feels like a rollercoaster: Some feel cheap and broken. Some feel broken on purpose. 
Some look really good.
</p>
<p>
Same goes for the game contents. To list a few:
<ul style="list-style-type:'- '"><li> You wander through a maze which is way too long and not filled with interesting things.</li><li> Jon and Ollie sometimes literally (mockingly) discuss artistic interpretations of some environments they are in. </li><li> Some places are barren. </li><li> Some places have a bunch of random, not worth mentioning things in them.</li><li> Jon is told that they are in a dream at one point</li><li> You move over to a dreamt up place by Ollie. You are invited to a place where Ollie lives.</li><li> We briefly get to play as Ollie, being invited over to Jon's place, drawn entirely in a different artstyle.</li><li> We get to explore Jon's desktop (including his browser history), which includes plans and sketches of the game itself.</li><li> We get to explore corrupted places, places which warp.</li><li> We get to explore places with glaringly obvious symbolism.</li><li> We get to read diary entries of Jon.</li>
</ul>
</p>
<p>
<img src="./03.png" style="width:500px;height:205px;" />
</p>
<h1>
 Are Games Supposed To Be Fun?</h1>
<p>
<audio controls="controls" preload="none">
<source src="./03_Ollie.ogg" type="audio/ogg" />
</audio></p>
<p>
I'm not a very artsy guy. I cannot articulate well why I like certain things.
I avoid most music with lyrics in them, and for most songs I cannot even tell you
what people are singing about, even if I like the track.
I don't really care about poems, and 
I'm not the guy to deeply analyze media (even when forced to, I always struggled in school in that regard).
</p>
<p>
For games, I usually exclusively enjoy game mechanics.
<ul style="list-style-type:'- '"><li> I enjoy playing Rocket League or Risk Of Rain with friends</li><li> I like roguelikes like The Binding Of Isaac</li><li> I like challenges like climbing mountains in PEAK</li><li> I enjoy solving puzzles in The Witness</li>
</ul>
</p>
<p>
This game feels different. It's not some story written to "hook you", to make you ponder life - or at least, it doesn't feel like that.
This doesn't feel like an art-project to me either. It's not some abstract space designed to the player.
And most importantly, to me, this doesn't feel like a story about Jon.
</p>
<p>
This feels like the story of the developer.
"It's about myself mostly" and "I'm sorry for making this" doesn't feel like some marketing bullshit. 
The game, including the art and including the music, was made by one person. 
The entirety of the game feels very personal. You get to see Jon being vulnerable.
Showing emotions, his dark points in life, him just generally feeling miserable.
</p>
<p>
I cannot describe this in another way; the game just hits differently.
There were sections of the game were I thought the gameplay was bad. 
There are bugs, and I didn't bother exploring everything either. 
But I felt intrigued to listen to their story, and even if I know that plenty of people 
have put their heart/soul into projects of theirs, this game felt personal 
like none other. Like there is a layer between most projects/games and their makers,
which is absent here.
</p>
<h1>
 Dark Places And More Pondering</h1>
<p>
<audio controls="controls" preload="none">
<source src="./06_Maze.ogg" type="audio/ogg" />
</audio></p>
<p>
Despite what I wrote above, the game does, in a classic fashion, "ramp up" over time,
even if the ramp looks more like a rollercoaster.
</p>
<p>
You have the "close to reality" start of the game, including a breakdown causing Jon to stay at home.
You get a text-adventure-ish part of the game, where you are essentially locked up in your home,
unable to do anything, stuck with the same set of menu options until you finally get the option to
"curl up on the floor".
</p>
<p>
You explore a world with some hazy like figures, until you reach a point where your (2D-)perspective is flipped, 
and you get to see the world from the previously unseen side: The hazy figures show their ugly faces.
Comfortable places become haunting and alienating.
</p>
<p>
Whenever you are with Ollie, the game seems peaceful, or the horrors seem managable.
Everytime you leave Ollie, it feels like the Jon is spiraling down, hard.
</p>
<p>
I'm having a hard time putting my feelings in regards to the end of the game into words.
I kind of just end up describing what happens in the game, which is not the point I'm trying to make.
When I first finished the game, I interpreted the end as the protagonist killing themselves.
In fact, after I finished the game, I looked up the developer for signs of life because I
felt like I just played through a suicide note <a href="#note-0" id="back-0">[0]</a>.
</p>
<p>
<img src="./05.png" style="width:500px;height:400px;" />
</p>
<p>
The day after, I looked up some reviews / video essays on the game.
For example, I enjoyed <a href="https://youtu.be/Zu6cQ5xgoRY">this video essay</a>.
They interpreted the ending in an entirely different way (which I don't dislike!). 
But this also caused me to realize that, when playing the game, I saw the world through my own lense (if that makes sense).
Let me elaborate:
</p>
<p>
When I played through the game, I didn't realize how much of a help Ollie is to Jon. 
Of course I was aware of the shared moments, of the times where Jon shows his vulnerable side. 
But I just didn't realize that it was Ollie who helped Jon climb out of the hole each time.
Or to formulate it differently: If Ollie didn't turn up, how would Jon's story look like?
My gut tells me that it wouldn't be too different, but I know that this is wrong.
I am confronted by the fact that I'm fucking projecting myself onto this game.
</p>
<p>
This lines up nicely with a struggle I have had for the last couple of years:
I tried finding some (digital) community in which I feel comfortable, where I want to socialize with
others, etc. Gotta say, so far, this has not worked out at all. 
I don't like the common social media platforms (facebook, instagram, ...). 
Reddit is fine for browsing stuff, but I have no desire to participate.
I tried looking at some Discord-servers, but I haven't found any which I deemed interesting enough to stay in.
I gave imageboards a shot, but they even the more obscure ones are often incredibly toxic (or not that interesting).
I joined a few Discord-servers of twitch streams I lurked in, and again, 
the discussions were just totally not aligned with my interests 
(at least for the servers which had a bunch of active members in them). 
Seems like "communities" really just aren't a thing for me and I'm working better with just small groups of people.
(Although befriending new people has been pretty hit or miss so far).
</p>
<p>
<img src="./07.png" style="width:500px;height:343px;" />
</p>
<p>
Compared to Jon, I'm glad that I am (at most) alone, but don't feel lonely. 
I didn't really had that sense of "loss" when friendships ended or drifted apart, when I decided to leave 
communities or isolate myself further from other people. 
Probably helps a lot that my hermit life stems from a feeling alienation / desinterest on my end, 
instead of rejections coming from others.
</p>
<h1>
 It's A Good Game</h1>
<p>
<audio controls="controls" preload="none">
<source src="./05_End.ogg" type="audio/ogg" />
</audio></p>
<p>
Even after all of the rambling above, I'm still having troubles putting my thoughts and feelings into words. 
After work, after other programming projects other video games, my mind keeps wandering back to the game (and especially the music).
Even though I interpret the game as a pretty brutal experience of depression and self-destructive thoughts / actions,
I don't get in a bad mood when thinking about that game. 
I think it's just making me appreciate all the various aspects of my life which I take for granted. 
I wonder, if I were Jon at the start of the game, how would the game play out? 
</p>
<p>
This might also be the first time where I'm truly appreciating an artistic work 
of personal self-expression, without the arstist being some close friend of mine.
And I can't even say why: I don't know why. I don't know what makes this game feel so special to me.
As I said in the beginning, I'm fully aware that other people have poured 
their hearts and souls into projects of theirs, but I cannot think of other projects
of any kind which have had this impact on me.
</p>
<p>
Maybe at the age of 25, I finally learned to have some empathy with people I don't know?
I keep digging through my brain, asking myself questions
whether there is some unique aspect which I super relate to but am to embarrassed to admit.
I just don't know. 
</p>
<p>
With the exception of The Witness, I can't recall another game where
I thought about it afterwards for a longer period, even 
if I would say that I enjoyed the actual gameplay of it far more.
I only played this game for 3-4 hours, that's not even that long.
</p>
<p>
I feel like I should explore experiences like this more (for myself).
No idea how I can do that, but I feel like I'm missing out if I don't.
</p>
<p>
<img src="./06.png" style="width:500px;height:342px;" />
</p>
]]></content>
</entry>
<entry>
<title>An Update on Various Things #2</title>
<link rel="alternate" href="https://p4m.dev/posts/31/" />
<updated>2025-10-25T00:00:00Z</updated>
<id>https://p4m.dev/posts/31/</id>
<content type="html">
<![CDATA[<p>
Quick rundown on my living situation:
<ul style="list-style-type:'- '"><li> Still living with my parents. Not too proud of that as a 25 year old guy, but 
at least I'm able to build up my savings I suppose.</li><li> Making some good progress on losing weight, still got ways to go though.</li><li> Still working my 40h full-remote job. Comfy, but lots of stuff to do.</li><li> Progress on personal projects has been kind of random, but progress has been made nonetheless.</li><li> I'm isolating myself more and taken the opportunity to reflect on things.</li><li> I found out a few people of the internet have somehow stumbled upon my websites.</li><li> I got myself a very fancy piano! Now I just need to be able to play it.</li>
</ul>
Okay, now a bit more in-depth:
</p>
<p>
I have been in a bit of a Hermit Mode recently (or at least by my own metric). 
Still talking to friends every now and then, and I haven't turned down any invites 
from people I haven't talked to in a while, but I have been more passive than usual
and just kind of enjoyed having quiet weekends. No idea how this will develop in the long-term;
guess I will find out.
</p>
<p>
In regards to personal projects: okay-ish. I often feel like I'm rotating around the same three hobbies
of mine (guitar/piano, programming, gaming), while socializing with people wants me to "recharge my batteries"
and not do anything for a bit.
When it comes to my programming projects, my own stuff has been a bit on-hold. 
I experimented with replacing git with my own <b>very</b> simple version control system. Proof-of-concept went fine,
but when it actually came to polishing a few things and finalizing some ideas, I kind of just lost my momentum.
I have streamed a few hours of my development on twitch, but that hasn't been going on either. 
I just don't feel like having (even the smallest of) a spotlight on me I guess.
</p>
<p>
I am helping some acquaintance out with his game project though. Nothing major from end; just small bug-fixes,
simple additions, and little development tools. That has been fun, and it's nice that I'm making at least 
some progress on some project.
</p>
<p>
During these quiet days, I realized that my backup-situation is kind of ass. 
I used to have proper backups, but I kind of slacked off big time on this front.
In the long run, it probably makes sense investing some money into a small NAS computer or something, 
but I haven't found the motivation to read into hardware/software solutions to this.
Besides, my room is messy enough as is - maybe when I move out (who the fuck knows when).
</p>
<p>
At the very least, I have created a remote backup of my shit which seems to be easy enough to keep up-to-date.
Previously, backing up my files involved running <code>rsync</code> with a lot of cryptic arguments I setup once, which
just uploades my files as-is on some other local machine. With the remote machine I'm renting, 
I'm using a <code>borg</code>-frontend which simplifies stuff <b>a lot</b>. This also supports encryption,
so I feel comfortable using a rented remote server for this. 
If you want to know more about this solution, I just spend some time 
<a href="https://howthefu.cc/posts/17/index.html">writing my shit up on HowTheFu.cc</a>. 
Once I have a local NAS I'd actually be following the 
<a href="https://en.wikipedia.org/wiki/Backup#3-2-1_Backup_Rule">3-2-1 rule</a> correctly.
I still don't have complete system images of my drives in case my boot disk fails,
and I'm not quite sure how to do that in a convenient way either <a href="#note-0" id="back-0">[0]</a>.
</p>
<p>
Completely different topic: People have (randomly?) found and used my shit (in a good way!).
</p>
<p>
A while ago, I got a message from my thesis advisor (from two years ago) who wanted to let me 
know that someone wrote a paper, based on the works in bachelor thesis, and that the paper
was accepted into "a top conference". Holy. At first I thought that it was just a footnote or something for 
the relevant works or something. But I found out, that the person has written a long form (master thesis)
and a short form (paper which got accepted), and boy did I get a glazing in the master thesis. 
They actually used the (very crude) testing framework I setup to compare a few algorithms, as well
as used some terminology my advisor and me came up with. 
Funniest shit was them mentioning that my shitty Bachelor Thesis was <b>still</b> the only non-theoretical comparison
of the algorithms. I have no idea how they found my thesis in the first place (and I still think that someone at 
my university might have directly linked to my shit or something), but that was a nice boost to confidence nonetheless :)
</p>
<p>
Then, a few months later, I got another funny email. 
Someone stumbled over <a href="https://howthefu.cc/posts/04/index.html">short post on Linux Audio</a>
and thanked me for providing a fix to the issue.
I did not expect this to actually happen, given that I haven't found anyone else having this issue either.
But after a quick search, I then found a link to that post stored in some public linux dot-files repository.
So I at least helped out two completely random strangers by just uploading my sheet cheats / fixes 
to my niche problems - very cool!
</p>
<p>
Also, keep in mind:
Neither p4m.dev nor howthefu.cc contain any sort of (easily accessible) contact info.
Poor guy went through the troubles of looking up my domain info and using the (mandatory) mail address just to shoot me
a quick thanks. 
I'm still thinking about whether I actually want to put out an easy way to contact me or not.
So, uh, I guess feel free to use the domain-information until then.
</p>
]]></content>
</entry>
<entry>
<title>Fixing My Tablet Buttons On Linux</title>
<link rel="alternate" href="https://p4m.dev/posts/30/" />
<updated>2025-07-26T00:00:00Z</updated>
<id>https://p4m.dev/posts/30/</id>
<content type="html">
<![CDATA[<p>
You know, I'm not really a fan of Linux. 
Usually, shit is completely fucked when you plug something new in. 
On the flipside, once everything is setup &amp; configured in the most cryptic way possible,
things generally keep working.
</p>
<p>
Not this time though.
</p>
<h1>
 The Situation</h1>
<p>
I programmed a simple blackboard application to be used with my tablet.
The idea is not to do anything serious in it, but to have a 
virtual (dark) whiteboard where I can quickly visualize something
for myself, without having to wait for GIMP / Krita to boot up
and being required to setup canvas sizes, colors, etc.
I'm pretty happy with the application (despite my utter hate for Wayland), 
and all of the buttons of the tablet are usable: There's the buttons on 
tablet itself, but there's also two buttons on the tablet pen, which 
I use for a quick switch between erasing/drawing, as well as to move around
on the canvas.
</p>
<p>
Last time I used the application, I noticed that I couldn't use the tablet buttons
at all. Very annoying because the undo &amp; redo buttons are mapped on there, 
as well as the Zoom In/Out. 
</p>
<h1>
 The Investigation</h1>
<p>
As I mentioned before, I hate programming for Wayland. 
I did finally pull out some common code for window creation &amp; input handling
into some helper utilities, such that I can hopefully keep my interaction with
the awful Wayland-way of doing to a minimum. 
I have also updated my blackboard application to make use of that utility, 
and I couldn't remember whether I actually tested the tablet buttons back then,
so I thought this was my own fault.
</p>
<p>
I have updated the weird Wayland libraries / xml files, re-generated the headers - no dice.
Stepping through my code it seems like the tablet (and tablet tools) are properly 
registered. I can get pen-events and pen-button-events just fine, 
but no tablet-button-events.
I tried to register more callback functions in case I was relying on some undefined
behavior of the compositor - nothing.
</p>
<h2>
 Next Stop: Wayland Compositor Sway</h2>
<p>
I checked through the github issues of the Wayland Compositor I use (sway).
Again, nothing in regards to "hey we fucked up tablets oopsie" came up.
Quick look at the code: There's really not much code for tablet inputs.
So I started a second instance of the compositor with logs and went through them: 
Couldn't find anything suspicious there either.
</p>
<h2>
 Next Stop: Libinput</h2>
<p>
Next stop: <code>libinput</code>. I saw <code>libinput</code> references in the code, 
and when googling tablet wayland input issues, some people suggest 
checking out the following command in order to see, whether the input events
are generated properly:
<pre><code>
> libinput debug-events --verbose</code></pre>
</p>
<p>
Aha! I don't get <b>any</b> button events when pressing the tablet buttons.
In contrast, I lots of events whenever I move the tablet-pen (apparently even with angles, 
I didn't know the tablet could do that), and the tablet-pen-buttons also generate events.
Plugging in the tablet generates events looking like this:
<pre><code>
event9  - Hanvon Ugee Technology Co.,Ltd Deco L: is tagged by udev as: Mouse Tablet
event9  - Hanvon Ugee Technology Co.,Ltd Deco L: libinput bug: missing tablet capabilities: xy pen btn-stylus resolution. Ignoring this device.
event9  - Hanvon Ugee Technology Co.,Ltd Deco L: device is a tablet
event9  - failed to create input device '/dev/input/event9'
event11 - Hanvon Ugee Technology Co.,Ltd Deco L: is tagged by udev as: Tablet
event11 - Hanvon Ugee Technology Co.,Ltd Deco L: libinput bug: missing tablet capabilities: xy pen btn-stylus resolution. Ignoring this device.
event11 - Hanvon Ugee Technology Co.,Ltd Deco L: device is a tablet
event11 - failed to create input device '/dev/input/event11'
event10 - Hanvon Ugee Technology Co.,Ltd Deco L: is tagged by udev as: Tablet
event10 - Hanvon Ugee Technology Co.,Ltd Deco L: device is a tablet
-event10  DEVICE_ADDED                 Hanvon Ugee Technology Co.,Ltd Deco L seat0 default group2  cap:T  size 254x152mm left</code></pre>
</p>
<p>
"bug" doesn't sound too good, but "tablet capabilites [...] pen" makes it sound like it's looking for
the tablet pen. The tablet, in linux, apparently consists of several devices, so I wouldn't be
too surprised if only one of the devices is responsible for cursor input.
So onto <code>libinput</code>, someone fucked up my shit >:(
</p>
<p>
Well, there are <b>closed</b> issues on <code>libinput</code> referencing broken tablet buttons, but no 
new or open stuff. The most relevant stuff I could find is 
<a href="https://gitlab.freedesktop.org/libinput/libinput/-/issues/527">this issue</a>, which
is several years old already.
But turns out, I'm having the same problem: 
</p>
<p>
<img src="./libinput.png" style="width:500px;height:235px;" />
</p>
<p>
Looking at this response, and through another 
<a href="https://gitlab.freedesktop.org/libinput/libinput/-/issues/356">similar issue</a>, 
I get mixed feelings:
<ul style="list-style-type:'- '"><li> <code>ID_INPUT_TABLET_PAD</code> is not set in <code>udev</code>. No idea what that means.</li><li> <code>libinput</code> is not responsible for that, it's relying on <code>libwacom</code>. So that's the next stop.</li><li> This is "generally fixed" in systemd - which I don't use on my distro.</li>
</ul>
</p>
<p>
There's similar stuff described in 
<a href="https://who-t.blogspot.com/2015/06/libinput-and-lack-of-device-types.html">this blogpost</a>
for (or from?) libinput. 
My tablet device is missing a tag. It's supposed to get it from <code>libwacom</code>, but 
<a href="https://youtu.be/k238XpMMn38?t=39">Too Bad!</a>
</p>
<h2>
 Next Stop: libwacom</h2>
<p>
In the repository, I found 
<a href="https://github.com/linuxwacom/libwacom/blob/33e72d5d5011f97d00f55e68744d05c9ab67a23c/data/xp-pen-deco-l.tablet">the file for my tablet</a>.
<ul style="list-style-type:'- '"><li> What exactly is supposed to be wrong in this file?</li><li> As of writing, the last change is from 9 months ago. <ul style="list-style-type:'- '"><li> Was my shit fucked for that long?</li><li> Was it only added in some release? Or did my distro package that release lately?</li><li> Is the latest change even responsible for that? It removes a <code>Class=</code> keyword - no idea what that means.</li>
</ul>
</li>
</ul>
</p>
<p>
So I decided to pivot. I supposedly just need this one <code>ID_INPUT_TABLET_PAD</code> tag on 
my tablet, can't be that fucking difficult, right?
</p>
<h2>
 Next Stop: udev</h2>
<p>
Googling. Lots of googling. Trying lots of different commands. Without any more side-tracks, 
here are the keypoints from my <code>udev</code> shenanigans:
<ul style="list-style-type:'- '"><li> You should be able to modify the tags of a device with a custom rule.</li><li> You can create custom rules by creating a file <code>/etc/udev/rules.d/[anyName].rules</code>.</li><li> You can list a bunch of tags of your devices by doing the following:<ul style="list-style-type:'- '"><li> Unplug the device</li><li> Run the command <code>udevadm monitor -p</code></li><li> Plug the device in and look at the output</li>
</ul>
</li>
</ul>
</p>
<p>
So, let's look the output of that udev-command. There's a lot in there,
but some of the entries look like this on my end:
<pre><code>
[... lots of stuff here ...]

UDEV  [1003.360012] add      /devices/pci0000:00/0000:00:01.2/0000:02:00.0/usb1/1-6/1-6.1/1-6.1:1.0/0003:28BD:0935.001D/input/input49/event9 (input)
ACTION=add
DEVLINKS=/dev/input/by-id/usb-Hanvon_Ugee_Technology_Co._Ltd_Deco_L_0000000000-event-mouse /dev/input/by-path/pci-0000:02:00.0-usb-0:6.1:1.0-event-mouse
DEVNAME=/dev/input/event9
DEVPATH=/devices/pci0000:00/0000:00:01.2/0000:02:00.0/usb1/1-6/1-6.1/1-6.1:1.0/0003:28BD:0935.001D/input/input49/event9
ID_BUS=usb
ID_INPUT=1
ID_INPUT_MOUSE=1
ID_MODEL=Deco_L
ID_MODEL_ENC=Deco\x20L
ID_MODEL_ID=0935
ID_PATH=pci-0000:02:00.0-usb-0:6.1:1.0
ID_PATH_TAG=pci-0000_02_00_0-usb-0_6_1_1_0
ID_REVISION=0000
ID_SERIAL=Hanvon_Ugee_Technology_Co._Ltd_Deco_L_0000000000
ID_SERIAL_SHORT=0000000000
ID_TYPE=hid
ID_USB_DRIVER=usbhid
ID_USB_INTERFACES=:030002:030000:
ID_USB_INTERFACE_NUM=00
ID_VENDOR=Hanvon_Ugee_Technology_Co._Ltd
ID_VENDOR_ENC=Hanvon\x20Ugee\x20Technology\x20Co.\x2cLtd
ID_VENDOR_ID=28bd
LIBINPUT_DEVICE_GROUP=3/28bd/935:usb-0000:02:00.0-6
MAJOR=13
MINOR=73
SEQNUM=5784
SUBSYSTEM=input
USEC_INITIALIZED=3359948

UDEV  [1003.360348] add      /devices/pci0000:00/0000:00:01.2/0000:02:00.0/usb1/1-6/1-6.1/1-6.1:1.2/0003:28BD:0935.001F/input/input50/event10 (input)
ACTION=add
DEVLINKS=/dev/input/by-id/usb-Hanvon_Ugee_Technology_Co._Ltd_Deco_L_0000000000-if02-event-mouse /dev/input/by-path/pci-0000:02:00.0-usb-0:6.1:1.2-event-mouse
DEVNAME=/dev/input/event10
DEVPATH=/devices/pci0000:00/0000:00:01.2/0000:02:00.0/usb1/1-6/1-6.1/1-6.1:1.2/0003:28BD:0935.001F/input/input50/event10
ID_BUS=usb
ID_INPUT=1
ID_INPUT_HEIGHT_MM=152
ID_INPUT_WIDTH_MM=254
ID_MODEL=Deco_L
ID_MODEL_ENC=Deco\x20L
ID_MODEL_ID=0935
ID_PATH=pci-0000:02:00.0-usb-0:6.1:1.2
ID_PATH_TAG=pci-0000_02_00_0-usb-0_6_1_1_2
ID_REVISION=0000
ID_SERIAL=Hanvon_Ugee_Technology_Co._Ltd_Deco_L_0000000000
ID_SERIAL_SHORT=0000000000
ID_TYPE=hid
ID_USB_DRIVER=usbhid
ID_USB_INTERFACES=:030002:030000:
ID_USB_INTERFACE_NUM=02
ID_VENDOR=Hanvon_Ugee_Technology_Co._Ltd
ID_VENDOR_ENC=Hanvon\x20Ugee\x20Technology\x20Co.\x2cLtd
ID_VENDOR_ID=28bd
LIBINPUT_DEVICE_GROUP=3/28bd/935:usb-0000:02:00.0-6
MAJOR=13
MINOR=74
SEQNUM=5795
SUBSYSTEM=input
USEC_INITIALIZED=3360267

[... some more stuff ...]

UDEV  [1003.367906] add      /devices/pci0000:00/0000:00:01.2/0000:02:00.0/usb1/1-6/1-6.1/1-6.1:1.2/0003:28BD:0935.001F/input/input51/event11 (input)
ACTION=add
DEVLINKS=/dev/input/by-id/usb-Hanvon_Ugee_Technology_Co._Ltd_Deco_L_0000000000-event-if02 /dev/input/by-path/pci-0000:02:00.0-usb-0:6.1:1.2-event
DEVNAME=/dev/input/event11
DEVPATH=/devices/pci0000:00/0000:00:01.2/0000:02:00.0/usb1/1-6/1-6.1/1-6.1:1.2/0003:28BD:0935.001F/input/input51/event11
ID_BUS=usb
ID_INPUT=1
ID_MODEL=Deco_L
ID_MODEL_ENC=Deco\x20L
ID_MODEL_ID=0935
ID_PATH=pci-0000:02:00.0-usb-0:6.1:1.2
ID_PATH_TAG=pci-0000_02_00_0-usb-0_6_1_1_2
ID_REVISION=0000
ID_SERIAL=Hanvon_Ugee_Technology_Co._Ltd_Deco_L_0000000000
ID_SERIAL_SHORT=0000000000
ID_TYPE=hid
ID_USB_DRIVER=usbhid
ID_USB_INTERFACES=:030002:030000:
ID_USB_INTERFACE_NUM=02
ID_VENDOR=Hanvon_Ugee_Technology_Co._Ltd
ID_VENDOR_ENC=Hanvon\x20Ugee\x20Technology\x20Co.\x2cLtd
ID_VENDOR_ID=28bd
LIBINPUT_DEVICE_GROUP=3/28bd/935:usb-0000:02:00.0-6
MAJOR=13
MINOR=75
SEQNUM=5797
SUBSYSTEM=input
USEC_INITIALIZED=3367843

[... lots more stuff ...]</code></pre>
</p>
<p>
Important stuff:
<ul style="list-style-type:'- '"><li> I see my tablet and <code>ID_INPUT</code> as pointed out in the gitlab issue, but <code>ID_INPUT_TABLET_PAD</code> is indeed missing.</li><li> There's (at least) three different linux devices associated when plugging in the tablet (input49, input50, input51).</li>
</ul>
</p>
<p>
I found 
<a href="https://linuxconfig.org/tutorial-on-how-to-write-basic-udev-rules-in-linux">this post</a>
to create custom udev rules.
After a bit of trial and error, I deduced 
that the things listed in the udev-command, like <code>ID_INPUT_TABLET</code>, 
correspond to <code>ENV{ID_INPUT_TABLET}</code> for udev rules.
</p>
<p>
The tutorial uses <code>idVendor</code> and <code>idProduct</code> to target a device. 
This looks like <code>ID_VENDOR_ID</code> and <code>ID_MODEL_ID</code> in the udev-command-output, 
but I doubled checked just in case: 
<ul style="list-style-type:'- '"><li> Unplug / replug your device</li><li> Run <code>doas dmesg</code></li><li> The relevant output for your device should be at the bottom:</li>
</ul>
</p>
<p>
<pre><code>
[ 7411.920304] usb 1-6.1: new full-speed USB device number 27 using xhci_hcd
[ 7412.335132] usb 1-6.1: New USB device found, idVendor=28bd, idProduct=0935, bcdDevice= 0.00
[ 7412.335137] usb 1-6.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 7412.335140] usb 1-6.1: Product: Deco L
[ 7412.335142] usb 1-6.1: Manufacturer: Hanvon Ugee Technology Co.,Ltd
[ 7412.335144] usb 1-6.1: SerialNumber: 0000000000</code></pre>
</p>
<p>
I'll post the solution (to my problem) at the bottom. But first, a small headsup:
</p>
<p>
I initially tried to create a custom rule to just add <code>ID_INPUT_TABLET_PAD</code> to any input device
which matched the vendor- &amp; model-id. While it did add the tag, it rendered my tablet unusable.
Apparently the tag needs to be present at the correct linux device, not simply all three.
</p>
<p>
So I started comparing the different outputs of the <code>udevadm monitor -p</code> once more.
I didn't want to pick something like <code>DEVNAME</code>, <code>DEVPATH</code> or <code>USEC_INITIALIZED</code>, because 
these things seem prone to change (on replug / reboot / different USB slot, etc).
Lots of properties look the same, but the one differentiator that I have found which
(hopefully) works is:
</p>
<p>
<pre><code>
// input49
MAJOR=13
MINOR=73

// input50
MAJOR=13
MINOR=74

// input51
MAJOR=13
MINOR=75</code></pre>
</p>
<p>
I know that one of these is for the pen input, which leaves two other <code>MINOR</code>. I just
tried one, and it seems to work (for now)!
</p>
<p>
Now as promised:
</p>
<h1>
 The Solution</h1>
<p>
For future me, these are the specific steps I used to fix the issue:
</p>
<p>
1.) Create the file <code>/etc/udev/rules.d/99-xppen.rules</code> with the following content:
</p>
<p>
<pre><code>
ACTION=="add|change", SUBSYSTEM=="input", ATTRS{idProduct}=="0935", ATTRS{idVendor}=="28bd", ENV{MINOR}=="75", ENV{ID_INPUT_TABLET_PAD}="1"</code></pre>
</p>
<p>
2.) Either reboot, or run:
<pre><code>
> doas udevadm control --reload-rules &amp;&amp; udevadm trigger</code></pre>
</p>
]]></content>
</entry>
<entry>
<title>I Hate: Programming Wayland Applications</title>
<link rel="alternate" href="https://p4m.dev/posts/29/" />
<updated>2025-05-12T00:00:00Z</updated>
<id>https://p4m.dev/posts/29/</id>
<content type="html">
<![CDATA[<p>
A quick introduction:
</p>
<p>
If you want to program a graphical application for linux, your primary choices are using either X11 or Wayland.
According to Wikipedia, <a href="https://en.wikipedia.org/wiki/X_Window_System">X11</a> had its first release in 1984. 
X11 follows a client-server-model. 
I assume it's because the whole computational environment, was very different back then. 
If you have a central server which is doing all of the heavy lifting, while the user only connects to it
via a slim client / dumb terminals / whatever, having the desktop system follow a client-server-model makes sense.
In contrast, <a href="https://en.wikipedia.org/wiki/Wayland_%28protocol%29">Wayland (protocol)</a> had its first release
in 2008. That's also quite a while ago, in the 2000s the computational environment was probably much closer 
to what we have today: A PC usually comes with a desktop / graphical interface, and the machine doesn't need
to rely on an external server to do most of the computing.
</p>
<p>
So, over the years there has been a push to switch from X11 to Wayland. 
And, at least on a surface level, this makes sense to me: Developers probably have learned a lot about
the various requirements of desktops, so having a (mostly) clean cut for this new desktop environment 
seems promising. I have read claims stating that Wayland is inherently more secure than X11.
Wayland isn't "outdated", we can design the desktop with performance and modern use-cases in mind.
</p>
<p>
I am typing this on a desktop machine running sway, which is a Wayland compositor. 
There definitely have been the common hurdles like desktop recording / sharing not working.
But over time, these issues have been resolved - at least for my machine.
Some years ago, I tried out both X11 and Wayland (I think back on Arch Linux). 
And honestly, the sway installation was far easier than the i3/X11 one.
This ease of installation, combined with Wayland supposedly being "the future of Linux Desktops",
and it supporting X11 applications via XWayland, made me stick to sway, even
with its rough edges.
</p>
<p>
That was the story of me <b>using</b> Wayland. Now comes the <b>developing</b> part - which has been a
fucking nightmare.
</p>
<h1>
 Foundational Differences</h1>
<p>
For libraries to be used by other developers, I'm a big fan of:
<figure>
	Make easy things easy. Make hard things doable.
</figure>
</p>
<p>
If you just want to open a window and do some simple rendering with your GPU,   
<a href="https://github.com/raysan5/raylib/">raylib</a> is a fantastic library.
Here is an example application:
<pre><code>
#include &lt;raylib.h>

int
main(void)
{
	InitWindow(1280, 720, "Test Window");
	SetTargetFPS(144);
	while ( ! WindowShouldClose())
	{
		BeginDrawing();
		ClearBackground(RAYWHITE);
		EndDrawing();
	}
	return 0;
}</code></pre>
</p>
<p>
Incredibly simple. Raylib is <b>really good</b> at covering the "make easy things easy" part.
Ideally, <a href="https://www.youtube.com/watch?v=ZQ5_u8Lgvyk">you'd have an "upgrade path"</a> where, 
using more complex code, you can handle more complicated edge-cases step-by-step <a href="#note-0" id="back-0">[0]</a>. 
</p>
<p>
When developing graphical Windows applications, you have to use <code>Windows.h</code>, do a few rather cryptic 
function calls to create and get window handles, and then you have your "main loop", where you work
through a bunch of window events (mouse moves, keyboard input, window wants repaint, ...) and respond
accordingly. It's fairly more complicated compared to raylib, so I see lots of potential for improvement.
</p>
<p>
This is the reason why I had high hopes for Wayland. Boy was I wrong.
Wayland does not care for the simple use-case at all. 
Getting any example application to work is so incredibly ridiculous, that every second I program on Wayland,
I yarn for the times I did Win32 programming.
</p>
<p>
Don't get me wrong: I'm not expecting that e.g. DPI aware mult-monitor applications using several input devices,
mixed refreshrates and hot-plugging of devices "just works". 
It's just that every single thing, which I would expect to be reasonably simple, or have helper functions
of any kind, is so incredibly painful at every step of the way.
</p>
<h1>
 Opening A Wayland Window</h1>
<p>
I'm not posting code here, because my helper functions to open up an OpenGL Window 
and transform the whole Wayland insanity into a list of events is >1300 lines of code. 
</p>
<p>
In Wayland, opening up a roughly works as follows:
<ul style="list-style-type:'- '"><li> You connect connect to a Wayland socket (this is ok)</li><li> Then you connect to the "registry". The "registry" is responsible for returning "global objects".
This includes stuff like your monitors, but also some core Wayland objects (WlShm, WlCompositor, ...) and protocol extensions (XdgShell, WlrShell, etc).</li><li> <b>Almost everything is done via callbacks</b>.</li><li> You trigger Wayland gathering events and calling callbacks using <code>wl_display_roundtrip()</code> &amp; <code>wl_display_dispatch()</code></li><li> You need to setup a surface in order to display anything. How exactly this works varies wildly depending on if you are using e.g. OpenGL or not, and the type of surface you use</li>
</ul>
</p>
<p>
And when I mean everything, I do mean everything.
<ul style="list-style-type:'- '"><li> Want to retrieve the globals? Register registry callback functions. </li><li> Want to retrieve mouse/keyboard input? Register all callback functions, then you get them in a callback.</li><li> Need monitor information? Save the <code>wl_output</code> you got from the registry callback, then register all the callbacks on them.</li><li> Xdg needs you to regularly respond to PING functions. You can respond by registering a callback for the PINGs, and then calling the appropriate PONG in there.</li><li> Want to know whether your application just got focussed? Register all callbacks for surface events.</li>
</ul>
</p>
<p>
I fully blame Wayland being an Object Oriented Protocol for this.
The control flow <b>is horrible</b>. Have fun trying to predict what code executes in what order after your 
<code>wl_display_roundtrip()</code> &amp; <code>wl_display_dispatch()</code> calls - and I still don't know what's the difference between 
them and in what order to call them on. Initialization code for OpenGL is rather fragile, as some of these
callback functions are called several times during initialization.
</p>
<p>
If you fuck anything up during initialization, just likely just get no window and the program is running endlessly. Even if do all of this callback bullshit, none of it is simple to use.
<ul style="list-style-type:'- '"><li> Keyboard input: You also need to initialize and translate the event info using <code>xkb</code>, otherwise you don't know what character the key press is supposed to represent.</li><li> You only get an event for key press and key release. If you want to support key repetition, you guessed it, get the key repetition info from some callback. Then manually setup a timer FD using said info, and keep track which button is supposed to repeat yourself.</li><li> Want to know what the current refreshrate is? <ul style="list-style-type:'- '"><li> Track all global <code>wl_output</code> objects and register all the callbacks for each</li><li> Store the refreshrate info from the callback alongside the <code>wl_output</code> object</li><li> Register callbacks for the surface you are displaying.</li><li> When you enter a surface, you get a callback including the <code>wl_output</code> being used. 
Match that <code>wl_output</code> with your stored globals and the corresponding refreshrate.</li>
</ul>
</li><li> By default on sway, you get window decorations if the program is tiled, but no decorations when you make the window floating. If you want to change this behavior:<ul style="list-style-type:'- '"><li> Get the <code>zxdg_toplevel_decoration</code> global from the registry</li><li> Use that to explictly request what kind of decorations you want to have.</li>
</ul>
</li><li> Is the window supposed to be a pop-up? Then set its min- and max-size to be equal. </li>
</ul>
</p>
<p>
The most valuable resource is <a href="https://wayland.app">Wayland.app</a>.
It has an overview over 
<ul style="list-style-type:'- '"><li> the core protocol functions</li><li> accepted extensions</li><li> WIP extensions and where are they are used</li><li> Which version of the extension / protocols is used by which compositor.</li>
</ul>
</p>
<p>
You can see how fragmented this whole thing is. It's a complete mess.
Oh and I haven't even mentioned how you can use these extensions. 
This is crucial, because <b>you cannot open a window if you just use the core protocol</b>. 
You <b>used to</b> be able to, but the "shell" which was used to display things, <code>wl_shell</code>, 
<a href="https://wayland.freedesktop.org/docs/html/apa.html#protocol-spec-wl_shell">has been deprecated</a>. 
I'm not kidding.
You are supposed to use <code>XdgShell</code> instead <a href="#note-1" id="back-1">[1]</a>. But if you lookup the extension, you will
probably only find an XML-file - because the interface code is generated from it using 
<code>wayland-scanner</code> as follows:
<pre><code>
wayland-scanner private-code  &lt; xdg-shell.xml > xdg_shell.c
wayland-scanner client-header &lt; xdg-shell.xml > xdg_shell.h</code></pre>
</p>
<p>
The <a href="https://wayland.freedesktop.org/docs/html/ch04.html">official Wayland Documentation</a> does not mention <code>wayland-scanner</code>, 
only that it's generated from the XML. I'm also still not sure where I'd get the XML files from.
For Void Linux, there is a <code>wayland-protocols</code> package, which puts the XML files in <code>/usr/share/wayland-protocols</code>.
This is sheer insanity. There are so many obstacles you have to get over in order to produce 
just a blank window, and even if you get past that, the control flow of the application is fucking garbage.
I have no idea why they didn't stick to "main event loop" instead, and just provided an easy way
of dismissing events you don't care about.
</p>
<p>
To give you another glimpse: For some fucked up reason, opening up an OpenGL Window 
is easier than just drawing some pixels on the CPU. Yes, really. 
Here is, roughly, what you need to do for a software rendered application:
<ul style="list-style-type:'- '"><li> Get all the global objects</li><li> Create a <code>WlSurface</code></li><li> Register all the callbacks for the <code>WlSurface</code></li><li> Create an <code>XdgSurface</code></li><li> Register all the callbacks for the <code>XdgSurface</code></li><li> Create an <code>XdgToplevel</code></li><li> Register all the callbacks for the <code>XdgToplevel</code></li><li> Create a shared memory object which I'll call <code>ShmFD</code> using <code>shm_open</code></li><li> Set its size using <code>ftruncate</code> and map it using <code>mmap</code></li><li> Using the global <code>WlShm</code> and <code>ShmFD</code>, create an <code>wl_shm_pool</code></li><li> Using the <code>wl_shm_pool</code>, create a <code>WlBuffer</code></li><li> Call <code>wl_surface_commit</code> on your <code>WlSurface</code></li><li> Call <code>wl_display_dispatch()</code> and <code>wl_display_roundtrip()</code><ul style="list-style-type:'- '"><li> In the <code>XdgSurface.Configure</code>-callback, attach <code>WlBuffer</code> to the <code>WlSurface</code>. 
Damage and commit <code>WlSurface</code> to indicate that you have stuff to be displayed.</li><li> In the <code>XdgToplevel.Configure</code>-callback, you need to keep track whether your 
resolution changed. If so, you probably want to create another <code>WlBuffer</code> with new 
dimensions, and draw to it</li>
</ul>
</li><li> To know when you need to repaint:<ul style="list-style-type:'- '"><li> Create a <code>wl_callback</code> for the <code>WlSurface</code></li><li> Create a callback for it. When it's called you:<ul style="list-style-type:'- '"><li> should do the rendering</li><li> destroy the current <code>wl_callback</code></li><li> create a new <code>wl_callback</code></li><li> add the callbacks to the <code>wl_callback</code></li>
</ul>
</li>
</ul>
</li>
</ul>
</p>
<p>
I'm skipping over some details here, but you can see that this shit is fucking insane.
Fuck anything up, and your application is less responsive, doesn't render at all or way too often,
is leaking memory, and/or so on and so forth.
</p>
<h1>
 Random Bullshit Go</h1>
<p>
Here's a list of stuff I randomly stumbled over, in no particular order.
</p>
<p>
If you use your GPU for rendering, you are probably using <code>eglSwapBuffers</code> using EGL.
If you activate VSync, <code>eglSwapBuffers</code> will automatically block until the frame is displayed,
which is quite handy (no manual sleeping / refresh-rate querying required).
But if you unplug / replug the monitor, <code>eglSwapBuffers</code> will 
<a href="https://gitlab.freedesktop.org/mesa/mesa/-/issues/4180">block indefinitely</a>.
</p>
<p>
Wayland, AFAIK, has no concept of primary monitors. 
For my personal application, I wanted to hardcode something using the right-most monitor.
Wayland offers a geometry callback, which is supposed to return the x &amp; y position within the global
compositor space (and other info like physical dimensions, subpixel layouts, transforms, etc).
Apparently <a href="https://github.com/swaywm/sway/issues/8164">several Wayland environments</a> always return (0, 0) for the monitor position.
</p>
<p>
The Wayland Protocol development is so slow, that someone (from Valve?) started
<a href="https://github.com/misyltoad/frog-protocols">Frog Protocols</a>, with the sole purpose of 
being able to iterate much more quickly.
</p>
<p>
As far as I know, there is no standardized way of retrieving the current "desktop state",
meaning retrieving a list of open windows, their positions, etc. I'm aware that 
Wayland is supposed to be "secure", but simply not offering this functionality introduces
fragmentation and is likely more insecure than offering an API with some sort of permission system.
On Sway, you can retrieve the "desktop state" using the sway-ipc-socket, which communicates 
via JSON (kill me). However, there is no way to query for applications / surfaces 
using the Wlr Layer Shell extension, which are used for workspace independent windows (e.g. status bar) <a href="#note-2" id="back-2">[2]</a>.
</p>
<p>
Getting the Wayland Clipboard to work is a nightmare.
I just wanted to copy some text into the clipboard, but I gave up after while.
For text, the easiest hack I found was to start another process running <code>wl-clipboard</code> and 
passing the relevant arguments to that.
</p>
<p>
Hotplugging stuff doesn't necessarily work. The keys of my drawing tablet pad 
are not recognized by any application until I restart the programs.
Judging from my experiments, Wayland doesn't seem to generate the relevant events
to announce that the device has been plugged in, while unplugging does send 
the events to render the device invalid <a href="#note-3" id="back-3">[3]</a>.
</p>
<p>
Xdg-Desktop-Portal is required to do any form of screensharing. 
Thanks to Wayland thinking that screensharing / recording is "out of scope", 
xdg-desktop-portal has been implemented by several compositors, leading to fragmentation.
On Void Linux, there are the following implementations available:
<ul style="list-style-type:'- '"><li> GNOME</li><li> GDK</li><li> KDE</li><li> LXQT</li><li> WLR</li><li> XAPP</li>
</ul>
</p>
<p>
While I was able to make parts of a Wayland Window transparent, I wasn't able to
make it "click-through" / forward the events to the window behind it.
</p>
<p>
Setting mouse cursors is a massive pain in the ass.
While I now know how to hide the cursor or how to display the "normal" cursor, 
I'm not sure how to handle other cursor types: You need to pass a "CursorType" string,
and I legit couldn't find a list of all the valid valid strings <a href="#note-4" id="back-4">[4]</a>.
</p>
<h1>
 Conclusion</h1>
<p>
As a user, using Wayland is nice. 
</p>
<p>
Compared to X11, the internals of Wayland Compositors might also be a great upgrade, I don't know.
</p>
<p>
As a developer, I want to kill myself when working with Wayland code.
The API of this <a href="https://wayland.freedesktop.org/docs/html/ch04.html">"asynchronous object oriented protocol"</a>
is a fucking disaster. It's a huge downgrade compared to Win32 or X11 with XLib.
You cannot write a simple application with Wayland. Every part of it, the different extensions, 
the fact that you generate the api code from XML, and the entire control flow when interacting with Wayland,
is utterly horrible.
<b>This is the foundation all future Linux applications should supposedly build upon</b>. 
</p>
]]></content>
</entry>
<entry>
<title>Releasing Music Files (Almost) No-One Has Asked For</title>
<link rel="alternate" href="https://p4m.dev/posts/28/" />
<updated>2025-03-22T00:00:00Z</updated>
<id>https://p4m.dev/posts/28/</id>
<content type="html">
<![CDATA[<p>
A friend of mine recently had an usual request:
He would like to have a way to listen to all of my piano recordings
without manually switching tracks every couple of minutes.
Imagine my shock when I learned that this poor dude is actually 
listening to them (??? no idea why).
</p>
<p>
It's not like I record a new piece every week,
but I feel like I'd still be annoyed if I had to manually update
this "master track" from time to time - so I automated that!
I feel like this niche request doesn't warrant restructuring/modifying
my website too much, so I opted to put this on a subdomain instead.
You can find the new site at:
</p>
<p>
<a href="https://music.p4m.dev/">https://music.p4m.dev/</a>
</p>
<p>
Again, it's literally just all of the piano pieces concatenated.
I took the liberty to also do this for the guitar tracks, 
and also adding a third one, where <b>all</b> recordings are concatenated.
I don't think I'll record new guitar stuff anytime soon, 
but I'm still working on my piano skills. 
Progress is pretty slow though, as this includes
some pauses, dropping pieces, not really getting into others, and so on
(lately I have been listening to way too much of 
<a href="https://youtu.be/S_vFsC0Kolw">Marasy8 arrangements</a>, which are <b>way</b>
outside of my skill level).
Now I have a new metric to look forward to: Have at least as much piano
stuff recorded as I did for the guitar :)
</p>
<p>
For future reference, I'll quickly cover how I can generate these
master tracks with a bash script.
</p>
<h1>
 Technical Explanation</h1>
<p>
To be clear: Doing this by hand with e.g. <a href="https://audacityteam.org">Audacity</a> is completely fine for a one-off.
In fact, that was the first version I quickly put together before I looked into ways of automating it.
For all things encoding related, <code>ffmpeg</code> comes to the rescue - although it wasn't really smooth sailing.
</p>
<p>
Turns out over the many years I recorded these things, I didn't use a consistent samplerate.
That's not really too big of a deal, but if you just concatenate all of the audio samples into one big 
file, shit will break at some point.
So I need to re-sample / re-encode the file. This hurts the perfectionist in me, but then again,
it's literally just my recordings, that shit is not worth being stored losslessly to begin with.
</p>
<p>
Here's the strategy:
<ul style="list-style-type:'- '"><li> Gather all of the tracks in two directories (piano / guitar)</li><li> Re-encode all files with a consistent samplerate to <code>FLAC</code>, as an intermediate step (via <code>FFMPEG</code>)</li><li> Create lists of files to be concatenated (piano / guitar / all) (via <code>find</code>)</li><li> Use list to concatenate &amp; encode the resulting file (via <code>FFMPEG</code>)</li><li> Cleanup temporary files</li><li> Upload the resulting files to the server (via <code>rsync</code>)</li>
</ul>
</p>
<p>
Here are some relevant snippets of the script:
<pre><code>
# Convert Guitar Tracks
for file in $(find "$siteDir/recordings/guitar/" -type f); do
	name=$(basename $file)
	ffmpeg -hide_banner -loglevel error -y -i $file -osr 48000 "$tempDirGuitar/$name.flac" &amp;
done

# ...


# Create lists
find $tempDirGuitar -type f -fprintf $listGuitar "file '%p'\n"

# ...

# Convert to single tracks
ffmpeg -hide_banner -loglevel error -f concat -safe 0 -y -i $listGuitar -acodec libvorbis -q:a 10 guitar.ogg &amp;</code></pre>
</p>
<p>
The trick here is passing the correct arguments to <code>FFMPEG</code>. For concatenating files, 
it mostly supports a list provided by a text file in a weird format:
<pre><code>
file 'myMusic.ogg'
file 'myOtherTrack.ogg'
file 'alsoThisTrack.ogg'</code></pre>
</p>
<p>
Flags like <code>hide_banner</code> or <code>loglevel</code> are just there to make the output quiet,
while <code>-safe 0</code> is required due to my file structure. I'm assuming it has to do with
me using relative paths to navigate to my website holding the tracks, but I don't care
enough to find out why exactly <code>FFMPEG</code> is careful in that instance.
</p>
<p>
Surprisingly, re-encoding all of that music, at least with my current track list,
takes <code>~55 seconds</code>. It would be well over two minutes if I didn't run most of the conversions in parallel
(one big parallel block for all of the converting to <code>FLAC</code>, and then one parallel block for the three 
concatenated tracks).
</p>
<p>
Given that the "everything"-master-track is well over an hour long, it's a chonky boy, and probably
not really suitable for something version controlled. 
The tracks of this site are in version control, so that should suffice in my opinion.
That's why I'm just straight up uploading the files via <code>rsync</code>, instead of having 
some git repo with automated chron jobs and such.
</p>
]]></content>
</entry>
<entry>
<title>Notes On Automatic Dereference For The Dot-Operator In C</title>
<link rel="alternate" href="https://p4m.dev/posts/27/" />
<updated>2025-03-08T00:00:00Z</updated>
<id>https://p4m.dev/posts/27/</id>
<content type="html">
<![CDATA[<h1>
 What Is This Post About?</h1>
<p>
In the programming language C, you can access the members
of a struct by using the dot-operator:
</p>
<p>
<pre><code>
// Struct definition
typedef struct my_type my_type;
struct my_type
{
	int MemberA;
	char MemberB;
};

// Accessing the members of a struct in some function
void PrintMyType_ByValue(my_type MyStructInstance)
{
	printf("my_type members: \n");
	printf("  MemberA: %d\n", MyStructInstance.MemberA);
	printf("  MemberB: %c\n", MyStructInstance.MemberB);
}</code></pre>
</p>
<p>
C is pretty explicit about a bunch of things.
If you only have a pointer to the struct instance, you have to dereference
it first in order to access the members. 
Alternatively, you can use the arrow-operator to dereference and access
the members:
</p>
<p>
<pre><code>
// Struct definition
typedef struct my_type my_type;
struct my_type
{
	int MemberA;
	char MemberB;
};

// Accessing the members of a struct in some function, by passing a pointer
void PrintMyType_ByPointer(my_type *MyStructInstance) 
{
	printf("my_type members: \n");
	
	// Explicit dereference and access
	printf("  MemberA: %d\n", (*MyStructInstance).MemberA);
	printf("  MemberB: %c\n", (*MyStructInstance).MemberB);
	
	// Alternatively: Use the arrow operator
	printf("  MemberA: %d\n", MyStructInstance->MemberA);
	printf("  MemberB: %c\n", MyStructInstance->MemberB);
}</code></pre>
</p>
<h1>
 The "Problem"</h1>
<p>
When I write "new code", e.g. a new function, this isn't really an issue.
But if I <b>refactor / restructure existing code</b>, this gets pretty annoying 
pretty quickly.
</p>
<p>
Imagine you change a function to take the struct by pointer instead of by value
(or vice versa). In addition to changing the function signature and the 
function calls, you now have to replace the appropriate <code>.</code> with <code>-></code> (or vice versa).
As soon as multiple structs are involved, a blanket "find and replace" within the function
is no longer sufficient; instead you have to go over the compiler errors or vet 
each line individually. 
</p>
<h1>
 The "Solution"</h1>
<p>
At some point, you might begin to wonder: Couldn't you just make <code>.</code> work for both struct
literals and pointers? In other words: Couldn't you make the dot-operator automatically 
dereference the pointer? Couldn't you modify the language / compiler such that the following
"just compiles correctly":
</p>
<p>
<pre><code>
void PrintMyType_Idea(my_type MyValue, my_type *MyPointer)
{
	// Use "." for struct value
	printf("  MemberA: %d\n", MyValue.MemberA);
	printf("  MemberB: %c\n", MyValue.MemberB);
	
	// Make "." behave like "->" for struct pointer
	printf("  MemberA: %d\n", MyPointer.MemberA);
	printf("  MemberB: %c\n", MyPointer.MemberB);
}</code></pre>
</p>
<p>
I even randomly stumbled upon this twice on the internet
(<a href="https://guide.handmadehero.org/intro-to-c/day4/#4496">Handmade Hero</a> and <a href="https://x.com/tsoding/status/1527660533201178625">Tsoding</a>).
Apparently, there might be some <a href="https://stackoverflow.com/questions/13366083/why-does-the-arrow-operator-in-c-exist">historic reasons</a>
why C was initially designed this way.
However nowadays, the answer seems to be: <b>You could absolutely change the language that way</b>.
<a href="https://github.com/tsoding/tic-tac-toe-auto-deref">Tsoding even modified the C compiler "TCC" to support this behavior within 45min</a>.
<b>This doesn't even break (functioning) existing code</b>!
</p>
<p>
So this got me wondering: Has no one made a C proposal for that? 
</p>
<h1>
 The Proposal(s)</h1>
<p>
Good news: Someone has already put in the effort to make this an official proposal!
Sadly, it seems like this feature will not be part of the C/C++ standard (at least in the foreseeable future).
</p>
<p>
I found two proposals of this feature: One for <a href="https://gist.github.com/d3x0r/a574459e4ad18ea1e10a2367b06bd257">C</a>,
and one for <a href="https://gist.github.com/d3x0r/f496d0032476ed8b6f980f7ed31280da">C++</a>. 
I couldn't find any discussion for the C proposal, but there has been discussions on the C++ proposal, which also
includes some context for C.
</p>
<p>
As of writing, the C++ proposal is almost 5 years old, but the developments are, to my surprise, pretty recent.
The proposal has the document number <code>P2142R1</code>. My first search led to an open github issue on 
<a href="https://github.com/cplusplus/papers/issues/868">cplusplus/papers</a>. While the issue is still open, 
commenters mention that feedback was given to the author. In fact, another issue in 
<a href="https://github.com/sg22-c-cpp-standard-compatibility/sg-compatibility/issues/20">sg22-c-cpp-standard-compatibility/sg-compatibility</a> (for the same proposal)
is linked. This one is closed, with the final comment stating:
</p>
<p>
<figure>
	"We do not think this paper is a good candidate for inclusion in C++."
</figure>
</p>
<p>
The discussion of this proposal has been documented and is <a href="https://github.com/sg22-c-cpp-standard-compatibility/sg-compatibility/blob/main/README.md">linked</a> 
as well. While I initially thought that the rejection for C++ might not be a dealbreaker, the discussion / review / feedback paints a different picture.
In it, you find statements like:
</p>
<p>
<figure>
	"Beginning programmers at my most recent company still had trouble recognizing the need for ->"
</figure>
</p>
<p>
<figure>
	"The Linux kernel developers actively don't want this; -> heralds a potential cache miss and allowing . hides errors."
</figure>
</p>
<p>
<figure>
	"I'll drop the paper; <b>WG14 was interested if WG21 was</b>." (Emphasis added by me; WG14 being the working group for C, while WG21 is the working group for C++)
</figure>
</p>
<p>
Due to C++'s operator overloading, the issue of adding this automatic dereference becomes more complicated, 
as C++ allows custom definitions of the <code>-></code> operator for your structs/classes, but not the <code>.</code> operator.
Quite frankly, I don't really care too much about C++, but this rejection effectively meaning a rejection
for the C proposal is quite the downer for me.
</p>
<p>
To my surprise, the argument of ease of refactoring didn't come up in the discussion at all
(while the argument is made in the proposal). I don't think parity with other languages, 
nor potentially confusing for beginner programmers make good pro/contra arguments 
in programming language design.
</p>
<p>
I also find the argument of potential cache-misses a bit weak.
It's not wrong; but I find it hard to think of a scenario where I'm super aware about individual cache-misses,
while not being aware of where my stuff is stored in memory.
It's quite the opposite: Most of my code where I switch between passing-by-value and passing-by-pointer, thus
leading to refactoring annoyances, is not code where I worry about cache-misses in the first place.
</p>
<p>
And finally, I just don't understand the argument that "allowing . hides errors".
I assume that the author is imagining a scenario where one would e.g. switch from passing-by-value to passing-by-pointer,
and the switch simply compiling would lead to missing null-pointer-checks or something like that? 
Personally in this context, most of my annoyances stem from changing how I pass the data to functions. 
So this requires be changing the function signature, at which point I'm automatically at the function definition,
confronted with potential missing null-pointer-checks (at least as much as I am when changing <code>.</code> to <code>-></code>).
</p>
<h1>
 Conclusion</h1>
<p>
I'm sad that one of the few pain points I have when using C will not be alleviated, especially
considering how viable and easy fixing this problem would be.
Heck, you can even imagine emitting an optional compiler warning for the people which
prefer sticking to <code>-></code>, which would make this change as appealing to everyone as possible.
</p>
<p>
Too bad! Instead, all I got was this lousy blogpost, such that I can reference the proposal and 
its discussion / rejection in the future.
</p>
<p>
<img src="./ItHurtsALittle.png" style="width:110px;height:125px;" />
</p>
]]></content>
</entry>
<entry>
<title>Quick Vent #2</title>
<link rel="alternate" href="https://p4m.dev/posts/26/" />
<updated>2025-01-15T00:00:00Z</updated>
<id>https://p4m.dev/posts/26/</id>
<content type="html">
<![CDATA[<p>
I feel bamboozled
<ul style="list-style-type:'- '"><li> Became chubby</li><li> Decide to at least move a bit more</li><li> Day 1: 10k steps</li><li> Day 2: 15k steps</li><li> Day 3: Right foot hurts too much to take a longer walk</li>
</ul>
</p>
<p>
DUDE. I'm already too lazy to do proper sports, but now my 
body is bitching about taking a fucking walk? It's <b>walking</b>.
Humans are designed to be able to walk, no?
</p>
<p>
<img src="./mood.png" style="width:500px;height:500px;" />
</p>
]]></content>
</entry>
<entry>
<title>Quick Vent About My PC Acting Up</title>
<link rel="alternate" href="https://p4m.dev/posts/25/" />
<updated>2024-11-17T00:00:00Z</updated>
<id>https://p4m.dev/posts/25/</id>
<content type="html">
<![CDATA[<p>
Turns out: Tech problems become infinitely more annoying
once you have a fulltime job.
<ul style="list-style-type:'- '"><li> PC does fucky shit when under full load, like<ul style="list-style-type:'- '"><li> completely freezing</li><li> ignoring all USB input, such that even replugging doesn't help until reboot</li><li> audio being muted / crackled / etc</li>
</ul>
</li><li> Used to only happen very rarely, but it's getting noticably worse</li><li> PSU dies </li><li> oh, maybe it was that old thing, not able to deliver enough power</li><li> Get a new one with plenty of power to spare</li><li> Same shit</li><li> try CPU stress test</li><li> everything works fine, so I guess it's the toasty GPU</li><li> I have a small PC case, so the temps are bad. I know they should downclock if too hot, but maybe the hardware is a bit fucky and overheats?</li><li> transplant the pc parts into a new case</li><li> new fans, new CPU cooler</li><li> way nicer to work with</li><li> do testing</li><li> problem is less pronounced, but still there</li><li> try GPU stress test</li><li> PC consistenly freezes or kills the driver</li><li> oh so the gpu is fucked</li><li> Severely powerlimit GPU</li><li> performance is fucked, but problem doesn't arise</li><li> try old gpu</li><li> similar symptoms, audio is fucked, but no crash</li><li> ?????</li><li> so it's not the GPU I guess?</li><li> check RAM, lower frequency (disable XMP profile)</li><li> still fucked</li><li> try various motherboard settings</li><li> still fucked</li><li> when just focussing on the switched parts, it has to be one of the following<ul style="list-style-type:'- '"><li> motherboard</li><li> CPU</li><li> storage</li>
</ul>
</li><li> But:<ul style="list-style-type:'- '"><li> Storage doesn't make any fucking sense</li><li> CPU could be possible I guess, but feels unlikely given that stress-testing the CPU doesn't do anything.</li>
</ul>
</li><li> so I feel like it has to be the motherboard</li><li> Remember that I have a second CPU laying around, which even fits in the socket, but 
I cannot test it due to incompatible BIOS versions</li><li> Fuck it</li><li> Ordered a second motherboard</li>
</ul>
</p>
<p>
I didn't want to spend my weekend on this shit.
I'm going to be so fucking pissed if it ends up being the CPU after all, 
especially because the CPU I use (5800X3D) isn't being sold anymore,
so I'd either have to 
<ul style="list-style-type:'- '"><li> buy used</li><li> downgrade</li><li> buy a new motherboard, RAM and CPU to upgrade</li>
</ul>
</p>
<p>
And now my entire room is filled with cardboard bullshit / packages /
screws / tools and shit aaaaaaaaaaaaaa
</p>
<p>
<img src="./RageIsConsumingMe.png" style="width:500px;height:616px;" />
</p>
<h1>
 Update 2024.11.19</h1>
<p>
I switched the motherboard, PC is working properly now.
</p>
<p>
<img src="./WeAreBack.png" style="width:500px;height:375px;" />
</p>
]]></content>
</entry>
<entry>
<title>Speeding Up Code At Work By >20x</title>
<link rel="alternate" href="https://p4m.dev/posts/24/" />
<updated>2024-11-09T00:00:00Z</updated>
<id>https://p4m.dev/posts/24/</id>
<content type="html">
<![CDATA[<p>
TLDR: The code was using a suboptimal data layout,
<ul style="list-style-type:'- '"><li> requiring conversions to other formats for intermediate processing and back</li><li> the memory layout was wasting most of the cache lines used</li>
</ul>
</p>
<p>
Links:
<ul style="list-style-type:'- '"><li> I used <a href="https://excalidraw.com/">Excalidraw</a> for the visualizations</li><li> If you want to learn all about how to program for modern desktop CPUs, 
checkout <a href="https://ComputerEnhance.com/">ComputerEnhance</a>.</li><li> The <a href="https://www.amd.com/en/search/documentation/hub.html">AMD Documentation Hub</a>.
I didn't actually read much from there, but if you want lookup some AMD CPU
specific things, this should be the place to do it.</li>
</ul>
</p>
<h1>
 The Setup</h1>
<p>
The software at work processes files containing signal values.
The size of these files can vary wildly - I've seen files consisting of a few kilobytes,
and I've seen some which take up several gigabytes.
</p>
<p>
We are working in C++, so for small signals, we simply store them 
using <code>std::vector&lt;float></code> <a href="#note-0" id="back-0">[0]</a>. 
In case you aren't familiar with C++: You can think of <code>std::vector</code> 
as a resizable array.
The software might apply some additional processing / conversions,
so we just create a new <code>std::vector&lt;float></code>. 
All the resizing and managing memory is handled by <code>std::vector</code>, 
such that we don't need to worry about it.
</p>
<p>
<img src="./01.png" style="width:472px;height:406px;" />
</p>
<p>
For small signals, everything is fine.
Displaying them just entails iterating over the array, 
using some knowledge about which range of indices are 
visible and relevant for the user.
</p>
<p>
However, these signals can get <b>large</b> <a href="#note-1" id="back-1">[1]</a>.
So large in fact, that displaying them quickly is kind of difficult:
Even if you know start/end indices, the sheer amount of 
values is completely overkill for displaying,
making you skip over most values holding the rest in memory for no 
good reason.
</p>
<p>
The authors of the file format came up with some <b>signal reduction</b> data.
Basically using some resolution factor, you can get a "pre-processed" signal,
where each entry contains
<ul style="list-style-type:'- '"><li> mean</li><li> min</li><li> max</li>
</ul>
</p>
<p>
One of these entries maps to <b>a lot</b> of the "raw" signal values,
such that the signal reduction data can be used for displaying 
(unless you are super zoomed in).
</p>
<p>
The code I was looking at decided to store this signal 
reduction data as <code>std::vector&lt;std::vector&lt;float>></code>:
</p>
<p>
<img src="./02.png" style="width:500px;height:381px;" />
</p>
<p>
Not pretty, but it works I guess.
However, there's two problems with this approach:
</p>
<p>
First, we do additional processing on the signal. 
The existing code is 
<ol>
<li> building three different <code>std::vector&lt;float></code> of the 
mean/min/max values</li><li> re-using the processing functions we have for "normal" signal values</li><li> converts the result back to the <code>std::vector&lt;std::vector&lt;float>></code></li>
</ol>
</p>
<p>
These conversions are obviously a complete waste of time; we
can just store three <code>std::vector&lt;float></code> and save us 
all of the conversion code.
</p>
<p>
However, even if we don't do any conversions, 
accessing all the values of <code>std::vector&lt;std::vector&lt;float>></code> comes 
with harsh performance penalties (when comparing to <code>std::vector&lt;float></code>).
This makes the conversion functions <b>even worse</b>.
</p>
<p>
To skip ahead, I switched the representation as follows:
<pre><code>
// From
std::vector&lt;std::vector&lt;float>>

// To
struct sample_reduction_data
{
	std::vector&lt;float> mean;
	std::vector&lt;float> min;
	std::vector&lt;float> max;
};</code></pre>
</p>
<p>
This resulted in a speedup of <b>>20x</b>.
For non-trivial files, we are talking
reducing the loading times from <b>1.2s to 0.06s</b>.
That's absolutely insane! Think of how many
generations of hardware it takes to give you a speedup of 20x.
And it resulted in <b>less code</b> because the conversion functions are
gone.
</p>
<p>
So, what do I mean with performance penalties?
</p>
<h1>
 Behind The Abstraction</h1>
<p>
First, we need to understand, very roughly, 
how <code>std::vector</code> works.
</p>
<p>
<code>std::vector</code> handles all the memory allocations / re-allocations / deallocations.
You can easily hold gigabytes of data using an <code>std::vector</code> you placed on the stack,
without crashing your program.
This is because the actual elements of <code>std::vector</code> aren't allocated on the stack.
The elements are stored somewhere on the heap, 
which I like to imagine like this:
</p>
<p>
<img src="./03.png" style="width:500px;height:195px;" />
</p>
<p>
Second of all, the memory setup of modern desktops is pretty important.
During university, most of the time, this is just some irrelevant 
implementation detail. 
For the most part, Computer Science is about the science of computing stuff, and 
not really computers themselves.
</p>
<p>
<img src="./04.png" style="width:500px;height:290px;" />
</p>
<p>
But we are dealing with <b>actual</b> hardware now, and the performance penalty 
comes from wasting the CPU cache.
CPUs are <b>extremely fast</b>. 
So fast in fact, that requesting memory from your RAM is 
utterly dogshit slow. 
So hardware designers decided to use several levels of CPU caches <a href="#note-2" id="back-2">[2]</a>:
<ul style="list-style-type:'- '"><li> The L1 is your very fast cache. Unless your stuff is in a CPU
register, this is as fast at it gets.
Fast is expensive, so this one is the smallest.
Each core has its own L1 cache.</li><li> The L2 is larger, but also slightly slower.
Each core also has its own L2 cache.</li><li> The L3 is the largest cache before you go to your RAM. 
But it's also the slowest of the three CPU caches.
(And for current hardware, the L3 is usually shared among all cores).</li>
</ul>
</p>
<p>
<img src="./05.png" style="width:500px;height:542px;" />
</p>
<p>
So whenever you need some bytes (which are not in a CPU register), your CPU
<ul style="list-style-type:'- '"><li> first checks the L1,</li><li> then the L2,</li><li> then the L3,</li><li> and finally your RAM <a href="#note-3" id="back-3">[3]</a></li>
</ul>
</p>
<p>
If it finds the bytes you are looking for, it brings the bytes into 
all caches, replacing older stuff <a href="#note-4" id="back-4">[4]</a>.
</p>
<p>
Now that you know all of this, we can talk about the actual reason
why the data format was bad: Cache lines.
</p>
<h1>
 Cache Lines</h1>
<p>
You might imagine that your CPU queries individual bytes,
e.g. four bytes when trying to access a float in memory:
</p>
<p>
<img src="./06.png" style="width:500px;height:68px;" />
</p>
<p>
<b>That is incorrect for most desktop CPUs</b>.
</p>
<p>
Your CPU requests memory bytes in form of <b>cache lines</b>.
Each cache line consists of 64 bytes, so even if you 
query just a single <code>uint8_t</code>, if the cache line isn't 
in your cache, you are pulling in 64 bytes at a time <a href="#note-5" id="back-5">[5]</a>.
</p>
<p>
If you are really interested, you should check the documentation from your CPU vendor. 
For example for AMD, you can look this stuff up in the 
<a href="https://www.amd.com/en/search/documentation/hub.html">AMD Documentation Hub</a>:
</p>
<p>
<img src="./07.png" style="width:500px;height:185px;" />
</p>
<p>
So when you access the single float, it will fall into some cache line:
</p>
<p>
<img src="./08.png" style="width:500px;height:82px;" />
</p>
<p>
When thinking about performance, you have to keep these cache lines in mind.
As I said for small signals, we use a single <code>std::vector&lt;float></code>.
When processing all values, the CPU will (roughly) work like this:
</p>
<p>
First, we start with the first value. It's likely not in the cache,
so that's a cache miss, meaning we need to fetch the cache line.
</p>
<p>
<img src="./09.png" style="width:500px;height:247px;" />
</p>
<p>
Now we process the second value of the <code>std::vector&lt;float></code> elements.
As the elements are right next to another, these two elements
will (likely) share the same cache line. 
As we just fetched the same cache line, the value is in our cache,
so accessing this element is super fast now.
</p>
<p>
<img src="./10.png" style="width:500px;height:206px;" />
</p>
<p>
A cache line is 64 bytes. 
A single float is 4 bytes. 
If we process the elements in order in quick succession, we will get:
<ul style="list-style-type:'- '"><li> a cache miss for the first element of the cache line,</li><li> cache hits for the next 15 elements </li>
</ul>
</p>
<p>
<img src="./11.png" style="width:500px;height:206px;" />
</p>
<p>
And obviously, this process repeats once we reach the next cache line:
</p>
<p>
<img src="./12.png" style="width:500px;height:214px;" />
</p>
<h1>
 Putting It All Together</h1>
<p>
You might already now understand why a flat <code>std::vector&lt;float></code> is 
preferrable when processing lots of values, but I'll go over
it anyway.
</p>
<p>
To recall, the original code used a <code>std::vector&lt;std::vector&lt;float>></code>,
which stores elements in groups of three:
</p>
<p>
<img src="./13.png" style="width:500px;height:315px;" />
</p>
<p>
So when we process all elements, we are wasting most of our cache line:
<ul style="list-style-type:'- '"><li> the first element is not in cache. Cache line is fetched. This is slow.</li><li> the next two elements are in the cache. This is fast.</li>
</ul>
</p>
<p>
<img src="./14.png" style="width:500px;height:212px;" />
</p>
<p>
The process repeats, as the next three elements are probably somewhere else entirely.
</p>
<p>
<img src="./15.png" style="width:500px;height:528px;" />
</p>
<p>
A float is 4 Bytes, so using three floats of a cache line leaves us with an 
cache line utilization of <code>3*4 / 64 = 0.1865 => 18.75%</code>.
Ouch!
</p>
<p>
Let's compare this to the "three seperate <code>std::vector&lt;float></code>"-approach.
In memory, it will look something like this:
</p>
<p>
<img src="./16.png" style="width:500px;height:392px;" />
</p>
<p>
So when processing all elements, this is our cache line utilization:
</p>
<p>
<img src="./17.png" style="width:500px;height:413px;" />
</p>
<h1>
 Conclusion</h1>
<p>
No wonder the performance is much better with this approach.
Caches are a huge deal when it comes to performance. 
And here, these "optimizations" <a href="#note-6" id="back-6">[6]</a> stack on top of another:
The better cache lines speed stuff up a lot, and 
you can multiply the performance boost with the 
reduced amount of computational waste due to the conversions.
</p>
<p>
Once again: This was a <b>>20x</b> performance improvement, while
<b>using less code</b>!
And I'd even argue the code is more readable, given that 
<code>std::vector&lt;std::vector&lt;float>></code> doesn't tell you much
about the sizes of the nested <code>std::vector&lt;float></code>.
</p>
<p>
I didn't apply any fancy algorithms, I just shuffled some things in memory.
Same "O(n)" stuff.
This is why I like to learn stuff about computers. 
Treating everything as a magical blackbox/abstraction can very quickly
lead to wasted performance.
</p>
<p>
I'll probably port a short explanation of CPU Cache lines 
to the <a href="https://HowTheFu.cc">HowTheFucc</a> website, 
but for the time being, this is my write up of this
interesting incident at work.
</p>
]]></content>
</entry>
<entry>
<title>Forcing A Positive Perception Of Oneself</title>
<link rel="alternate" href="https://p4m.dev/posts/23/" />
<updated>2024-09-16T00:00:00Z</updated>
<id>https://p4m.dev/posts/23/</id>
<content type="html">
<![CDATA[<p>
Super spontaneous post,
a short announcement in order to hold myself (more) accountable:
I will try to perceive / talk to myself in a more positive light,
and I guess we'll see how that works out and where I end up.
</p>
<p>
Everyone keeps saying that you shouldn't belittle oneself, 
but for some reason I never thought about <b>why</b>.
My intuition tells me it's because there's a fine line between
"reasonable self-criticism" and "the downwards spiral of self-hatred".
But as long as I don't feel depressed, it's fine, right?
</p>
<p>
Here's a short series of statements. 
If they are true and/or logically follow from another, 
then they make a pretty good argument as to why I should work on my
perception of myself:
<ol>
<li> Everyone is, to some extent, shaped by their environment.
(This shouldn't be controversial)</li><li> Thus each individual person / friend / acquaintance has 
an impact on you.
The extent might vary (family member / childhood friend vs brief acquaintance), but it should be there.</li><li> If they have an impact, the medium through which one is 
impacted can vary.
It doesn't need to be an action or activity; just conversations or monologues 
also have an impact.</li><li> If all of this holds for speaking with friends, why shouldn't 
your own thoughts or self-talk have an impact?
Imagine you were stranded on a deserted island. 
Would your character development be stopped? 
If the only conversations you had were with yourself, 
would the way you think about yourself really have no impact on
how you develop?</li><li> Therefore, positive thoughts about myself should, in the long term, 
have a measurable effect on myself.</li>
</ol>
</p>
<p>
Obviously I don't disregarding any self-criticism in favor of
"I'm great, actually". 
But, at least for the moment, I believe just shifting the 
perspective on some issues in a more neutral light 
could positively influence the development of oneself.
Maybe even giving yourself a pat on the back at the end of the day 
for finishing task x, even if it's just a routine, or something mundane.
</p>
]]></content>
</entry>
<entry>
<title>How Did University Affect Me?</title>
<link rel="alternate" href="https://p4m.dev/posts/22/" />
<updated>2024-09-12T00:00:00Z</updated>
<id>https://p4m.dev/posts/22/</id>
<content type="html">
<![CDATA[<p>
I recently got the simple question of how the years I spent at university changed me.
Like a well adjusted human being, I responded to a question consisting of eight words
by writing several paragraphs about my expectations, the reality, university vs school and so on.
</p>
<p>
I'm going to borrow from that schizopost and try to summarize my thoughts on this in a (somewhat) more organized fassion, as I have thought about this a bunch.
</p>
<h1>
 Expectations</h1>
<p>
I was roughly 18 years old when I signed up for a Computer Science Bachelors Degree at a rather large german university. And at the time, I was looking forward to it. 
School contained a lot of subjects I did not care about, and this rather common experience feels like a vicious circle: 
People don't want to attend classes or engage with the subject. 
People talk more among themselves or disrupt the lesson, which usually disturbs the rest of the class, which is annoying and makes me not want to attend the lesson, and so on <a href="#note-0" id="back-0">[0]</a>. 
</p>
<p>
Back then I was already pretty introverted / antisocial. 
Surprisingly, this got me on the good site of some teachers:
If you are part of the smaller group of people who just shut up and try to finish up the assigned work, you leave a better impression than other students who are disrupting the lesson.
</p>
<p>
So I imagined that a lot of things would change in university. 
After all, my fellow university students <b>chose</b> to study Computer Science as well.
While I was one of <b>the</b> computer nerds in my grade, university is probably full of people like me.
That should get me out of my shell: Lots of nerds / like-minded people, probably with at least some shared interest in computers or programming.
No more awkward group assignments; instead people are doing their share of work. 
The lectures, even if dry, should be related to the practice of programming, right?
</p>
<h1>
 Reality: Applicability</h1>
<p>
Sadly, very little of that was true. 
</p>
<p>
Most lectures weren't interesting to me. 
To say that the courses were dry would be an understatement:
It feels like the practical parts, especially in the beginning, were rushed through. 
As if learning about the programming paradigm and the syntax of the language is all there is. 
</p>
<p>
At times, it felt like the professors were going out of their way to make their lectures as unapplicable as possible.
Imagine my frustration when I tinkered around with OpenGL, only to find the same matrices and space transformations 
which are found in linear algebra. 
Why not link these things together? Every 3D application extensively relies on linear algebra! 
Closing the gap between theory and practice cannot be more obvious. 
And hell, the visualization would have been more than helpful! <a href="#note-1" id="back-1">[1]</a>
</p>
<p>
I chose the module compiler construction. 
The idea of creating a small programming language, or even just parts of it, sounds awesome!
But nope, we never did a lot of code. 
We primarily """learned""" to """write""" (or rather define) a compiler mathematically.
I left that course roughly as knowledgable as I went into it; nothing an afternoon of Wikipedia 
couldn't achieve.
</p>
<h1>
 Reality: People And Introversion</h1>
<p>
I also didn't become more extroverted / social, it was quite the opposite. 
I became even more of a hermit than during school. 
I had one or two university friends (one of which I still keep in touch with) - that's it. 
It's not like wasn't able to socialize; but clearly, my guess that I'd magically become more extroverted fell flat.
When you are not forced to interact with people, I sure as fuck don't choose to start conversations.
</p>
<p>
For a while, I was wondering where the fuck I would end up in 10 years or something. 
Not from the perspective of a job or anything, I mean just the social aspect. 
Most of the friends of my parents are people which my mother met during university.
In contrast, I went out of university with <b>1</b> person I keep in touch with. 
But to be clear: That guy is awesome. 
We did, whenever possible, all of our assignments together, shared our notes and prep-work for exams, and so on.
Even if one of us was slacking in one subject, we'd usually make up for it by focussing on the homework of another one.
</p>
<p>
That one friend for group assignments was crucial, because here's something we both realized far too late:
The productive work groups are formed in the first semester, and
they are likely to stick together afterwards.
The people which switch groups are, a lot of the time, the types of people which you don't want to have in your group assignments.
That part we all know of from school doesn't change.
Not after the first semester(s) where people are filtered. 
Not at to the end of the Bachelor's Degree.
Not even in your masters or PhD studies, from what I gather from friends and relatives.
There will always be people like that.
</p>
<h1>
 Pacing And Responsibility</h1>
<p>
In school, keeping up with the course is often just paying attention to the lessons at hand.
For <b>very</b> easy courses, that stays the same.
For a lot of harder courses, this doesn't hold up. At all.
</p>
<p>
If you attend a large university like I did, the professor doesn't know you.
They don't give a shit if you don't attend the lesson. It's not their fucking problem.
A lot of the times, even the homework was voluntary.
I like this "no bullshit" attitude: You're responsible with keeping up, in whatever way you see fit.
Good luck.
</p>
<p>
Here's another experience you will hear a lot:
If you didn't struggle with school, you will likely get fucked in the first semester of university,
because the little effort you put in during school, sure as fuck doesn't fly here <a href="#note-2" id="back-2">[2]</a>. 
I screwed up my first semester, as many friends / of mine did.
Hell, my 6 semesters degree took me 10 semesters.
</p>
<p>
And noone cares. 
</p>
<p>
Failing like that is/was, I think, a pretty important experience to me.
Struggling to make progress, to structure things on your own, 
to be confronted with your own lack of discipline,
failing due to noone's fault but your own. 
</p>
<p>
My parents <b>always</b> had my back, and supported me in every way imaginable. 
That still didn't stop me from thinking that I was a complete failure at times.
Or the rare stressful evenings of the Bachelor's Thesis at some point - wowie, I cannot recall 
another instance where I was freaked out like that,
even though I knew: All I had to do was pass,
which is really difficult to fail if you put at least <b>some</b> amount of time into it.
</p>
<p>
I'm not sure how much I changed in terms of productivity. I'm still slacking a lot and making less 
progress than I'd like (as if I have written about this before, curious).
But my attitude to / perspective of these things have changed drastically, I think. 
It's as obvious as ever that the situation of was in was anything but dire. 
There was no reason to freak out.
Even if it feels like the world is coming down hard, it's probably fine.
</p>
<h1>
 The Importance Of Networking</h1>
<p>
One of the slightly scary lessons I learned is the importance of networking.
A single person was responsible for 40%-60% of the practicals I did during university.
If it wasn't for her, a large part of the more interesting part of university would have been missing.
</p>
<p>
Here's a summary:
<ul style="list-style-type:'- '"><li> We were required to take a practical module. 
My uni-buddy and me picked a course about making a bot for a modified game of reversi in groups,
which ended in the bots competing against each other in a tournament.
That person was managing / guiding said module.</li><li> Due to our code- and report-quality <a href="#note-3" id="back-3">[3]</a>, we got an offer for a student assistant job from her, 
where we were working on a C-code generator, which was used to compare the performance 
of various (C-)model checkers.</li><li> During / at the end of that job, we were talking about needing to find a Bachelor Thesis.
She asked her colleagues if there was anything with available with some coding,
and that's how I got my Bachelor Thesis on implementing and comparing 
some algorithms.</li>
</ul>
</p>
<p>
Ironically enough, if you only know the name of the academic chair this all 
happened at, you'd think that this was the most dry shit ever.
While these weren't the only times were we programmed for some university stuff,
it definitely was like half of it. 
If it wasn't for said person, my whole university experience might have
been significantly worse.
</p>
<h1>
 Reflecting And Learning</h1>
<p>
The one part I miss about university is the amount of "free time" you have.
I write "free time", as I was (and still am) absolutely dogshit at 
scheduling me shit properly.
This led to me feeling like I never can relax completely, like 
there is always some shit I should be studying / learning for / etc.
But I believe that this amount of time one is free to schedule was 
crucial for some self-reflection.
</p>
<p>
In contrast with my current fulltime job, it's nice to know how
many hours you have to work for in the day. 
Once that timer is up, you are free to relax.
I'm aware that I could have treated university like a job as well,
but I lacked the discipline (and probably still do).
It's also nice to know that every task at work, 
regardless of how stupid the problem is, 
is actually some task that people want to have completed,
one way or another.
That's a huge motivation-boost in comparison to some of the university exams,
with answers that could have been found on the internet or my notes, 
if only I had access to it.
</p>
<p>
I learned a lot about myself during university. 
I got confronted with a lot of my shortcomings. 
I learned about what motivates me: 
For me, the same course material can be anything between "boring as fuck" and "super interesting",
just depending on the context and applicability.
</p>
<h1>
 End</h1>
<p>
There's probably a lot more which I could write about.
I guess that shouldn't really surprise me, given that it was ~5 years of my life.
There was also the covid-semesters, which was an interesting experience on its own, 
but now that I see how much I ended up typing in my text editor, 
I think this is a good moment to stop for the time being. 
</p>
]]></content>
</entry>
<entry>
<title>Burn Down The Tower Of Software</title>
<link rel="alternate" href="https://p4m.dev/posts/21/" />
<updated>2024-09-06T00:00:00Z</updated>
<id>https://p4m.dev/posts/21/</id>
<content type="html">
<![CDATA[<p>
When I work on my personal projects, I program in C using a small amount of libraries for specific things.
To compile, I use a unity-build: Everything is compiled within a single compilation unit; 
the main <code>.c</code>-file includes other <code>.c</code>- and <code>.h</code>-files.
This vastly simplifies the compilation process, such that my "build-system" is just a single 
<code>build.sh</code>-script.
</p>
<p>
While this approach works fantastically for me, I used to think that this is only feasible for small projects.
"This doesn't scale" or "This doesn't support x" is thrown around a lot.
After all, compile any somewhat popular open source project, and you'll find a combination of
<ul style="list-style-type:'- '"><li> Ninja</li><li> cmake</li><li> make</li><li> meson</li><li> Visual Studio Project / Solution Files</li>
</ul>
</p>
<p>
In contrast to my personal projects, I have worked on some larger projects for 
my bachelor thesis, student assistant job and now at a company as a full time software developer.
These projects span from ~20k LoC, to somewhat recently started projects using
C++, C++/CLR and C#  (for backend, interop and frontend, respectively),
to ~1 million LoC of hacky mess of C++ code.
</p>
<p>
There isn't a single instance in which I don't miss my simple setup.
</p>
<p>
I wish I could say that the mountain of complexity that is introduced to these projects comes with a tremendous amount
of benefits, but from my point of view, the upsides are pretty limited.
</p>
<p>
The tooling, while supporting what feels like a billion different things, always falls short for the 
usecases we need, while containing a lot of baggage in terms of complexity, lacking ease-of-use, 
prone to failure, speed, and lack of flexibility, as soon as you do anything that deviates from the 
trivial case.
</p>
<h1>
 Anecdote Visual Studio</h1>
<p>
This software is so unbelievably fucking slow, at every fucking opportunity.
Opening files? Finding stuff? Slow. Jumping around? Slow. 
Need to install an update? 30min down the drain, if not more if you skipped a bunch. 
</p>
<p>
The information density of the software is also dogshit. "Compilation error in this header".
Understandable - now, which <code>.cpp</code> did you try to compile when that error occured? 
It doesn't know; or rather it doesn't want to tell me, for some reason. 
It is easier + faster to copy the behemoth of a <code>msbuild.exe</code> compilation command into a console, 
and see which compilation step failed.
</p>
<p>
Visual Studio comes with a bunch of optional features and support, like Google Test (GTest) and 
Address Sanitizers (ASAN for short). 
If you enable ASAN on your project and run the program <b>from the Visual Studio debugger</b>, 
it will crash and complain about a missing DLL.
Enabling ASAN is done using a drop-down option, but there is 
<ul style="list-style-type:'- '"><li> no out-of-the-box support for actually running the software, if Visual Studio / the software wasn't started 
from the developer console environment</li><li> no indication that you have to do that</li><li> no mention of where the DLL is located</li><li> no automatic copying of the DLL next to the resuling program</li>
</ul>
</p>
<p>
Other fun thing: You can enable ASAN for DLLs, which you can reference from a C# project to execute native code.
No complaints from the compiler, linker, nor Visual Studio. 
But even if the DLL is part of PATH, the C# program crashes. 
Even if you copy the DLL over, the program crashes.
</p>
<p>
And googling reveals that in order to be able to use ASAN with C#, you'd 
have to compile the entire C# runtime with ASAN support enabled. 
</p>
<p>
As if this wasn't already a huge waste of my time, 
here's another fun story:
</p>
<p>
Visual Studio offers both configurations (by default: "Debug" and "Release"), 
and the target architecture (e.g. "Win32" and "x64").
But you are free to add your own configurations! 
Visual Studio even provides a handy "copy configuration from"-optio, such 
that I can e.g. create a separate <code>Debug_Clang</code> or <code>Release_ASAN</code> configuration,
such that I can contain my changes to these configurations and be able to 
quickly switch between them.
</p>
<p>
But as soon as you do that in conjunction with GTest,
your debug builds will fail. 
Why?
Because the linking is done using some XML-configuration files (kill me),
which conditionally reference the libraries you need to link to depending on the 
configuration name.
If your configuration is called "Debug", it's linking against the debug libraries of GTest. 
For <b>all other configuration names</b>, it's using the release version.
And there doesn't seem to be a way to overwrite this behavior in the Visual Studio UI.
And here's the best part: This has been 
an issue <a href="https://developercommunity.visualstudio.com/t/google-test-project-link-fails-if-project-configur/474186">since 2019</a>,
with <a href="https://developercommunity.visualstudio.com/t/Google-test-project-doesnt-compile-on-c/10351716?space=62&amp;q=Test+Adapter+for+Google+Test+">no plans of fixing it</a>.
Ironically enough, I encountered the same issue when using the C++ package manager Conan; but hey,
at least that one is open source.
</p>
<h1>
 The Problem In General</h1>
<p>
It feels like as soon as you buy into a complicated system like
Visual Studio / large build environments, or languages like modern C++ with paradigms like OOP,
you are not spending time fixing actual problems.
Instead, a large amount of time is wasted on trying to fix issues which 
shouldn't exist in the first place.
</p>
<p>
With C, I have a simple language, including its various shortcomings.
There is not a lot of hidden things going on (in comparison to other languages).
I don't need to think about memory management thanks to arenas. 
For the most part, I have a decent control over what I want the computer to do.
</p>
<p>
With "professional", modern C++, the language is a mess:
<ul style="list-style-type:'- '"><li> The compilation time of large, templated projects quickly grows out of hand.</li><li> In order to solve the memory issues I didn't have beforehand, 
everyone is advised to use <code>std::unique_ptr&lt;...></code> and <code>std::shared_ptr&lt;...></code> everywhere. </li><li> In order to solve the various casting problems I didn't have beforehand, 
you are instructed to use one of <ul style="list-style-type:'- '"><li> <code>std::static_cast&lt;..></code>, </li><li> <code>std::dynamic_cast&lt;..></code>, </li><li> <code>std::reinterpret_cast&lt;..></code>, or </li><li> <code>std::bit_cast&lt;..></code>, </li>
</ul>

as C-style casts are considered "bad practice".</li><li> Usage of const whenever possible aims to prevent bugs 
I didn't have, and might force the use of <code>std::const_cast&lt;...></code>, which I didn't need.</li><li> Zero-Cost abstractions and possible performance optimizations using const, which don't happen in practice,
are parroted, but let's fragment the memory some more and create more objects. 
After all, it's "easier" and "more modern" that way.</li><li> Classes and Structs are now used to tightly couple data to behavior. 
It becomes impossibly difficult to understand the data and the operations one is working with.
Separating these two turns, which you get by default in C, turns into a long-term 
problem, spanning over several sprints.</li><li> While <code>-Wall -Wextra -Werror</code> used to have me covered,
the implicit conversions happening everywhere warrants the introduction of the <code>explicit</code> 
keyword for most constructors, for situations I didn't use to have.</li><li> The introduction of OOP with v-tables blurries the explicit data layout of a class / structure.
In order to cope with the plenty newly introduced pitfalls (while I'm still waiting for the 
benefits to become apparent), people come up with stuff like <code>Rule of Three</code> or <code>Rule of Five</code>.</li>
</ul>
</p>
<p>
Feel free to add to the list. 
These are the ones I can come up with on the spot. 
I hope it illustrates how buying into a set of beliefs / working within a certain environment
redirects a lot of energy to discussing strategies and coming up with solutions for problems 
that you could also just avoid altogether.
</p>
<p>
And for those that still claim that this is simply required for large scale projects,
checkout the C/C++ debugger 
<a href="https://github.com/EpicGamesExt/raddebugger/">RadDbg</a>:
<ul style="list-style-type:'- '"><li> Written in C</li><li> Compiled in a single (or at least very few compilation units)</li><li> Dependencies are contained in the repository <a href="#note-0" id="back-0">[0]</a></li><li> Build system is <code>build.bat</code> for Windows and a <code>build.sh</code> for Linux</li><li> To preprocess data, a meta-program is compiled and executed, before the main application is compiled.
I'm currently trying incorporate this simple idea into my projects.
So far, I'm very pleased with the results and flexibility.</li><li> The sofware is fast (and pretty!)</li>
</ul>
</p>
]]></content>
</entry>
<entry>
<title>Dreams And Reoccurring Nightmares</title>
<link rel="alternate" href="https://p4m.dev/posts/20/" />
<updated>2024-09-05T00:00:00Z</updated>
<id>https://p4m.dev/posts/20/</id>
<content type="html">
<![CDATA[<p>
Dreams are a funny thing.
I remember dreaming "in a normal frequency" when I was a child, but that
sort of stopped when I was a teenager; that is, 
dreams were a rare occurrence for me (less than once a month).
</p>
<p>
Way later during university, some weird dream caused me 
to start a dream journal on a small notebook.
Apparently recalling the dream(s) immediately after waking up helps a lot
with having dreams in general:
During that period, I had a lot of dreams to the point where I ended 
up filling the whole notebook, after which I stopped.
Nowadays, I dream on occasionally - once every week or two maybe? 
</p>
<p>
For the most part, my dreams are largely "neutral" in nature.
The contents are usually a series of random, uninteresting events,
which aren't even related to any recent events,
with zero impact on my mood or thoughts <a href="#note-0" id="back-0">[0]</a>.
That's also the reason why I haven't started another dream journal.
</p>
<p>
One exception to the unremarkable dreams are rare nightmares. 
While still unrelated to my day-to-day life, 
a suspiciously large percentage of my nightmares are about some teeth 
issues. 
It's always either multiple teeth falling out,
our a teeth being shattered, resulting in me panicking and trying
to spit the remains out of my mouth. 
It's a disgusting, physical sensation. 
</p>
<p>
Nightmares about teeth stuff are, apparently, really common. 
A quick search for "nightmare teeth" on Google Scholar had some interesting 
results <a href="#note-1" id="back-1">[1]</a>. 
First, I learned that there is a 
<a href="https://antoniozadra.com/sites/default/files/biblio/nightmares_and_other_common_dream_distur_2005.pdf">"DSM-IV Diagnostic Criteria for Nightmare Disorder"</a>.
Not relevant to me, but I never thought about such an disorder existing
in the first place. 
Second,
<a href="https://www.frontiersin.org/journals/psychology/articles/10.3389/fpsyg.2018.01812/full">there is a study about trying to correlate teeth nightmares with 
either psychological distress or teeth tension</a>.
In their results, assuming I skimmed this correctly,
<ul style="list-style-type:'- '"><li> teeth tension was only slightly correlated,</li><li> psychological distress was uncorrelated (in contrast to some other study).</li>
</ul>
</p>
<p>
I would have expected a stronger correlation on at least one of these to be honest.
I have neglected going to the dentist though, so I should probably 
address that sometime soon.
Reading that the brain might also just fuck with you for no reason,
even if you are doing fine otherwise, sure is ... something.
</p>
<p>
The other reoccurring nightmares I have are about school.
It's so dumb - it's usually about a test I didn't learn for,
or some homework I forgot to do. 
Like, brain, my brother in christ, <b>IT'S BEEN OVER 5 YEARS</b>.
<b>I HAVE A JOB NOW</b>. <b>I AM AN ADULT</b>. 
I never struggled to just pass a school year either, but that doesn't 
stop my brain from randomly producing a dream in which 
I'm stressing out over passing a math class.
Fuck, math class was one of my good subjects; at least 
come up with something plausible.
</p>
<p>
After waking up, these rare nightmares aren't 
really stressing me out or anything.
In dreams, I "see" sequences (often less detailed in a snapshot fassion), 
there's "sound", but I almost never have a sense of touch. 
I do have one every single time that teeth dream appears, though.
In contrast to all other "non-nightmare dreams", it's so rare
that they always stick out for me, and I even remember a handful of them
years later.
</p>
<p>
For example, 
there was one dream taking place in some weird city.
I entered a room which was kind of like a bar,
and then suddenly I was hugging someone.
And everytime I hugged them, they hugged me back stronger.
Even though that was a stranger, I felt incredibly safe(?) 
and comforted that moment, until it slowly faded into me 
waking up <a href="#note-2" id="back-2">[2]</a>.
It's been years, but I don't think I will forget that one anytime soon.
</p>
<p>
Other senses like smell or some other lasting emotions rarely occur.
I'll keep you posted in case something comes up. 
</p>
]]></content>
</entry>
<entry>
<title>Baking Bread</title>
<link rel="alternate" href="https://p4m.dev/posts/19/" />
<updated>2024-06-02T00:00:00Z</updated>
<id>https://p4m.dev/posts/19/</id>
<content type="html">
<![CDATA[<p>
So I found this Baguette Recipe that I 
really liked (<a href="https://howthefu.cc/posts/09/index.html">link</a>).
It's 
<ul style="list-style-type:'- '"><li> very easy to do, </li><li> is not labour intensive,</li><li> tastes pretty good, and</li><li> it consists of very few ingredients.</li>
</ul>
</p>
<p>
The only thing I was struggling with was the "fluffyness" of the baguette.
The original recipe used more water, but I couldn't reproduce 
it, even after experimenting a bunch:
<ul style="list-style-type:'- '"><li> Amount of yeast? Didn't seem to change much.</li><li> Amount of salt? Changed the taste, but not the consistency.</li><li> Less water? Baguette becomes flat and looks weird.</li><li> More water? Baguette is partially less flat, 
but the dough quickly becomes runny, which also results in a flat one.</li>
</ul>
</p>
<p>
Last week I purchased two other flours - same type and everything, just a different brand.
A quick glance at the food composition data was a bit underwhelming, as they didn't seem to differ much at all.
Yesterday, I tried one of them out.
Mixing with my usual ingredient proportions made the dough way too dry. 
I added some water, which was cleary too much, and I course corrected by gradually adding 
more flour until I was satisfied with the texture.
Today I baked the dough, and look at that:
</p>
<p>
<img src="./Fluffy.png" style="width:500px;height:232px;" />
</p>
<p>
The baguette is fluffy, no longer flat as fuck, and it still tastes good.
I might want to focus on getting the baguette to have a more aesthetic shape,
but for now I'll call this a complete success. 
</p>
]]></content>
</entry>
<entry>
<title>Pleased With Progress</title>
<link rel="alternate" href="https://p4m.dev/posts/18/" />
<updated>2024-05-09T00:00:00Z</updated>
<id>https://p4m.dev/posts/18/</id>
<content type="html">
<![CDATA[<p>
This morning I stumbled upon a piano track on youtube. 
I thought it sounded both easy and pretty, found sheets for it online and gave it a shot.
It's a super easy to memorize song, so after an hour (maybe two?) I also recorded 
and uploaded it to the site this evening. 
</p>
<p>
Is it difficult to play? Nope, it's really not that impressive.
But I was certainly not able to do that when I started playing the piano.
The other songs are way longer and more complex, so just memorizing them is a pain in the ass, 
let alone getting good enough such that I don't stumble my way through them.
In comparison, this short one is a nice change of pace, and as I upgraded my audio setup, 
recording the piano doesn't require me to rewire and configure everything.
</p>
<p>
So even if I wasn't productive on this holiday - today was a good day.
</p>
]]></content>
</entry>
<entry>
<title>Stories And Types Of Media</title>
<link rel="alternate" href="https://p4m.dev/posts/17/" />
<updated>2024-04-21T00:00:00Z</updated>
<id>https://p4m.dev/posts/17/</id>
<content type="html">
<![CDATA[<p>
I act grumpy at a lot of things: Software, games, movies, books - you name it.
You might have even read about me trash talking certain games <a href="#note-0" id="back-0">[0]</a>.
Lately, I have been thinking about stories and their relationships with the types 
of media they are presented in. 
And I think this, to some extent, covers the difference between experiences 
that I will continue to remember for years, and e.g. games that I, at most, will rant about.
I've been strugging to verbalize these thoughts, so this will be a super schizo rambling.
Ironically enough, this exact problem is caused by the thing which I think makes certain 
experiences unforgettable.
</p>
<p>
You might get something out of it, but probably not. 
</p>
<p>
A lot of games feel like two distinct experiences: Gameplay &amp; Story.
To me, it feels like you often get games where the developers have 
two seperate ideas which they try to connect 
to another - <b>after</b> they came up with them.
This kind of works sometimes, but often enough, it doesn't work at all.
</p>
<p>
The most interesting media to me is the type that offers me
experiences that I wouldn't have otherwise.
Video games for example have interactive experiences that you don't really
get in other settings. 
For example, you get to explore worlds yourself, at your own pace, doing whatever you want to do.
In e.g. <a href="https://store.steampowered.com/bundle/234/Portal_Bundle/">Portal</a>, you get to 
figure out interesting interactions and/or consequences of, well, Portals. 
I'll let you imagine similar arguments for experencies using books and movies.
</p>
<p>
But this is also where it gets complicated.
What kind of experiences can you get "somewhere else"?
If you have a story which you want to tell: 
<ul style="list-style-type:'- '"><li> When should you experience it in a book?</li><li> When should you experience it in a movie?</li><li> When should you experience it in a game?</li>
</ul>
</p>
<p>
The story of portal augments the gameplay, but there is nothing stopping me 
from reading the story online, or as a book. 
There is very little story required to make the gameplay experience work.
</p>
<p>
When we want to experience horror, what kind of medium is best?
What are the tradeoffs? 
With books, your visualization can be gruesome and add to the experience,
regardless of how detailed an author describes the horror.
You can make similar arguments for and against movies in that regard.
For games, you might get the additional aspect of "being in control", 
which might help with immersion.
</p>
<p>
There is this weird, abstract and difficult to verbalize thing. 
That "something", which is conveyed with an experience.
And what I'm currently obsessed with is that "something", 
which is what games with stories often lack.
</p>
<p>
Let's go over a few games.
</p>
<p>
There is <a href="https://store.steampowered.com/app/258520/The_Vanishing_of_Ethan_Carter/">The Vanishing of Ethan Carter</a>,
where you explore and uncover the mysteries.
The act of being in control and uncovering things is unique to games, sure.
The story &amp; facts behind a case could also be conveyed using a book or a movie though.
</p>
<p>
There is the 2D puzzle platformer <a href="https://store.steampowered.com/app/224760/FEZ/">FEZ</a>,
whose main mechanics entirely depend the quirks introduced by the most commonly used 2D representation
for traditional platforming games.
The story is not too relevant, but and the main mechanic is unique to video games as a whole.
</p>
<p>
<a href="https://cdn.cloudflare.steamstatic.com/steam/apps/335670/page_bg_generated_v6b.jpg?t=1711056114">LISA</a>
is a 2D RPG game. It's depressing, absurd and funny.
You play a character in a world where porn magazines are the currency because 
there are no women left in the world.
During the story progression, your character loses some limbs, which will permanently alter the types of 
moves you can do during combat.
The story and world is a devastating, dystopian and unfair place.
So unfair, that at one point of the game, you are forced to play russian roulette
using your party members. 
The amount of characters you <b>permanently lose</b> is up to pure luck.
A wonderful example of how story and gameplay augment another.
The cruilty of the russian roulette cannot be replicated with other types of media.
</p>
<p>
<a href="https://store.steampowered.com/app/504230/Celeste/">Celeste</a> is an amazing 2D 
platformer game. 
The story is about Madeline, a character which struggles with anxiety, self-esteem issues
and depression, and the struggle to get to the top of the mountain.
Interestingly, there are not a lot of abilities that your character "unlocks"
during the gameplay. 
In a very late bonus chapter of the game, you actually get a tutorial for a technique, 
which is required to beat this chapter, but which was also available to you from the very start.
I'm not talking about a secret button press or unlock; it's a combination of 
actions which you can use to your advantage (and which I totally missed myself up until that point).
</p>
<p>
These games range from classic video game experiences, to games where the story and 
gameplay augment another very well.
In my opinion, there is another level above that though.
I think one of the best games to demonstrate this is <a href="https://store.steampowered.com/app/210970/The_Witness/">The Witness</a>.
</p>
<p>
<figure>
	<img src="./Witness.png" style="width:500px;height:281px;" />
<figcaption>
One day I will actually play you to 100% completion.</figcaption>
</figure>
</p>
<p>
In The Witness, the gameplay and the "story aspects" are designed for 
a specific experience. 
This is a type of experience that you cannot get in any other medium.
</p>
<p>
I'm really not that into media analyses of any kind, but this games screams "purpose" to me. 
The longer I think and read about it, the more I recognize how basically every part 
of the game is designed to provide this unique experience to the player.
</p>
<p>
The whole game is about solving line puzzles.
It plays on an island separated into several areas. 
<ul style="list-style-type:'- '"><li> There is no music, because it would distract from the experience <a href="#note-1" id="back-1">[1]</a>.</li><li> There is no tutorial, because that would lessen the experience.</li><li> The game doesn't treat you like a baby and it also doesn't want to waste your time.
Ironically enough, most of the criticism I read about this game stems 
from implicit conventions have been formed over time for the medium of video games,
but which do not really apply to this game.</li><li> The reward of solving line puzzles are more puzzles. </li><li> You don't have to solve most of the areas because that's not what the game is about.</li><li> You are free to leave and switch puzzles at any time.</li><li> The game has this whole second part to it.
Realizing that this part exists, and that is was with you at all times
is one of the greatest moments I had in a video game.
But in order for this experience to fully work, it has to be, and is, completely 
optional. </li><li> The game is nudging and urging you to get this experience in so many different 
ways and situations. 
You are bound to miss, struggle with and dislike some.</li>
</ul>
</p>
<p>
It sounds absurd, but I cannot put this experience into words.
That is not to say that this experience is intrinsically "good" or "bad".
If I had to try, I'd say it's about experiencing these Eureka moments,
being perceptive, switching perspectives, questioning the constraints
you took as granted and so on.
</p>
<p>
I don't even like puzzle games that much, but this is the best puzzle game
I have ever played.
And this "focused purposed" of providing that experience is something 
I miss so dearly in most other games.
That something which cannot be put into words. 
That something that you can only get using this type of medium.
</p>
<p>
If I had more time I would also talk about mediocrity, but this wall
of text is already longer than I anticipated.
Maybe these awesome experiences are to blame for my high standards for things; 
who knows.
But it definitely made me think like no other game.
</p>
]]></content>
</entry>
<entry>
<title>Fix Your God Damn Audio Mixing</title>
<link rel="alternate" href="https://p4m.dev/posts/16/" />
<updated>2024-03-13T00:00:00Z</updated>
<id>https://p4m.dev/posts/16/</id>
<content type="html">
<![CDATA[<p>
This one is for all the independent artists out there:
For the love of god, <b>fix your fucking audio mixing!</b>
</p>
<p>
I found a random ass Indie band. You know,
<ul style="list-style-type:'- '"><li> one album</li><li> released a few years ago</li><li> posted a banger album</li><li> never to be heard of again</li>
</ul>
</p>
<p>
But I think this is the third time where I listen to
some artist on bandcamp, whose audio <b>is fucking clipping</b>.
Producing music, especially if it isn't a cover, takes <b>a lot</b> of work.
How come no one sat down in a quiet environment with good headphones, and gave this thing a good listening?
</p>
<p>
It's always this subtle kind of clipping.
The one that is unnoticed if you do anything else (e.g. play video games at the same time).
</p>
<p>
But god forbid you notice the clipping.
I can't unhear it now, argh.
</p>
]]></content>
</entry>
<entry>
<title>Entering The World of Work</title>
<link rel="alternate" href="https://p4m.dev/posts/15/" />
<updated>2024-03-07T00:00:00Z</updated>
<id>https://p4m.dev/posts/15/</id>
<content type="html">
<![CDATA[<p>
<s>It's a sunday evening, I have roughly an hour before I want to head to bed, and</s> I'm bored. 
A bunch of things have happened since my last post, so it's time for a life update.
</p>
<h1>
 Finding Work</h1>
<p>
After slacking off for a few months at my parents' place, I finally started to look for a job
at the beginning of this year. 
And I have to admit: looking for a programming job with a computer science degree really makes
this ridiculously easy. 
My plan was as follows:
<ul style="list-style-type:'- '"><li> Create a CV and include some projects of mine / during uni to cover a variety of topics</li><li> Create (yet another) website for more details and video demos of my projects</li><li> Once I have these ready, start a first wave of applications using just that CV document</li><li> If that fails to work, do more waves but put an increasing amount of effort into my applications:<ul style="list-style-type:'- '"><li> Professional picture </li><li> Cover letter</li><li> Company tailored CV</li>
</ul>
</li>
</ul>
</p>
<p>
Interestingly enough, the first round of just sending out my CV was already enough to land me 
a job I'm interested in - against my own expectations.
</p>
<h1>
 Interview Process</h1>
<p>
It was really interesting to see the different interview processes.
All first-round-interviews were online, while some companies requested an in-person 
meeting for a second round, which made the whole process easier to manage.
</p>
<p>
For the most part, is was an interesting opportunity to find out what 
kind of stuff I'm interested in (short-term or long-term projects? Team sizes? Company structure?
Actual projects? Company benefits / opportunities?). 
It's probably not representative to actually trying these things out, but I feel like my 
second round of interviews would have been more targetted towards my (current) interests.
I was hella nervous at each interview, and that probably won't change in the future.
</p>
<p>
Most companies just did "vibe checks" and wanted me to talk about my projects, 
interests, and my university experience. 
The company I ended up with used this strategy as well. 
I think that this approach, depending on the projects you can show off, makes the most sense.
Given that the source code of my stuff was <b>not</b> available <a href="#note-0" id="back-0">[0]</a>, I kind of expected some
technical questions about my projects, but that didn't really happen.
Some companies asked me about my prior experience in certain fields
(Have you ever did "x" / Have you worked with "y" before?),
but we the conversations were pretty chill in that regard. 
</p>
<p>
Interviewing for a C++ developer position, one company asked me to explain various C++ aspects for <b>an hour</b>:
<ul style="list-style-type:'- '"><li> Tell me about the C++ history <a href="#note-1" id="back-1">[1]</a>. What interesting stuff happened in the last 10 years? </li><li> What are data structures / mechanism used in multi-threaded applications?</li><li> Tell me about access qualifiers (<code>public</code>, <code>private</code>, <code>protected</code>)</li><li> What does <code>const</code> do?</li><li> What does <code>mutable</code> do?</li><li> What are lambdas? What do you use them for?</li><li> Tell me about the different kind of constructors.</li><li> What is the difference between Smart Pointers and garbage collected language like Java?
How do these differences manifest in practice?</li><li> Tell me about TCP / UDP</li><li> How many bits are in an IPv4 address? How many in IPv6?</li><li> What is a subnet-mask? How do you use them?</li>
</ul>
After each answer of mine, I got a short explanation from the interviewer as well.
While I think I got the majority right, there where a lot of aspects I was shaky on / unsure off.
I tried to keep my bullshitting to a minimum, so I think I was pretty straight forward when I was
unsure of things or straight up never heard of stuff (e.g. <code>mutable</code> in C++, that was a TIL).
While I got a stuff wrong, they asked me back for a second round, but I declined 
(<b>not</b> due to the interview process).
</p>
<p>
Another company pre-screened me with three very basic C questions:
<ul style="list-style-type:'- '"><li> What does <code>static</code> do?</li><li> What does <code>volatile</code> do?</li><li> What is the difference between UDP and TCP?</li>
</ul>
</p>
<p>
I think that's pretty fair, but their second round was brutal:
<ul style="list-style-type:'- '"><li> they gave me an <b>8 hour</b> (unpaid) homework assignment, for which I had a week to complete</li><li> then I presented my approach + solution in a presentation,</li><li> after which we had a discussion / Q&amp;A about my stuff with the team</li>
</ul>
</p>
<p>
While I did all of these things, I felt pretty mixed about the process and I'm not sure I'd do that again.
It also didn't help that I got a rejection <a href="#note-2" id="back-2">[2]</a> afterwards, which made the whole
thing feel like a waste of time.
</p>
<p>
No company told me a salary up front; instead they all asked for my expectations,
to which I gave a range of 55k€ - 58k€ / year (germany).
Given that I didn't have a full-time job like that before, I also explicitly said 
that I don't know what's realistic and that I might adjust accordingly given the offers I receive,
to which most responded with a gist of "I cannot guarantee that right now, but it's not unrealistic".
</p>
<p>
The company I ended up with 
<ul style="list-style-type:'- '"><li> had a really sparse job description,</li><li> was the only company offering full-remote work, which was the only reason why
I decided to sent them my CV in the first place,</li><li> actually offered my a salary within my salary expectation, 
even though I intentionally left myself room for negotiations <a href="#note-3" id="back-3">[3]</a>.</li>
</ul>
</p>
<h1>
 The Job</h1>
<p>
It's been three weeks, but I'm still in the introductory phase, meaning 
I'm still being introduced to projects, to my coworkers, to the parts my coworkers are working on, 
what the plans for each project are, what the workflow (for both programming and actually using the
software) looks like, etc etc.
</p>
<p>
The actual amount of programming that I contributed to the projects is pretty sparse at best, 
but I think that somewhat normal.
Right now I feel like a digital cleaner: I'm kind of doing annoying work like moving modules around,
fixing up fucky or straight up missing build processes, and so on. 
This is frustrating at times (as linker errors always tend to be, Visual Studio straight up 
doesn't help at all here though), but it's also rewarding, because this is work I'd consider
useful - if only to the project itself, but still useful.
That usefulness is something I was lacking during my university studies, so I'm actually really motivated.
</p>
<p>
I had some days were I couldn't / shouldn't really do anything: 
Everyone has their set of tasks assigned to them, 
meaning if I'm waiting for something or someone else to come back to me for all projects,
there's nothing for me to do.
It's a really weird feeling - especially after getting my first paycheck (which isn't even "a full one"
because I started work in the middle of the month). 
Stuff like that, seeing how high the invoices given to clients are, the scope and amount of people
on each project - it's a really weird alienating feeling seeing how much money is involved in all of these
things.
</p>
<p>
Looking at the code, I feel like you can't really escape OOP, and I mean that in a bad way.
The amount of additional complexity being introduced to projects / problems is insane.
Want to read in a file? I'd have written a function, but the code I'm reading is a hierarchy of 
inheritence with specialized classes for each type of object being read.
I know I've got a sample size of n=1, but I'm starting to believe a salary is dependent on
the management of complexity for a problem which shouldn't even exist.
Yet somehow this house of card doesn't seem want to seem to fall. 
It's fascinating.
</p>
<h1>
 Personal Life</h1>
<p>
I'm still at my parents' place for the time being. I can't really complain: 
<ul style="list-style-type:'- '"><li> They are very chill, </li><li> I've got a feeling of safety during my job probabtion period, and</li><li> the amount of money I can save is insane.</li>
</ul>
</p>
<p>
Due to remote work, I still kind of have to figure out where I want to live although I'm (at least for now)
very flexible obviously.
The flexible working hours have given me some structure in life, in the best way possible: 
8 hours a day force me to stop slacking off so much, but I still have the freedom of putting in the 
hours when I want to (given that I'm available for meetings, but they are at pretty reasonable times).
</p>
<p>
I am realizing how valuable time has suddenly become (for me). There's pretty little time left in the day
after work. Hell, I even wrote this post over several days because I wanted to keep my schedule in tact.
Right now I'm working overtime in order to build up a nice cushion of a few work hours - just in case, 
as long as I'm still highly motivated for work.
I'll probably tone this down sometime soon though.
I already know that I don't want to work 8 hours a day (like this) for the rest of my "career" (if possible).
</p>
<p>
This post is a bit rambly and unguided, which I think kind of fits into my whole situation.
It still feels surreal that I actually entered this next chapter of my life. 
It's just a job, but still :)
</p>
]]></content>
</entry>
<entry>
<title>I Hate: Everything?!</title>
<link rel="alternate" href="https://p4m.dev/posts/14/" />
<updated>2023-12-30T00:00:00Z</updated>
<id>https://p4m.dev/posts/14/</id>
<content type="html">
<![CDATA[<p>
It's the end of the year, and I feel like I'm as grumpy as ever.
I am a bit scared of my current development, especially when it comes 
to my current taste in media in general.
Why? Because I find it harder and harder to find things which I'm not annoyed at.
</p>
<h1>
 Persona 4 </h1>
<p>
Persona 4 is the favorite games of a close friend of mine.
The reviews speak for themselves: 97% of ~56k reviews are positive on steam.
Some steam-sale inevitably came around around, so I got the game to give it a try.
<img src="./persona4.png" style="width:500px;height:161px;" />
</p>
<p>
I started into the game with mixed feelings: 
I'm not too much of a fan of <b>a lot</b> of anime, 
as the ones I watched seem pretty generic, awfully written,
predictable, full of tropes, unnecessary sexualization / fanservice 
or all of the above.
But if you read reviews of such anime or look at the hype around VTubers <a href="#note-0" id="back-0">[0]</a>,
it feels like people are basically following the following infographic:
<img src="./thing.png" style="width:500px;height:531px;" />
</p>
<p>
So this thing having both the "JRPG" and the "Anime"-tag left me a bit worried.
But I got it for cheap, and it's <b>97%</b> positive.
How bad can that be? So I booted up the game...
</p>
<p>
...and dropped it an hour later.
</p>
<p>
While the game opens up later on (or so I was told), 
it's railroading hard in the beginning. 
And I get that: You probably want to introduce the gameplay, 
the characters and startup the story.
Dialogue-heavy games / sections are certainly not everyone's favourite,
but I did enjoy some telltale games, so that's not inherently an issue for me.
</p>
<p>
Problem is: If you fill the first hour with dialogue, it kind of has to be not complete dogshit.
The dialogue was as cliche and generic as Anime gets, leaving you to listen to unlikable characters
for an hour, whose voice acting might be appropriate, but fucking annoying to listen to.
The "story" being """developed""" within that time-frame could be condensed to 10min easily, 
and there is basically no gameplay involved.
</p>
<p>
Could the game get way better later on? Sure.
But 60 minutes is <b>a lot of time</b> to setup a lot of things. 
Just look at any good movie.
Even if you don't understand anything, media can be very engaging <a href="#note-1" id="back-1">[1]</a>.
Given the same friend of mine has played 72 hours of that game,
I'm not interested in sinking that much time into a game which clearly does not respect my time
(and sanity), so I dropped it shortly after playing it for an hour.
</p>
<h1>
 Outer Wilds</h1>
<p>
This one is less ranty, just an observation of my own.
</p>
<p>
<b>95% of 50k reviews are positive</b>.
Everyone keeps telling you:
<ul style="list-style-type:'- '"><li> Go into the game blind</li><li> It provides an experience like no-other game</li><li> It has an incredible story</li><li> ...</li>
</ul>
</p>
<p>
In contrast to Persona 4, I played Outer Wilds for over 7 hours.
I liked exploring stuff in the beginning,
but I just didn't find the story that interesting - which is kind of bad if the whole game
is about exploration in order to uncover the story <a href="#note-2" id="back-2">[2]</a>.
Certainly doesn't help that the movement feels wonky to me, and the time-based in 
conjunction with the basic game-loop simply felt tedious to me without feeling gratification.
</p>
<p>
I think I get what the developers were going for and why the game is liked by so many people,
but it simply wasn't for me.
</p>
<h1>
 Anodyne</h1>
<p>
Another friend of mine has recommended "Anodyne 2" to me.
Due to the steam winter sale, I got both games in a bundle for cheap and decided to start with the prequel.
<b>87% of 800 reviews are positive</b>. 
It looks like a Zelda-like with its top-down pixel graphics. Sounds good to me!
</p>
<p>
The first 40min were great: You are dropped into an open world and are free to explore it.
You are supposed to collect cards, find one or two weapon upgrades and find new 
world regions.
Your little weapon, the broom, can also help you navigate through obstacles in the world 
using balls of dust.
You find dungeons and fight enemies, while also having some parkour / easy puzzle sections.
This sounds good, but it only get worse after that.
</p>
<p>
The world is open, but not really interesting: 
Apparently there are only three upgrades to your weapon, one of which I find pretty much useless.
The only reward for exploring the world therefore is the act of exploring the world itself 
and collecting the cards, the latter of which is just tedious.
The same enemies are encountered repeatedly, meaning the become uninteresting very quickly.
There are bosses in the game, which are all trivial and beaten by just spamming attack.
I've seen people describe them as "challenging but fair", which makes you wonder what kind of other "challenging" games
they have played.
</p>
<p>
Screen scrolling in general is pretty janky when combined with drowning in the water 
or jumping over a pit.
The game also contains (several) game breaking bugs.
The one I found for myself was that you can pixel-walk over any pit.
In the game, there are three big statues which are supposed to be an obstacle, which block 
the path to certain game areas.
<ul style="list-style-type:'- '"><li> One statue is a proper obstacle</li><li> You can just jump around the second one</li><li> You can pixel-walk to navigate around the third one</li>
</ul>
</p>
<p>
The some dungeons / rooms can be shortcutted, while the rest of the design 
does not indicate that these cuts are on purpose.
The game contains a "nexus" which you can use to teleport to several world regions / dungeons.
In the nexus, there is also an indicator for each teleport to show whether you found all cards within a region.
This indicator is misleading and made me look up a guide because it showed a section as completed, 
even though the dungeon contained loot required to progress with the game.
This all made me comnpletely uninterested in the secrets sprinkled through out the game, which are completely optional 
and don't do anything.
</p>
<p>
There is not much of a story to this game.
Each section has some motif, but it isn't doesn't feel connected to other regions and constantly feels out-of-place.
The game feels like it wants to be a Yume Nikki spin-off, but it slapped a Zelda demo on top of it, without 
any of the parts which make me like Zelda in the first place. 
This makes the whole exploration a tedious task. 
Furthermore, I'm a big fan of "show, don't tell"-rule, but the game mostly dumps these thoughts and ideas
onto you using dialogue boxes, which also ruins the whole Yume Nikki aspect of the game for me.
So I dropped the game after 3 hours.
</p>
<h1>
 Other</h1>
<p>
I could go on and on. This website is already full with software / technology I dislike.
I've been really tired of the youtube algorithm lately, so I'm just rewatching old-ish let's plays or 
stream VODs instead of watching new things.
I currently have no interest in watching any anime, because the last few animes / series I watched were pretty bad.
For movies, I have no interest in any current movies <a href="#note-3" id="back-3">[3]</a>.
The games I've tried this year were pretty disappointing.
</p>
<p>
Maybe I'm just unlucky with my picks, or I'm becoming more and more grumpy. I don't even know at this point.
</p>
]]></content>
</entry>
<entry>
<title>C++ People Must Be Trolling</title>
<link rel="alternate" href="https://p4m.dev/posts/13/" />
<updated>2023-12-04T00:00:00Z</updated>
<id>https://p4m.dev/posts/13/</id>
<content type="html">
<![CDATA[<p>
Someone on Twitch mentioned this C++ Committee insanity,
and I feel like I'm going to explode not writing this down.
I already posted a wall of text to two friends of mine, 
so I might as well save this here.
</p>
<h1>
 The Proposal</h1>
<p>
Someone did <a href="https://isocpp.org/files/papers/P2723R1.html">an official proposal to the C++ specification</a>
to zero-initialize memory of all objects using "automatic storage duration".
<a href="https://en.cppreference.com/w/cpp/language/storage_duration">To the best of my knowledge</a>, this means (non-static) variables on the stack.
In short:
<figure>
	We propose to zero-initialize all objects of automatic storage duration, making C++ safer by default.
<figcaption>
<a href="https://isocpp.org/files/papers/P2723R1.html#summary">Source</a></figcaption>
</figure>
</p>
<p>
which means:
<pre><code>
void TestFunction(void)
{
	// Before:
	{
		int y;     // y is not initialized
		int x = y; // Reading from y is undefined behaviour, let there be dragons!
		// ...
	}

	// After
	{
		int y;     // is equivalent to "int y = 0;"
		int x = y; // Well defined, x has the value 0.
		// ...
	}
}</code></pre>
</p>
<p>
I'm seeing less undefined behaviour and less having to type <code> = 0</code> -> I like.
</p>
<p>
Even better, they already did performance benchmarks, and the results seem pretty reasonable:
Some projects showed a performance decrease of up to <code>0.5%</code>, and some projects have seen a 
performance <b>increase</b> of up to <code>1.0%</code>. 
And for new code, they introduced a new attribute such that you can explicitly ask for 
uninitialized memory.
This should help mitigate a few performance regressions when working with e.g. big structs
or something <a href="#note-0" id="back-0">[0]</a>.
</p>
<p>
So this is the part I am be pleasantly suprised that C++ implemented 
some thing simple and nice.
I'm gonna give this a thumbs up and hope that this behaviour is 
ported to C in some future revision, right?
This change seems very simple and uncontroversial.
Surely people see the benefit of this proposal, right?
</p>
<p>
Right, guys?
</p>
<h1>
 The Other Proposal</h1>
<p>
You know how the C (and especially the C++) spec is clusterfuck of 
<ul style="list-style-type:'- '"><li> undefined behaviour,</li><li> unspecified behaviour, and</li><li> implementation-defined behaviour?</li>
</ul>
</p>
<p>
I already have to <a href="https://stackoverflow.com/questions/44191626/undefined-vs-unspecified-vs-implementation-defined-behavior">look up the differences</a>
between these three "behaviours" too often.
You know what C++ needs?
</p>
<p>
That's right, <a href="https://isocpp.org/files/papers/P2795R1.html">"Erraneous Behaviour" (EB for short), obviously</a>.
And not only that, reading from an uninitialized local variable should 
be EB.
</p>
<p>
...What does that mean? Well, in this specific instance, it means:
<ul style="list-style-type:'- '"><li> The value of said local variable is <b>implementation defined</b> (there <b>is</b> a fixed value
with which the variable is initialized, but it depends on the compiler)</li><li> Reading the value of a local variable witht uninitialized memory is "<b>a conceptual error</b>"
(I assume this means "don't do that")</li><li> Compilers <b>are encouraged</b> to diagnose this error, <b>but</b> they are allowed to ignore the error
and treat the code as valid.</li>
</ul>
</p>
<p>
<img src="./clown.png" style="width:500px;height:491px;" />
</p>
<p>
Ok, time to take a breather.
This shit does not makes sense to me.
</p>
<p>
It's <b>just a proposal</b>.
No need to be upset.
This shit will be discarded and the other one accepted. Surely.
Let's look at the proposal progress <a href="#note-1" id="back-1">[1]</a>:
</p>
<p>
The proposal for zero-initialized objects was 
<a href="https://github.com/cplusplus/papers/issues/1401">last updated / discussed in February</a>.
Is that recent? 
I don't know, I don't have context for this. 
This could be fine, and the issue even states that 
they are interested in pushing through some form of automatic stack variable initialization.
Sounds good I guess? Not much discussion around it and no indicator 
on whether it's accepted into the next standard, but <b>maybe</b> that comes in the future?
</p>
<p>
The proposal for EB was posted in February. Oh oh.
It was <a href="https://github.com/cplusplus/papers/issues/1460">last updated / discussed two weeks ago</a>.
Oh no.
They don't want to pull in the proposals as is, but they want to extend 
the amount of cases in which EB is applied. Oh fuck no.
</p>
<p>
Again, the proposal is not yet accepted either, but it sure does not seem to be discarded at all.
But I have ommitted a little detail:
What do you think is the argument <b>against</b> initializing variable to zero by default?
</p>
<p>
It's not performance.
</p>
<p>
Oh no, it's a much better argument.
</p>
<p>
Wait for it...
</p>
<p>
IT'S "<b>UNDERSTANDABILITY</b>":
<figure>
	"The resulting behaviour is desirable, but the cost on code understandability is unacceptable to the present author."
<figcaption>
<a href="https://isocpp.org/files/papers/P2795R1.html#relwork">Source</a></figcaption>
</figure>
</p>
<p>
They, <b>in the context of C++</b>, are arguing, that
<pre><code>
int b; // is zero</code></pre>
is <b>unacceptable</b> because it makes code harder to understand?????????
They have to be trolling. 
</p>
<p>
I refuse to believe this.
</p>
<p>
They shot this idea down, <b>because of understandability</b>, and then 
decided to introduce the notion of "Erraneous Behaviour".
<img src="./thinking.png" style="width:500px;height:500px;" />
</p>
<h1>
 The C Standard</h1>
<p>
Good news: 
I probably don't have to worry about C introducing this kind of shit.
</p>
<p>
Bad news:
It's because <a href="https://github.com/sg22-c-cpp-standard-compatibility/sg-compatibility/issues/10">they generally dislike the idea of automatic zero-initialization</a> 
in this context.
</p>
<p>
Jai pls save me
</p>
]]></content>
</entry>
<entry>
<title>The Sad State of Development Tools and Features</title>
<link rel="alternate" href="https://p4m.dev/posts/12/" />
<updated>2023-11-28T00:00:00Z</updated>
<id>https://p4m.dev/posts/12/</id>
<content type="html">
<![CDATA[<p>
Here's a small update on programming related stuff.
</p>
<h1>
 Code Formatter</h1>
<p>
I think pretty much every developer has heard about the 
"Tabs vs Spaces" debate before, which only shows one thing:
Development tools are pretty bad.
A <b>good</b> IDE should be able to just 
handle either encoding and display the indentation
as the user desires.
</p>
<p>
Given that I recently decided to try out 
using an indentation width of 2 instead of 4
(and I've seen people use the widths 1,2,3,4 and 8),
the encoding which makes the most sense to me is
<ol>
<li> Tabs for indentation and</li><li> Spaces for alignment.</li>
</ol>
</p>
<p>
That way the indentation is consistent, while 
just the <b>display of tabs</b> may change.
But of course whenever more than one developer
is involved, usually:
<ul style="list-style-type:'- '"><li> Tabs are inserted to align, which obviously doesn't work
and just fucks shit up</li><li> The perceived indentation is wrong due to a clusterfuck
of whitespace</li><li> This also leads to a lot of commits with
changes in lines where only the whitespace is modified, 
meaning the <code>diff</code> is now useless or full of noise</li>
</ul>
</p>
<p>
I am often using (neo)vim, which, 
at least with my configuration, only fucks with the indentation.
In comparison, IDEs not only fuck the indentation up, but
they also tend to do """helpful""" formats like
the following:
<img src="./PrettyFormatFix.png" style="width:381px;height:700px;" />
</p>
<p>
<b>I think</b> vim handles the indentation fine if I format the whole file;
but it does tend to insert the wrong characters (tabs for alignment)
when writing the line initially.
As I often forget to format the file completely,
one alternative would be to have a dedicated code formatter,
which you could automatically run on 
the changed files before pushing a commit with <code>git</code> <a href="#note-0" id="back-0">[0]</a>.
Big downside: Tools like 
<a href="https://clang.llvm.org/docs/ClangFormat.html">clang-format</a>
and <a href="https://www.gnu.org/software/indent/">Indent</a>
require lots of configuring if you <b>just</b> want 
it to do the indentation / alignment thingy.
I'm not even sure whether there was a tool which <b>just</b>
does that. 
<a href="https://invisible-island.net/bcpp/">bcpp</a> could fit the 
bill, but I'm not sure from the description whether
it supports mixing these two properly.
</p>
<p>
So that's how I ended up with my weekend project <code>cif</code>. 
<code>cif</code> <b>just</b> does the formatting and alignment for 
C code. 
It handles some things like strings, comments and preprocessor formatting,
but it will do its job wrong if you e.g. want to
open scopes using macros.
I setup a hotkey for vim and a hook for <code>git</code>, so I'm all set <a href="#note-1" id="back-1">[1]</a>.
</p>
<h1>
 Static Website Generator Experiments</h1>
<p>
Due to the Performance Aware Programming Course,
I wanted to see whether I can speedup 
some memory allocations.
The results were mixed and I'm annoyed.
</p>
<p>
Good news: There was some real low hanging fruit.
During the initialization of the threads, 
I allocate a lot of memory, because the pages on linux
are only mapped to physical memory once
the pages are written to once.
But I did a whoopsie and called <code>ArenaAllocateZero</code>
instead of <code>ArenaAllocate</code> in my code on big buffers
of memory.
While this helps with tracking down uninitilized memory bugs,
it's a waste of work (assuming that my program is written correctly).
Not doing that speeds up the generator by ~50-100ms.
So it's not really a big concern, but 
now this website is generated in ~15ms (when in cache),
which is pretty awesome.
</p>
<p>
The other "quick" thing I wanted to test was using 
larger (memory) pages.
Given the time scale I am working with, 
I thought that generating less page faults might be
beneficial,
especially because linux, in contrast to Windows, 
doesn't require elevated privileges to use large pages.
Or so I thought.
After adding <code>MAP_HUGETLB</code> and <code>MAP_HUGE_2MB</code> to the arguments
passed into my <code>mmap</code> call, my memory allocation failed.
From what I gathered, it seems like you need to pass some additional
flags to the kernel on boot such that these larger pages are actually
allocated <a href="#note-2" id="back-2">[2]</a>. 
</p>
<p>
I also want to look into getting rid 
of memory-mapped files and replacing 
them with good ol' <code>read</code> calls.
However, that change would require a bunch more adjustments to my code,
so that will have to wait.
</p>
<h2>
 Quick Update:</h2>
<p>
I found and fixed some multi-threading bugs (<code>static</code> variables are not thread-safe, whoopsie).
Personal websites are still building within ~15ms (when in cache),
while the test site with <b>20k</b> posts now builds within <b>600ms</b> (when in cache).
Pretty happy about that.
</p>
<h1>
 Other Programming Projects</h1>
<p>
I'm working on a matrix client with a friend.
Progress has been slow because most of the work is 
either juggling some C# bullshit or
figuring out the various steps and formats 
which matrix expects.
So far we have:
<ul style="list-style-type:'- '"><li> Retrieve login methods</li><li> Login with password</li><li> Using the <code>libOlm</code> library, create an account 
with public/private (and onetime / recovery) keys</li><li> Serialize this account to/from disk (<code>libOlm</code> is actually somewhat nice to use)</li><li> Uploading public keys onto the server</li><li> Retrieving public keys from the server</li><li> Getting the initial <code>sync</code> request to retrieve a mapping from users to room IDs</li>
</ul>
</p>
<p>
But this all is written in a "sandbox"-y / fucking around kind of way, 
meaning we don't even have a window open yet.
I hope once we manage to send + receive encrypted text messages that
we can actually turn this experiment into something somewhat usable.
</p>
<p>
Additionally, given my recent usage of <a href="https://neovide.dev/">Neovide</a>, 
I dig the smooth animations but I'm hitting more shortcomings of neovim.
While these probably could be fixed with more plugins / an LSP / ..., 
I'm kind of tempted to roll my own text editor for C programming.
At least my short list of requirements seems somewhat 
reasonable, if I am able to get OpenGL to cooperate:
<ul style="list-style-type:'- '"><li> Pixel perfect bitmap font display / scaling</li><li> The smooth animations of Neovide (which actually 
help navigating the code when jumping around in my opinion)</li><li> keep a low startup time</li><li> be able to run build scripts and parse the output such that 
I can jump from error to error</li><li> have some rudimentary C parsing to be able to<ul style="list-style-type:'- '"><li> Jump to definition</li><li> Show program arguments</li><li> List functions</li><li> ...</li>
</ul>
</li><li> Maybe have a nice way of changing folders / files than neovim</li>
</ul>
</p>
<p>
And I still need to work on my C debugger.
Probably some update of GCC shuffled some debug information
around, which lead to me needing to fix the hardcoded 
values of the debugger.
It would be <b>really</b> badass if I am able to get it into a usable state.
But hey, I managed to recod a little demo video which I'm gonna put / link to
on my resume, so that's gotta be worth something. 
</p>
]]></content>
</entry>
<entry>
<title>Decentralized Internet</title>
<link rel="alternate" href="https://p4m.dev/posts/11/" />
<updated>2023-11-18T00:00:00Z</updated>
<id>https://p4m.dev/posts/11/</id>
<content type="html">
<![CDATA[<p>
I spend most of my time on the internet on the same webpages:
<ul style="list-style-type:'- '"><li> Reddit</li><li> YouTube</li><li> Twitch</li>
</ul>
</p>
<p>
Apart from searching for shit, that's basically it <a href="#note-0" id="back-0">[0]</a>.
Even if I start counting websites I visit occasionally, 
the list of websites remains manageable - a stark contrast
to the idea that the web is decentralized and full of wonders
of things to explore.
</p>
<p>
Some people are trying to revive the old days of the internet
by creating personalized websites and creating webrings,
the sites of a webring link to another.
However, if you actually take the time to explore these 
websites, there is one theme which <b>a lot</b> of them have in
common:
</p>
<p>
The websites are dead.
</p>
<p>
Maybe I have yet to find a super active webring with
lots of interesting content. 
But the few webrings I am aware of either 
<ul style="list-style-type:'- '"><li> constantly change, as a lot of websites come and go, never 
staying online for too long,</li><li> are unmaintained such that a lot of links from the webrings
point onto websites with invalid domains, or</li><li> contain websites which have not been updated within the last year.</li>
</ul>
</p>
<p>
This realization made me a bit sad, and it also was a big drive for me
to fix up my shit and push some updates onto my sites.
The content doesn't even have to be engaging; it's just 
nice to see people doing their own thing at their own 
little corner of the internet. 
I feel like that's what the internet is (or at least used to be) about,
and maybe I'm in the minority here, but I'd like it to remain that way.
</p>
]]></content>
</entry>
<entry>
<title>An Update on Various Things</title>
<link rel="alternate" href="https://p4m.dev/posts/10/" />
<updated>2023-11-16T00:00:00Z</updated>
<id>https://p4m.dev/posts/10/</id>
<content type="html">
<![CDATA[<p>
It's been a while.
</p>
<p>
First, a quick status update on my life, before I cover
some of them in more detail:
<ul style="list-style-type:'- '"><li> Finished by bachelor thesis</li><li> Moved out of a student apartment complex back into my parents' place</li><li> Currently looking for a programming job (or rather I <b>should</b> be looking, but I'm lazy)</li><li> Improved my programming skills and I'm currently taking the <a href="https://ComputerEnhance.com/">Performance Aware Programming Course</a></li><li> Programmed on some new projects (who doesn't?)</li><li> I have rewritten parts of my static website generator twice</li><li> Programmed a Risk of Rain 2 mod, which gives me some mad bragging rights in my group of friends</li><li> Playing some Risk of Rain Returns (nostalgia is still hitting hard)</li><li> Gained some weight (oof)</li><li> I upgraded my computer</li><li> I (temporarily) decommissioned my server and instead am hosting some of my shit on a VPS I'm renting</li><li> I'm still highly unproductive</li><li> I got myself a very fancy keyboard (for the computer, I'm still using my "piano"-keyboard)</li><li> That means I'll hopefully scream into the void (read: create posts here) more often</li><li> (and probably more stuff I can't recall at the moment)</li>
</ul>
</p>
<h1>
 Bachelor Thesis</h1>
<p>
I have to admit: I initially just wanted to be done with the whole thing, 
but after spending that much time on it I can't help but feel a little bit 
proud of the result. 
With >60 pages, this bachelor thesis of mine has become quite the chonker.
To put this into perspective: 
I expected to end up with roughly ~30 pages. 
</p>
<p>
My thesis advisor, pretty much from the very beginning, 
knew that it'd be more in the ballpark of 50 or 60 pages.
Granted, I used a lot of pictures / visualizations (which are mostly generated in LaTeX; not fun btw), 
which ended up taking a lot of space.
Regardless, my advisor has been just super awesome (and way too lenient with my whole bullshit).
His feedback invaluable as he always tried to make me understand of <b>why</b> he recommends certain changes.
I was able to explore a lot of my ideas / try to approach things from various angles,
and everytime I was out of ideas and asked him for advice, he always showed me new approaches 
which ended up fixing all the complaints / problems I had.
No wonder this guy ended up becoming a doctor in the process, while it took 
me roughly a year to complete my 60 pages. Big oof.
</p>
<p>
Honestly, if the rest of my studies were more like this bachelor thesis, I'd 
probably be motivated to get a master's degree, and I would have <b>way</b> more 
fun along the way. 
The way this research topic combined theoretical constructions with 
(somewhat) practical applications is <b>exactly</b> the stuff the
stuff that makes me go down rabbit holes.
Just as an example: 
If a professor covered Boolean functions in class and explained how 
they can be efficiently represented in the computer, I'd probably fail 
that class hard because of sheer boredom.
But give me a concrete, difficult problem and show me how 
Boolean functions can be used to solve said problem, and
I'm super into it.
</p>
<p>
To sum my thesis up quickly: 
In this one niche of problem modelling and solving, 
at least two algorithms were introduced which, theoretically,
solve a part of this problem more quickly.
But these algorithms have not been benchmarked (and AFAIK one
of which was never actually implemented in code).
I did some benchmarking and behold: 
The theoretical improvements don't really show up in practice.
The older, more naive and easier to implement algorithm ended
up being the fastest most of the time.
It's not the most interesting result, but it's a (somewhat) important
result nonetheless.
</p>
<p>
And with the submission and defense of my thesis, 
my bachelors degree comes to an end. 
It's been 5 years. Utter insanity, but at least at the moment,
no one seems to mind my incompetency.
So I moved back to my parents' place.
They have been super supportive (and, again, probably way 
too lenient on me slacking off and not doing shit).
So the next step is to find a job and move out again.
</p>
<h1>
 Website Generator Shenanigans</h1>
<p>
My static website generator is in the third iteration now.
To roughly sketch the approaches, here are the three 
iterations:
<ol>
<li> <code>Input -> Html</code></li><li> <code>Input -> Tokens -> Tree -> Html</code></li><li> <code>Input -> Tokens -> Html</code></li>
</ol>
</p>
<p>
<b>Iteration 1</b> had no pre-processing what-so-ever, 
which resulted in a huge mess of code, lookaheads and trying
to "escape" sequences in multiple places.
Not Ideal, pretty error prone, and absolutely shite 
error handling.
</p>
<p>
<b>Iteration 2</b> was a "side-grade".
Error handling was better and there was less duplicated code.
But the different stages overall increased the amount of code
substantially <b>and</b>  it made a bunch of things (e.g. nested lists) way more 
complicated than they needed to be. 
In hindsight, I'd say this approach was overengineered,
and it wasn't even free of bugs.
As I kept finding more errors, I decided that the whole tree approach wasn't worth the effort.
</p>
<p>
<b>Iteration 3</b> just generates the html straight from the tokens.
I still need to spend some time generating proper
error messages, 
but I'm working with way less code, 
and most of the existing input files for this website just worked.
Additionally, I added some features to the website, 
as can be seen by the <a href="/recordings.html">Recordings</a> section of the website.
</p>
<p>
I took the opportunity to add multithreading, which actually doesn't 
really do a lot until I add a ridiculous number of posts:
<ul style="list-style-type:'- '"><li> ~1000 Posts still take ~240ms (cold: roughly double that if the files are not in cache,).</li><li> 20.000 Posts take 1.43s (cold: 6s, but we are working with almost half a gigabyte of text at this point).
Single-threaded, this takes 3s. Not really a big win if i'm increasing the core count by 12x.
I probably should do some benchmarking to identify bottlenecks, but:</li><li> My website still just takes ~110ms to process. That's good enough for me.</li>
</ul>
</p>
<p>
I also downloaded some Twitch archives of me playing my guitar, so if I'm bored 
I'll go through the recordings and look whether I can upload some audio excerpts from some older streams 
onto here.
</p>
]]></content>
</entry>
<entry>
<title>I Hate: Python</title>
<link rel="alternate" href="https://p4m.dev/posts/09/" />
<updated>2023-04-30T00:00:00Z</updated>
<id>https://p4m.dev/posts/09/</id>
<content type="html">
<![CDATA[<p>
The official Python implementation is dogshit slow; 
although you can argue that one can use implementations
like <a href="https://en.wikipedia.org/wiki/PyPy">PyPy</a>, which
is mostly a drop-in replacement with 
<a href="https://www.pypy.org/index.html">significantly better performance way better performance</a>.
Regardless, the few times I actually use Python (for e.g. quick and
dirty data processing / visualization), there's is a
surprising amount of friction and pitfalls 
despite it being <a href="https://docs.python.org/3/faq/general.html#is-python-a-good-language-for-beginning-programmers">recommended for beginners</a>.
</p>
<h1>
 Type safety</h1>
<p>
One of my biggest issues is the complete lack of type
safety. I get why people might not want to worry about types, 
but for any project with >10 lines it's a pain in the ass.
What is usually a quick glance at the variable definition
becomes a tedious search for the type one is working with.
Certain refactorings which are trivial in other languages
where you can be certain that shit works if the compiler doesn't complain
becomes a minefield where you have to test every single
modified codepath for runtime errors.
</p>
<p>
To counter this problem, one can either use an excessive amount of comments
or encode the type within the variable name. 
However, both of these approaches need to be maintained "manually", as Python
itself simply does not care.
Another """solution""" is to use <a href="https://docs.python.org/3/library/typing.html">"type hints"</a>,
a feature which is so utterly bizarre and useless to me:
<pre><code>
def testFunc(name: str) -> str:
    print(name)
    return 5
    
testFunc(42)</code></pre>
This feature provides the ability to <b>annotate</b> the type of 
function parameters and return values. Now, you might think:
"Wait a moment, the types of this code snippet don't match at all.
Is there some type conversion happening?".
No. Not at all. <b>The Python runtime completely ignores
these type annotations</b>. The provided code snippet runs 
without any errors or warnings. The official documentation
notes that they "can be used by third party tools", meaning
these are just glorified and standardized comments. 
Requiring third party tools to make
certain language features even remotely useful 
is certainly an interesting strategy.
</p>
<h1>
 Rounding</h1>
<p>
How would you round <code>1.5</code>? What about <code>2.5</code>?
This might be a cultural thing, but Python's answer 
completely threw me off:
<pre><code>
round(0.5)  # 0
round(1.5)  # 2
round(2.5)  # 2
round(3.5)  # 4</code></pre>
The concept of <a href="https://en.wikipedia.org/wiki/Rounding">"Banker's rounding"</a> was 
completely new to me, where people round halfway numbers to the nearest even number.
With experience in programming this one isn't too bad,
but beginner's which were not exposed to various rounding 
methods would probably not expect
their bug to because <code>round()</code> doesn't work as they expected.
</p>
<h1>
 Globals</h1>
<p>
The rational behind globals in Python makes sense if you don't care
about shadowing variables.
But for small scripts where you don't want to pass variables to every single
function, this behaviour is a nasty one:
<pre><code>
var = 5  # Global variable

def printGlobal():
    print(var)
    
def modifyGlobal(value):
    var = value

    
printGlobal()     # 5
modifyGlobal(42)
printGlobal()     # Still 5 :)</code></pre>
Python decided it would be a great idea
that global variables can be read from without issue,
but writing to them <b>creates a local variable which shadows the global one</b>.
If you want to modify the global variable, you have to write the function as follows:
<pre><code>
def modifyGlobal(value):
    global var
    var = value</code></pre>
Writing <code>global ...</code> in every single function where you want to modify 
the global variable is incredibly tedious and error prone.
I suppose this is Python's way of discouraging the use of global 
variables, but honestly: Fuck off.
</p>
<p>
I have to at least give them credit that runtime checks 
prevent accessing <b>and</b> editing global variables within
the same function:
<pre><code>
var = 5

def printAndModGlobal(value):
    print(var)
    var = value
    
printAndModGlobal(90)  # "UnboundLocalError"</code></pre>
</p>
<h1>
 Programming Philosophy</h1>
<p>
Some Python syntax choices really throw me off.
The global variable thing has burnt me often enough 
that I know that I need to include the <code>global</code> keyword somewhere. 
A good friend of mine has recently made the following innocent mistake:
<pre><code>
global var = 5

def modifyGlobal(value):
    var = value</code></pre>
The global keyword in this context is <b>literally useless</b>,
it has <b>no effect</b> outside of a function.
<code>modifyGlobal</code> still creates a local variable 
which shadows the global. I'm confused why
you'd even allow the keyword to be used that way (maybe <code>grep</code>-ability?)
as it just incudes a false sense of security ("no error, 
that must have worked :)").
</p>
<p>
Other times, Python can be <b>very</b> concise, most of the
time to the detriment of readability, e.g.
<code>return ... if ... else ...</code>.
But I can choose to simply not write my programs that way.
Some syntax choices such as <code>//</code> as the integer division operator
or not supporting the logical operators <code>&amp;&amp;</code> / <code>||</code> / 
<code>!</code> in favor of <code>and</code> / <code>or</code> / <code>not</code> feels very clumsy to me, but 
that is probably just me not getting used to the language.
I get that you don't want to duplicate operators,
but then again, both <code>==</code> and <code>and</code> exist, 
<b>which have a different runtime speed for some reason</b>:
<pre><code>
def testVariable(var):
    if var == None:
        print("Blub")

for i in range(10000000):
    testVariable(5)


> time python ./python.py

________________________________________________________
Executed in  641.75 millis    fish           external
   usr time  641.24 millis  167.00 micros  641.07 millis
   sys time    0.01 millis   15.00 micros    0.00 millis

========================================================
========================================================

def testVariable(var):
    if var is None:
        print("Blub")

for i in range(10000000):
    testVariable(5)

> time python ./python.py

________________________________________________________
Executed in  529.14 millis    fish           external
   usr time  525.52 millis    0.00 micros  525.52 millis
   sys time    3.19 millis  197.00 micros    2.99 millis</code></pre>
</p>
<p>
Or the fun lesson that Python
uses <a href="https://docs.python.org/3/library/functions.html#staticmethod">"decorators to make class functions static"</a>,
but if you try to save yourself writing a constructor you create static class members by accident:
<pre><code>
class a:
	var = 5                # Static member variable

class b:
	def __init__(self):
		self.variable = 5  # Non-static member variable</code></pre>
</p>
<p>
Python's construction of a class is fucky in general. 
When calling a member function, the first parameter is implicitly the 
class instance, so you get to write <code>func(self, ...)</code> for every member function.
Then, it has very fucky access """restrictions""" on class functions - which don't really
restrict the access at all:
<pre><code>
class A:
    def __init__(self):
        pass
    
    # Public function
    def funcA(self):
        print("A")
        
    # Public function, "but pls dont use" by convention
    def _funcB(self):
        print("B")
        
    # """private""" function, 
    def __funcC(self):
        print("C")
    
    # Public function calling the private function
    def funcD(self):
        self.__funcC()
    
i = A()
i.funcA()     # A
i._funcB()    # B
#i.__funcC()  # AttributeError
i.funcD()     # C
i._A__funcC() # C</code></pre>
</p>
<p>
But out of all the random tricks, I cannot believe that 
Python <b>does not support breaking out of nested loops</b>.
I'm serious. Online workarounds suggest putting
the loops into a function you can return from or
throwing and catching an exception instead. Wowie.
It gets even worse though:
There was a <a href="https://peps.python.org/pep-3136/">proposal for labeled break and continue which was rejected</a>.
This is already sad enough, but 
take a look at <a href="https://mail.python.org/pipermail/python-3000/2007-July/008663.html">the given rational</a>,
which claims that
<ul style="list-style-type:'- '"><li> "code so complicated to require this feature is very rare" (???),</li><li> "existing workarounds [...] produce clean code" (kill me)</li><li> they expect that "the feature will be abused more than it will be
used right, leading to a net decrease in code clarity" (?????????????????)</li>
</ul>
</p>
<p>
This straight up feels like gaslighting.
</p>
]]></content>
</entry>
<entry>
<title>I Hate: C++ (and its whole toolchain)</title>
<link rel="alternate" href="https://p4m.dev/posts/08/" />
<updated>2023-04-28T00:00:00Z</updated>
<id>https://p4m.dev/posts/08/</id>
<content type="html">
<![CDATA[<p>
I've touched (not properly used) a few programming languages over the years.
But holy hell do I despise C++. 
Let's go over a few things which are awful, in no particular order of madness.
</p>
<p>
The C++ specification is not freely available <a href="#note-0" id="back-0">[0]</a>. 
You can get <b>drafts</b> of the specification for free 
(and hope for the best that no important changes are made to the final release).
This is good enough in practice, but it's still bothering me out of principle.
The latest specification (I could find) contains 
<a href="https://github.com/cplusplus/draft/releases/tag/n4917">2105 pages</a>.
Let that sink in.
This is the reason why you can spend your entire life learning just this language.
</p>
<p>
This language contains an enormous amount of what feels like duplicate 
ways to express the same thing. 
The talk 
<a href="https://www.youtube.com/watch?v=KAWA1DuvCnQ">"The Last Thing D Needs" by Scott Meyers</a> contains
gems like the following:
<figure>
	<img src="./01.png" style="width:314px;height:379px;" />
<figcaption>
</figcaption>
</figure>
</p>
<p>
Or casts: I'm not even going to pretend to know the differences between 
the following cast operations:
<ul style="list-style-type:'- '"><li> <code>static_cast</code></li><li> <code>const_cast</code></li><li> <code>reinterpret_cast</code></li><li> <code>dynamic_cast</code></li>
</ul>
</p>
<p>
But funnily enough, the few times I needed to work with C++ 
these <a href="https://devtut.github.io/cpp/smart-pointers.html#unique-ownership-without-move-semantics-auto-ptr">cast operations weren't even sufficient</a>:
<figure>
	<img src="./02.png" style="width:500px;height:453px;" />
<figcaption>
</figcaption>
</figure>
</p>
<p>
Or when iterating over something:
<ul style="list-style-type:'- '"><li> <code>for (auto   i : list)</code></li><li> <code>for (auto  &amp;i : list)</code></li><li> <code>for (auto &amp;&amp;i : list)</code></li>
</ul>
</p>
<p>
Trying to find out what the differences between these things is one hell of a ride:
There are some rule of thumbs on which operator to use.
More accurate explanations contain wonderful paragraphs like the following:
<figure>
	<img src="./03.png" style="width:500px;height:173px;" />
<figcaption>
</figcaption>
</figure>
</p>
<p>
Confused what this means? Just read 
<a href="https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers">this concise explanation</a>,
that won't take any time at all <a href="#note-1" id="back-1">[1]</a>.
</p>
<p>
Do you dislike the ambiguity of the <code>static</code> keyword in C? 
Boy do I have a treat for you. Again, not claiming my understanding 
of the semantics are 100% correct, but you get the point:
<pre><code>
static int x; // variable is "private" to the compilation unit

static int testFunc() { // function is "private" to the compilation unit
  static int y;         // variable is persistent between function calls
}

class testClass {
  static int z;      // "class variable", shared across all class instances
  static int func(); // "class function", can be called without a class instance
}</code></pre>
</p>
<p>
<a href="http://david.tribble.com/text/cdiffs.htm">C++ isn't even a superset of C</a>.
While the feature of designated initializers was implemented in C99, 
it took C++ almost 20 years to <a href="https://en.cppreference.com/w/cpp/language/aggregate_initialization">implement a weaker version in C++20</a>.
And compound literals just straight up not exist at all:
<pre><code>
struct A { int x, y; };
struct B { struct A a; };
 
// Designated initializers
struct A a = {.y = 1, .x = 2}; // valid C, invalid C++ (out of order)
int arr[3] = {[1] = 5};        // valid C, invalid C++ (array)
struct B b = {.a.x = 0};       // valid C, invalid C++ (nested)
struct A a = {.x = 1, 2};      // valid C, invalid C++ (mixed)
// Note: out-of-order designated initialization, 
// nested designated initialization, 
// mixing of designated initializers and regular 
// initializers, and designated initialization 
// of arrays are all supported in the C programming 
// language, but are not allowed in C++. 

// Compound Literals
return (struct A){1, 2}; // Valid C, invalid C++</code></pre>
</p>
<p>
Then there's object oriented programming in conjunction with C++:
I could probably fill a rant just about this particular paradigm, 
but I'll keep myself short. 
Creating a <code>.cpp</code> and a <code>.h</code> for each class is fucking tedious. 
Changing a function signature becomes busy work <a href="#note-2" id="back-2">[2]</a>.
<figure>
	<img src="./04.png" style="width:500px;height:375px;" />
<figcaption>
</figcaption>
</figure>
</p>
<p>
Don't even get me started with compiler messages.
Not only does the template system bloat up the errors:
<pre><code>
FAILED: src/tool-cli-utilities/CMakeFiles/tool-cli-utilities.dir/cli.cpp.o 
/bin/c++  -I./tool/src -I./tool/src/tool -I./tool/cmake-build-debug/include/resources/3rdparty/parallel_hashmap -I./tool/resources/3rdparty/cpphoafparser-0.99.2/include -I./tool/cmake-build-debug/include -isystem ./tool/resources/3rdparty/l3pp -isystem ./tool/resources/3rdparty/gmm-5.2/include -isystem ./tool/cmake-build-debug/include/resources/3rdparty/toolEigen -isystem ./tool/resources/3rdparty/exprtk -isystem ./tool/resources/3rdparty/modernjson/src -isystem ./tool/cmake-build-debug/resources/3rdparty/cudd-3.0.0/include -isystem ./tool/resources/3rdparty/sylvan/src -isystem ./tool/resources/3rdparty/cpptemplate -isystem ./tool/build/resources/3rdparty/carl_download/source_dir/src -isystem /usr/include/eigen3 -isystem ./tool/build/resources/3rdparty/carl/resources/include -g -fPIC -std=gnu++17 -MD -MT src/tool-cli-utilities/CMakeFiles/tool-cli-utilities.dir/cli.cpp.o -MF src/tool-cli-utilities/CMakeFiles/tool-cli-utilities.dir/cli.cpp.o.d -o src/tool-cli-utilities/CMakeFiles/tool-cli-utilities.dir/cli.cpp.o -c ./tool/src/tool-cli-utilities/cli.cpp
In file included from ./tool/src/tool-cli-utilities/model-handling.h:54,
                 from ./tool/src/tool-cli-utilities/cli.cpp:15:
./tool/src/tool/storage/SymbolicDecomposition.h: In instantiation of 'tool::dd::Bdd&lt;LibraryType> symMec(const tool::dd::Bdd&lt;LibraryType>&amp;, uint_fast64_t, tool::dd::Bdd&lt;LibraryType>*, tool::dd::Bdd&lt;LibraryType>*, tool::dd::Bdd&lt;LibraryType>*, tool::dd::Bdd&lt;LibraryType>*, const std::set&lt;tool::expressions::Variable>&amp;, const std::set&lt;tool::expressions::Variable>&amp;, const std::vector&lt;std::pair&lt;tool::expressions::Variable, tool::expressions::Variable> >&amp;) [with tool::dd::DdType Type = tool::dd::DdType::CUDD; ValueType = double; uint_fast64_t = long unsigned int]':
./tool/src/tool/storage/SymbolicDecomposition.h:526:37:   required from 'std::vector&lt;tool::dd::Bdd&lt;LibraryType> > symbolicMECDecomposition(const tool::dd::Bdd&lt;LibraryType>&amp;, const tool::dd::Bdd&lt;LibraryType>&amp;, const tool::dd::Bdd&lt;LibraryType>&amp;, const tool::dd::Bdd&lt;LibraryType>&amp;, const std::set&lt;tool::expressions::Variable>&amp;, const std::set&lt;tool::expressions::Variable>&amp;, const std::vector&lt;std::pair&lt;tool::expressions::Variable, tool::expressions::Variable> >&amp;, uint_fast64_t) [with tool::dd::DdType Type = tool::dd::DdType::CUDD; ValueType = double; uint_fast64_t = long unsigned int]'
./tool/src/tool-cli-utilities/model-handling.h:784:103:   required from 'std::shared_ptr&lt;tool::models::ModelBase> tool::cli::buildModel(const tool::cli::SymbolicInput&amp;, const tool::settings::modules::IOSettings&amp;, const tool::cli::ModelProcessingInformation&amp;) [with tool::dd::DdType DdType = tool::dd::DdType::CUDD; ValueType = double]'
./tool/src/tool-cli-utilities/model-handling.h:1687:51:   required from 'std::shared_ptr&lt;tool::models::ModelBase> tool::cli::buildPreprocessModelWithValueTypeAndDdlib(const tool::cli::SymbolicInput&amp;, const tool::cli::ModelProcessingInformation&amp;) [with tool::dd::DdType DdType = tool::dd::DdType::CUDD; BuildValueType = double; VerificationValueType = double]'
./tool/src/tool-cli-utilities/model-handling.h:1708:106:   required from 'std::shared_ptr&lt;tool::models::ModelBase> tool::cli::buildPreprocessExportModelWithValueTypeAndDdlib(const tool::cli::SymbolicInput&amp;, const tool::cli::ModelProcessingInformation&amp;) [with tool::dd::DdType DdType = tool::dd::DdType::CUDD; BuildValueType = double; VerificationValueType = double]'
./tool/src/tool-cli-utilities/model-handling.h:1728:107:   required from 'void tool::cli::processInputWithValueTypeAndDdlib(const tool::cli::SymbolicInput&amp;, const tool::cli::ModelProcessingInformation&amp;) [with tool::dd::DdType DdType = tool::dd::DdType::CUDD; BuildValueType = double; VerificationValueType = double]'
./tool/src/tool-cli-utilities/model-handling.h:1745:75:   required from 'void tool::cli::processInputWithValueType(const tool::cli::SymbolicInput&amp;, const tool::cli::ModelProcessingInformation&amp;) [with ValueType = carl::RationalFunction&lt;carl::FactorizedPolynomial&lt;carl::MultivariatePolynomial&lt;cln::cl_RA> >, true>]'
./tool/src/tool-cli-utilities/cli.cpp:272:82:   required from here
./tool/src/tool/storage/SymbolicDecomposition.h:416:61: error: no matching function for call to 'getSingleSymbolicSCC(tool::dd::Bdd&lt;tool::dd::DdType::CUDD>&amp;, tool::dd::Bdd&lt;tool::dd::DdType::CUDD>, tool::dd::Bdd&lt;tool::dd::DdType::CUDD>&amp;, const std::set&lt;tool::expressions::Variable>&amp;, const std::set&lt;tool::expressions::Variable>&amp;)'
  416 |             tool::dd::Bdd&lt;Type> sNew = getSingleSymbolicSCC(v, s &amp;&amp; ( ! t), *transitions, metaVariablesRow, metaVariablesColumn);
      |                                         ~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
</code></pre>
</p>
<p>
But the whole build process is fucked.
People like to compile basically each individual <code>.cpp</code> file.
Assuming your build process works 
(<code>make</code>, <code>cmake</code>, <code>ninja</code>, <code>meson</code> or whatever the fuck people now use),
you can get helpful <b>linker</b> errors like the following:
<pre><code>
[7/7] Linking CXX executable bin/tool
FAILED: bin/tool 
: &amp;&amp; /bin/c++ -g -rdynamic   -rdynamic src/tool/CMakeFiles/tool-main.dir/tool.cpp.o -o bin/tool  -Wl,-rpath,./tool/cmake-build-debug/lib:./tool/build/resources/3rdparty/carl:./tool/build/resources/3rdparty/carl/resources/lib:  lib/libtool-cli-utilities.so  lib/libtool-counterexamples.so  lib/libtool-parsers.so  lib/libtool.so  /usr/lib/libboost_filesystem.so  /usr/lib/libboost_system.so  /usr/lib/libz3.so  /usr/lib/libglpk.so  resources/3rdparty/cudd-3.0.0/lib/libcudd.a  resources/3rdparty/sylvan/src/libsylvan.a  /usr/lib/libhwloc.so  ../build/resources/3rdparty/carl/libcarl.so.14.22  /usr/lib/libboost_filesystem.so  /usr/lib/libboost_system.so  /usr/lib/libboost_program_options.so  /usr/lib/libboost_regex.so  /usr/lib/libboost_unit_test_framework.so  -ldl  -lpthread  ../build/resources/3rdparty/carl/resources/lib/libginac.so  /usr/lib/libcln.so  /usr/lib/libgmpxx.so  /usr/lib/libgmp.so  -lpthread  lib/libtool-version-info.so &amp;&amp; :
/bin/ld: lib/libtool.so: undefined reference to `std::vector&lt;tool::dd::Bdd&lt;(tool::dd::DdType)1>, std::allocator&lt;tool::dd::Bdd&lt;(tool::dd::DdType)1> > > tool::storage::symbolicDecomposition&lt;(tool::dd::DdType)1, double>(tool::models::symbolic::Mdp&lt;(tool::dd::DdType)1, double> const&amp;, unsigned long)'
/bin/ld: lib/libtool.so: undefined reference to `std::vector&lt;tool::dd::Bdd&lt;(tool::dd::DdType)0>, std::allocator&lt;tool::dd::Bdd&lt;(tool::dd::DdType)0> > > tool::storage::symbolicDecomposition&lt;(tool::dd::DdType)0, double>(tool::models::symbolic::Mdp&lt;(tool::dd::DdType)0, double> const&amp;, unsigned long)'
/bin/ld: lib/libtool.so: undefined reference to `std::vector&lt;tool::dd::Bdd&lt;(tool::dd::DdType)1>, std::allocator&lt;tool::dd::Bdd&lt;(tool::dd::DdType)1> > > tool::storage::symbolicDecomposition&lt;(tool::dd::DdType)1, carl::RationalFunction&lt;carl::FactorizedPolynomial&lt;carl::MultivariatePolynomial&lt;cln::cl_RA, carl::MonomialComparator&lt;&amp;carl::Monomial::compareGradedLexical, true>, carl::StdMultivariatePolynomialPolicies&lt;carl::NoReasons, carl::NoAllocator> > >, true> >(tool::models::symbolic::Mdp&lt;(tool::dd::DdType)1, carl::RationalFunction&lt;carl::FactorizedPolynomial&lt;carl::MultivariatePolynomial&lt;cln::cl_RA, carl::MonomialComparator&lt;&amp;carl::Monomial::compareGradedLexical, true>, carl::StdMultivariatePolynomialPolicies&lt;carl::NoReasons, carl::NoAllocator> > >, true> > const&amp;, unsigned long)'
/bin/ld: lib/libtool.so: undefined reference to `std::vector&lt;tool::dd::Bdd&lt;(tool::dd::DdType)1>, std::allocator&lt;tool::dd::Bdd&lt;(tool::dd::DdType)1> > > tool::storage::symbolicDecomposition&lt;(tool::dd::DdType)1, __gmp_expr&lt;__mpq_struct [1], __mpq_struct [1]> >(tool::models::symbolic::Mdp&lt;(tool::dd::DdType)1, __gmp_expr&lt;__mpq_struct [1], __mpq_struct [1]> > const&amp;, unsigned long)'
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.</code></pre>
Now you get to binary search for the line(s) which fuck up your compilation :)
But that is <b>if</b> the build system works in the first place <a href="#note-3" id="back-3">[3]</a>.
Let me tell you the tale of when I tried to build a project whose main source code 
consisted of ~200k LoC. 
Building the project on a cluster (for later benchmarks) greeted me with this wonderful error:
<figure>
	<img src="./05.png" style="width:479px;height:477px;" />
<figcaption>
</figcaption>
</figure>
</p>
<p>
After the internet helped me decipher that this means that the compilation process
is taking too many resources, I was a bit puzzled. But yes, 
this indeed was the case:
<figure>
	<img src="./06.png" style="width:365px;height:95px;" />
<figcaption>
</figcaption>
</figure>
</p>
<p>
How the fuck can the compilation take 64GB of RAM? 
Well, the culprit was the line <code>make -j</code> in the build script:
You see, when every <code>.cpp</code> is compiled individually into into its own 
compilation unit, build processes tend to parallelize these compilations.
The line <code>make -j</code> however does not limit the number of parallel jobs.
That means <b>all</b>  <code>.cpp</code> files were compiled and optimized at the same time
(instead of processing e.g. <code>n</code> files at a time), which
apparently was sufficient to grind the system to a halt.
Fun times.
</p>
<h1>
 Bonus Entry (2023.05.20)</h1>
<p>
Thanks to reddit, here's a fun edge case <a href="https://en.cppreference.com/w/cpp/compiler%20support">coming in C++23 (according to this page)</a> for
custom <code>== / !=</code> operator overloads:
<a href="https://stackoverflow.com/a/76291004">This stackoverflow post</a> sums
up <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2468r2.html">this proposal</a>: 
<figure>
"if we find an operator <code>==</code> and an operator <code>!=</code> in the same scope with the same parameters, 
use the C++17 rules. Otherwise, use the C++20 rules."
<figcaption>
</figcaption>
</figure>
</p>
<p>
Wild.
</p>
]]></content>
</entry>
<entry>
<title>I Hate: Communication</title>
<link rel="alternate" href="https://p4m.dev/posts/07/" />
<updated>2023-04-01T00:00:00Z</updated>
<id>https://p4m.dev/posts/07/</id>
<content type="html">
<![CDATA[<p>
Given that humans communicate with each other every single day, we sure are
incredibly fucking bad at it.
It's one of the few things which makes me irrationally angry, 
so I might as well put my anger into this wall of text.
</p>
<p>
The latest incident on my end happened yesterday. 
I received a text message saying:
</p>
<p>
<figure>
	"Can you please give me a call? It would be important."
<figcaption>
</figcaption>
</figure>
</p>
<p>
I'm not exaggerating: Never in my life 
was a call preceding with just
"it's important" actually important enough for 
me to drop all of my shit and call them. 
In every single fucking case, a text message with 2-5 sentences
would have been sufficient.
</p>
<p>
This has happened (several times) with family, friends and strangers.
And it's triggering the fuck out of me.
If it's actually important - why the fuck don't you give me a quick rundown?
Every single fucking time I call and the gist of the conversation is handled 
within 20 seconds.
</p>
<p>
I'm tired of it. 
I won't be answering any of these anymore as a matter of principle
(and spite <a href="#note-0" id="back-0">[0]</a>).
</p>
<p>
What kind of logic is this? 
We have the technology to send text messages, which is the sole reason why someone was
able to notify me in the first place.
It's an <b>asynchronous</b> medium. 
Do you know how awesome that is?
Someone can send message without the other party actively expecting to receive it.
For important shit, that's fantastic: 
I'll give you all of the important information, maybe with additional requests (like 
fucking "can we discuss this more in detail?" or something), and 
<b>as soon as I can</b> I am able to read this and decide 
for myself on what to do next.
Even better, I am able to <b>respond</b> with <b>another</b> text message, maybe even resolving
the whole issue.
</p>
<p>
But no.
What people tend to do is to send me a text message saying "It's important".
The issue at hand is (so far 100% of the time) in some form of quantum superposition,
in which it requires immediate attention, <b>but</b> it is not important enough
to spend one minute writing a few sentences so <b>I can get the information as soon as possible</b>.
It gets even more ironic: After not reaching me immediately, there tends to be a solid 50% 
chance of them spamming the message over several other channels: Other messangers, 
Email, or even telling other people to message me as well.
</p>
<p>
Do you realize how much effort that is?
How a <b>fucking fraction</b> of that effort could have been spent on just <b>fucking texting 
me the fucking issue</b>? How much faster this whole thing could have been resolved?
No, that is apparently impossible. 
Instead of spending a minute, one rather waits for the next opportunity 
of a synced schedule so they can describe the problem over the phone.
Probably because of some "convenience", 
or because "it's easier" or "faster" - which is just wrong.
</p>
<p>
But don't get me wrong: I don't want to dodge phone calls at all costs.
Quite the opposite: Most (if not all) important conversations I had
were over the phone. Some of which even required immediate attention.
The important calls I had so far
<ul style="list-style-type:'- '"><li> were announced beforehand. "I might give you a call this evening about x due to y".
"I might need to talk about x with you after y", ...</li><li> sent me a text message containing the reason why it's important.</li>
</ul>
</p>
<p>
And I'm not talking a life or death situation.
Giving me an urgent call can be for the most miniscule reason:
<ul style="list-style-type:'- '"><li> "Hey I feel lonely and just need someone to talk to"</li><li> "I had a shit day and need to vent to someone, are you free?"</li><li> "I had some incident with x and y and need your opinion on the matter"</li><li> ...</li>
</ul>
</p>
<p>
and you bet your ass I'll try to reach them as soon as I can <a href="#note-1" id="back-1">[1]</a>.
All I want is to not be stressed out over stupid shit that 
<ul style="list-style-type:'- '"><li> can be resolved within two sentences</li><li> do not require immediate attention</li><li> are not within my capabilities at fucking all</li>
</ul>
</p>
<p>
Oh that's not all of it, don't you worry.
There is so much more I can rant about:
</p>
<h1>
 The Dialogue Tree</h1>
<p>
Oh how I fucking hate the dialogue tree. 
I'm not exaggerating: I have ended friendships with 
people who did this shit consistently.
Some of my friends and family are still doing this to some
extent, and it annoys me greatly.
It's best explained by the following image:
<figure>
	<img src="./DialogueTree.png" style="width:500px;height:436px;" />
<figcaption>
My drawing is technically a directed graph, but you get the point.</figcaption>
</figure>
</p>
<p>
It's a gigantic waste of both of our time. 
Just fucking talk about the thing you actually want to talk about.
You are not "rude" if you don't start the convo with a greeting.
If you still feel bad, just <b>put all of your shit in one message</b>.
For the love of god, don't make me walk all of the fucking tree myself, 
sending a single message after each fucking element and expecting me to
give you an answer.
Posting a text message only consisting of "hey" can basically be completely ignored.
</p>
<p>
That is not to say that I we can't talk about the things that happened during the day,
your feelings or just smalltalk in general.
If that is the point of the conversation, that is perfectly fine.
I just hate it when people try to "pad" their conversations with this when they
don't actually care about it.
</p>
<h1>
 "Can I ask you a question?"</h1>
<p>
Asking to ask is a common phenomenon, which is also incredibly infuriating to me.
So common in fact that 
<a href="https://www.nohello.com/">several people</a>  <a href="https://nohello.net/en/">have dedicated</a> <a href="https://dontasktoask.com/">websites for this</a>.
Basically a short form of the dialogue tree, just even more pointless.
</p>
<h1>
 "Do you have a minute/second" / "Can I give you a quick call?"</h1>
<p>
This is never a short / quick thing. This shit always takes up way too much time.
And fucking 75% of the time my responds ends up being either
<ul style="list-style-type:'- '"><li> "I don't know" or</li><li> "Your idea sounds ok"</li><li> "I don't know, I have to think about it"</li>
</ul>
</p>
<p>
Again, the leitmotif of this rant, just send me a fucking text message: 
<ul style="list-style-type:'- '"><li> If it was a short thing, then asking for a call is
probably about as much effort as asking me the thing directly.</li><li> You lazy fuck don't want to spend 5 minutes describing the problem,
which has a decent chance of <a href="https://en.wikipedia.org/wiki/Rubber_duck_debugging">resolving the problem in the process</a>,
so why the fuck should I spend my time trying to help?</li><li> There is no need to drag me into a call for a thing I might not know jack shit about. 
Waiting for me to respond to this is a gigantic waste of our time.</li><li> If the problem is too complicated I probably can't come up with a solution on the spot.</li>
</ul>
</p>
<h1>
 Asking Computer Related Questions</h1>
<p>
Last one, because I can probably write about this shit for weeks. 
Especially with computer related problems, people are so fucking 
incredibly bad at asking things.
There's <a href="http://catb.org/~esr/faqs/smart-questions.html">an even longer wall of text</a> on how to ask questions, 
but here is the short form I mostly care about:
<ul style="list-style-type:'- '"><li> Try to look up your problem on your own. 
There's a pretty high chance you are not the first person on the planet to have 
this problem, so there might be solutions to this.</li><li> Post the whole problem, including error messages and what not.
"It doesn't work" is utterly pointless.</li><li> Say what you expected to happen.</li><li> State the approaches you tried (hint: When working with computers, 
there is basically no penatly of just trying shit 99% of the time.
In these situations: If you haven't tried anything, you can fuck right off)</li>
</ul>
</p>
]]></content>
</entry>
<entry>
<title>What If I Don't Improve Myself?</title>
<link rel="alternate" href="https://p4m.dev/posts/06/" />
<updated>2023-03-18T00:00:00Z</updated>
<id>https://p4m.dev/posts/06/</id>
<content type="html">
<![CDATA[<p>
I have been struggling to 
<ul style="list-style-type:'- '"><li> get (seemingly) important things done,</li><li> stick to my schedules,</li><li> stay productive,</li><li> ...</li>
</ul>
</p>
<p>
...which is kind of a common theme in the few posts of mine.
But today I stumbled upon a lecture / speech by 
<a href="https://en.wikipedia.org/wiki/Alan_Watts">Alan Watts</a>, which 
kind of addresses this inner fight in an interesting way <a href="#note-0" id="back-0">[0]</a>.
I'll try to summarize the bits which were most important to me:
</p>
<p>
First the obvious: Other people cannot improve you. They can guide, they can aid,
they can make you think, but they cannot do the work for you.
The person trying to improve themself needs to be the one to make the improvement.
</p>
<p>
Now the problem: 
To improve, I need to <b>know what I need to do</b> in order to improve. 
But <b>if I knew, I would already be improved</b>, so I obviously don't.
It's a catch-22. I'm basically fucked, it's impossible.
</p>
<p>
Watts even addresses meditation: 
I can try to take a step back and watch myself 
- analyze my thoughts, my feelings, my doings, and so on.
But who's doing the observations, the processing and the analyzing?
Myself of course. 
So that part requires introspection as well.
But what about the part doing the introspection of my introspection? 
</p>
<p>
It's a laughable cat and mouse game:
I'm trying to outplay myself.
I'm playing against myself - and I'm hoping to win <a href="#note-1" id="back-1">[1]</a>.
</p>
<p>
Watts continues: 
We are trying to grow, we <b>want</b> to grow, <b>somehow</b>. 
It's the child craving some candy all over again, only more
spiritual this time around.
It's inherently selfish.
After all, what difference does it make? 
We all know or heard of people that feel like they figured it out, 
only to end up a little worse than some average dude.
</p>
<p>
Do you want to be selfish? Of course I don't. 
But why don't I want to? Because it's better that way.
Better than what? <b>Better than others?</b>
</p>
<p>
We all have the drive to do something in life. 
Some interest, some hobby, some profession, some knowledge, etc.
Some people are focussing on trying to maximize their income and money,
but often solely to persue some other interest of theirs afterwards.
I did not (and do not) enjoy attending uni, I'm mostly doing it for the degree;
but I like low-ish level programming and creating software.
</p>
<p>
In this instance, university has failed miserably:
It's no longer about the passion and profession. 
It's not about the interest in things. 
It's simply about the degree. 
</p>
<p>
But for the people persuing their true interests, 
for the people who are enjoying university, 
for the people who are happy in life;
ask yourself the following:
Whatever you are doing, studying, learning or
persuing - are you doing this to improve yourself, 
or is it "simply" some interest of yours?
</p>
<p>
For me personally (and this is where the realization kicks in):
No, I'm not trying to improve myself.
Improving in that field or profession is merely a byproduct.
I'm interested in creating software, being able to satisfy
my curiosity and overcoming obstacles along the way.
But I'm not doing this because "it's the right thing to do"
or because "it's better for myself" or anything like that.
Just like me learning the piano - becoming good at it is a side effect.
The mere fact of enjoying playing the piano or playing certain songs 
is my drive.
</p>
<p>
So know we can approach this whole fiasco in a different light:
There is nothing you can do to improve yourself,
and this does not matter.
</p>
<p>
This sounds oddly comforting to me, probably because this 
train of thought exempts me of any personal shortcomings. 
I'm not sure at the moment of what to make of Watts' insight, 
but it's definitely something to think about.
</p>
<p>
If this thought sounds interesting, dreadful, depressing or confusing,
I can only recommend to listen or read the talk for yourself.
It's quite likely that I will look into more stuff of his regardless
of any upcoming personal conclusions on this topic.
</p>
]]></content>
</entry>
<entry>
<title>I Hate: Audio On Linux</title>
<link rel="alternate" href="https://p4m.dev/posts/05/" />
<updated>2023-02-09T00:00:00Z</updated>
<id>https://p4m.dev/posts/05/</id>
<content type="html">
<![CDATA[<p>
There's no fucking way "the year of the linux desktop"
will ever come given the current shitshow that is 
Linux audio jungle. 
</p>
<p>
Let's start with a quick overview of audio systems.
There is:
<ul style="list-style-type:'- '"><li> <a href="https://wiki.archlinux.org/title/Open_Sound_System">OSS</a></li><li> <a href="https://wiki.archlinux.org/title/Advanced_Linux_Sound_Architecture">ALSA</a></li><li> <a href="https://wiki.archlinux.org/title/JACK_Audio_Connection_Kit">JACK</a></li><li> <a href="https://wiki.archlinux.org/title/PulseAudio">PulseAudio</a></li><li> <a href="https://wiki.archlinux.org/title/PipeWire">PipeWire</a></li>
</ul>
</p>
<p>
The bottom layer is basically formed by OSS and ALSA.
Apparently ALSA has replaced OSS, so ALSA is the thing
actually making Linux play sounds at the end of the day.
Consequentially, ALSA is also the only thing available 
on a minimal Linux installation.
</p>
<p>
From what I understand, PulseAudio, JACK and PipeWire all act 
as middlemen to the user (and software) and work with ALSA under the hood.
Ironically enough, this means that not only do they all implement the ALSA
API for software, but also APIs of another. What a mess.
</p>
<p>
ALSA, by default, is not able to play two sounds at the same time.
Just from the user perspective, this is fucking unusable garbage.
Sure, you can configure some additional bullshit to make this work.
But holy fuck the ALSA configuration files are <b>fucking horrible</b>.
Configuring your output devices is fucking awful - which is 
something I had to do on any system using an HDMI connection,
because I am lucky enough that my system always tries to 
output sound using my monitor (which does not have any speakers).
Disabling audio modules requires you to do some <code>modprobe</code> bullshit,
which most often does not really do the thing I want it to do,
and this is entering the part of Linux where I don't have the slightest 
clue of how to apply changes without restarting my whole system,
fucking everything up in the process.
The only thing that is somewhat working is <code>alsamixer</code>.
You can see and configure some sound channels
(e.g. the "mic"-channel is for some god forsaken reason muted after
the initial installation, requiring you to unmute it). 
You can globally tune the volume and it persists after boot.
I appreciate AlsaMixer.
</p>
<p>
Here comes our saviour PulseAudio: 
By default, we can play multiple sounds at the same time.
A blessing from the lord. We can now also adjust the volume levels
of individual applications easily: Just pop open <code>pavucontrol</code>
and work them sliders. Default audio devices can also be 
configured there. 
However, PulseAudio introduces its own set of <b>additional</b> problems.
When I first used wine, the whole audio of my system became lower pitched
because there was some mismatch between the sample rate of my audio interface
and the sample rate PulseAudio decided to use.
But you can configure PulseAudio as well - which is <b>horrible</b>. 
Not fucking horrible, so this is an improvement,
but still horrible. 
Then there's also fun bugs like some application hogging ALSA,
then starting e.g. a browser trying to initialize PulseAudio, 
which promptly shits itself because ALSA is hogged so PulseAudio cannot
become the middleman. 
Just restarting the applications once usually works, 
but this is not fun at all.
</p>
<p>
I can honestly not comment on JACK. 
It's some audio implementation often used for more professional 
audio setups. While I assume it's for loops and lower latency stuff,
it also has the reputation of being a bit more complicated to setup,
so I don't want to find out if not required.
</p>
<p>
However, after I tried to fiddle with my audio setup a bit,
I realized that I would need to do some additional configuration 
of ALSA and/or PulseAudio, so I decided to give PipeWire a try.
</p>
<p>
So far, it's been a wild ride of emotions. 
PipeWire, which is rather new, decided to handle both video and audio streams while aiming for low latency.
That sounds complicated, but from a user perspective my first installation 
basically just worked. Although there is a caveat (for my specific distro):
PipeWire uses a "session manager" - no fucking clue what that really does.
PipeWire, per default, ships with the "PipeWire Media Session" 
manager - which is deprecated and should not be used anymore. Great.
Instead, <a href="https://wiki.archlinux.org/title/WirePlumber">WirePlumber</a> should be used.
That installation just required me to execute four commands which seemed to just work.
</p>
<p>
Ok, celebrations?
<b>No</b>. After upgrading, my whole system was simply quieter. 
I assumed it was some level setting, so I decided to look how to adjust this.
In an odd twist of events, I have seen people recommend configuring audio levels
of PipeWire using <code>pavucontrol</code>, which PipeWire properly translates into its own 
configuration. 
This "just worked" after I setup the WirePlumber (which is good).
</p>
<p>
Now, you <b>can</b> do this with WirePlumber as well. 
In particular, you can find commands like
<pre><code>
$ wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
$ wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+</code></pre>
on the web. I wouldn't have guessed to use a WirePlumber tool, but alright.
What leaves a bitter taste is how you were supposed to find this out:
<pre><code>
$ man wpctl
man: No entry for wpctl in the manual.

$ wpctl -h
Usage:
  wpctl [OPTION] COMMAND [COMMAND_OPTIONS] - WirePlumber Control CLI

Commands:
  status
  get-volume ID
  inspect ID
  set-default ID
  set-volume ID VOL[%][-/+]
  set-mute ID 1|0|toggle
  set-profile ID INDEX
  clear-default [ID]

Help Options:
  -h, --help       Show help options

Pass -h after a command to see command-specific options


$ wpctl status
 Clients
 ...

Audio
 ...

Video
 ...

Settings
 ...</code></pre>
No mention of <code>@DEFAULT_AUDIO_SINK@</code> whatsoever,
so just stick to <code>pavucontrol</code>.
</p>
<p>
So, why video streams as well? Who the fuck uses that?
</p>
<p>
Without going too much into the details, there are two large desktop environments on Linux:
X11 and Wayland. Wayland is the new and shiny one, while providing compatibility
with X11 using XWayland, so some distros have started
migrating to it. 
</p>
<p>
I gotta admit, setting up e.g. i3 (X11) was always a fucking pain in the ass
and caused me troubles every single time, while sway (Wayland) pretty much flawlessly
for me. So props to that.
</p>
<p>
On the other hand: 
<ul style="list-style-type:'- '"><li> Developing Wayland applications fucking sucks. I can write a whole post
about this fucking garbage, might as well do so the next time I'm in the trenches trying to 
get my shit to work. </li><li> In the infinite wisdom of the core protocol developers, 
screensharing was deemed a security risk (fair) and deemed out-of-scope, meaning
there is no uniform way for a user to opt-into this (??????????).</li>
</ul>
</p>
<p>
So on sway, OBS  can record individual windows (iirc), but recording the whole screen is not possible
on its own. This also bricks Zoom or Discord screen sharing. Fucking marvellous.
</p>
<p>
PipeWire fixes that! 
With "xdg-desktop-portal" and PipeWire, OBS screen recording just works again, 
that was a pleasant surprise.
Here comes the downer again though:
</p>
<p>
So far, all audio levels were fine, <b>except</b> for MPV, which is really quiet.
Popping open <code>pavucontrol</code> reveals that the audio levels were just set to low,
but at seemingly random time intervals this would switch back.
I can't even just tune MPV louder, because that makes the audio clip while staying
quieter. 
It turns out, this is because, <b>for some fucking reason</b>, MPV decides to 
use the same audio levels as MPD, which I use for background music.
Whenever I update the audio levels of MPD using <code>mpc</code>, a <b>client of MDP</b>,
the audio levels I set for MPV in <code>pavucontrol</code> are updated to MDP's new levels
as well. 
</p>
<p>
<figure>
<img src="./05.png" style="width:500px;height:151px;" />
<figcaption>
The audio levels of MPD and MPV are equal. 
I would call this neat but I didn't ask for this and I can't get rid of it.</figcaption>
</figure>
</p>
<p>
This shit is driving me crazy because it's just so fucking mildly inconvenient,
and I can't find other people having this problem.
It certainly does not fucking help that the documentation of PipeWire / WirePlumber
is so fucking garbage. How do I even begin to tackle this problem?
I thought using <code>wpctl</code> could help, because it's quite verbose:
<pre><code>
$ wpctl status
PipeWire 'pipewire-0' [0.3.65, void@voidbox, cookie:1960366277]
  Clients:
      32. WirePlumber                         [0.3.65, void@voidbox, pid:1403]
      33. WirePlumber [export]                [0.3.65, void@voidbox, pid:1403]
      50. pipewire-pulse                      [0.3.65, void@voidbox, pid:1364]
      51. Music Player Daemon                 [0.3.65, void@voidbox, pid:1372]
      57. xdg-desktop-portal-wlr              [0.3.65, void@voidbox, pid:1673]
      64. Chromium input                      [0.3.65, void@voidbox, pid:30537]
      65. mpv                                 [0.3.65, void@voidbox, pid:9918]
      71. Firefox                             [0.3.65, void@voidbox, pid:31125]
      72. Steam                               [0.3.65, void@voidbox, pid:15222]
      73. Steam Voice Settings                [0.3.65, void@voidbox, pid:15222]
      74. Chromium input                      [0.3.65, void@voidbox, pid:15641]
      84. Firefox                             [0.3.65, void@voidbox, pid:31125]
     103. wpctl                               [0.3.65, void@voidbox, pid:10061]

...

Audio
  Streams:
      52. Music Player Daemon
           54. output_FL       > Scarlett 2i2 USB:playback_FL	[active]
           56. output_FR       > Scarlett 2i2 USB:playback_FR	[active]
      70. Firefox
           61. ouGtput_FR       > Scarlett 2i2 USB:playback_FR	[active]
           77. output_FL       > Scarlett 2i2 USB:playback_FL	[active]
      98. mpv
           86. output_FL       > Scarlett 2i2 USB:playback_FL	[active]
           95. output_FR       > Scarlett 2i2 USB:playback_FR	[active]

...</code></pre>
</p>
<p>
You can check both clients and streams, making this shit more complicated.
Let's check for some overlap between the clients of MDP and MPV:
<pre><code>
# MPV                                      | # MPD
$ wpctl inspect 65                         | $ wpctl inspect 51
id 65, type PipeWire:Interface:Client      | id 51, type PipeWire:Interface:Client
    application.language = "en_US.UTF-8"   |     application.icon-name = "mpd"
  * application.name = "mpv"               |     application.language = "en_US.UTF-8"
    application.process.binary = "mpv"     |   * application.name = "Music Player Daemon"
    application.process.host = "voidbox"   |     application.process.binary = "mpd"
    application.process.id = "9918"        |     application.process.host = "voidbox"
    application.process.session-id = "1"   |     application.process.id = "1372"
    application.process.user = "void"      |     application.process.session-id = "1"
    clock.power-of-two-quantum = "true"    |     application.process.user = "void"
    core.name = "pipewire-void-9918"       |     clock.power-of-two-quantum = "true"
    core.version = "0.3.65"                |     core.name = "pipewire-void-1372"
    cpu.max-align = "32"                   |     core.version = "0.3.65"
    default.clock.max-quantum = "2048"     |     cpu.max-align = "32"
    default.clock.min-quantum = "32"       |     default.clock.max-quantum = "2048"
    default.clock.quantum = "1024"         |     default.clock.min-quantum = "32"
    default.clock.quantum-limit = "8192"   |     default.clock.quantum = "1024"
    default.clock.rate = "48000"           |     default.clock.quantum-limit = "8192"
    default.video.height = "480"           |     default.clock.rate = "48000"
    default.video.rate.denom = "1"         |     default.video.height = "480"
    default.video.rate.num = "25"          |     default.video.rate.denom = "1"
    default.video.width = "640"            |     default.video.rate.num = "25"
    link.max-buffers = "64"                |     default.video.width = "640"
    log.level = "0"                        |     link.max-buffers = "64"
    mem.allow-mlock = "true"               |     log.level = "0"
    mem.warn-mlock = "false"               |     media.category = "Playback"
  * module.id = "2"                        |     media.class = "Stream/Output/Audio"
  * object.serial = "3458"                 |     media.name = "mpd"
  * pipewire.access = "unrestricted"       |     media.role = "Music"
  * pipewire.protocol = "protocol-native"  |     media.type = "Audio"
  * pipewire.sec.gid = "1000"              |     mem.allow-mlock = "true"
  * pipewire.sec.pid = "9918"              |     mem.warn-mlock = "false"
  * pipewire.sec.uid = "1000"              |   * module.id = "2"
    settings.check-quantum = "false"       |     node.autoconnect = "true"
    settings.check-rate = "false"          |     node.name = "mpd.PipeWire Sound Server"
    window.x11.display = ":0"              |     node.rate = "1/44100"
                                           |     node.want-driver = "true"
                                           |   * object.serial = "3451"
                                           |   * pipewire.access = "unrestricted"
                                           |   * pipewire.protocol = "protocol-native"
                                           |   * pipewire.sec.gid = "1000"
                                           |   * pipewire.sec.pid = "1372"
                                           |   * pipewire.sec.uid = "1000"
                                           |     settings.check-quantum = "false"
                                           |     settings.check-rate = "false"
                                           |     stream.is-live = "true"
                                           |     window.x11.display = ":0"</code></pre>
</p>
<p>
The only somewhat interesting overlap I can find is:
<pre><code>
application.process.session-id = "1"
* module.id = "2"
* pipewire.sec.gid = "1000"
* pipewire.sec.uid = "1000"</code></pre>
No clue what the <code>*</code> or any of these really mean. 
Let's cross check with the firefox client, whose audio seems to be 
independant of MPD / MPV:
<pre><code>
# MPD / MPV                          | # FireFox
application.process.session-id = "1" | application.process.session-id = "1"
* module.id = "2"                    | * module.id = "2"
* pipewire.sec.gid = "1000"          | * pipewire.sec.gid = "1000"
* pipewire.sec.uid = "1000"          | * pipewire.sec.uid = "1000"
                                     |   
                                     | # New entry
                                     | client.api = "pipewire-pulse"</code></pre>
Great, that overlap was not fucking helpful, because FireFox, which does not have that issue,
has the same overlap, so that's probably not it. 
Even worse, the only meaningful difference I see is that FireFox is using PulseAudio, so 
now I fear that <b>all</b> PipeWire-native clients are like this, <b>FUCK</b>. 
Let's check the MPV / MPD "Streams" for overlap:
<pre><code>
# MPD                                                   |  # MPV
$ wpctl inspect 52                                      |  $ wpctl inspect 98
id 52, type PipeWire:Interface:Node                     |  id 98, type PipeWire:Interface:Node
    adapt.follower.spa-node = ""                        |      adapt.follower.spa-node = ""
    application.icon-name = "mpd"                       |      application.icon-name = "mpv"
  * application.name = "Music Player Daemon"            |      application.id = "mpv"
    audio.adapt.follower = ""                           |    * application.name = "mpv"
  * client.id = "51"                                    |      audio.adapt.follower = ""
    clock.quantum-limit = "8192"                        |    * client.id = "65"
  * factory.id = "7"                                    |      clock.quantum-limit = "8192"
    factory.mode = "split"                              |    * factory.id = "7"
    library.name = "audioconvert/libspa-audioconvert"   |      factory.mode = "split"
    media.artist = "Disasterpeace"                      |      library.name = "audioconvert/libspa-audioconvert"
  * media.category = "Playback"                         |    * media.category = "Playback"
  * media.class = "Stream/Output/Audio"                 |    * media.class = "Stream/Output/Audio"
    media.name = "Disasterpeace - Beyond"               |      media.name = "Pixel Land - mpv"
  * media.role = "Music"                                |    * media.role = "Music"
    media.title = "Beyond"                              |    * media.type = "Audio"
  * media.type = "Audio"                                |      node.always-process = "true"
    node.autoconnect = "true"                           |      node.autoconnect = "true"
  * node.name = "mpd.PipeWire Sound Server"             |    * node.description = "mpv"
    node.rate = "1/44100"                               |      node.latency = "960/48000"
    node.want-driver = "true"                           |    * node.name = "mpv"
    object.register = "false"                           |      node.rate = "1/48000"
  * object.serial = "3452"                              |      node.want-driver = "true"
    stream.is-live = "true"                             |      object.register = "false"
                                                        |    * object.serial = "3459"
                                                        |      stream.is-live = "true"</code></pre>
I'm noticing that <code>factory.id</code> is overlapping, checking against FireFox:
<pre><code>
# MPV / MPD        | # FireFox
* factory.id = "7" | * factory.id = "6"</code></pre>
</p>
<p>
A lead! Ok, time to lookup what the fuck a factory is doing in WirePlumber.
</p>
<p>
<img src="./01.png" style="width:405px;height:700px;" />
<img src="./02.png" style="width:500px;height:358px;" />
</p>
<p>
Ok, this didn't help, but maybe this is a PipeWire and not a WirePlumber thing?
</p>
<p>
<img src="./06.png" style="width:446px;height:700px;" />
</p>
<p>
Pretty bad, <b>maybe</b> the developer docs can help me out here <a href="#note-0" id="back-0">[0]</a>?
<img src="./03.png" style="width:500px;height:303px;" />
</p>
<p>
Not helpful at all. <code>More...</code> has to save my ass here.
</p>
<p>
<img src="./04.png" style="width:445px;height:97px;" />
</p>
<p>
Fuck you too I guess.
</p>
<p>
I have no idea how that shit even happens.
Linking the sound levels of <b>two different applications</b> sounds like a pretty niche
feature. Hey, this <b>might</b> be useful to some, the fuck do I know.
But why the fuck is this the default behaviour I have? 
I'm pretty certain there is a one-liner somewhere to fix this.
But...
<ul style="list-style-type:'- '"><li> I have no idea what it is</li><li> I have no idea where I can find it</li><li> I have no idea where I have to look at find it</li><li> I have no idea <b>how</b> to find it</li>
</ul>
</p>
<p>
It's audio, on a desktop machine.
Why is audio causing so many problems? 
Why is this shit not solved?
</p>
<h1>
 The Fix (2023.04.10)</h1>
<p>
I did some more digging and finally found a workaround for this problem:
Create a file <code>.config/wireplumber/main.lua.d/51-mpv-fix.lua</code> with the following content:
<pre><code>
stream_defaults.rules = {
	{
		matches = {
			{
				{ "application.name", "matches", "mpv" },
			},
		},
		apply_properties = {
			["state.restore-props"] = false,
		},
	},
}</code></pre>
Restart pipewire / wireplumber and finally, mpv is starting with 100% volume
(and not copying the volume of MPD).
</p>
<p>
Apparently this has something to do with <code>media roles</code>? 
MPD and MPV share the same role when playing music, so adjusting the 
volume of MPD adjusts the volume of the role, which is used as the
initial volume for every newly started application using that role.
</p>
<p>
I get the use case for this - but fucking I hell I don't want this.
I should probably find a way to disable this mechanism completely, 
but I'm satisfied for now.
</p>
]]></content>
</entry>
<entry>
<title>Stream of Thoughts: What Do I Like?</title>
<link rel="alternate" href="https://p4m.dev/posts/04/" />
<updated>2023-01-24T00:00:00Z</updated>
<id>https://p4m.dev/posts/04/</id>
<content type="html">
<![CDATA[<p>
Man it's way too late for this, but here I go. 
First things first: What have I been up to?
What is my progress on things? 
</p>
<p>
I finished the book "The mythical man-month". 
That was a good read, would recommend to other 
programmers / people interested in programming. 
This book helped me gain a new perspective on the creation of software,
the intrinsic difficulty creating these systems
and more. 
I'm surprised how well some the contents of this book aged.
</p>
<p>
I started transcribing some sheet music for piano of an arrangement
of which I couldn't find / purchase any existing sheet music. 
My lack of music theory comprehension makes this a bit tricky,
but so far I can manage. I'm missing roughly 40 seconds worth of 
music in my transcription. The rest should mostly be repetition.
I should probably clean my transcription up afterwards, but 
I'm not sure whether I can be bothered doing that later.
Once I'm done with that I'll probably upload it either
here or on <a href="https://howthefu.cc">my other website</a>. 
And I still need to create a post describing how I did these
things in the first place, because, although it's tedious and stupid,
it actually somewhat works (for me). 
</p>
<p>
My piano practice is making steady progress. 
The piece I'm currently practicing will probably 
occupy me for several more months, and even after that
I'm certain there are two or more parts which I won't come close to
getting right. However, it's still lots of fun. 
And additionally, I have >2/3 of it (somewhat) memorized already, so that's 
a big chunk of work already done. 
</p>
<p>
What about my programming projects?
I think I haven't spent a single minute on them. 
Yikes, that's gotta improve.
</p>
<p>
Daily walks? 
There's been quite a bunch of snow lately, so I don't feel bad for skipping on that.
</p>
<p>
Ok and now for the main culprit of my ramblings: 
My fucking thesis. 
</p>
<p>
It's coming along. I, sadly, still have some 0-days <a href="#note-0" id="back-0">[0]</a>, which I absolutely fucking hate.
But I think, given a few actual productive fucking days, I can be done
with the main part of the thesis soon. 
The pages have been filling themselves pretty pretty much automatically thanks
to the visualizations, further explanations and overviews over various topics.
So I don't think I have to worry in that regard.
</p>
<p>
What have I been wasting my time on then?
This month it probably was <b>Reddit</b> and <b>YouTube</b>.
And here comes the worst part: I don't think I particularly enjoyed either of them.
</p>
<p>
Reddit? Waste of time. Full stop. 
Even the memes are feeling stale <a href="#note-1" id="back-1">[1]</a>. 
So I have been heavily reducing my reddit usage over the last few days,
and my (current) plan is to completely drop using it all together.
</p>
<p>
Dropping reddit made me use YouTube more extensively. Fugg.
And even here: Given a day spent mostly on YouTube, how many videos did I <b>actually enjoy</b>?
Honestly, ~1 hour? Maybe two? Certainly not most of the day.
So next big plan: Fucking drop that bitch as well.
Given the time I spent, I might very well be addicted to YouTube, which <s>has to</s>will fucking stop.
</p>
<p>
I feel like I wrote this before, but still: 
I want to fill my day with things that are either full of enjoyment or full of progress<a href="#note-2" id="back-2">[2]</a>.
This involves reflecting on each day, and deciding which activities I did were worth doing.
</p>
<p>
This worked fine for reddit and other stuff, but why not YouTube?
I've been realizing that I try incredibly hard to <b>not be bored</b>.
And that lack of boredom is problematic:
Most of my days are filled with "just enough"-lackluster activities to <b>just</b> be 
not bored enough. On top of that come the actual fun activities 
(playing piano, writing this, reading, hanging out / chatting / watching stuff with friends).
</p>
<p>
I need to embrace boredom. 
Not because the state of boredom is something to strive for, 
but because it is boredom which drives us to fulfilling activities.
Neither do I mean that I need to be either productive or having fun throughout the whole day.
I want boredom to focus my time: Explore things, learn things, 
do the task I didn't want to do because what else am I going to do otherwise? 
Might as well spend my time working or improving myself at doing x.
Boredom should drive me to either be productive (because what else should I do otherwise?)
or do to activities I truly enjoy doing.
</p>
<p>
Here's my weakness:
It's the morning. I made food. 
Well, eating is nice, but also boring. So I'm gonna open up some YouTube-video
to watch while eating. But after I'm done eating, I probably won't stop the video half-way.
And depending on the video series / topic, I probably won't stop after finishing that video 
either. Minutes become hours, and there goes my time.
</p>
<p>
That shit won't fly anymore (or at the very least, way less than before).
I need to be on my own and become bored.
<ul style="list-style-type:'- '"><li> "I'm too tired to be productive right now":
This is a whole separate issue on its own, but for now: Fine.
But this will now mean that I'm too tired to watch videos as well.</li><li> "But I'm bored":
Well then you aren't that fucking tired after all, are you?
I can't be simultaneously "too tired" and bored. 
If I truly were too tired, I wouldn't mind not doing anything.
This shit is called resting, and resting is fine.</li><li> "But I don't wanna do x right now": 
Fine. Do y instead. But you won't spend the whole day e.g. on the piano.
So after a while, you will become bored of that as well.
Repeat until too bored to do anything but work.</li>
</ul>
</p>
<p>
So it's time to stop bullshitting myself. 
Become bored. Embrace boredom.
Let the boredom guide myself to improvement.
</p>
]]></content>
</entry>
<entry>
<title>Stream of Thoughts: Self-Criticism</title>
<link rel="alternate" href="https://p4m.dev/posts/03/" />
<updated>2023-01-09T00:00:00Z</updated>
<id>https://p4m.dev/posts/03/</id>
<content type="html">
<![CDATA[<p>
I am not as productive as I'd like to be. 
And it's not like I don't have things to do;
if anything it's quite the opposite.
I'd like to...
<ul style="list-style-type:'- '"><li> Do more programming<ul style="list-style-type:'- '"><li> Finish up an emulator</li><li> Get a rudimentary debugger to work</li><li> Write a C parser to have more useful code tools available</li><li> Maybe a compiler?</li><li> Maybe an IDE?</li><li> Get more into embedded system stuff. Maybe some bare metal? Assembly?</li>
</ul>
</li><li> Get better at playing the piano</li><li> Keep my room more clean (I'm writing this knowing full well that this apartment is in 
dire need of some vacuum cleaning)</li><li> Read more books</li><li> Go on daily walks because jesus fucking christ I sit in front of the pc the whole fucking day</li><li> Lose some weight (fucking christmas season, man)</li><li> Maybe start a little art hobby. Nothing fancy, just becoming <s>not shit</s>decent at 
pixel art or pencil sketches or something</li><li> Work on my posture as I walk around like the hunchback of notre-dame</li><li> Finish my god damn fucking bachelor's thesis and thus my degree</li><li> Spend more of my time being productive, or rather spending less "meh"-time on reddit and youtube</li>
</ul>
</p>
<p>
Having ambitions is good and all, but it's quite worthless if one does not work on them.
But this is just me being just a bit too harsh:
</p>
<p>
Self-criticism, or just criticism in general comes with a purpose: 
It's supposed to help someone to improve in some shape or form. 
This might result in "changing something", but it can also
be changing the way something is presented.
In these aspects, the self-criticism I indulge in seems pretty double-edged.
</p>
<p>
Let's start with the ugly: 
There's <b>quite</b> the room for improvement. 
I had my fair share of days where I was laying in bed, thinking about what I achieved 
or how I felt during the day the day, and concluded that I 
<ol>
<li> didn't make any progress on any of my goals,</li><li> spent most of my day browsing YouTube and Reddit, and worst of all:</li><li> felt pretty "meh" during most of it.</li>
</ol>
</p>
<p>
These "0-days" I want to get rid of entirely.
I don't need to have my life figured out at the moment, I don't need
to Min-Max every single day of mine. Hell, not even most days. 
</p>
<p>
What I want is a <b>baseline</b>. Regardless of what it is, 
each day I want to be able to say:
"Hey, even if I didn't achieve a lot, I managed to make progress on X".
I think that's a pretty achievable goal and a good starting point.
</p>
<p>
As of writing, this is the 9th day of the new year, and I have pretty mixed feelings
on my progress so far. Mentally, I'm always procrastinating "just one more hour",
which slowly but surely morphs into wasting the day. 
While I do feel bad about it, I try to justify it to myself 
by saying "oh well that was only one day. Tomorrow I'll be better, for sure".
</p>
<p>
Yeah that shit doesn't work, at least not for me.
A good thought exercise I've picked up somewhere was to focus
on the previous day and ask yourself: "If you'd spend the next 30 years
spending each day like that, where would you end up?"
This can be pretty brutal, but it helps internalizing the long term 
consequences of short term procrastination. 
30 years of baby-steps will still get you a long way in comparison to 
treading water for 30 years.
</p>
<p>
Generally speaking, <b>starting</b> a task is the largest hurdle for myself.
After I start working on something, spending a few hours on something 
is less of a problem. Just <b>starting</b> the thing is my largest problem.
I know that this is a somewhat common issue, but fucking hell this sounds
like utter insanity. Doing the thing, logically speaking,
<b>is supposed the difficult part</b>. Any dumbfuck can start working on something,
consistency, continuous effort and actual progress is the difficult part.
</p>
<p>
There are some little tricks which can help to get over said hurdle:
<ul style="list-style-type:'- '"><li> "3-2-1": Take a deep breath, count yourself down, and go get'em. 
Sounds stupid, but hey, as long as it works.</li><li> The "X Minutes"-Rule: If something takes less time than X minutes,
just fucking do it immediately instead of beating yourself up 
over the whole day. Works best for small things like vacuum cleaning.</li><li> Being a little self-deprecating: Make sure not to do this too much,
but sometimes telling oneself "quit being a bitch and clean your fucking room" can 
do wonders.</li><li> Meditation: <a href="https://www.youtube.com/watch?v=i7kh8pNRWOo">This little meditation exercise by Jonathan Blow</a> helps
examining physical and mental sensations. For some weird fucking reason, 
many mental thoughts can be "removed" by focussing on them, like pointing 
a flashlight at a shadow. It sounds utterly insane, but it has helped me 
before. Afterall, some temporary relief is all you need to get over the
initial hurdle. I practiced this on my walks, now I need to deploy this
where it matters.</li>
</ul>
</p>
<p>
More fundamentally, there are things like <b>motivation</b> and <b>discipline</b>:
Motivation is the thing making me start new projects, picking up new hobbies,
basically doing anything new besides work, while discipline is the thing
I lack most of. Having motivation is good, being disciplined is better. 
</p>
<p>
However, <b>routine</b> trumps them both. 
I don't think this necessarily works for "Deep Work", but for things
like the daily walks I feel meh about it works wonders: 
No need to have motivation nor discipline if your brain is on auto-pilot until
you step out of the apartment. <a href="https://jamesclear.com/atomic-habits">"Atomic Habits" by James Clear</a> is a
good book on building habits. While I do enjoy walks in the night more, 
I realized that for me, walking in the morning is easier to 
work into my morning routine and thus leads to a higher successrate of me
actually fucking walking. Bonus points for stacking these things together,
like doing exercises for my back <b>immediately</b> after returning back home from the walk.
</p>
<p>
This rambling is nothing new for me, as I had talked to two close friends of mine
about it (probably on several occasions). Both of them provided great input which 
helps me transform my "self-criticism" into actual criticism instead of hatred <a href="#note-0" id="back-0">[0]</a>:
</p>
<p>
Recognizing these shortcomings of mine is crucial. 
Heck, even if I spin around in circles, recognizing that one is within a 
circle provides new insight into the situation and is the first step
into breaking out of it. It sounds super cheesy, but man that is 
something important to internalize. 
That alone can shift the entire narrative from "I'm making no progress
whatsoever" to "I'm looping again. I have to change something up".
</p>
<p>
The other insight was just an innocent question: 
"Aren't you a bit hard on yourself?"
This small question helped me to properly differentiate
between proper criticism and self-deprecation.
Let's shift perspective for a moment: If I were a friend of mine
and that person said "boohoo, I didn't accomplish much this year" - what would
I say to this person? I'd say: "You're a dumb fuck". Let's go over the list of
things I want to do once more and set that into perspective:
<ul style="list-style-type:'- '"><li> Do more programming: </li><li> I (somewhat randomly) started practicing piano in september. Sure, I have neglected
guitar practice, but man, my progress is not that bad for just four months.
At the very least, that's way better progress than I expected, so that's a plus.
And being able to play two instruments is pretty badass.</li><li> Keep my room more clean: Yes, but this a <b>constant</b> process. 
The room will stay clean for a day or two, after which it will become dusty again.
So that "goal" is quite easy to fail and impossible to reach "the end". So just
vacuum more often, that's do-able.</li><li> Read more books: Yes, but I barely read any books as a teenager. Just going
over the <s>pdfs</s>list of finished books I have obviously improved a ton in that regard.</li><li> Go on daily walks: Again, even some walks from time to time is/was way better than
what I did years prior to that - which was nothing at all.</li><li> Lose some weight: It was fucking christmas season. If that's not the time to stuff 
yourself full I don't know what is. Just keep an eye on the scale and I'll be fine.</li><li> Maybe start a little art hobby: Sure! Sound great. Video games, programming, playing
the guitar and piano and reading take up quite some time already. It's nice to be able
to switch between hobbies easily, but, if I wanted to, I already have enough hobbies 
which I could spend enough time on.</li><li> Work on my posture: I am (sometimes) doing the 9min exercises for my lower back. 
Again, compared to previous years, that's a dope improvement.</li><li> Bachelor's thesis: I've done most of the programming part and "just" need to write 
things down for now. I got this.</li><li> Being more productive: I <b>might</b> be more productive than I used to! I need to remind
myself that last year I had more things going on at uni. Now there's only the thesis left,
which I am able to do at my own pace. This means while I might waste more "total hours"
in a day, I could be more productive in regards to "% of my free-time" <a href="#note-1" id="back-1">[1]</a>.</li>
</ul>
</p>
<p>
So: Always set goals, accomplishments and problems into context. 
Ironically enough, one could say that writing down these thoughts is a form 
of procrastination, and I'd somewhat agree. 
But I'm off to cleaning my room and putting some hours into my 
thesis - because writing all of this down only to then waste the rest of the day 
sounds fucking moronic, doesn't it?
</p>
]]></content>
</entry>
<entry>
<title>Dream Diary: A Home I Do Not Recognize</title>
<link rel="alternate" href="https://p4m.dev/posts/02/" />
<updated>2022-12-29T00:00:00Z</updated>
<id>https://p4m.dev/posts/02/</id>
<content type="html">
<![CDATA[<p>
My dreams, generally, are an incoherent mess.
They aren't realistic (visually nor story-wise), they aren't cool,
and I don't get much out of them. I used to have a little notebook
as a dream diary, but as I ran out of space I kinda just stopped doing that.
Besides, I usually wake up in the middle of the night at least once, 
and getting yourself to write legible notes while still half asleep is pretty annoying.
</p>
<p>
But regardless, the concept and the way dreams are experienced fascinates me.
For example, my dreams are barely visual (think like snapshots of a storyboard of something),
I barely remember audio cues after waking up and all other senses are basically non-existent.
But in my circle of friends, these experiences / senses involved differ quite a bit. 
And that's without getting into the actual plot of a dream.
</p>
<p>
But last night's dream was somewhat unique for me. 
</p>
<p>
The story itself wasn't ouf of the ordinary:
I dreamt that a class from my old school did a field trip to the netherlands and back.
But we had some freetime and were supposed to meetup at a busstation back in germany.
However, for some reason (which totally made sense in my dream), the teacher had my ID.
I was taking a bus which was supposed to drive for 70 minutes to a station in germany,
where I'd meet the teacher, get my ID and swap busses to get back to the meetup-spot.
But a ticket inspector wanted to see my ID and was threatening to give a fine.
After some back and forth the guy decided to let it slide - and suddenly
I realized that the bus just drove past the street of my house. So I got off the next stop <a href="#note-0" id="back-0">[0]</a>,
and walked back a street. There I met a childhood friend of mine, we exchanged a few
sentences, and I continued walking to my house, where, after entering through the main door,
I woke up. 
</p>
<p>
I spend some time thinking about that dream after I woke up - which is the reason why 
decided to write this all down. There are lots of oddities; none of which are actually 
that interesting, but I'll save them just in case.
</p>
<p>
The thing which surprised me most: That wasn't my actual home; no aspect of it
had any resemblance to my home, nor to any places I somewhat frequently visit.
The streets were <b>completely</b> different, I didn't get to see
the "dream house" itself, but the entry to the door is wildly different as well. 
</p>
<p>
<figure>
	<img src="./DreamHomeEntrance.png" style="width:500px;height:392px;" />
<figcaption>
Boy am I bad at drawing. Oh well, point is, I needed to walk "past" the house itself and around
a corner. So the main entrance of the home was "at the back of it". I do remember 
a lower garage for the neighbours to the right, for some reason</figcaption>
</figure>
</p>
<p>
As I said, I don't remember much of the house itself. My memory consist of:
<ul style="list-style-type:'- '"><li> This weird layout of the front door</li><li> Entering the door has you standing directly in the kitchen, with 
~1.5m between the door and the kitchen backwall</li><li> A very distinct archway</li>
</ul>
</p>
<p>
The archway got my attention. It felt very familiar and I felt "safe" at that place (safe from what?).
In hindsight I should have scribbled the archway down immediately after waking up, because I continued sleeping
so I lost a bunch of details of it. I feel like I have seen the archway before, but I can't recall from where.
My crudely and somewhat recollection from my dream looks like this:
</p>
<p>
<figure>
	<img src="./Archway.png" style="width:500px;height:556px;" />
<figcaption>
Whatever the top thingy actually was, I remember it being more "round", 
but my few attempts of adjusting the sketch just made it look "wrong".</figcaption>
</figure>
</p>
<p>
By writing this whole wall-of-text I'm making this a way bigger deal than it actually is, which
wasn't my intention. I just need to get this out of my system. Feeling that much comfort and 
safety from a completely foreign place is just a very... new(?) / odd experience for me. 
If anything, I usually tend to react the opposite way.
</p>
<p>
Here comes the part which fucks with my mind a bit: 
The layout of the streets feel familiar <b>from other dreams</b>. 
I am fully aware that this could be <a href="#note-1" id="back-1">[1]</a> just my brain messing with me / making
up memories / matching vague but irrelevant memories with this dream. 
Doesn't help me with this weird feeling though. I decided to briefly sketch a 
top-down view of the street(s) (with the path I took within the dream):
</p>
<p>
<figure>
	<img src="./Map.png" style="width:500px;height:562px;" />
<figcaption>
A quick map of the streets near my "dream home". I exited the bus (1), walked (2) and
crossed the street (3). There I met my friend on some grassy field road (4) and I ended up 
on "my street" again (5) where I entered my home (6).</figcaption>
</figure>
</p>
<p>
I distinctly remember the street at the bottom matching up with an older 
dream (a few months? half a year maybe?) I had: The left site of the street 
just kind of faded into this grassy-path, while the right side of the street 
leads into the village/city.
</p>
<p>
I also remember a completely different dream having the same bus "route events":
<ul style="list-style-type:'- '"><li> Bus is supposed to drive for a long time</li><li> It turns out the bus just randomly drives by my house, completely skipping hours
worth of traveling</li><li> I get out quickly and walk to my house -> happy me</li>
</ul>
</p>
<p>
I'm gonna be honest: <s>I have no idea why I decided to write this whole 
thing down.</s> The images I scribbled are incredibly generic and not interesting at all. 
I just want to make sure that, if I happen to have a dream which "matches" with my 
previous experiences, that they <b>actually</b> match and my brain is not just making shit 
up just to troll me bit.
</p>
]]></content>
</entry>
<entry>
<title>I Hate: The Web</title>
<link rel="alternate" href="https://p4m.dev/posts/01/" />
<updated>2022-12-23T00:00:00Z</updated>
<id>https://p4m.dev/posts/01/</id>
<content type="html">
<![CDATA[<p>
Here is the classic rambling:
<ul style="list-style-type:'- '"><li> Computers used to be slow -> Internet was slow</li><li> Computers are ridiculously fast now, but the internet is still dogshit slow</li><li> Everything is full of javascript and is completely broken without it</li><li> Copious amounts of cookie consent banners</li><li> Using an adblocker is basically mandatory </li>
</ul>
</p>
<p>
I'm going to skip all of that and instead just focus on the experience I had 
when creating this website.
So my website was obviously going to be a static one, customized to my liking
just by using HTML and CSS. 
</p>
<p>
Most of the design implementation was straight forward: 
Google how do to <code>x</code> in CSS, copy, and tweak. 
Repeat until satisfied.
I picked out a pixel font 
(which I got from <a href="https://int10h.org/oldschool-pc-fonts/fontlist/">here</a>)
because pixel fonts are incredibly sharp for small text sizes, 
which is what I prefer.
Make the text in a nice "block format" using <code>text-align: justify;</code>,
tweak the colors, 
adjust the whitespace / padding, and that's about it.
</p>
<p>
It was getting late because this took some time 
(but it was quite simple) and my vision was becoming blurry - damn, 
I must be really tired, huh? Time to...
</p>
<p>
...wait.
<img src="./IHateTheWeb01.png" style="width:500px;height:282px;" />
What the fuck is this? It's a <b>pixel</b> font. Why is it this blurry?
And why is it crisp <b>sometimes</b>? Fuck me, time to debug.
<ul style="list-style-type:'- '"><li> <code>font-weight</code>? Well, the whole block is in the same style, that's not it.</li><li> Am I missing some setting? I don't know, maybe? 
But I feel like it was sharp before. </li><li> <code>line-height</code>? No effect.</li><li> Checking the <code>ReadMe</code> of the provided web-font-file: 
I chose the "original" size in pixels, that's all correct.</li><li> Whitespace? Doesn't seem to do much.</li>
</ul>
</p>
<p>
So, who was the culprit? It was motherfucking <code>text-align</code>.
</p>
<p>
How fucking dare I to want my text to fit into a block I guess?
Setting it to <code>center</code> or <code>left</code> at least fixes this issue:
<img src="./IHateTheWeb02.png" style="width:500px;height:227px;" />
</p>
<p>
Here is another fun one:
<img src="./IHateTheWeb04.png" style="width:500px;height:207px;" />
What is the issue in this code block?
Well, the crisp lines are indented using <b>4 spaces</b>, while the blurry lines
are indented using <b>1 tab</b> with <code>tab-size</code> set to <code>4</code>. 
Why did foolish me expect that this would result in the same behaviour?
Silly me.
</p>
<p>
I bet you remember visiting some website which goes "hurr durr 
browser x is not supported, use browser y instead".
I always wondered what the fuck they did in order to achieve this 
incompatibility in the first place <a href="#note-0" id="back-0">[0]</a>. 
</p>
<p>
Anyways, I, in a moment of utter foolishness, opened the same page 
in chrome/chromium, expecting the result to be the same. Well it...
<img src="./IHateTheWeb03.png" style="width:500px;height:276px;" />
...just makes <b>everything</b> fucking blurry. You have to be shitting me.
</p>
<p>
I want to reiterate:
<ul style="list-style-type:'- '"><li> I have a <b>static</b> website</li><li> I chose a fucking <b>pixel</b> font</li><li> The web is struggling to display the pixels sharply</li>
</ul>
</p>
<p>
There has to be some way around, right?
Well, there very well might be. 
I'll have you know that there are non-standard
CSS properties which are browser dependent. Two quick thoughts:
<ol>
<li> I hate everything about this.</li><li> Not a single setting I tried actually fixed the issue, 
so at this point I don't even know nor care.</li>
</ol>
</p>
<p>
While not solving my problem, the stackoverflow posts I stumbled upon are 
hilarious. The type of workarounds people have found / need to use
for their problems are 
<a href="https://stackoverflow.com/questions/1752752/is-it-possible-to-disable-anti-aliasing-in-css-when-using-font-face-with-pixel">batshit crazy</a>.
Other possible solutions include <a href="https://github.com/sorccu/cufon">using a fucking javascript framework to render all of your text</a>,
because rendering a pixel font requires some advanced software engineering.
</p>
<p>
The bar is at the bottom, but boy can software limbo.
</p>
<h1>
 Update (2022.12.25) </h1>
<p>
By sheer coincidence I stumbled upon another site which used a 
pixely-font - and it was looking sharp on both of the browsers I use. Rude.
So I did a little more testing...
<ul style="list-style-type:'- '"><li> Good news: I found what's causing this problem.</li><li> Bad news: It's present in <b>both</b> firefox and chrome.</li>
</ul>
</p>
<p>
<code>margin: auto</code>, the thing I use to <b>center text</b>, is causing the problem, which means I'll probably slightly re-design my website in a bit.
You can't make this shit up.
My working hypothesis is the following:
Depending on the width of the browser window, centering the text causes
it to be drawn on some subpixel position (instead of snapping to the nearest pixel).
On both chrome and firefox, increasing the browser width by a single pixel "toggles" the blurriness.
</p>
<p>
So why did I not see the issue way earlier on firefox? On my desktop environment,
the windows are automatically tiled. Long story short, the window sizes 
I use on my machine <b>just happened</b> to
work out for firefox; pure coincidence. But, given the same window size, 
the "drawable"/canvas size of chrome is slightly smaller due to the scrolling bar: 
</p>
<p>
<figure>
	<img src="./IHateTheWeb05.png" style="width:319px;height:434px;" />
<figcaption>
The thing in white is Chrome's scrolling bar, which is not visible on Firefox (the window below). Given a fixed window size, this delta of 15 pixels
causes different text-alignment -> One window draws text exactly on the pixel boundaries (crisp text), while the other tries to place 
the glyphs inbetween two possible pixel boundaries (blurry text).</figcaption>
</figure>
</p>
<p>
I hate everything. So I can forget about centering the text without encountering this issue
because I still do not want to use javascript nor change to a non-pixely font. 
</p>
<p>
So, for a fixed window size, I can shift the whole thing by half a pixel via CSS 
to toggle which browser I want to fuck with. Apparently I can even retrieve / calculate
the subpixel position of the text by using <code>calc()</code>, which still is "vanilla" CSS.
But this function is just exposing the operators <code>* / + -</code> which makes it difficult to detect 
and thus fix this subpixel bullshit.
</p>
<p>
But here is a fun fact: In a few years, this issue <b>might</b> be fixable. 
Because CSS has an experimental <code>round()</code> function, which (I think) could be used
to round the text position to the nearest pixel and thus avoid this blurry mess.
As of writing, <a href="https://caniuse.com/mdn-css_types_round">only Safari and the Firefox Beta support this feature</a>.
It sounds and is incredibly stupid, but, with a snarky undertone, I can confidently say: 
</p>
<p>
The technology just isn't there yet.
</p>
<h1>
 Update (2023.01.25)</h1>
<p>
I updated my shit, and now it's blurry <b>again</b>.
</p>
<p>
<figure>
	<img src="./IHateTheWeb06.png" style="width:500px;height:514px;" />
<figcaption>
</figcaption>
</figure>
</p>
<p>
Admittedly, it's not as bad as previously. 
I would still prefer the webbrowsers not touching my fucking pixels though.
And this time I can't seem to turn it off using CSS alone.
So I guess: Get fucked? 
</p>
<p>
Now, dont' get me wrong: 
I understand the appeal of saying: "Here is just text, 
now just let the viewer style it how he wants".
But the web doesn't really function like that. 
Even worse, I'm apparently not allowed to style it using CSS
either. 
</p>
<p>
God I fucking hate software updates. Destroy all software.
Maybe I should just switch to <a href="https://en.wikipedia.org/wiki/Gopher_%28protocol%29">Gopher</a> or something. 
</p>
]]></content>
</entry>
<entry>
<title>Procrastinating by Creating This Website</title>
<link rel="alternate" href="https://p4m.dev/posts/00/" />
<updated>2022-12-20T00:00:00Z</updated>
<id>https://p4m.dev/posts/00/</id>
<content type="html">
<![CDATA[<p>
As a professional procrastinator, there is always a list of side-projects laying around. 
One of these items is a website: 
I always wanted to create a <a href="https://howthefu.cc/">website which serves as my own cheat sheet</a>,
because my memory is utter garbage and some of these notes might be helpful to other people as well.
Given that I just got some ancient computer up and running which serves as a git-server/NAS 
I thought: Why not finally host the website on it as well?
And well, once one site is set up, I might as well create a second, less-useful site 
for all of my ramblings <s>which literally no one asked for</s>.
</p>
<p>
Ok, let's talk websites. I kind of despise how the modern web turned out <a href="#note-0" id="back-0">[0]</a>.
To make this brief: I want a static website with some personal styling to make it pretty.
Static websites generators are a thing. I could have just picked any existing
solution, spent a day (or more realistically a week) on configuring it to my liking
and then forget about it. But, speaking from experience, it usually goes somewhat like this:
</p>
<p>
<ol>
<li> Search for various generator-thingies, pick one out</li><li> Try to use tutorials which are obsolete</li><li> Configuring the thing to my liking straight up does not work</li><li> I spend way too much time working around that issue shittily</li><li> I hate everything and everyone involved</li><li> The result is "meh" and I spent way too much time on it</li>
</ol>
</p>
<p>
Here comes the infamous thought: "Well, it can't be <b>that</b> difficult".
And that kicked of my ~7 sessions of creating my own static website generator. 
</p>
<p>
The very first step was to create the html/css that I want "manually" by hand.
Now that I now <b>what</b> to generate, I created some mockup theoretical input in 
markdown, simply because I somewhat knew this format and thought it would be 
good enough for my type of stuff. After I sketched out some folder structure for 
posts, the coding part started. I ended up with the following structure:
<ul style="list-style-type:'- '"><li> Walk all folders, count input files</li><li> Allocate memory for all posts (title, date, path)</li><li> Walk all folders again: From input-file, read date and title into a buffer</li><li> Generate two sorted lists for the overview pages (by date, by name)</li><li> For each input file:<ul style="list-style-type:'- '"><li> Parse file into abstract tree</li><li> Walk over the whole tree to build a list of footnotes</li><li> Using tree, list of footnotes and "surrounding" posts, generate an html file</li>
</ul>
</li><li> Generate html for overview pages and about page</li>
</ul>
</p>
<p>
That... doesn't sound particulary efficient, does it? Welp, when doing these projects
I learned to do the simplest things first. All this re-walking of folders and trees
made the memory allocation and content generation pretty simple. 
</p>
<p>
Full disclosure: After some parsing issues I decided to make things easier for myself
by modifying the markdown syntax I use for my sites just a bit. That way I didn't need to 
implement proper backtracking; instead I just need to do some lookahead.
I'll probably still be ironing out bugs from time to time, but the result is 
usable enough for me already (you are looking at the website after all).
</p>
<p>
Benchmark time! I copied the input of my test post, which is supposedly almost 13 Kilobytes big, 
1000 times and ran my generator. 1000 posts is really not a lot, but realistically, 
it's more posts than I'll ever have. 
<pre><code>
...

Found file:
Path:         .//1000/input.txt
Website Path: 1000
Title: Test Entry but this time with a very long title. How will it handle it?
Date:  2022.12.07


Converting all found files...
Parse and converting of "about" page...

Writing overview files...

________________________________________________________
Executed in  266.68 millis    fish           external
   usr time  137.05 millis  245.00 micros  136.81 millis
   sys time   84.82 millis   38.00 micros   84.79 millis</code></pre>
...&lt;300ms? The power of really dumb C code combined with modern computers keeps surprising me.
Which makes the whole "why the fuck is this program so slow?" even more frustrating.
The best part: This is single-core-performance because, again, I did the simplest thing
possible. This should be trivially parallizable (one task -> one thread), but that can wait
given the current performance.
</p>
<p>
Ok, one last circle-jerk: How much code is it? I know this comparison is unfair, but
let's take a look at two other static website generators first: 
<a href="https://jekyllrb.com/">Jekyll</a> and <a href="https://gohugo.io/">Hugo</a>. Obviously these
two projects can do way, way, way more than my little program - but let me have this moment >:(
<pre><code>
> cloc jekyll/
     751 text files.
     713 unique files.
      75 files ignored.

github.com/AlDanial/cloc v 1.94  T=0.25 s (2843.5 files/s, 249147.5 lines/s)
--------------------------------------------------------------------------------
Language                      files          blank        comment           code
--------------------------------------------------------------------------------
Markdown                        306           4925              0          19488
Ruby                            183           3615           2878          17167
Cucumber                         28            353             12           4522
YAML                             44            278            124           2203
SCSS                             18            433            235           2126
JavaScript                        5            115              6           1073
HTML                             74             63              9            966
Text                             11             32              0            888
Bourne Again Shell               13             47             42            222
JSON                              4              6              0            199
ERB                              13             56              0            168
CSS                               1             15             11             50
SVG                               3              0              0             32
XML                               1              3              0             29
Dockerfile                        1              7             22             26
CoffeeScript                      3              2              0             15
CSV                               1              0              0              3
PHP                               1              1              0              3
TOML                              1              0              0              2
XHTML                             1              0              0              1
Rmd                               1              0              1              0
--------------------------------------------------------------------------------
SUM:                            713           9951           3340          49183
--------------------------------------------------------------------------------</code></pre>
That's a lot of markdown. I suppose this is for documentation? I can't be bothered
to find out to be honest. <a href="https://cucumber.io/">Apparently "Cucumber" is a programming language</a>,
so TIL I guess. Counting Ruby and Cucumber, it's 21k LoC. 
That sounds pretty reasonable, what about Hugo?
<pre><code>
> cloc hugo/
    1646 text files.
    1596 unique files.
     394 files ignored.

github.com/AlDanial/cloc v 1.94  T=2.69 s (594.3 files/s, 89638.0 lines/s)
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
Go                             747          25623          19050         119192
Markdown                       551          11904              0          34177
HTML                           128            252             45          11847
JSON                            11              0              0           6903
CSS                             29            529           1011           5436
SVG                             62              3              7           1640
TOML                            19            274             58           1439
YAML                            11             45             14            537
JavaScript                      15             33             58            192
XML                              7              2              0            147
CSV                              1              1              0            129
Bourne Shell                     8             31             12             51
Dockerfile                       1             14             10             21
Text                             4              1              0             12
SCSS                             1              1              0              6
Sass                             1              1              0              5
-------------------------------------------------------------------------------
SUM:                          1596          38714          20265         181734
-------------------------------------------------------------------------------</code></pre>
120k LoC of Go? Nani the fuck? 
</p>
<p>
You know what? I don't even want to know.
Let's move on to my project:
<pre><code>
> cloc asswg/
      29 text files.
      23 unique files.
      20 files ignored.

github.com/AlDanial/cloc v 1.94  T=0.02 s (963.2 files/s, 129576.1 lines/s)
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
C                                5            307            112           1915
CSS                              1             53             29            225
C/C++ Header                     4             32              3            170
Text                             4             33              0            164
HTML                             6              0              0             24
Bourne Shell                     3              5              2             20
-------------------------------------------------------------------------------
SUM:                            23            430            146           2518
-------------------------------------------------------------------------------</code></pre>
That's not even 2.000 Lines of C-Code. And it does what <b>I</b> want. Cool.
While it would be interesting to compare the runtimes, I, for reasons stated above,
don't want to learn these other two projects. Too Bad!
</p>
<p>
Additionally, let's not forget: Programming these things from scratch makes you learn a ton. 
This time around it was parsing stuff and why you usually tokenize your input first.
I never understood why I should spend time writing a tokenizer when I could just work
on the input directly. Apparently, you <b>can</b> do that, it's just a bit more annoying.
Although I learned this the hard way, but I wouldn't want it any other way.
</p>
<p>
And now I have my own static website generator: A piece of software that I
actually use. That has to come with some bragging rights. 
If something doesn't work - that's completely my fault and not some weird unspecified behaviour <a href="#note-1" id="back-1">[1]</a>.
And for the things which do work I can feel pretty proud about. So I'll call
this procrastination project a success.
</p>
]]></content>
</entry>
</feed>
