00:00.000 Introduction
01:35.400 Cubing in Emacs
02:01.160 Prior art
02:32.040 The name
03:16.520 What's in wca-prep
03:49.240 Demo
05:15.340 Challenges: Representing the cube
07:09.220 Scrambling
08:09.500 Visualization
08:56.420 UI with Transient
09:55.580 Book-keeping with SQLite
11:12.580 Conclusion
Emacs is well-known for its kitchen-sink nature and sheer extensibility.
However, its utility for tasks beyond text manipulation is still
disputed. While it is possible to do most of your computing inside
Emacs, the existing solutions are of varying quality. Sometimes it is
necessary to create a custom solution tailored to one's personal needs
and I believe Emacs to be a worthwhile platform for this.
In this talk I present my journey of building a package to assist me
with speedcubing, a competitive sport with the goal of solving the
Rubik's Cube as fast as possible. Along with a demo, useful Emacs
features and challenges that came up during development will be shown.
Discussion
Questions and answers
Q: I see that there is a way to document the time it took to
complete the puzzle; however, what about other things such as the
date and time, and potentially a note on technique or warm up
routine etc? It seems like an interface that included these things
would also help people who are practicing and trying to improve. It
would help answer the question... what kinds of things do I need to
do to improve. ;;Thank you for your answer.
A: Currently, only the timestamp and completion time are
recorded for the puzzle/label. However, I've looked at
twisty-timer and it does record both the used scramble and a
comment field as well, so I plan adding those once the other
features work properly. This would allow keeping track of
particularly good/bad solves for example.
Q: As a side-note, could you say something about how you use emacs
to help with your cybersecurity or CTF actifivities? Are there some
recommended packages or do you use all of your own templates and
procedures to speed your activity? Maybe just post a link to your
homepage or GH repositories.
A: It's pretty much only Org usage to document my activities in
a way that I know what I did 3 weeks ago and can pick up my
research from then. I do not use Emacs for source code review
specifically (depending on the target environment, there are
better suited tools). The thing with the field is that often,
one has to resort to work with whatever tools are at hand and to
make the most of them, which is kind of at odds with using Emacs
first and foremost as an integrated environment for everything.
Other than Org, I use it as an editor for pretty much any
programming language I encounter.
Q: What are the biggest challenges to using transient?
A: The documentation was very high-level compared to what I'm
used to, so I had to skim it a lot to find out how to use it for
basic tasks. I think it would be useful to have some slightly
more hands-on examples for common tasks. One issue I've run
into a few times was the code using generic functions, so it was
difficult to debug errors (like using a non-interactive lambda
form when a command was expected and getting an unhelpful error
message).
Definitely, but as I've remarked in the talk, the
examples felt very "generic". Slightly more realistic
examples would make it even better.
Q: Very cool project. Alas I'm not a cuber, so my question is
merely, what did you learn in the process of making this
presentation?
A: I've never recorded a demo video happening outside of my
laptop before, so getting the external recording setup right
was... fun. It involved a ladder, several cardboard boxes and
my phone. After five attempts (one of which ended up with the
cube rolling off the desk loudly), I finally got an okayish
recording to use for the presentation.
Q: Does svg.el support tap events?
A: svg.el is only responsible for generating valid SVG documents
and one can put whichever tags/attributes there they wish. From
my understanding, anything interactive usually solved with JS in
the browser would need to be rewritten using Emacs Lisp instead.
Tap events for example could be solved with the ":map"
property put on the image and would work for other image formats
than SVG as well.
Notes
There's probably quite a few cubers in here. =) I tend to average 50s on 3x3, the kiddo is usually a bit faster.
I've recently got a 45s best with LBL
I have some code in my config to draw last-layer diagrams as SVGs and an Org link thing like #+LINK: pll https://alg.cubing.net/?stage=PLL&type=alg&setup=x_y_z&view=playback&alg=%s to link to algs quickly; https://sachachua.com/blog/2023/02/using-org-babel-to-learn-rubik-s-cube-algorithms/
speaker: ah yes, I've had the idea to try out roofpig or cubing.js for doing that in org documents, nice to see it has been done before
FWIW transient just had a v0.5.0 release which adds and fixes things. It continues to improve thanks to tarsius's tireless work.
i'm glad you're exploring Emacs UI wasamasa , i've also been confounded trying to write a transient, and its nice to see that sqlite is working for ya
to be fair, I've considered to just stick to my usual approach of writing boring code that does work on as many machines as possible, but there were so many new features that would help making a nice looking and working package that I decided to just depend on emacs 29.1
Hello, everyone, and welcome to Speedcubing in Emacs.First of all, a little bit about myself.My name is Vasilij Schneidermann. Online, I go by wasamasa.I'm 31 years old. I work in information security,and I do consulting and hackingand stuff like figuring outhow to break into other people's computersand how to secure their systems basically.You can reach me by email.I do have a self-hosted code repository thingy going on.I have a blog, and you can find mein some other places online, like IRC for example.So about the talk itself,I used to be into the Rubik's cube when I was in school.I forgot about it, though,because these cubes were not very good.Recently I did find some cheap looking cube at a shop.Did not pay terribly much for it.It was so, so much better than my old cube,it was unreal.This motivated me to get back intothis really weird kind of hobby.For this, you need to be good at producinga truly random scrambleand timing your attempts to get any better at it.There is, of course, existing softwareto do the scrambling for you and the recordingand the timekeeping and such,but all the good options seem to be either web or mobile,for example the cstimer softwareor the twisty-timer app on Android.
To my surprise, I did not find a single decent optioninside Emacs, so this is basically a case studyhow to do better. For this, I wanted to make use ofall the cool new Emacs features that appeared,like the SVG library; Transient,the library used for the Magit-style interfaces;and the recently added sqlite-mode.And most importantly it was about having fun.
So here's a full list of prior art,I will not go into detail about this,but basically we have things solvingvery different parts of this,but not all of it. For example: we have several,we have a timer. We have several solvers.We have some scramblers.We have some whole-cube simulators, including a 3D one.We have something for making it easierto enter your algorithms in the notation.But nothing that does all of those things in one package,which kind of surprised me.So I present the wca-prep package.
So the name, I found it difficultto come up with a good name and so I lookedand I saw, well there's this World Cube Associationthat holds these competitions where you compete.They do this for the Rubik's cubebut also a few others,so there's like a standardized listof events they have for this.There is a standard notation for thisand rules and everything.And the goal of my package is basicallyto help prepare myself for such a competitionand in fact a week ago I went to my first onewhich was wild, but pretty cool.So for this reason I chose this name wca-prep,because it helps me prepare for this kind of competitionand this limited the scope significantly,
I have a scrambler, visualization of the scramble,timer, and statistics.I excluded pretty much everything else I've seen.For this reason, I only tried to focus onsome very basic puzzles I can solve comfortably,and did not want to do anything elsethat may complicate things significantly.No other kinds of puzzles, no simulation, no solving,no exotic events, and no specialized scramblesthat are only good for practicing specific algorithms.
So at this point the organizer should hopefully showa small video I've prepared, a one minute video showing howI actually use this to solve a cube and to time my solve.
Okay, so building this thing, there were several challenges.The first one was how do I even representthe state of a Rubik's cube.For this there are many possible representations,no obvious best solution.I did not, well, what helped me was thatI did not have to programmatically solve this thing,so I picked the easiest possible representationwhich is just an array of every single facelet.For a 3x3 cube you have 9 facelets on one side,so times 6 sides you would have 54 elements in this array.So with this representation, it's very simple,but it's kind of weird to do scrambles with this.But otherwise, it worked very, very well.In the future, I plan to learn some group theory,pick a better representationand do this in a much, much more elegant waywithout compromising speed too much.Yes. Once I had the representation,the scrambling itself should not be too hard.For this, it's important to consider that basicallyif you do a face turnyou end up swapping some facelets with other facelets,that's the easiest way to think about this.To determine which one goes into which one's position,it was pretty confusing to figure this out.For this I went through a few papers,and I found one which suggestedto just build a cube out of paper,number every facelet, and turn itand keep track of which facelet moved into which position.And programmatically, the cl-rotatef macrowas very, very useful for doing this kind ofin-place swapping you need for this operation.So in the future, group theory would hopefullymake this a bit less awkward.Here's a photo of this paper cube I madealong with a real cube. As you can seemathematically speaking, they are the same thing,they just look very, very different.
So the scramble algorithm itself,I pondered how this would even be done. In the competitions,They do this in a very, very elaborate way.They generate a random cube,they try to solve it, and if it's solvablethey use these solution movesto turn into a scramble basically.And they also make sure to canonicalize the moves,so if you have subsequent moves that can be simplified,they do simplify these as much as possible.For example,if you have two subsequent rotations in one direction,it's turned into a different kind of rotation,so 90 and 90 equals 180.And the other Elisp scramblers I looked at,they generate random moves.Some of them do canonicalize. Not all of them.This one tries to do the best low-fi thing,that is, generating random moves,canonicalizing and repeatinguntil enough have been generated.
For the visualization I had to figure outsomething else too complicated.For this, I tried to figure outwhere every facelift would end up in the puzzle viewwhen you would unfold it.And for this, I did not consider the facelet orientation.This may be important later for some other puzzleswhere you can end up with very twisted faces,but for simple cubes, it's not a problem.My initial prototype used colored text,but later, I used the SVG library.It turned out to be easy enough to use, actually.Currently, I have hard-coded face-color mappings,but I plan to replace this so that theming is possible.For example, if you happen to have a cubethat does not have the same color mappings as I do,then you should be able to fix this.
Next challenge was to builda beautiful intuitive UI with Transient.The reason why I chose this isbecause it would be self-documenting and Magit-style,and everyone knows how Magit works basically.Since Transient has become part of Emacs,there is really no reason to not try it out.The problem was documentation is difficult to understand.It's very abstract and high level,and it's hard to figure out. "Okay,I want to do something,how am I supposed to do this?"I did find transient-showcase, which has lots of examples,but they don't really feel finishedand not realistic enough.When I tried to use the package,I got plenty of unhelpful error messageswhen using it incorrectly.I did manage to figure it out,but I plan to find more actual examples of it,to have an executable reference basicallyand try to improve my use of it.
For the book-keeping, I used SQLite.This is a very recent addition to Emacs,it only appeared in the current major version.It's still very early days.I found some oddities, one of them turned out to bea bug in the transaction macro.Like basically, if you do an SQL transactionand an error happens, then every helper I founddoes a rollback on an error.But this one did not. It actually committed on an error,and this was very weird to figure out.I reported a bug. Eli was nice enough to send me a patch.We did some patch review,and he ended up fixing it properly.So yes, there's still a lot to be done there, and yeah,the API is very basic.You don't have convenience helperslike fetch the first row or fetch the first valueor anything, but they're easy enough to write yourself.And the biggest challenge with this bookkeeping partwas figuring out a decent schema,like how to organize data correctlyso that it would not be awkward to manipulate.And with this, you can finally build a packagethat remembers its state properlyand don't have to run into foot gunswith Lisp-style serialization, deserialization.
So yes, that concludes it so far.So what did I learn from this exercise?Well, there are still plenty of packagesfor Emacs to be written.If you think everything you can think ofor you need has already been written, well, guess what?No.These are still plenty of specialized thingsthat could need your help.These cubes do not require advanced mathematics,contrary to what you may think.Yes, you can apply advanced mathematics to themif you want to, but you don't have to.What surprised me about this is basically group theory.I've heard of it before.It seemed to be a meme, basically,because it has been like mostly Haskell peoplebeing very excited about thisand it seemed kind of, like, divorced from reality, basically.But this puzzle, it actually proves that yes,it has its use.It definitely has.You just have to find the right problem matching it,and yeah.So yeah, once I understand it better,the topic, I expect to write better code.These new Emacs features, they work well enough.There are some rough edges.They definitely need more testing.So please, please, everyone,if you write Elisp, please try SQLite or Transientor anything else that looks cool and shiny.Report bugs.Find ways to improve them, anything. And yeah,I'm sure that if we do this,then Emacs will continue to get even better.So yeah, what's next for this package?Well, I could... There are lots of obvious UI improvementsand testing to be done.I basically want to reach feature paritywith the twisty-timer app, which this is very much inspired by.I want nice-looking stats like graphical onesinstead of just a simple list of times.And I want support for more puzzles, of course,not just the simple cubes,but as I progress learning these puzzles,I want to have Emacs supporting me for this.But generally, it's a very open-ended package.And this concludes the talk.Thank you very much.