Building an adding machine in a prison building
game
As of late, I really got into Prison Architect. It’s
a fantastic game - you get to plan your own prison just
the way you like, decorate it and then see how it fares
when ‘actual’ prisoners are living there. Also, its DLCs
are somewhat fair-priced, which isn’t usually the case
with Paradox’s games. I wanted to do something unique to
express my appreciation of the game, so I built a simple
calculator in it.
The plan
Luckily, the game features a logic gate system, so we don’t need
to figure out how to simulate one using game mechanics.
There’s also a ‘status light’ object which lights
up when it receives a signal, so we’ll use that as a
building block of a display. There’s no way of cloning
logic gates etc. with its connections to other
utilities, so since I don’t really want to spend eons on
connecting magical boxes in a video game (yet?), we’ll
limit our calculator’s capabilities to adding two
numbers with two binary coded decimal digits. That
means our calculator will be able to add 99 and 99 at
most, so we’ll actually need three digits on the result
display (something I’d figured out way after I built the
displays and connected them…).
I picked BCD as the encoding, because the only way of
displaying plain binary numbers in decimal I could
figure out was to connect each possible combinations of
bits to AND and NOR gates, then connect the NOR gate to
the AND gate, to then connect the AND gate to the
display in a proper way. That means I’d have to
mindlessly map about 99 + 99 + 198 = 396
possible outcomes onto the displays. With BCD, the
number of possibilities goes down to 10 + 10 + 10 +
10 + 1 + 10 + 10 = 61, since I only need to connect
each digit representation with its display and the first
digit of the result number can only be either 1 or
0.
You can add BCD digits with conventional binary adders, but you might need to convert them later by
adding six to the result and sending the carry bit to
the next digit’s adders (if that makes sense). Since
each BCD digit uses four bits, in order to add the
digits, we’ll need four full adders connected together
forming a ripple carry adder (I think). Although four
adders is enough, our big adder will consist of five
small adders, since if the last adder outputs a carry
bit, we will have an integer overflow. The additional
circuit allows us to incorporate the bit into the
computation’s result. Later, we’ll setup a bunch of NOR
gates connected with AND gates, which will be connected
to the output of the big adders, that will output signal
to another set of two big adders that will preform the
conversion, if required.
Normally we’d need some-kind of a flip-flops to build a keyboard with,
but the game features an object that emits signal constantly,
so we’ll just use it.
Adders
We can easily implement a full adder with the game’s logic
gates. We can then place four more adders underneath it,
connecting them together to form the big guy. Since, for
some reason, most in-game emitters send a high signal by
default, we should also connect a turned off lever to
the first adder’s carry input gates, and two turned off
levers to the ‘screw overflow’ adder’s input. We also
connect each adders output (the XOR gate) to a
corresponding light at the bottom. We could directly
connect the outputs to the next part, but I think it
would make the build less clear (click the image to
rotate)
Next, I connected the lights to a bunch of NOR and
AND gates, and these to an OR gate, so that the
‘circuit’ outputs signal only if the output lights form
a binary number that is greater than nine. The signal
then turns on the switches that are connected to a next
big adder that adds six to a digit only when a high
signal is emitted. However, these adders are different
from the previous ones, because the final adder of the
first big adder passes its carry bit to the first full
adder of the next ripple carry adder. And the last full
adder of the second big adder passes its carry bit to
the leftmost bit of the output.
Screen
The display is a straightforward beast: the rows of
lights under the BCD converter are appropriately mapped
to a bunch of NOR and AND gates, the NOR gates are
inputted into the appropriate AND, so that when the AND
gate emits a signal, lights corresponding to the
appropriate digit light up:
The light that corresponds to the hundreds digit of
the sum is directly connected to the display, since it
doesn’t need this kind of a dashboard.
Demonstration
Since I don’t really know much about electronics,
feel free to contact me if you think there’s an
error in the article or if you feel like something is
badly worded.
Last semester I was taking a mandatory "Programming
101" course, aka. drawing stairs made out of stars and
watching my classmates struggle with basic tasks, the
course - a time truly well spent. Even though the course
problems weren’t too enlightening, the silliness of one
of the tasks’ requirements gave me a chance to write a
simple code generator.
Problem
Without using an associative table (they weren’t
covered in class), write a program that encodes a
message using morse code. The characters should
map as follow (yes, a picture; who needs copy-paste
anyway?):
Implementation
First, I looked online for the table in a text format, downloaded it and,
using a vim macro, formatted it so that each
line would contain one of the ASCII symbols and its
Morse representation separated by a space. Since I
wanted to use envsubst, I created a file like
so:
Then, I wrote a script that reads each line from the
‘translation file’, and places the Morse representation
inside the if’s condition and the ASCII symbol
next to the return statement:
I ran it, ran it again with the values of the
CASE and VALUE variables switched as
to generate the other way translation, removed the
unneeded elses at the bottom, copy-pasted the
big if chains into the file where I would write
the wrapper code... and voila! An hour of time was just
saved (if you’re not counting the hour it took me to
write this lol)!
the ‘link’ buttons on the blog page now takes you to
the article’s title
the posts are now written in markdown and then
converted with pandoc to HTML so you can read them in
plain markdown under /files/markdown/posts/POST-NAME, here’s this post If you really want,
you can even read them in PDF, assuming pandoc
and zathura are installed:
pandoc-o---to pdf --from markdown https://jacadzaca.github.io/files/markdown/posts/website_update_2.md |zathura-
When you get a maths worksheet, it usually comes with
the answers to the problems from each section, so you
can check your work - pretty nifty. However, it turns
out that’s not the way they do it at my university.
Passing semester, I had to trudge through a ton
of answerless worksheets, which made studying much more
time-consuming, since I had to spend extra minute or two
per example inputting the equation into Symbolab, or googling for the
solution. Let for minor annoyances, when I couldn’t
input some problem into Symbolab or when it spouted out gibberish, I finished
the semester less than unharmed - I got inspired.
Leaving the question of whether not handing out
answer-sheets was just a big psyop by my instructors to to force
students into creating study groups for another time, I
decided I would generate my own worksheets (without
blackjack and hookers... sadly).
How?
Wolfram’s Problem Generator claims
to be using AI to generate the problem sheets, mathsbot probably uses some database
of predefined questions. Shouldn’t writing a maths
worksheet generator be complicated? or at least time
consuming? Also, don’t you need someone to handout
answers? With the right software and mindset - no, no
and no. If we think about it, maths worksheets are just
permutations of different symbols. We can generate these
just fine, for example with python’s itertools or random module. Now, since a
worksheet usually comes with an answers section, we will
also be needing a way of evaluating the generated
expressions, luckily there’s a whole bunch of software that dose
this, for example, sympy. To present the worksheets we
can generate a LaTeX document via jinja and then compile it with, for
example, pdflatex.
Implementation
For simplicity, we’ll write a quadratics worksheet
generator. First, we’ll need a function that spouts out
quadratics, we would like the generator to:
differentiate quadratics on basis of the number of
solutions, because a worksheet with, for example, only
two solutions quadratics would be
boring/incomprehensive,
ensure that the quadratic’s coefficients are not to
crazy - in the end it’s humans that will be solving the
equations.
To achieve the first goal, we’ll split the function
into three. Second one will require making some simple
observations:
it’s more difficult to randomize fraction
coefficents, so random coefficients will only be
integers,
coefficients should be bounded,
it’s easier to generate positive integers and then
to pick a sign
we know that a quadratic has two solutions, if and
only if its discriminant is positive, so given a
quadratic of the form: ax2 + bx + c ∧ a ≠
0, with two different solutions, we can write:
b2⁄4a > c. Since we
are looking for an integer upper-bound for a
and c, lets set c > 2, therefore
b2⁄8 > a,
for a quadratic to have one solution, it’s
discriminant must equal zero, so if we pick a
and c, b = √4ac, since
this could produe complicated coefficients, let’s
require a and c to be perfect
squares.
Figuring out bounds for no-solutions quadratics is
left as an exercise for the reader. Translating the
observations into python code:
import mathimport sympyimport random SIGN = [-1, 1]def generate_quadratic_two_solutions(max_coefficient=20): b = random.randint(3, max_coefficient) a = random.randint(1, (b**2)//8) c = random.randint(1, (b**2)//(4*a))return sympy.sympify(f'{a}*x**2 + {b}*x + {c}')def generate_quadratic_one_solution(max_coefficient=20): sign = random.choice(SIGN) a, c = sign * random.randint(1, max_coefficient)**2, sign * random.randint(1, max_coefficient)**2 b =int(math.sqrt(4*a*c))return sympy.sympify(f'{a}*x**2 + {b}*x + {c}')def generate_quadratic_zero_solutions(max_coefficient=20): sign = random.choice(SIGN) a, c = sign * random.randint(1, max_coefficient), sign * random.randint(1, max_coefficient) b = math.sqrt(random.randint(1, math.floor(math.sqrt(4*a*c)))) b = sympy.Rational(str(math.trunc(b *10)/10))return sympy.sympify(f'{a}*x**2 + {b}*x + {c}')
Wait a minute, problems in a worksheet are usually
ordered by difficulty - the further the problem, the
more difficult it is. I couldn’t come up with any
solid way of evaluating a quadratic’s
difficulty, based on it’s coefficients, so I went
with:
#!/usr/bin/env python3import mathimport randomimport collectionsimport sympyfrom jinja2 import Environment, FileSystemLoader#...quadratic generating code ommited for breviety...# Task = collections.namedtuple('Task', ['instruction', 'problems', 'awnsers']) ENV = Environment( loader=FileSystemLoader('.'), trim_blocks=True, lstrip_blocks=True)def main():# generate diffrent kinds of quadratic equations zero_solutions_quadratics = [quadratics.generate_quadratic_zero_solutions() for _ inrange(10)] one_solution_quadratics = [quadratics.generate_quadratic_one_solution() for _ inrange(10)] two_solutions_quadratics = [quadratics.generate_quadratic_two_solutions() for _ inrange(6)]# sort them according to 'difficulty' - the greater the sum of quadratic's coefficients, the more difficult it is zero_solutions_quadratics.sort(key=quadratics.quadratic_difficulty_comperator) one_solution_quadratics.sort(key=quadratics.quadratic_difficulty_comperator) two_solutions_quadratics.sort(key=quadratics.quadratic_difficulty_comperator)# arrange the problems in random order, but try to keep the problems' difficulty incremental problem_lists = [zero_solutions_quadratics, one_solution_quadratics, two_solutions_quadratics] problems = []for _ inrange(len(zero_solutions_quadratics) +len(one_solution_quadratics) +len(two_solutions_quadratics)): choice = random.choice(problem_lists) problems.append(choice.pop())ifnot choice: problem_lists.remove(choice)# generate the awnsers with sympy https://docs.sympy.org/latest/index.html awnsers = (sympy.printing.latex((sympy.solvers.solveset(quadratic, domain=sympy.S.Reals))) for quadratic in problems)# convert into LaTeX problems =map(sympy.printing.latex, problems)#output latex code latex = ENV.get_template('problem_sheet.jinja.tex').render(tasks=[Task('Find the roots of function $f$, given by expression:', problems, awnsers)])print(latex)if__name__=='__main__': main()
Slightly modifed version of this script can be found
here, along with scripts generating
worksheets on differentiation, integration and limits. Example worksheet generated
with the script can be found here. If you write a simillar script
on some other math topic, for exmaple function graphing
or trig equations, feel free to issue a pull request :). I will also gladly
accept links to simillar repositories and
include them in zadanko’s README.
mathematical equations are now rendered with an SVG
image
code snippets are now syntax-highlighted with pygments
‘long’ code line are now wrapped
I’ve added OpenGraph, favicon [1] and some other metadata tags. There’s
also a manifest.json file now (this means
you should be able to add this blog to your
smartphone’s home-screen)
I’m a big Warcraft fan. Actually, I consider Warcraft
3 to be the best video game of all time. I like the
story, the voice-acting (polish voice-over was great
until Reforged), and the music fits game-play. But
what’s best about Warcraft 3 is its universal game
engine that combined with the powerful game editor would
lead to creation of many unique mods. Of course, I have
my favorite: a polish modification called
Alchemicy - a combination of a hero defense and
a crafting game. Although the mod is loads of fun, one
aspect of it always bugged me: there are characters that
you can only play as after either making a donation to
the author or if you know him in-game. What’s more, the
donation service was shut-down in 2012 with the guy
quting the game. Since the map is protected, meaning
nobody can open the mod file in the editor, the
characters seemed to have been lost to the sands of
time... Until I figured out a way to produce a patch
that removes the paywall.
Protections, how
do they work?
First, a brief introduction to the Warcraft map file
format (w3x). For my purposes, every Warcraft 3 mod is
basically an archive (see here for proper docs) that
contains a few files, each relating to
different aspects of the mod. Certain files (from now on -
header files) only carry data that’s required
by the game editor to open up the map, other files are
mandatory (for example, the map file), there also might
be some auxiliary files; most probably custom models,
icons or sounds. What’s crucial is that each file
contains information that allows a human to identify it
(e.g, the file defining custom units contains units’
names, hitpoints etc.)
All map protection software dose is remove the header
files, therefore making the editor crush each time you
try to open a protected map with it. It also removes the
MPQ’s (name of the archiving format) listfile, therefore
obfuscating files’ names.
The plan
Since I’m familiar with the Warcraft ecosystem, a
glance at the map in-game revealed that there must be a
certain upgrade that is granted to all ‘premium’ users.
Since all of the custom upgrades are in the
war3map.w3q file, I figured that all I need to
do is:
identify the .w3q file
byte patch the mod-file directly or:
convert the file into editable form
make applicable changes
convert the file back and patch the mod-file using
an editor
Sadly, this approach doesn’t work, because:
files in the MPQ are somehow compressed, so you
cannot byte-patch them directly
the MPQ’s listfile is gone, so you cannot add new
files. You cannot replace a file without adding a
file
the .w3q files only cotains the upgrade’s definition
(ID, description etc). The correct place to apply the
patch is in the war3map.w3u file
Luckily, the new insight allowed me to conjure an
approach that works:
acquire a Warcraft map with a listfile - a
template
extract and identify the files inside the
Alchemicy mod file
make applicable changes to the war3map.w3u
file
replace the files inside the template with the ones
extracted
We are going to need:
the MPQ editor (it runs under Wine) to
both extract, and overwrite files found in a .w3x
file
a 128 by 128, Cityscape tileset, Warcraft
map to use as a template
The implementation
First, I downloaded one of my old, unfinished maps
for a template. Then, I created two directories:
identified-files and
unidentified-files and extracted all files from
the map (save for .blp and .mdx files) into the second
one. Second, I noticed that it’s possible to identify
few of the files just by either looking at them or by
opening them in your favorite text editor:
since File00000000.w3e has an extension, it’s
probably the war3map.w3e file
by comparsion with your template map,
File00000001.xxx is the war3map.w3i file
since File00000002.xxx is fillied with strings, it
must be the war3map.wts file
since File00000003.xxx looks like computer code, it
must be the war3map.j file
since File00000007.wpm has an extension, it’s
probably the war3map.wpm file
the File0000000008.doo is either the the war3map.doo
or the war3mapUnits.doo
by comparsion with your template map,
File00000015.xxx is the war3mapMisc.txt file
by comparsion with your template map,
File00000016.xxx is the war3mapExtra.txt file
I renamed the identified files and moved them into
the other directory. I also ran this example script that is provided
by the parser to figure out that the .doo file is the
war3Map.doo file. Nearly all other files can be
identified using this script, after applying this
‘patch’ inside the
WC3MapTranslator/examples/warToJson
directory:
File00000004, File00000006 and File00000012 couldn’t
be parsed into anything sensible. I would later figure
out that (using a method of trail and error)
File00000004 is the .shd file and that File00000006 is
the .mmp file. I couldn’t figure what File00000012
is.
Thirdly, I would convert both the .w3q and the .w3u file into JSON and compare
them:
I figured that the simplest solution would be to
blank-out the value record with:
I’ve noticed that the contempt for landlords (example in polish) has recently
reached a new level - landlord being are equated with
social parasites, who are going to cause an overpopulation crisis in literal
hell. Surely, behind such brutal rhetoric stands
some merit?
Landlords bad!1!1!
Landlords are said not to do any work - they just
siphon others’ efforts. If you and your landlord earn a
similar wage and you’re both saving for a new flat, it’s
going to be your landlord that can buy it first,
although they already have a place of their own. Albeit,
a landlord makes sure your apartment is a decent place
to live (e.g they call in a plumber once in a while) it
doesn’t lessens their parasitism, because then they
become a redundant middleman (it’s not rocket
science to call a plumber). Some might claim that
becoming a landlord actually requires much effort - you
must take risk, familiarize yourself with the
appropriate laws, go around searching for a property
etc. but why someone should bother with it all? Can’t we
organize into housing cooperatives or establish a
government monopoly on rentiership and thus socialize
the trouble?
Landlords bad?
Imagine you’re moving into city of Ekslandia - let’s
say you’ve landed a job opportunity there. You’re pretty
sure that you won’t stay in Ekslandia for more than N
years. Sadly, all of the established housing
cooperatives are already full (they provide high quality
housing, so nobody want to leave) and the ongoing
initiatives either will take more than N years to
provide you with a quarter (establishing an organization
is not a timely process) or are not welcoming of total
strangers that hardly have a job in the city housing coops are allowed to select
who’s to live with them). You try applying for
social housing, but it turns out that it favors people
with turbulent past. Running out of options (and since
people on the internet told you that all landlords do is
exploit), you want to take out a loan and buy an
apartment. You meet up with your financial adviser and
he tells you that the loan over the N years that you
plan to stay in the city will cost you X, however he
also mentions that due to the growth of available
housing alternatives, the typical rent has fallen
drastically and it wouldn’t be hard to find a similar
apartment that over the next N years will only cost you
(X - 1). Since everyone can subtract, you quickly figure
out that by renting you could actually save one unit of
value… Since when does being exploited saves you
money?
Landlord good???
Although the above story lays down a rather specific
scenario (all ‘better’ options are unavailable, renting is cheaper etc.) and thus is
not very convincing, it’s still a scenario that seems to
presume most of the skeptics’ propositions, while
allowing a landlord to contribute to a society.
Basically, what a landlord does is allowing the tenant
not to buy an apartment; if we were to let go of some
skeptics’ tenets, e.g that housing coops are
always more economically efficient, we could
ask whether the landlord doesn’t produce value by
elevating the tenant from the chore of attending coop’s
board meetings? Surly, if someone is attending a board
meeting they are not, for example, spending time with
their family. Summarizing, we cannot conclude whether
landlords are cringe and useless ex offico -
when a landlord grants you affordable accommodation they
are not cringe otherwise they probably are.
It turns out that you can find the value of sin(18°)
by the following method:
Notice that by the sin addition formula: Also: Moreover, by the double cosine
formula: Now use the Pythagorean identity
like this: Now equate the right-hand side of
equation 2° with the right-hand side of statement 1°,
and substitute for cos(36°): Notice that for t = 1 the equation
is satisfied, so: Now notice that 1 > t >
0, because sin(x) is an increasing
function when 90 > x > 0 and sin(90°)
= 1 > sin(18°) > sin(0°) = 0, so t =
sin(18°) = (-1 + √5)⁄4 ,
since that’s the only solutions that meets the
criteria
While this method works, it’s not easy to come up
with the first equation. I stumbled on it by pure
coincidence. I personally prefer the geometrical way of finding the value
of sin(18), because it strikes me as the more obvious
way of doing it.
I can recall the first time I wrote a program that
used a trigonometric function - it was back in secondary
school. I was making a game and wanted to make some
object float around another. Back then, I didn’t know
what trig functions were and how they worked, so I
copied some code from the web and, to my astonishment,
it worked. I got curious how these functions worked, so
I pressed F3 in my IDE and tried to look for the source
code of Math.sin. I can’t remember whether I found the
code and didn’t understand it or whether I couldn’t find
the implementation at all. It doesn’t really matter.
What dose, is that back then I swore to myself that one
day I will implement my own sin function. Two days ago,
I’ve learned about Taylor Series.
Taylors, how do they
work?
Taylor series is a tool to express some function as a
polynomial, using its nth derivative. Since
sin(x) and its derivatives are differentiable,
we can express f(x) = sin(x) as:
In this case, we can’t add infinitely many terms in a
finite amount of time, so we have to approximate. Since
this is a toy implementation, we will just compare it
with python’s math.sin implementation and call it quits
when they will converge good enough.
Implementation
First, we need some way of obtaining the nth
derivative of sin, evaluated at some center a.
By writing down sin’s first fifteen derivatives, we can
see that the odd derivatives are either 1 *
cos(x) or (-1) * cos(x), while the plural
ones take the form of 1 * sin(x) or (-1) *
sin(x). What is more difficult to see, is that
derivatives with an ordinal that yields a reminder of
two or three when divided by four are the derivatives
with and minus sign. I don’t know how to formally prove
it... yet, but you need to trust me on this
one. Translating into python code:
def nth_sin_derivative(n, a=math.pi/2):if n %4in (2,3): sign =-1else: sign =1if n %2==0: function = sinelse: function = cosreturn sign * function(a)
Second, we need to actually be able to evaluate both
cos(x) and sin(x) at our center. Since
we are implementing sin(x), we should deal with
cos(x) first. We don’t have to implement
cos(x) separately - notice that
sin(π⁄2 - x) =
cos(x):
def cos(x):return sin((math.pi/2) - x)
Great. That solves the cos(x) part. Now, we
can finally implement sin(x):
def sin(x, center=math.pi/2, term_count=5):if x == math.pi/2:return1elif x ==0:return0else: values = (((x - center)**i / math.factorial(i)) * nth_sin_derivative(i, a=center) for i inrange(term_count))returnsum(values)
We specify two special cases: x =
π⁄2 for evaluating sin
derivatives that require to compute sin(x) at
center, and x = 0 for evaluating sin
derivatives that require to compute cos(x) at
center. Else, we compute the Taylor series.
Is the
implementation any good?
Well, it sure can compute sin(x)! With
term_count=19 the approximation is nearly as good as the
python’s math.sin:
However, assemblies actually provide an fsin instruction, so computing
sin(x) in software when speed matters is kinda
cringe. On the side note, CPUs don’t actually use a
Taylor series to compute trig functions - they use CORDIC.
As I don’t use my arch laptop that much, I’ve figured
that I can use it as a backup storage for my collections
- collections of memes and movies.
Rsync is bloat?
Using some kind of a USB as an intermediary wouldn’t
do the trick, because my meme collection is 14GB big
(pathetic), whereas my movies take 139GB. My first
though was to use rsync. I’ve never used rsync before,
so I perused its man page and quickly found out that you
can use:
to sync the files. Then... I got a ssh error. I
couldn’t be bothered to install a ssh server on my
laptop, because that would only bloat my precious
Arch Linux install. I
continued the search.
Rsync
is bloat, so let’s pipe stuff into some program
I’ve stumbled on this StackOverflow
answer. Not only does this guy have a method that would
allow me to transfer my movies without installing a ssh
server, but he also claims that it’s faster (rsync
shines more when it comes to syncing files that are ‘similar’). It turns
out that you can compress the files with tar and then
use netcat to send them over the network with:
on the destination computer. The traffic isn’t
encrypted at all, but that’s not a problem over LAN (e.g
sending movies to my laptop). Albeit, encryption can be provided with ssh
or with a VPN.
I think this method is very linux-like, because it
combines two programs in some unusual fashion to create
something new. I might consider replacing scp with the ssh version of this
trick.
TL;DR: I spend too much time on the
Internet, should find some frens and go out more lol?
Over the past three years, I’ve developed this odd
habit of writing down everything I do
in my calendar. I’ve developed the habit mostly out of
curiosity: I wanted to know how much time I spend on the
Internet, playing video games, programming etc. Besides,
I’m rather sentimental.
Last week, I realized that having one calendar
doesn’t actually allow me to do that, because each event
has a unique name (e.g if a play some video concrete
game I write down that I’m playing concretely it). That
means that running some simple script, on the
calendar, to sum the events’ durations would not be
plausible (just imagine the regex!). I should have
several calendars, so that I could sort each event in to
its proper category.
Categories
Coming up with the categories turned out to be more
difficult that I’ve anticipated. They should be both not
too specific, yet not too broad, so the ‘time spent on X
statistic’ wouldn’t be complete bullocks. Should working
out be considered its own category, or should I just put
it under the ‘necessary, cannot live without it, but
boring’ label? Is distro-hopping programming related?
Should competitive programming be considered as studying
or as programming? In the end, I’ve converged on these
ten different categories:
relaxing (basically every time, when I don’t do
anything ‘productive’ and don’t browse the
Internet)
studying (that includes reading books; dose not
include homework)
programming (includes distro-hopping and such)
chores (includes homework, working, being at, going
to and coming back from school, shopping etc.)
social (includes writing emails)
internet (does NOT include responsible usage;
e.g. looking up public transport info)
games (video games, not board games or whatever -
that goes into social)
movies (watching them, NOT going to cinema - that’s
social... sometimes)
blog
life (the ‘necessary, cannot live without it, but
boring’ category. Does include working out, because my
life quality would decrease without it)
Splitting the calendar (nearly 10k events) proved to
be impossible by hand; wrote a script for it. I concur that some
events that should be in the ‘chores’ category landed in
the ‘life’ category, but only pedants would notice
that.
Results
Basically, over the last three years I’ve spent
around 36.8% of my time on mindless Internet browsing,
while allocating about 2.3% of it to being ‘off the
grid’ (relaxing + social). On the other hand, I’ve used
about 37% of my time on doing useful stuff (i.e
programming, studying/reading and chores; the number
goes down to 22.7%, if doing chores would NOT to be
included).
Conclusion
Well, it’s kind of problematic to draw conclusion
from my ‘experiment’, because... I have no clue what the
average might be. How can I tell if I’m doing ‘good’,
whether I’m spending too much (or too little?) time on
the Internet, studying etc? Besides, the antecedent (that’s literally the
fanciest word I know) presupposes that the average even
exist or is possible to ‘compute’! Nonetheless, I surely
should try leaving my basement more often, because with
that 2.3% staying constant I will either lose eyesight
or die from vitamin D deficiency - not going outside is
surely not lindy. I also like how calendaring
makes me think about my life - when you go on to write
down yet another five hour long mindless Internet
browsing session, you kinda start to doubt your life
decisions lol. It kinda functions like Benjamin
Franklin’s 13 Virtues [sample chart]
I’ve finally got around to installing Arch Linux on
my laptop. Installing Arch was simple enough, the only
problem that I’ve had was understanding the difference
between a boot partition and a ‘boot partition’. A BIOS
boot partition is a type of a partition, whereas a ‘boot
partition’ is a partition you create for your /boot/
directory - you don’t actually need a ‘boot partition’,
while a boot partition is more or less required -
manually telling your boot loader (most likely GRUB)
where everything is located is way too tedious.
Programs I run
The first thing that I installed was GNOME3. I run
GNOME on my Ubuntu desktop and it works just fine, I
especially like the DE; it looks nice out of the box and
the Activities tab is amazing. But that’s mutter36
(mutter is the GNOME DE). mutter40 is nothing like it.
As of now I run xfce4 on my laptop and it’s alright,
albeit a little retro. Actually, xfce’s so vintage that
it might be the best desktop environment for an eldery
person, but that’s neither here or there. I’m actually
thinking of switching to dwm
or i3,
but I’m yet to decide which one is better. For the login
manager I’ve chosen LightDM - it just worked.
I don’t run NetworkManager, because I have no
need for it - just connecting to wi-fi with iwd and running a dhcpcd daemon in
the background works for me. I also installed an iwd frontend program, because some
normal person might have to input a wi-fi password into
my laptop someday.
I use udisks with udiskie for automating USB mounting.
I also run gvfs, so I can have a Trash bin (which is
less useful than I’ve thought). gvfs also seems to
provide an alternative to insync, but it remains unclear
whether you can actually use gvfs effectively without
all the GNOME bloat.
I use CUPS directly for printer manging. I
even have a desktop shortcut to a chromium app that starts the CUPS
web gui.
I also considered installing a cron-like program
(most probably anacron) and running a simple pacman
update script, but after a little research, I’ve decided to postpone
creating such cron job. If after a while of updating
nothing breaks, I will surely consider it.
Final thoughts
As of now, Arch Linux is my favourite distro; it
boots faster than Ubuntu, it eats a lot less RAM (which
is cool, becouse now I can brag on the internet about
how little memory my setup needs) and the package
manager seems to be full of useful programs, especially
compared to apt. Also, there’s AUR, which looks like a
both more managable and faster version of snap,
Aren’t you tired of having to use your mouse in order
to click a link? Of course you are, but worry no more -
there exists a remedy.
Vimium is a browser (download for Chrome, download for Firefox) extension that
binds all the functionality that you would need to some
key combination. You can go to the previous/next page,
you can look through your bookmarks, you can even copy
the URL of the page you are looking at.
What’s also great is the fact that you remap Vimium’s
key-binds how you like.
Link hints
While being able search your bookmarks etc. is all
fun and games, all Vimium’s feature pale in comparison
to link hints. By default, pressing ctrl-f will make
little boxes with letters (called link hints) appear
next to all the links on the web-page. You now are only
(at most) two key-strokes away from
clicking that link! You can customize
the boxes’ look with CSS, however the feature seems to
be a little clunky - CSS sometimes only loads after
refreshing a page.
By the way, I’ve brought back a ridiculously random site about red
pandas. I think it was supposed to be a fan-fiction
about Killian, but I can’t really
remeber.
It turns out that you don’t need fancy JavaScript to
have your webpage change the color theme based on user’s
preference.
You can access system’s color theme preference with
@media (prefers-color-scheme dark).
Now your you only need to write two separate CSS styles
and you’re good to go.
Sadly, most pages don’t seem to use the feature. It’s
good to know about it, but for a dark mode
conesouir (like myself) would yern for
something better.
Inside of chrome (and Chromium based browsers, I
assume) you can got to the
chrome://settings/appearance page, and set the
theme there to a some dark one. This only changes the
looks of your start page and the window’s border, but
it’s a start.
We need to dig deeper.
A moment of browsing the internet, reveals the
chrome://flags/ page, where you can the
Auto Dark Mode for Web Contents option which,
when enabled, forces every page to render in
dark theme. It breaks some pages a little (especially
the ones making extensive use of fancy CSS
animations):
but it surly doesn’t render them unusable. Great
stuff.
What if I don’t use
Chrome?
You’re probably stuck with using Dark
Reader then. It works with every popular browser,
although it in my opinion it produces worse looking
webpages than the native Chromium’s feature. If you’re a
using an extensible browser like surf there’s probably a script or
even a CSS file that does the same. Although, the kinds
of people that use browsers like surf probably have
known about since before I was born or something (I’m
bad at role-playing a boomer, sry)
I’ve decided to take up blogging. I’m mainly going to
write about programming, but from time to time I will
write a piece about some cool math fact that I’ve
learned or a book review. I plan to keep the site
bare-bones (no js!), because I believe
that the web should be faster.
To build this website, I’ve rolled out my own static
site generator (e.g. a few python3 scripts and some
jinja templates), which you can find here.