 I'm going to try that now, and I'll just wait and see if I can work it out. Ready? But I definitely will. I think it's on the phone. You can use any of the popular or whatever. There's no area that I like that. Awesome. Thank you. It's not that amazing. Here we go. So, now we're just going to use a demo of a pop-loan framework using torture screws. Yes. Take that. Yeah. I think the backstory for this, I think, is kind of timely because it's the time of the year where we're going to have the Hour of Code. So, I think December 7th to the 15th is CS Education Week, and one of the activities is the Hour of Code, and the number of places in Singapore where this is organized. So, this thing got started last year when I volunteered at the Science Centre for the Hour of Code. So, I was thinking of a thing to try to teach the students to come by something about writing programs that play games. So, game-playing, artificial intelligence programs, kind of a side interest of mine. So, okay. I thought, okay, let's try playing Tic-Tac-Toe then because that's maybe most games that kids know. So, you don't have to explain to them what the game is. But then the question is, how would you get them to create a Tic-Tac-Toe program? Because these are primary school children. They don't really know. They can't really type. I mean, they don't have, like, the hand-eye coordination to even type. So, how would you ask them to create a program to play Tic-Tac-Toe? And eventually, I came up with the idea that we can design a Tic-Tac-Toe AI with a set of rules, which is what you see over here. And it looks quite complex, but actually, so we just have, like, two rules at the top which are sort of built into every AI. So that's sort of for free. You don't have to design that one. And intuitively, just, you know, if you can win in this current step, win. If I can't win, but the opponent is going to win, then block the opponent. Otherwise, I try to place in a square if it's empty. So you can have a set of places in the lower left and so on. And you can actually represent the last nine rules with just a grid. So if you put a 1, it means if you check this square first, if this square is empty, you would place your mark there. And if that is occupied, you try to place in the second, the square number 2, and so on. So the first two rules combined with these nine rules gives you a complete tic-tac-toe playing program. Does that make sense? So this will be able to play as a program. So I thought, what would be some way for us to evaluate or study, like how well, of course, we could sort of play with the students or the visitors interactively, right? So you can ask them to design the program, essentially by filling in nine numbers, and then you want to sort of, you can ask them to play with you and you can ask them to try to simulate the program. It's kind of nice for thinking about how the sort of rule-based system works. But I thought it would be interesting to also do some computational study of the rules. Can we find some metrics? Can we evaluate these AIs and come up with some numbers? So I wrote a sort of closure program to do that, which I will try to show you now. So it's just a normal closure program. There's a function that, it's a problem with line, right? The wrapper, this takes forever, okay. So there's a function called check that reads, let's just use the really dumb, reads a description of the nine rules at the back, 79, that's sort of a matrix notation and it just outputs some statistics. So this is not very good. So we test both your program as first player and as second player because that makes a difference. And calculate the number of win-lose and draws against all possible moves by the opponent. So the opponent, you consider all the possible ways the opponent could move and then apply your program and then do the opponent and so on. In terms of that, so I'm actually interested in statistics from this. So for example, manage to find some interesting programs which could use as like a challenge to the students. Give them one where we know that it has exactly one way to lose when going first. You can ask them to find, okay, what's that way to win the AI and so on. Okay, so fast forward, I wanted to make this a little bit more interactive. So right now it's very hard to show this because I have to have a rappel and I have to type in this for the visitors. So that's why I started to think of creating a front-end and hopefully let me show you the front-end. That's sort of what came out of that exercise. So it's basically what you saw just now, but now sort of on the website. Yeah, so now they can sort of do it themselves, it becomes more DIY. So I don't have to be there sort of operating the rappel. So basically they would type in the matrix or the rules and then it would show the result on the right. So you can just sort of change it and just make sure it actually is working. I think the numbers at the bottom changed. So actually this takes a while to compute. It's not instantaneous because it sort of brute force checks all the possible lines of play. So this is actually built using something called Hoflon which is also by the same folks that developed Boot which we heard earlier. So actually I'll talk a little bit more about how this is done in Hoflon and how Boot is used to the development. Okay, so the next part of it we're just talking about the... I'll go through actually the Hoflon getting started tutorial. So if you ever saw that, this is basically the same thing. And I'll talk about how I actually built this particular sort of front end which is fairly simple. Okay, so let's get to the demo. So we don't need this anymore. So I have a Hoflon demo project which is also on GitHub. So right, so this is what you get if you do... Unfortunately you're going to get Bootstrap using line. So you can say line new Hoflon and then folder name. This is line new Hoflon. In this case I typed line new Hoflon demo. And essentially you get this structure. So you can see there's boot.properties which just says like the versions of boot that you're using. Then you have a build.boot file. So boot, it's more like make in a sense you can declare tasks and tasks have a series of different things you want to do. So I think the dev task you have like serve the web server. So Hoflon compiles the Hoflon files. Then CLGS compiles the files to JavaScript. You have a live reloading. Then you have sort of checking for changes. So let's just see how this works. So I'm going to start boot dev, which is... Oh no, I only have one terminal. So I'll start boot dev on a different terminal. So that I don't tie up my terminal. Sorry, this is too small to see. But ignore that. Hoflon demo. So just run boot dev. So boot dev essentially starts all those tasks. So I'm going to edit the page. So this is the scary bit. Okay, so... And boot dev also takes a little while to get going. Is it working? Okay, yeah. Yeah, so you see actually... So in Hoflon you write your pages as .hl files. They call it hlisp. And Hoflon itself compiles that to a .cljs file. And then hands over to the closure script compiler, which compiles it to the JavaScript files. Okay, sorry, I just need to wait for the... Never mind. The problem is this laptop is... Okay, oh. Oh, wait. Sorry, I think I screwed up somewhere. So I have two versions of Hoflon. They're trying to bind to the same port. So we can do that all over again. But anyway, let me just walk through what the hl file looks like. So this is the default. You don't get the comments at the bottom. But this is the default index.cljs.hl file you get. So the reason I use Hoflon was because it's actually a lot easier to get started, I think, if you don't have any front-end experience like myself. So I'm mostly a back-end developer. So I've worked in Java, Scala, closure. So I've not really tried closure script. So this is the first closure script experience. And I wanted to build something like a static HTML page, which is really simple. So Hoflon seems to fit the build in terms of building a very simple static page. So the page directive is very much like the NS directive in closure. This is a Hoflon thing. It's not a closure script thing. And in Hoflon, you construct the HTML functions. So you can see the HTML head and body and so on. Hopefully, we can see the page. So this is what you get. So if you go to the website, it shows you this page. So the thing about Hoflon is it integrates with another library called Javelin, which is, I guess it's kind of easy to describe as spreadsheet programming or functional reactive programming if you're the academic type. So I think the demo goes, you can define a cell. This is exactly like a cell in, I think the analogy is really, they're using the energy of a spreadsheet. So in a spreadsheet, you have a normal cell. So you can declare this cell. Then you can include it in your HTML. So, right. Notice I didn't have to refresh, right? Because they're doing the automatic reloading via WebSockets. So you see the value of the cell. So that seems kind of boring. So if you interact with the cell, with a button, click, swap. The cell is kind of like an atom. So we can say swap, click, ink, okay. So this just applies the ink function on the cell. So if you, well, like you would expect, it increments the button, right? So I think the thing to say is that it doesn't require that much code to get some kind of simple interactivity going on in Hoplon. So, you know, this is just declared HTML and I declared that, you know, I just obviously have a handler that says when you click the button, it performs, it runs this closure function, a closure script function. So that's kind of nice. What else? I think there's a mouse over effect you can do. It's also part of the tutorial. So, yeah, it loses the state, unfortunately. So if you mouse over the number, it goes down. Not fantastic, but yeah, just to show that you can do some other things besides click. What else? Okay, and here's where it sort of gets more interesting. So you can declare something called formula cells. Click even, question mark. And that is constructed with cell equal function. So I think you can say even, question mark, click. Hope I got that right. Then you can render that to even... So there's a sort of a templating language in there that works with a text macro. Did I close all my... Yeah, missed one. Okay, let's see if that works. So yeah. So what happens is the click even cell is called a formula cell and it depends on the click cell because it uses the click cell in the expression. So Hufflon or rather Javelin figures that out and knows it will update click even automatically when click changes. Notice we only change click. I mean, in our functions, we only update the value of click and click even is calculated for us automatically. Just like in a spreadsheet, if you have a formula in a cell and you change one of the dependent cells, the value of the formula gets updated automatically and that is exactly what they were going for which I thought was a very nice simple analogy if you're building a not too complicated website like I was doing. Okay, what else? You can have further, like, more complicated stuff like colors that depends on the click, the evenness of the click. So maybe color is a cell equal if... Oh no, click even, red, blue, otherwise red. Oh, sorry, thank you. Then we can style the text. Style, cell equal, stir, color, colon, color. Something like that. Fingers crossed. So the property of the text, the color property depends on the evenness of the value. And what else? Making a sequence. Oh, this is where it gets complex. Okay, so we can also track the history of the... Unfortunately, it doesn't do that for you automatically, the history of the values. You would think that it does record the history, but it doesn't really, but you could do it yourself. So this part is going to be... The part I always forget. So I'm just going to cheat. Okay, it has to be a cell, right, forgot. Okay, so history is a cell that initially is the empty vector. And then you can... This is a half-long function, add watch, that it's called whenever the value of clicks change, but then this is the sort of the var that is going to be modified, and then this is the modification function. And I guess the %3 is the new value... Oh, sorry, it's the old value of the... of clicks, which is the one we are watching. We are watching the cell clicks. Oh, click. Oh, click. Why is it called clicks? Maybe it was always called clicks, and I just wrangled the name. Okay, it's always called... Never mind, it's called click now. In the tutorial, it's called clicks, but you can just mentally map it to click. Yeah, thanks. Otherwise, that wouldn't have worked. Yeah, so that's the history. And I think we need one more thing to sort of render the history, which I'll also just copy from here, because I'm lazy to type. The only thing that's a little bit odd is that for the... What happened? For generating DOM elements in a loop, the recommended way in Hofflon is to use the loop template macro. I'm not quite sure I understand exactly why that is. I think they were saying something like, the DOM nodes are not garbage collected, so if you generate them in a map, it ends up with a lot of DOM nodes, because as you can sort of see, it actually keeps updating the DOM as you change the values of the cells. So the recommended method is to use the loop TPL macro. And then it takes bindings, which is kind of like a for loop, right? Or do-sick kind of thing. So N loops over the history. It generates LI nodes, which is a formula cell with the string N was something. N, yeah. So let's see that works. If I save that. Right, so N was 0. N was... Well, what happened? Why did it disappear? Okay. Yeah. So that's just... More. Yeah. And I think the last step, the last element is just to show that you can actually... Again, it's kind of complex. I wouldn't type it on the spot. It's kind of the same thing, except we also generate a background color. Sometimes it's like a table. You might like it to alternate between two colors. So here we just use regular closure stuff. So we cycle between EE and FFF. And we create a list of pairs, which is a formula cell. And then the list of pairs is the background color and the number. And we generate the... I'll just delete the earlier one, because it's the same thing. So... Ooh, okay. I screwed up somewhere. No? Seems to be fine. Now we have to do a refresh. There isn't the color. Maybe I really screwed up somewhere. Yeah. Yeah. Which line is it? Line 27? Is it the same line? Hopefully. Yeah. So... Oh, yeah. This is because the OL had the additional two. Yeah. Okay, as you see, it reloaded, right? So you may not be able to see the background, actually. It's rather faint. It's just... So the application of styling and... I guess here you just have to be careful. You have to make sure that you use the cell-equal formula that ensures that it regenerates all the values correctly when you update the cell of the model, which is in this case just a single cell. Of course, your model can be a lot more complex, like a tree of, you know, stuff. So here in this simple demo, it's just a single number. Okay. So that's the demo, which is essentially the Getting Started tutorial. So now I'll show you the actual program that you saw just now. There's that. That's TTT, which is pretty much the same thing, except the index file is different. So... Yeah. Okay, so here you see a more complex version of the page macro, which is showing its NS roots. So you can say, you know, refer closure, require... This is a bit more complex. I needed a bit more of a libraries. So I also required my fictactole logic, which is in TTT.core. So here I'm showing the macro version of the def cell. So in saying def something cell, you can say def C, which means def cell. It's like def N. It's def f N. Yeah, it's just a macro. It's all macros, right? It's a macros. But it's def something cell something, right? So that's def cell. These are just the three lines of the program. I guess there are three input sections. Then there's the text. And then this is the slow part. So this is the def cell equal, which is the formula cell, which is def C equal as a shortcut. This is the statistics, right? The how many wins, how many loses. So this is this computation, which is actually a bit slow. Yeah. So in half-long, you can just declare, you can just return DOM nodes from functions as well. So if you have some repetitive DOM structure, you can define a function. And then just return the DOM node as the result. So here's the actual sort of the business logic where it actually does the update. So in this case, I want to actually update all the three cells, the prop one, two, and three, the three lines of the program. I want to update them at the same time. That's why I'm doing it in the do sync block. Here, I'm just going to do a reset because I want to just stick the new value, right? And I also change the text. And yeah, here's just like a small trick to do the actual update stats in a separate loop so that the DOM actually gets refreshed. So you see the please wait, and then the slow update happens later. So it doesn't block the rendering. And this is just the rest of the HTML. I guess here I'm just showing you you can actually use like bootstrap, for example. If you put the CSS in the assets folder, here it's referring bootstrap CSS using some bootstrap classes just to make things look a little bit nicer and have this two column format, which is really hard to do otherwise in HTML. What else? So yeah, I mean it's quite standard. So there's input field, which is the thing I defined earlier, actually. It's a function. It returns an input type of text box and I think this is the default value. And this is the ID of the field which we need to use later to extract the string to push to the computation. Yeah, and then the actual button that does the update, that will actually do the reset into the cell. So that means as you type, it doesn't change. It's only when you click the button. And then, yeah, so this is just to render the results, right? So using the text macro to extract the, to compose a text string that, like the human readable description and the value inside the structure, which is called STAT, which is the formula cell. So STAT was the formula cell and here we're extracting a nested structure, right? Get in STAT as first, so win as the first player, lose and draw and so on, and as the second player, win, lose and draw. So I think this is still running, right? So pretty much what you saw. I think this is still, is this is running? No, because I had to kill that to run the other thing. So let me just go back to that one. Boot. So there's also boot prod, I think, that generates the static HTML and CSS file, which is actually what I use for the actual demo. So I generate the static files and just upload them to some static hosting. So it's just basically two, well three files. I mean I have the CSS, which is essentially bootstrap.css. So doing the boot stuff, it seems like it's faster now. So, yeah, it's just this laptop is a bit slow. But anyway, once it got started, it's actually fast. That's a typical JVM problem. Yeah, okay. So basically what you saw just now, I think. So maybe just some interesting things I learned. Well, maybe not so much from the front-end stuff, but it's actually possible to design an AI in this case that never loses when it goes first. So you can actually obtain lose equal to zero over here, if you can see that. So for lose, you can actually get something like zero. Unfortunately, it's not possible to obtain both lose zero, it's not possible to obtain lose zero as a second player. So, of course, it's an interesting question as to what is the most defensive possible AI you can write in the sense that it has the smallest number of losers, let's say the sum, as first player and as second player. I'll leave that as an exercise for you to think about. Okay, so that's pretty much all I have actually, yeah. Questions? How did the kids define that? Actually quite well, I think. So for example, I actually presented, so during the hour of court, I didn't have a chance to do this because it was all the grapple. So I managed to show this during maker fair, which was like middle of the year. And we had a running contest going on where I record down, like maybe like why is the highest win for the day or something like that. And then they try to like beat that value. So whoever comes by to see this demo, ask them the key in their AI and like you can calculate and then you can see like, did you beat like the highest win for today? And you get some a small prize or something. And I think the more interesting part actually is the first part, which I didn't show you here, which is actually the interaction with the visitors. You can ask them to, so first of all you can show them how it works by you play against them, right? So they'll play like as themselves and you like be the AI, right? You simulate the computer and then you ask them to do the same thing. So you ask them to write and you ask them to simulate the AI. And then the most interesting part is then you play using the AI program and you ask them to beat it, find the, sort of find the, like find the bug almost, right? Because it's... Well... So it's pretty interesting, especially the part where you ask them to try to find a way to beat their own program, which kind of, I guess for me that was, I was trying to get the idea of like debugging, like you're finding like the weak points, right? Because we can see that, oh, there are some ways you could lose, right? Because they will think it's invincible, right? They think, oh, this can never lose, right? But then you can run it in the program and you can show up here. Actually, we found that there's like this number of ways that your program could be beaten. Could you find one of them? So that gives them a little flavor of like a debugging. Hopefully, I don't know. I mean, that's just sort of... But one thing I realized that was not so good is it's fairly opaque in a sense, how would you see, how would you improve an existing program? So if you have a program, how would you tell how you could make it better? So this format is actually kind of opaque. It's kind of hard to say if I swap the numbers here, what's going to happen? Like you can't really think about it. I mean, you can run it through this, but you know, still, yeah. This is a question regarding the popular itself. So we saw that it's refreshing the values in terms of the difference in the values. And I think the question is how does it figure out which values have changed? Is it even though it doesn't have some distance to the bottom? It's probably a listener, I think. And the refresh is probably just like a virtual DOM update. I think there was a really good talk on Hopflon, which I'll refer you to, because I'm not going to do a good job of explaining it. So I think at closure this year, Mitch and Niskin, I think, is actually from Adzirk, the people who built the boot and Hopflon. So I think what it does is actually builds a dependency graph between the formula cells and the cells, and it makes sure it performs all the updates before it calls for a redraw, essentially. So you can actually have quite a complex graph of dependencies between your inputs, the normal cells and formula cells, and it performs all the updates and then calls for the DOM update. But I seriously haven't built a really big application yet, so I can't really say it would be performant. So this, as you can see, is all pretty small apps. So Hopflon. Actually, Hopflon has changed quite a bit. So this is like version six. I was using version five. I had to change some stuff to get it to work. Actually, the other quite a bit of stuff in the last, since I checked, so there's the depth element thing, which wasn't around the last time I looked at it. You can see the live update here, which is kind of nice. So you can actually have state in, not sure you want to do that, but you can actually have state if you want in each element individually. So here, obviously, each element is tracking the start time separately, right? Yeah. What are the page-based web frameworks out there right now? What? Sorry? You know, the types of web frameworks, basically it's a depth page. Like you said, but this was easier to use because it was easier for non-designer views, which are the other ones you looked at? I looked at reagent as well. I think Isaac talked about reagent, and obviously OM and all this other stuff. So those actually seem rather complex. I mean, you have to like build a component, and then you got to hook the component up, and then the component has all these functions. They got to implement, render, and so on. So it seems a bit overkill for what I was trying to do. I was just trying to build a very simple page with a simple, like click the button and this thing updates. That's it, right? So to me, half-long was simpler because I could just express the HTML, you know, as a list structure. And then just have that, the data sort of embedded in there, and then it just updates for you. Yeah. So basically, I think if you have a complicated app, you definitely want to perhaps have components. I would think that definitely helps. Yeah. Have you looked at the front-end store? Sorry? Have you looked at the front-end store? No, I have not. Yeah. But that's not, I think it's more of a back-end. I'm not sure they have a front-end story. They did. OK. OK. OK. Right. Right. Yeah. OK. All right. Thank you so much.