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:05:15.239 I actually use this to solve a cube and to time my solve. NOTE Challenges: Representing the cube 00:05:15.240 --> 00:05:18.508 Okay, so building this thing, there were several challenges. 00:05:18.509 --> 00:05:20.508 The first one was how do I even represent 00:05:20.509 --> 00:05:22.468 the state of a Rubik's cube. 00:05:22.469 --> 00:05:25.508 For this there are many possible representations, 00:05:25.509 --> 00:05:27.708 no obvious best solution. 00:05:27.709 --> 00:05:29.628 I did not, well, what helped me was that 00:05:29.629 --> 00:05:31.988 I did not have to programmatically solve this thing, 00:05:31.989 --> 00:05:35.188 so I picked the easiest possible representation 00:05:35.189 --> 00:05:38.268 which is just an array of every single facelet. 00:05:38.269 --> 00:05:42.508 For a 3x3 cube you have 9 facelets on one side, 00:05:42.509 --> 00:05:47.268 so times 6 sides you would have 54 elements in this array. 00:05:47.269 --> 00:05:49.708 So with this representation, it's very simple, 00:05:49.709 --> 00:05:52.388 but it's kind of weird to do scrambles with this. 00:05:52.389 --> 00:05:54.908 But otherwise, it worked very, very well. 00:05:54.909 --> 00:05:57.268 In the future, I plan to learn some group theory, 00:05:57.269 --> 00:05:58.748 pick a better representation 00:05:58.749 --> 00:06:01.188 and do this in a much, much more elegant way 00:06:01.189 --> 00:06:07.868 without compromising speed too much. 00:06:07.869 --> 00:06:10.708 Yes. Once I had the representation, 00:06:10.709 --> 00:06:13.628 the scrambling itself should not be too hard. 00:06:13.629 --> 00:06:17.748 For this, it's important to consider that basically 00:06:17.749 --> 00:06:19.148 if you do a face turn 00:06:19.149 --> 00:06:22.428 you end up swapping some facelets with other facelets, 00:06:22.429 --> 00:06:26.028 that's the easiest way to think about this. 00:06:26.029 --> 00:06:29.268 To determine which one goes into which one's position, 00:06:29.269 --> 00:06:32.470 it was pretty confusing to figure this out. 00:06:32.471 --> 00:06:34.308 For this I went through a few papers, 00:06:34.309 --> 00:06:36.028 and I found one which suggested 00:06:36.029 --> 00:06:37.948 to just build a cube out of paper, 00:06:37.949 --> 00:06:40.028 number every facelet, and turn it 00:06:40.029 --> 00:06:44.348 and keep track of which facelet moved into which position. 00:06:44.349 --> 00:06:47.508 And programmatically, the `cl-rotatef` macro 00:06:47.509 --> 00:06:49.388 was very, very useful for doing this kind of 00:06:49.389 --> 00:06:51.628 in-place swapping you need for this operation. 00:06:51.629 --> 00:06:54.868 So in the future, group theory would hopefully 00:06:54.869 --> 00:06:57.988 make this a bit less awkward. 00:06:57.989 --> 00:07:00.108 Here's a photo of this paper cube I made 00:07:00.109 --> 00:07:03.868 along with a real cube. As you can see 00:07:03.869 --> 00:07:07.348 mathematically speaking, they are the same thing, 00:07:07.349 --> 00:07:09.268 they just look very, very different. NOTE Scrambling 00:07:09.269 --> 00:07:14.308 So the scramble algorithm itself, 00:07:14.309 --> 00:07:19.428 I pondered how this would even be done. In the competitions, 00:07:19.429 --> 00:07:21.588 They do this in a very, very elaborate way. 00:07:21.589 --> 00:07:22.748 They generate a random cube, 00:07:22.749 --> 00:07:25.388 they try to solve it, and if it's solvable 00:07:25.389 --> 00:07:28.548 they use these solution moves 00:07:28.549 --> 00:07:30.828 to turn into a scramble basically. 00:07:30.829 --> 00:07:34.948 And they also make sure to canonicalize the moves, 00:07:34.949 --> 00:07:38.548 so if you have subsequent moves that can be simplified, 00:07:38.549 --> 00:07:40.588 they do simplify these as much as possible. 00:07:40.589 --> 00:07:41.228 For example, 00:07:41.229 --> 00:07:43.748 if you have two subsequent rotations in one direction, 00:07:43.749 --> 00:07:46.668 it's turned into a different kind of rotation, 00:07:46.669 --> 00:07:49.388 so 90 and 90 equals 180. 00:07:49.389 --> 00:07:53.308 And the other Elisp scramblers I looked at, 00:07:53.309 --> 00:07:55.108 they generate random moves. 00:07:55.109 --> 00:07:57.508 Some of them do canonicalize. Not all of them. 00:07:57.509 --> 00:08:00.908 This one tries to do the best low-fi thing, 00:08:00.909 --> 00:08:02.388 that is, generating random moves, 00:08:02.389 --> 00:08:04.028 canonicalizing and repeating 00:08:04.029 --> 00:08:09.548 until enough have been generated. NOTE Visualization 00:08:09.549 --> 00:08:13.148 For the visualization I had to figure out 00:08:13.149 --> 00:08:14.508 something else too complicated. 00:08:14.509 --> 00:08:17.228 For this, I tried to figure out 00:08:17.229 --> 00:08:19.868 where every facelift would end up in the puzzle view 00:08:19.869 --> 00:08:21.428 when you would unfold it. 00:08:21.429 --> 00:08:25.668 And for this, I did not consider the facelet orientation. 00:08:25.669 --> 00:08:29.268 This may be important later for some other puzzles 00:08:29.269 --> 00:08:31.148 where you can end up with very twisted faces, 00:08:31.149 --> 00:08:33.028 but for simple cubes, it's not a problem. 00:08:33.029 --> 00:08:36.308 My initial prototype used colored text, 00:08:36.309 --> 00:08:38.748 but later, I used the SVG library. 00:08:38.749 --> 00:08:41.588 It turned out to be easy enough to use, actually. 00:08:41.589 --> 00:08:46.108 Currently, I have hard-coded face-color mappings, 00:08:46.109 --> 00:08:49.108 but I plan to replace this so that theming is possible. 00:08:49.109 --> 00:08:51.588 For example, if you happen to have a cube 00:08:51.589 --> 00:08:54.689 that does not have the same color mappings as I do, 00:08:54.690 --> 00:08:56.468 then you should be able to fix this. NOTE UI with Transient 00:08:56.469 --> 00:09:01.428 Next challenge was to build 00:09:01.429 --> 00:09:03.948 a beautiful intuitive UI with Transient. 00:09:03.949 --> 00:09:06.868 The reason why I chose this is 00:09:06.869 --> 00:09:10.348 because it would be self-documenting and Magit-style, 00:09:10.349 --> 00:09:12.348 and everyone knows how Magit works basically. 00:09:12.349 --> 00:09:15.308 Since Transient has become part of Emacs, 00:09:15.309 --> 00:09:17.228 there is really no reason to not try it out. 00:09:17.229 --> 00:09:21.668 The problem was documentation is difficult to understand. 00:09:21.669 --> 00:09:23.388 It's very abstract and high level, 00:09:23.389 --> 00:09:25.868 and it's hard to figure out. "Okay, 00:09:25.869 --> 00:09:26.788 I want to do something, 00:09:26.789 --> 00:09:28.908 how am I supposed to do this?" 00:09:28.909 --> 00:09:33.348 I did find transient-showcase, which has lots of examples, 00:09:33.349 --> 00:09:35.628 but they don't really feel finished 00:09:35.629 --> 00:09:39.068 and not realistic enough. 00:09:39.069 --> 00:09:40.748 When I tried to use the package, 00:09:40.749 --> 00:09:42.908 I got plenty of unhelpful error messages 00:09:42.909 --> 00:09:44.108 when using it incorrectly. 00:09:44.109 --> 00:09:45.948 I did manage to figure it out, 00:09:45.949 --> 00:09:50.588 but I plan to find more actual examples of it, 00:09:50.589 --> 00:09:53.428 to have an executable reference basically 00:09:53.429 --> 00:09:55.628 and try to improve my use of it. NOTE Book-keeping with SQLite 00:09:55.629 --> 00:10:01.548 For the book-keeping, I used SQLite. 00:10:01.549 --> 00:10:04.548 This is a very recent addition to Emacs, 00:10:04.549 --> 00:10:07.308 it only appeared in the current major version. 00:10:07.309 --> 00:10:09.388 It's still very early days. 00:10:09.389 --> 00:10:13.028 I found some oddities, one of them turned out to be 00:10:13.029 --> 00:10:14.828 a bug in the transaction macro. 00:10:14.829 --> 00:10:17.588 Like basically, if you do an SQL transaction 00:10:17.589 --> 00:10:20.188 and an error happens, then every helper I found 00:10:20.189 --> 00:10:20.948 does a rollback on an error. 00:10:20.949 --> 00:10:26.748 But this one did not. It actually committed on an error, 00:10:26.749 --> 00:10:29.868 and this was very weird to figure out. 00:10:29.869 --> 00:10:34.308 I reported a bug. Eli was nice enough to send me a patch. 00:10:34.309 --> 00:10:35.428 We did some patch review, 00:10:35.429 --> 00:10:37.988 and he ended up fixing it properly. 00:10:37.989 --> 00:10:45.668 So yes, there's still a lot to be done there, and yeah, 00:10:45.669 --> 00:10:46.908 the API is very basic. 00:10:46.909 --> 00:10:48.908 You don't have convenience helpers 00:10:48.909 --> 00:10:51.308 like fetch the first row or fetch the first value 00:10:51.309 --> 00:10:54.429 or anything, but they're easy enough to write yourself. 00:10:54.430 --> 00:10:56.369 And the biggest challenge with this bookkeeping part 00:10:56.370 --> 00:10:58.028 was figuring out a decent schema, 00:10:58.029 --> 00:11:00.148 like how to organize data correctly 00:11:00.149 --> 00:11:02.348 so that it would not be awkward to manipulate. 00:11:02.349 --> 00:11:05.748 And with this, you can finally build a package 00:11:05.749 --> 00:11:07.388 that remembers its state properly 00:11:07.389 --> 00:11:10.468 and don't have to run into foot guns 00:11:10.469 --> 00:11:12.628 with Lisp-style serialization, deserialization. NOTE Conclusion 00:11:12.629 --> 00:11:18.188 So yes, that concludes it so far. 00:11:18.189 --> 00:11:22.188 So what did I learn from this exercise? 00:11:22.189 --> 00:11:24.508 Well, there are still plenty of packages 00:11:24.509 --> 00:11:25.588 for Emacs to be written. 00:11:25.589 --> 00:11:28.908 If you think everything you can think of 00:11:28.909 --> 00:11:31.348 or you need has already been written, well, guess what? 00:11:31.349 --> 00:11:31.788 No. 00:11:31.789 --> 00:11:34.044 These are still plenty of specialized things 00:11:34.045 --> 00:11:36.788 that could need your help. 00:11:36.789 --> 00:11:39.788 These cubes do not require advanced mathematics, 00:11:39.789 --> 00:11:41.148 contrary to what you may think. 00:11:41.149 --> 00:11:44.708 Yes, you can apply advanced mathematics to them 00:11:44.709 --> 00:11:47.468 if you want to, but you don't have to. 00:11:47.469 --> 00:11:50.988 What surprised me about this is basically group theory. 00:11:50.989 --> 00:11:52.068 I've heard of it before. 00:11:52.069 --> 00:11:53.828 It seemed to be a meme, basically, 00:11:53.829 --> 00:11:56.468 because it has been like mostly Haskell people 00:11:56.469 --> 00:11:58.188 being very excited about this 00:11:58.189 --> 00:12:02.508 and it seemed kind of, like, divorced from reality, basically. 00:12:02.509 --> 00:12:05.948 But this puzzle, it actually proves that yes, 00:12:05.949 --> 00:12:06.948 it has its use. 00:12:06.949 --> 00:12:08.428 It definitely has. 00:12:08.429 --> 00:12:11.388 You just have to find the right problem matching it, 00:12:11.389 --> 00:12:13.468 and yeah. 00:12:13.469 --> 00:12:15.388 So yeah, once I understand it better, 00:12:15.389 --> 00:12:18.548 the topic, I expect to write better code. 00:12:18.549 --> 00:12:24.468 These new Emacs features, they work well enough. 00:12:24.469 --> 00:12:25.908 There are some rough edges. 00:12:25.909 --> 00:12:27.428 They definitely need more testing. 00:12:27.429 --> 00:12:30.668 So please, please, everyone, 00:12:30.669 --> 00:12:34.548 if you write Elisp, please try SQLite or Transient 00:12:34.549 --> 00:12:36.708 or anything else that looks cool and shiny. 00:12:36.709 --> 00:12:38.468 Report bugs. 00:12:38.469 --> 00:12:41.588 Find ways to improve them, anything. And yeah, 00:12:41.589 --> 00:12:44.868 I'm sure that if we do this, 00:12:44.869 --> 00:12:47.668 then Emacs will continue to get even better. 00:12:47.669 --> 00:12:51.788 So yeah, what's next for this package? 00:12:51.789 --> 00:12:55.988 Well, I could... There are lots of obvious UI improvements 00:12:55.989 --> 00:12:57.348 and testing to be done. 00:12:57.349 --> 00:12:59.708 I basically want to reach feature parity 00:12:59.709 --> 00:13:02.428 with the twisty-timer app, which this is very much inspired by. 00:13:02.429 --> 00:13:06.668 I want nice-looking stats like graphical ones 00:13:06.669 --> 00:13:08.788 instead of just a simple list of times. 00:13:08.789 --> 00:13:11.228 And I want support for more puzzles, of course, 00:13:11.229 --> 00:13:12.548 not just the simple cubes, 00:13:12.549 --> 00:13:14.588 but as I progress learning these puzzles, 00:13:14.589 --> 00:13:18.068 I want to have Emacs supporting me for this. 00:13:18.069 --> 00:13:22.428 But generally, it's a very open-ended package. 00:13:22.429 --> 00:13:26.628 And this concludes the talk. 00:13:26.629 --> 00:13:30.909 Thank you very much.