WEBVTT captioned by sachac, checked by sachac
NOTE Introduction
00:00:00.000 --> 00:00:08.359
Hello, everyone, and welcome to Speedcubing in Emacs.
00:00:08.360 --> 00:00:10.119
First of all, a little bit about myself.
00:00:10.120 --> 00:00:13.679
My name is Vasilij Schneidermann. Online, I go by wasamasa.
00:00:13.680 --> 00:00:18.039
I'm 31 years old. I work in information security,
00:00:18.040 --> 00:00:20.479
and I do consulting and hacking
00:00:20.480 --> 00:00:22.479
and stuff like figuring out
00:00:22.480 --> 00:00:25.279
how to break into other people's computers
00:00:25.280 --> 00:00:29.359
and how to secure their systems basically.
00:00:29.360 --> 00:00:31.439
You can reach me by email.
00:00:31.440 --> 00:00:36.639
I do have a self-hosted code repository thingy going on.
00:00:36.640 --> 00:00:40.399
I have a blog, and you can find me
00:00:40.400 --> 00:00:45.919
in some other places online, like IRC for example.
00:00:45.920 --> 00:00:48.679
So about the talk itself,
00:00:48.680 --> 00:00:52.839
I used to be into the Rubik's cube when I was in school.
00:00:52.840 --> 00:00:54.039
I forgot about it, though,
00:00:54.040 --> 00:00:56.279
because these cubes were not very good.
00:00:56.280 --> 00:01:02.279
Recently I did find some cheap looking cube at a shop.
00:01:02.280 --> 00:01:04.119
Did not pay terribly much for it.
00:01:04.120 --> 00:01:07.039
It was so, so much better than my old cube,
00:01:07.040 --> 00:01:08.639
it was unreal.
00:01:08.640 --> 00:01:11.479
This motivated me to get back into
00:01:11.480 --> 00:01:13.559
this really weird kind of hobby.
00:01:13.560 --> 00:01:17.999
For this, you need to be good at producing
00:01:18.000 --> 00:01:19.399
a truly random scramble
00:01:19.400 --> 00:01:22.319
and timing your attempts to get any better at it.
00:01:22.320 --> 00:01:23.719
There is, of course, existing software
00:01:23.720 --> 00:01:26.239
to do the scrambling for you and the recording
00:01:26.240 --> 00:01:28.079
and the timekeeping and such,
00:01:28.080 --> 00:01:31.239
but all the good options seem to be either web or mobile,
00:01:31.240 --> 00:01:33.239
for example the cstimer software
00:01:33.240 --> 00:01:35.399
or the twisty-timer app on Android.
NOTE Cubing in Emacs
00:01:35.400 --> 00:01:39.319
To my surprise, I did not find a single decent option
00:01:39.320 --> 00:01:41.959
inside Emacs, so this is basically a case study
00:01:41.960 --> 00:01:44.999
how to do better. For this, I wanted to make use of
00:01:45.000 --> 00:01:47.799
all the cool new Emacs features that appeared,
00:01:47.800 --> 00:01:50.879
like the SVG library; Transient,
00:01:50.880 --> 00:01:53.599
the library used for the Magit-style interfaces;
00:01:53.600 --> 00:01:56.439
and the recently added sqlite-mode.
00:01:56.440 --> 00:02:01.159
And most importantly it was about having fun.
NOTE Prior art
00:02:01.160 --> 00:02:02.759
So here's a full list of prior art,
00:02:02.760 --> 00:02:04.279
I will not go into detail about this,
00:02:04.280 --> 00:02:06.239
but basically we have things solving
00:02:06.240 --> 00:02:08.039
very different parts of this,
00:02:08.040 --> 00:02:10.759
but not all of it. For example: we have several,
00:02:10.760 --> 00:02:14.239
we have a timer. We have several solvers.
00:02:14.240 --> 00:02:16.039
We have some scramblers.
00:02:16.040 --> 00:02:19.359
We have some whole-cube simulators, including a 3D one.
00:02:19.360 --> 00:02:20.759
We have something for making it easier
00:02:20.760 --> 00:02:23.119
to enter your algorithms in the notation.
00:02:23.120 --> 00:02:25.919
But nothing that does all of those things in one package,
00:02:25.920 --> 00:02:28.119
which kind of surprised me.
00:02:28.120 --> 00:02:32.039
So I present the `wca-prep` package.
NOTE The name
00:02:32.040 --> 00:02:35.559
So the name, I found it difficult
00:02:35.560 --> 00:02:39.959
to come up with a good name and so I looked
00:02:39.960 --> 00:02:42.559
and I saw, well there's this World Cube Association
00:02:42.560 --> 00:02:46.039
that holds these competitions where you compete.
00:02:46.040 --> 00:02:47.759
They do this for the Rubik's cube
00:02:47.760 --> 00:02:48.919
but also a few others,
00:02:48.920 --> 00:02:50.799
so there's like a standardized list
00:02:50.800 --> 00:02:52.639
of events they have for this.
00:02:52.640 --> 00:02:55.159
There is a standard notation for this
00:02:55.160 --> 00:02:56.519
and rules and everything.
00:02:56.520 --> 00:02:58.199
And the goal of my package is basically
00:02:58.200 --> 00:03:01.279
to help prepare myself for such a competition
00:03:01.280 --> 00:03:03.679
and in fact a week ago I went to my first one
00:03:03.680 --> 00:03:06.719
which was wild, but pretty cool.
00:03:06.720 --> 00:03:10.919
So for this reason I chose this name wca-prep,
00:03:10.920 --> 00:03:13.639
because it helps me prepare for this kind of competition
00:03:13.640 --> 00:03:16.519
and this limited the scope significantly,
NOTE What's in wca-prep
00:03:16.520 --> 00:03:18.999
I have a scrambler, visualization of the scramble,
00:03:19.000 --> 00:03:23.319
timer, and statistics.
00:03:23.320 --> 00:03:25.559
I excluded pretty much everything else I've seen.
00:03:25.560 --> 00:03:28.788
For this reason, I only tried to focus on
00:03:28.789 --> 00:03:32.199
some very basic puzzles I can solve comfortably,
00:03:32.200 --> 00:03:34.839
and did not want to do anything else
00:03:34.840 --> 00:03:36.439
that may complicate things significantly.
00:03:36.440 --> 00:03:40.479
No other kinds of puzzles, no simulation, no solving,
00:03:40.480 --> 00:03:43.919
no exotic events, and no specialized scrambles
00:03:43.920 --> 00:03:49.239
that are only good for practicing specific algorithms.
NOTE Demo
00:03:49.240 --> 00:03:54.199
So at this point the organizer should hopefully show
00:03:54.200 --> 00:03:57.999
a small video I've prepared, a one minute video showing how
00:03:58.000 --> 00:04:03.080
I actually use this to solve a cube and to time my solve.
NOTE Challenges: Representing the cube
00:05:19.840 --> 00:05:22.959
Okay, so building this thing, there were several challenges.
00:05:22.960 --> 00:05:24.959
The first one was how do I even represent
00:05:24.960 --> 00:05:26.919
the state of a Rubik's cube.
00:05:26.920 --> 00:05:29.959
For this there are many possible representations,
00:05:29.960 --> 00:05:32.159
no obvious best solution.
00:05:32.160 --> 00:05:34.079
I did not, well, what helped me was that
00:05:34.080 --> 00:05:36.439
I did not have to programmatically solve this thing,
00:05:36.440 --> 00:05:39.639
so I picked the easiest possible representation
00:05:39.640 --> 00:05:42.719
which is just an array of every single facelet.
00:05:42.720 --> 00:05:46.959
For a 3x3 cube you have 9 facelets on one side,
00:05:46.960 --> 00:05:51.719
so times 6 sides you would have 54 elements in this array.
00:05:51.720 --> 00:05:54.159
So with this representation, it's very simple,
00:05:54.160 --> 00:05:56.839
but it's kind of weird to do scrambles with this.
00:05:56.840 --> 00:05:59.359
But otherwise, it worked very, very well.
00:05:59.360 --> 00:06:01.719
In the future, I plan to learn some group theory,
00:06:01.720 --> 00:06:03.199
pick a better representation
00:06:03.200 --> 00:06:05.639
and do this in a much, much more elegant way
00:06:05.640 --> 00:06:12.319
without compromising speed too much.
00:06:12.320 --> 00:06:15.159
Yes. Once I had the representation,
00:06:15.160 --> 00:06:18.079
the scrambling itself should not be too hard.
00:06:18.080 --> 00:06:22.199
For this, it's important to consider that basically
00:06:22.200 --> 00:06:23.599
if you do a face turn
00:06:23.600 --> 00:06:26.879
you end up swapping some facelets with other facelets,
00:06:26.880 --> 00:06:30.479
that's the easiest way to think about this.
00:06:30.480 --> 00:06:33.719
To determine which one goes into which one's position,
00:06:33.720 --> 00:06:36.921
it was pretty confusing to figure this out.
00:06:36.922 --> 00:06:38.759
For this I went through a few papers,
00:06:38.760 --> 00:06:40.479
and I found one which suggested
00:06:40.480 --> 00:06:42.399
to just build a cube out of paper,
00:06:42.400 --> 00:06:44.479
number every facelet, and turn it
00:06:44.480 --> 00:06:48.799
and keep track of which facelet moved into which position.
00:06:48.800 --> 00:06:51.959
And programmatically, the `cl-rotatef` macro
00:06:51.960 --> 00:06:53.839
was very, very useful for doing this kind of
00:06:53.840 --> 00:06:56.079
in-place swapping you need for this operation.
00:06:56.080 --> 00:06:59.319
So in the future, group theory would hopefully
00:06:59.320 --> 00:07:02.439
make this a bit less awkward.
00:07:02.440 --> 00:07:04.559
Here's a photo of this paper cube I made
00:07:04.560 --> 00:07:08.319
along with a real cube. As you can see
00:07:08.320 --> 00:07:11.799
mathematically speaking, they are the same thing,
00:07:11.800 --> 00:07:13.719
they just look very, very different.
NOTE Scrambling
00:07:13.720 --> 00:07:18.759
So the scramble algorithm itself,
00:07:18.760 --> 00:07:23.879
I pondered how this would even be done. In the competitions,
00:07:23.880 --> 00:07:26.039
They do this in a very, very elaborate way.
00:07:26.040 --> 00:07:27.199
They generate a random cube,
00:07:27.200 --> 00:07:29.839
they try to solve it, and if it's solvable
00:07:29.840 --> 00:07:32.999
they use these solution moves
00:07:33.000 --> 00:07:35.279
to turn into a scramble basically.
00:07:35.280 --> 00:07:39.399
And they also make sure to canonicalize the moves,
00:07:39.400 --> 00:07:42.999
so if you have subsequent moves that can be simplified,
00:07:43.000 --> 00:07:45.039
they do simplify these as much as possible.
00:07:45.040 --> 00:07:45.679
For example,
00:07:45.680 --> 00:07:48.199
if you have two subsequent rotations in one direction,
00:07:48.200 --> 00:07:51.119
it's turned into a different kind of rotation,
00:07:51.120 --> 00:07:53.839
so 90 and 90 equals 180.
00:07:53.840 --> 00:07:57.759
And the other Elisp scramblers I looked at,
00:07:57.760 --> 00:07:59.559
they generate random moves.
00:07:59.560 --> 00:08:01.959
Some of them do canonicalize. Not all of them.
00:08:01.960 --> 00:08:05.359
This one tries to do the best low-fi thing,
00:08:05.360 --> 00:08:06.839
that is, generating random moves,
00:08:06.840 --> 00:08:08.479
canonicalizing and repeating
00:08:08.480 --> 00:08:13.999
until enough have been generated.
NOTE Visualization
00:08:14.000 --> 00:08:17.599
For the visualization I had to figure out
00:08:17.600 --> 00:08:18.959
something else too complicated.
00:08:18.960 --> 00:08:21.679
For this, I tried to figure out
00:08:21.680 --> 00:08:24.319
where every facelift would end up in the puzzle view
00:08:24.320 --> 00:08:25.879
when you would unfold it.
00:08:25.880 --> 00:08:30.119
And for this, I did not consider the facelet orientation.
00:08:30.120 --> 00:08:33.719
This may be important later for some other puzzles
00:08:33.720 --> 00:08:35.599
where you can end up with very twisted faces,
00:08:35.600 --> 00:08:37.479
but for simple cubes, it's not a problem.
00:08:37.480 --> 00:08:40.759
My initial prototype used colored text,
00:08:40.760 --> 00:08:43.199
but later, I used the SVG library.
00:08:43.200 --> 00:08:46.039
It turned out to be easy enough to use, actually.
00:08:46.040 --> 00:08:50.559
Currently, I have hard-coded face-color mappings,
00:08:50.560 --> 00:08:53.559
but I plan to replace this so that theming is possible.
00:08:53.560 --> 00:08:56.039
For example, if you happen to have a cube
00:08:56.040 --> 00:08:59.140
that does not have the same color mappings as I do,
00:08:59.141 --> 00:09:00.919
then you should be able to fix this.
NOTE UI with Transient
00:09:00.920 --> 00:09:05.879
Next challenge was to build
00:09:05.880 --> 00:09:08.399
a beautiful intuitive UI with Transient.
00:09:08.400 --> 00:09:11.319
The reason why I chose this is
00:09:11.320 --> 00:09:14.799
because it would be self-documenting and Magit-style,
00:09:14.800 --> 00:09:16.799
and everyone knows how Magit works basically.
00:09:16.800 --> 00:09:19.759
Since Transient has become part of Emacs,
00:09:19.760 --> 00:09:21.679
there is really no reason to not try it out.
00:09:21.680 --> 00:09:26.119
The problem was documentation is difficult to understand.
00:09:26.120 --> 00:09:27.839
It's very abstract and high level,
00:09:27.840 --> 00:09:30.319
and it's hard to figure out. "Okay,
00:09:30.320 --> 00:09:31.239
I want to do something,
00:09:31.240 --> 00:09:33.359
how am I supposed to do this?"
00:09:33.360 --> 00:09:37.799
I did find transient-showcase, which has lots of examples,
00:09:37.800 --> 00:09:40.079
but they don't really feel finished
00:09:40.080 --> 00:09:43.519
and not realistic enough.
00:09:43.520 --> 00:09:45.199
When I tried to use the package,
00:09:45.200 --> 00:09:47.359
I got plenty of unhelpful error messages
00:09:47.360 --> 00:09:48.559
when using it incorrectly.
00:09:48.560 --> 00:09:50.399
I did manage to figure it out,
00:09:50.400 --> 00:09:55.039
but I plan to find more actual examples of it,
00:09:55.040 --> 00:09:57.879
to have an executable reference basically
00:09:57.880 --> 00:10:00.079
and try to improve my use of it.
NOTE Book-keeping with SQLite
00:10:00.080 --> 00:10:05.999
For the book-keeping, I used SQLite.
00:10:06.000 --> 00:10:08.999
This is a very recent addition to Emacs,
00:10:09.000 --> 00:10:11.759
it only appeared in the current major version.
00:10:11.760 --> 00:10:13.839
It's still very early days.
00:10:13.840 --> 00:10:17.479
I found some oddities, one of them turned out to be
00:10:17.480 --> 00:10:19.279
a bug in the transaction macro.
00:10:19.280 --> 00:10:22.039
Like basically, if you do an SQL transaction
00:10:22.040 --> 00:10:24.639
and an error happens, then every helper I found
00:10:24.640 --> 00:10:25.399
does a rollback on an error.
00:10:25.400 --> 00:10:31.199
But this one did not. It actually committed on an error,
00:10:31.200 --> 00:10:34.319
and this was very weird to figure out.
00:10:34.320 --> 00:10:38.759
I reported a bug. Eli was nice enough to send me a patch.
00:10:38.760 --> 00:10:39.879
We did some patch review,
00:10:39.880 --> 00:10:42.439
and he ended up fixing it properly.
00:10:42.440 --> 00:10:50.119
So yes, there's still a lot to be done there, and yeah,
00:10:50.120 --> 00:10:51.359
the API is very basic.
00:10:51.360 --> 00:10:53.359
You don't have convenience helpers
00:10:53.360 --> 00:10:55.759
like fetch the first row or fetch the first value
00:10:55.760 --> 00:10:58.880
or anything, but they're easy enough to write yourself.
00:10:58.881 --> 00:11:00.820
And the biggest challenge with this bookkeeping part
00:11:00.821 --> 00:11:02.479
was figuring out a decent schema,
00:11:02.480 --> 00:11:04.599
like how to organize data correctly
00:11:04.600 --> 00:11:06.799
so that it would not be awkward to manipulate.
00:11:06.800 --> 00:11:10.199
And with this, you can finally build a package
00:11:10.200 --> 00:11:11.839
that remembers its state properly
00:11:11.840 --> 00:11:14.919
and don't have to run into foot guns
00:11:14.920 --> 00:11:17.079
with Lisp-style serialization, deserialization.
NOTE Conclusion
00:11:17.080 --> 00:11:22.639
So yes, that concludes it so far.
00:11:22.640 --> 00:11:26.639
So what did I learn from this exercise?
00:11:26.640 --> 00:11:28.959
Well, there are still plenty of packages
00:11:28.960 --> 00:11:30.039
for Emacs to be written.
00:11:30.040 --> 00:11:33.359
If you think everything you can think of
00:11:33.360 --> 00:11:35.799
or you need has already been written, well, guess what?
00:11:35.800 --> 00:11:36.239
No.
00:11:36.240 --> 00:11:38.495
These are still plenty of specialized things
00:11:38.496 --> 00:11:41.239
that could need your help.
00:11:41.240 --> 00:11:44.239
These cubes do not require advanced mathematics,
00:11:44.240 --> 00:11:45.599
contrary to what you may think.
00:11:45.600 --> 00:11:49.159
Yes, you can apply advanced mathematics to them
00:11:49.160 --> 00:11:51.919
if you want to, but you don't have to.
00:11:51.920 --> 00:11:55.439
What surprised me about this is basically group theory.
00:11:55.440 --> 00:11:56.519
I've heard of it before.
00:11:56.520 --> 00:11:58.279
It seemed to be a meme, basically,
00:11:58.280 --> 00:12:00.919
because it has been like mostly Haskell people
00:12:00.920 --> 00:12:02.639
being very excited about this
00:12:02.640 --> 00:12:06.959
and it seemed kind of, like, divorced from reality, basically.
00:12:06.960 --> 00:12:10.399
But this puzzle, it actually proves that yes,
00:12:10.400 --> 00:12:11.399
it has its use.
00:12:11.400 --> 00:12:12.879
It definitely has.
00:12:12.880 --> 00:12:15.839
You just have to find the right problem matching it,
00:12:15.840 --> 00:12:17.919
and yeah.
00:12:17.920 --> 00:12:19.839
So yeah, once I understand it better,
00:12:19.840 --> 00:12:22.999
the topic, I expect to write better code.
00:12:23.000 --> 00:12:28.919
These new Emacs features, they work well enough.
00:12:28.920 --> 00:12:30.359
There are some rough edges.
00:12:30.360 --> 00:12:31.879
They definitely need more testing.
00:12:31.880 --> 00:12:35.119
So please, please, everyone,
00:12:35.120 --> 00:12:38.999
if you write Elisp, please try SQLite or Transient
00:12:39.000 --> 00:12:41.159
or anything else that looks cool and shiny.
00:12:41.160 --> 00:12:42.919
Report bugs.
00:12:42.920 --> 00:12:46.039
Find ways to improve them, anything. And yeah,
00:12:46.040 --> 00:12:49.319
I'm sure that if we do this,
00:12:49.320 --> 00:12:52.119
then Emacs will continue to get even better.
00:12:52.120 --> 00:12:56.239
So yeah, what's next for this package?
00:12:56.240 --> 00:13:00.439
Well, I could... There are lots of obvious UI improvements
00:13:00.440 --> 00:13:01.799
and testing to be done.
00:13:01.800 --> 00:13:04.159
I basically want to reach feature parity
00:13:04.160 --> 00:13:06.879
with the twisty-timer app, which this is very much inspired by.
00:13:06.880 --> 00:13:11.119
I want nice-looking stats like graphical ones
00:13:11.120 --> 00:13:13.239
instead of just a simple list of times.
00:13:13.240 --> 00:13:15.679
And I want support for more puzzles, of course,
00:13:15.680 --> 00:13:16.999
not just the simple cubes,
00:13:17.000 --> 00:13:19.039
but as I progress learning these puzzles,
00:13:19.040 --> 00:13:22.519
I want to have Emacs supporting me for this.
00:13:22.520 --> 00:13:26.879
But generally, it's a very open-ended package.
00:13:26.880 --> 00:13:31.079
And this concludes the talk.
00:13:31.080 --> 00:13:35.360
Thank you very much.