Hey everyone, today we're going to go over Nintendo's financial results for the second quarter of fiscal year ending March 2022. We're going to put all of the stories here from this in one video conveniently for you guys. Before we get into this stuff though, I want to remind you, we do have a giveaway going on right now for Prime October. We are giving away a Switch OLED bundle. So obviously the Switch OLEDs in there will reveal other parts of the bundle as the month goes on. And we are also going to be donating $100 to a charity of your choice after we obviously vet that charity as a legit place to give money to. So thank you guys so much for all of your support in making these giveaways possible. To enter all you need to do is be subscribed to the channel. That being said, let's get right into this financial results and let's go baby. So we got financial results for the expenditure. This is the material provided by Nintendo from their financial meeting. So some of the stuff we're not really going to go over too much. You can kind of see that they actually are a bit down year over year. Their net sales, their operating profits, their profit ratios a little bit down. The ordinary profits a little down. Net profits a little down. Net profit ratios a little down. Everything's a little bit down year over year. But again, there's been bigger supply issues at this point than there was last year. So it is what it is. I don't care too much about this. All you need to know is even though it's downed a little bit across the board, this is still very, very good numbers and highly profitable. And one of Nintendo's most profitable years in the history of the company. At least profitable quarters in the history of the company. So yeah, Nintendo's doing just fine. It doesn't really matter that they're down a little bit year over year. And you're going to kind of see this in the consolidated sales. It's a little bit of royalty income. And you can kind of see that still where we are, the Americas, which is North America and South America, but a majority of the sales come from North America, still make up a vast majority of Nintendo's actual sales and profitability and all that jazz. You'll see Europe obviously makes up a cool 24% in Japan and then the rest of the world here at 10.5%. So yeah, I mean, these are pretty typical. This is what we know. United States has essentially been the number one market for Nintendo systems since day one. And then obviously Japan and Europe is right there as well. All right, let's go down the gross profits again. Everything's going to be a little bit down across the board. Although their profit ratio looks like it did go up 3.3 points in the percentage. Overall, everything's going to be down slightly. It is what it is. Some of this is based on exchange rates and all that. So I don't really care necessarily about Nintendo's profitability. As long as they're making money and not losing money, that's usually a good sign for the company on the whole. So we're going to kind of glance over some of these ordinary profits and consolidate a financial forecast and all this. One thing we do want to note is that we did a report earlier where we talked about how, oh yeah, Nintendo is going to be downing their forecast or like they're going to be 20%. Nikkei was reporting that 20% short of Nintendo's original forecast is 30 million and Nintendo does actually confirm this. So for Nintendo Switch Hardware, we have reduced our forecast by another 1.5 million because they originally had it at 30, they reduced it to 25.5. Now they've reduced it to 24, which is exactly what Nikkei reported. So again, Nikkei got it right, credit to them. Our shipment forecast for the second half was reduced because of the change in our production plan due to the effects of the global semiconductor shortage, which is exactly what Nikkei told us. So anyone who is calling that report false really doesn't pay attention. Nikkei, while they do have false reports sometimes, is generally pretty spot on with Nintendo. On the other hand, we revised the Nintendo Switch software forecast up by 10 million units to 200 million units based on the sales performance of the first half. So basically they outperformed their expected software sales performance. So they up their projections there while lowering the actual switch unit projections. We also modified other factors including exchange rate, assumptions, all this stuff. That stuff doesn't matter as much to us. So we get to the highlights here. Here's where some interesting stuff comes in. So hardware for fiscal year 2021 quarter to one to quarter two. This last year was 12.53 million. This year it's 8.28 million.  Now Switch has been selling out and you could argue some people were holding out for the Switch OLED. So we don't want to switch OLED sales in here. But yeah, that's obviously a drop over last year. Still really really good. Still well on pace for Nintendo to hit 20 million because they usually sell a cool 10 plus million in quarter three in the holiday period. And then you round that out with 2.3 million in quarter four and suddenly you're back over 20 million anyways. But it does look like Nintendo is probably going to fall short of the sales of last year. It is what it is. We'll have to just wait and see. Maybe we're wrong. Maybe OLED will end up boosting things. But again, Nintendo is massively impacted by supply at this moment. So you see the base Nintendo switch obviously still 8.36 last year. 6.45. And the big drop off seems to be here with Switch Lite where that is at a 56.3% drop off in sales. I think interest in Switch Lite in general has been waning for quite some time. That being said, while they sold 100.25 million software last year they've sold 93.89 million. And we have some updates on some of the software sales here as well for that quarter. So in, you know, so far anyways this this year Ledger has always covered. So we have launched sales now for that it sold 6 or 3.6 million. That is roughly about the same as it sold on the Wii. So we're people hoping that, oh man, this will see a sales boost due to all the Breath of the Wild fans. Yes and no. It is selling better. At this point it's probably hit 4 million in sales which is more than it sold on the Nintendo Wii. But also it's not like crazy sales and really falls in line with the sales increase we saw when Link's Awakening was brought over here and sort of remastered and all this for Nintendo Switch. That saw about a 500,000 or 600,000 unit bump in sales and this seems to be probably what we got in the Skyward Sword HD although we obviously don't have the most up to date figures. So yeah, there seems to be a trend here where some of these old Zelda games are just barely selling better than their original releases. Hey, you know what? It is what it is. It's still good to sell more. But yeah, Breath of the Wild has not really had an impact on reselling old Zelda games. Just something to kind of note in the back of your mind for future ports and remasters to maybe not expect massive sales well beyond what the original sold. Mario Kart 8 Deluxe continues to do really really well at 3.34 million. In fact, when we get to the actual overall sales of Mario Kart 8 you're going to find out that it's actually now the best-selling Mario Kart game of all time. Anarchos and New Horizons moved another 2.22 million. Pokemon Snap, by the way we have sales in for that. That's 2.19. You'll notice the asterisk here. That is because it does not include sales from Japan because Nintendo did not publish the game in Japan. There is 18 titles to date through fiscal year 2022 that have sold at least a million units. 14 of those are Nintendo and four are by other software publishers, so third party. So yeah, unit sales for the entire Nintendo Switch family to climb by 34% year on year to 8.28 million that breaks down to sales of 6.4 million. Switch 1.82 is a Switch Lite. You guys can kind of see all the figures here. Slowing on down, we got Nintendo Switch hardware sell in an outlook. Anarchos and New Horizons drove hardware sales significantly in the first half of fiscal year 2021. First half of fiscal year 2022 was down from fiscal year 2021 but exceeded fiscal year 2020. So what they're trying to tell you is things are down compared to a record breaking year last year but they're still well ahead of two years ago. Even after the modification, second half of fiscal year 2022 is expected to be at the same level as fiscal year 2021. So that's pretty cool. Scrolling on the list, we can see a little update on digital sales. Obviously there was also a slight decline in digital sales as well but nothing too bad. It's just more so there wasn't the big animal crossing kind of games in there to push things like crazy. So we go by million seller first party list. Obviously we have a Scarlet Star here. You know these numbers by the way are in the million. So it's 3.6 million. Mario Kart 8 Deluxe has sold 38.74 million. Animal Crossing New Horizons has sold 34.85. Pokemon Snap at 2.19. We have Ring Fit Adventure at 12.21 million. Ring Fit Adventure, baby. Likely going to hit 15 million at some point. That's awesome. Mario Kart Super Rush. Yeah, didn't exactly break records. But hey, it did do 1.94. That's pretty good for a Mario Golf game. We have Super Smash Bros. Ultimate at 25.71 and we'll go look at the full top 10 here so you guys can get an idea of the order because these are not in order. Super Mario 3D Whirlpool's Bowser's Fury has sold 7.45 million. We have Breath of the Wild here at 24.13. Super Mario Party at 16.48. Although I expect those sales to fall off with superstars out. So yeah, we have Pokemon Sword and Shield at 22.64. We have Metopia at 1.37. Good on Metopia to become a million seller. Super Mario Odyssey at 21.95. And then Super Mario Bros. U Deluxe at 11.48. So that's kind of all of Nintendo's first party slash second party sort of games that the Pokemon is technically owned by Nintendo but also it's not really developed by Nintendo. If that makes sense. Alright, so moving past some of the sales stuff down here these are some things that I really want you guys to take a look at here. So this is a very important part of Nintendo's financial briefing every time because if there's game delays this is where you would see those game delays. So if there's like a game that was essentially announced for next year but has been delayed and pushed to 2023 they will talk about it here even if it hasn't been like announced in another form. So if you're wondering like is Breath of the Wild still going to come next year? Well, let's go through this list. So this is from April 21st through September of 2021. Sorry, this is just the current games that came out. I'm sorry, the list we want to look at is actually this one. These are the ones coming in the future or you know have already come out technically but are after the publication of these. Also we know the OLED model launch Metroid Dread. We all know about that. Mario Party Superstars. We got Pokemon Brilliant Diamond, Shining Pearl, you know, on 11 at 19. We have Big Rain Academy, you know, coming out on 12-3. Pokemon Legends Archies on 128. So no delays there. Kirby in the Forgotten Land, Spring 2022. Again, that's looking good. Splatoon 3 still listed for 2022. We got the sequel to the Legend of Zelda Breath of the Wild still listed for 2022. Mario Plus Rabbids sparks a Hope for 2022, Bandit 3 for 2022, and then Metroid Prime 4 is still TBA. So essentially nothing has changed. They obviously publicly announced the delay of Advance Wars 1 Plus 2 Reboot Camp, which is interestingly not on the Japan list. Although I think it is over here, yes. It's still here for Spring officially, even though the eShop is listed April. It's here for Spring officially and for the United States and Europe. So Triangle Strategy as well makes that list because Nintendo publishes these games in some regions. So here's the thing. It looks like nothing's really been delayed. So if you want to hold a Hope, the Breath of the Wild 2 is still next year. Hey, guess what? There is no reason at this moment to think otherwise. Plans have not changed on any of the games outside of the game, one game that was announced to be delayed. So hey, pretty cool. You can see Nintendo's got a pretty strong lineup for 2022 already. These are obviously dealing with some third-party partners and publishers. You know, they make games. You can see FIFA on here and all this. We're not going to go too much over this stuff. But yeah. Now they got all the supplementary information. Let's head on over to this. So this is the Mario Kart 8 Deluxe at 38.74. So I mentioned it is now the best-selling Mario Kart of all time. So let's figure out by how much. Go over to Wii. You see Wii Sports is here. Mario Kart Wii. Oh look, 37.38. 37.74. So it's about 1.4 million units more and it's going to keep going up. It's going to cross 40 million. That's huge. When you look at this, you know, the only game that beat it on Wii was Wii Sports, which was packed in with the Switch. Now, or packed in with the Wii. So yeah, that's pretty crazy. I mean, these sales in general, I mean, look at this. 37.38, 33.14, 30.32 for Super Mario Bros. Wii, Wii Play. Like these are some pretty crazy numbers, right? Then it starts to drop off of it. Well, that's what 1, 2, 3, 4, 5, 6 and then the packing game. So 7, 20 plus million selling games on Wii. Nintendo's best-selling home console ever. Well, probably till the end of this fiscal year. Look at Switch. 1, 2, 3, 4, 5, 6, almost 7. Switches almost matched it and Switch isn't even done. So yeah, you want to know how crazy games are selling on Switch for Nintendo. They're doing Wii numbers, actually doing better than Wii numbers in general. The only reason we don't see it at 80 million is because it isn't like a packing game. So yeah, pretty crazy. It's pretty interesting to see Animal Crossing New Horizons still sort of keep pace with Mario Kart 8 Deluxe. Obviously not selling quite as much, but still. I mean, who would have thought Animal Crossing of all games like 20 years ago was going to end up being potentially Nintendo's second most important IP behind something Mario related. Super Smash Resultant. Who saw that being a 20 plus million seller? Maybe it's 30 million at some point. Breath of the Wild. Zelda's never even sold 10 million. We have a Breath of the Wild Zelda game here at 24. Who saw that? Now Pokemon being up here. Yeah, we actually haven't had a Pokemon game hit 20 plus million in a while, so this is actually impressive. But still, it's not as shocking to see Pokemon get up there. Mario Odyssey getting up there is really, really good. So this is a really good list. We'll go through the rest of this top 10 quick here. You can see there's Splatoon 2 in there, which obviously didn't really have much sales on the chart. Splatoon 2 sales are kind of done now, which to be expected. People are kind of waiting for Splatoon 3. And there's Ring Fit. So think about this. You essentially have to sell 12.5 to 13 million units to crack Nintendo's top 10. I keep thinking like how many games does Nintendo have enough to do that? I mean, if Splatoon 3 grows past Splatoon 2, maybe Splatoon 3 could do it. Breath of the Wild 2 could probably get on this list, at least based on these sales on Breath of the Wild. So I'm very curious how many more games Nintendo has that can actually change what's in this top 10. I guess time will tell, you know? So essentially that's really it for the main story. I think I had a couple stories here from Nintendo Life. Yeah, this is the reconformation. We talked about that. Just to make sure that I go through everything. Yeah, everything looks like we pretty much covered all these stories here that I had queued up. Well, this is one that's interesting. Just to talk about in terms of home console sales, because remember, Nintendo Switch is considered a home console by Nintendo. And they do list it in their home console sales. What's interesting is obviously Nintendo Switch already has the second most amount of software ever sold in a Nintendo platform. That's really, really cool. Although one can argue this 61 million for NES but selling 500 million software is really, really impressive. Because we obviously almost sold a billion, but had like 40 million more in sales. So I find this number to actually be really, really impressive. But the Nintendo Switch is right here. And this 92.87, they're going to pass the Wii this year. They're going to pass it in the next quarter. The third quarter is going to pass Wii. Nintendo Switch is about to become Nintendo's best-selling home console of all time. And the question is, where can it go from there? You know, can it catch up to some of the handheld stuff? Like if we go over to the IR information here and pop on over to top-selling video game systems, you'll see it already passed 3DS. If you look at the handheld side of things, DS is obviously Nintendo's best-selling system ever. It's passed Game Boy. Game Boy Advance, sorry. Next up is actually Game Boy. I think it's pretty safe to say it'll probably pass Game Boy. The real question is, can it become Nintendo's best-selling platform ever made? And who would have thought, you know, back in 2017, we'd be talking in 2021 about the possibility of Nintendo Switch being the best-selling system in Nintendo history. Now, it does have to get past 154 million units, which, I mean, that's no easy task. So we'll see if Switch can do that. It's probably going to be, let me see, if it gets to say 105 to 108 this year. You know, that's probably still going to take at least another three to four years to do. And we don't really know how long Switch is going to be around and sold for, let alone be popular for. So to imagine that in 2024, Switch is still moving like 20 million units is a little, I don't know, probably a little wishful thinking, but on Nintendo's part anyways. But yeah, this is good. Nintendo's got great sales. Everything's looking solid and it's hard to really be disappointed in any of this stuff. You know, pretty much everything is sold well. And now we just await because we're not going to get official numbers for Nintendo for Switch OLED or, you know, say Metroid Dread.  It deserves to be. Maybe it's the best Metroid game ever made. And people are really curious how well did it actually sell? We're not really going to know for now another three months or so. Like, you know, we're not going to find out until what? Let me see. It's November now, so December, January, February next year. You know, we'll maybe finally find out about this maybe end of January, depending on when they want to post the numbers. But I'm pretty sure it's going to be a bit here. So yeah, we'll have to wait and see. I'm really hopeful for Metroid Dread. And we'll have to see a Shimagawa Tensei V and the rest of the games do from this holiday period. So yeah, it is what it is. Thank you guys so much for tuning in. I am Nathaniel Roblojans from Nintendo Prime. You guys are amazing. Be sure to enter that giveaway by subscribing to the channel. And I got one more bonus video for sure coming later today, if not another news video, a standard news video. But we'll see. We've got to talk about something that I said yesterday that, you know what, we just got to have some fun with it because let's just say I might have lost a little bit of my Zelda gamer card last night. But we'll talk about that a bit later today in a rather fun manner. Because guess what? Folks, I ain't perfect. I make a lot of mistakes. Sometimes vehemently make some pretty blatantly bad mistakes. It is what it is. I got no problem comping to it. You know, it happens. Catch you guys in the flip side.


Welcome. I'm Jeffrey de Smit and I'm going to show you how to use artificial intelligence in Kotlin. More particularly, I'm going to show you how to use planning optimization AI, which is one of the most profitable areas of artificial intelligence, I would argue. So let's take a look at how we're going to do that. Let's get started. And so I'm going to build you an application from scratch and more particularly I'm going to build you this application from scratch, where as we press the solve button over here, it's going to assign these lessons, such as English, chemistry and math, to time slots and to rooms A, B and C and so forth. And we're going to make sure that no student has two lessons at the same time, no teacher has two lessons at the same time and so forth. So we're going to build some constraints into that and we're going to use an AI algorithm to scale that for us to do the hard work for us. So you might wonder why is this a difficult problem? Well, imagine we have four lessons here, math, chemistry, French and history. We need to assign these to these four slots, room A, room B and those two time slots. And we need to make sure that math and chemistry, which are being taught to the same student group in the ninth grade, are not happening at the same time, of course, because those students cannot be in two places at the same time. Same thing applies for French and history, two different lessons, but again the same student group. And also chemistry and French are both taught by Marie Curie, so they have the same teacher, different student group, but the same teacher, which should also not be happening at the same time, of course. And so we're going to write a Kotlin application and this Kotlin application will give this problem to Optoplanar and Optoplanar will solve this. So Optoplanar is a constraint optimization engine, which I'll be explaining a bit more about later. And so this is the solution. Now we can see that the ninth grade can follow both the math and chemistry lesson, the tenth grade can follow both lessons, and of course Marie can actually teach both lessons to first French and then chemistry. So that's the challenge, that's the AI algorithm, and we're going to use an AI algorithm to solve this for us. Now these kinds of planning problems are all across the world, and so we're going to use Optoplanar to use it, and you might, and there's more of these kind of planning problems. For example, when you're scheduling equipment such as hospital beds, rental cars, cat scanners and all kinds of other things, the more you can optimize those kinds of schedules under the constraints when people need to use those things, and under constraints in which combinations you might have them, you can actually improve the utilization of those things. So basically save a lot of money and also ecological footprint. Same thing for job shop scheduling, when you might manufacturing things, for example cars, furniture or books or things like that. Some of the jobs you can do in parallel, others you cannot. For some of the jobs you need particular resources available such as machines or people, and with particular skills or abilities, and you need to make sure that that all fits into a plan that actually is executable, a feasible plan, and you want to reduce the mixpan, again, to improve efficiency. In other cases, the vehicle routing problem, a very famous problem, where we need to assign a number of vehicles to drive across the country to a number of locations. And we decide which vehicles goes to which location and in which order they do that. Now we have this in production for tens of thousands of vehicles, for example for technician scaling, and what we saw is we could actually, over the old system, over the non-AI systems, or more immature AI systems, we could actually reduce the drive-all time year over year by 25%, 25% less driving time. That resulted in massive financial savings, of course, as you can imagine, as well as massive fuel consumption reductions, which saves over 10 millions of kilograms of CO2 a year actually in that case. So vehicle routing is definitely one of the most profitable AI cases you can solve. Then there's bin packing where we are assigned process to machines or other kinds of bin packing, and there's also employee rostering. This is one of my favorites. It's basically assigning people to shifts and we need to take into account the wishes of those people as well as their skill sets and their affinities. The goal basically is to make them as happy as possible, given of course the constraints that our hospital or organizations or whatever the case may be still needs to keep rolling. This is actually applies for any employees that are not working 9 to 5, not just nurses and doctors, also guards and any kind of standby technicians as well as and so forth, right? So without further ado, let's get coding. So how are we going to code this today? Well, what we're going to do is we're going to build this application, so a browser interface, connects Trajacin to REST service, it will be a Quarkus application, and it's going to connect to relational database to store the information of those lessons and so forth, and OptaPlanter will optimize those. Now, just to know, we're going to use Kotlin to implement this, but you could do this in Java too. So the original requirement, you can choose whatever you like most. And also, if you are going to use Quarkus today, but you can also use Spring Boot to do this of course too, but we really like Quarkus and I'm going to show you some of the advantages of Quarkus during this presentation too. Okay, let's get started, the project setup. So we're going to set up Quarkus and with the REST service. So we're going to go to code.quarkus.io and generate our application. So I've got this opened up here already, this is code.quarkus.io and let me just increase the font a bit, not too much. Okay, and let's see what do we want. First of all, we're going to give our application a name. We're going to call it the timetabling application. I like building tool Maven, so I'm going to stick with that. And I'm going to use a REST application, yes, and I'm going to use REST-E and I'm going to expose the information through JSON to our UI and so we'll use Jackson to do that for us. So REST-EJ Jackson. On top of that, what else do we need? We're going to use Kotlin. So let's get Kotlin involved. Here we go. And let's get, I'm going to use Hibernate with Kotlin. So let's get a Hibernate with Kotlin and Panache involved too. Panache is basically some improvements on top of Hibernate to make it easier to use. So what else do we need? If you use a database, well, if you use Hibernate, we want to go to a database. So we need a database. I'm going to use the H2 database here. Why that is an in-memory database, so that's going to make it very easy. I don't need to run any other processes. I don't need to have anything, any demon running on my machine. So I'm just going to go for that. And of course, we need some Kotlin for the AI part. So we use the Kotlin AI constraint solver and the Jackson bindings as we'll send some of the information back to the UI also. I think this is my shopping list. It's time to get started. So let's generate the application. This will download a zip for us. Here it is. Time-tabling zip. Let's open it. Here we go. I'm going to extract this into my demo directory. Here we go. I'm going to show the files. Let me close up this one. All right. And this one goes too. And here we go. Here we have it set up. Well, here we have the in-blend thing. So this is the time-tabling zip we just got. There's the POM file. You can see. I'm not sure why this says yesterday. Okay. Weird. Anyway. And we're going to open this POM file with IntelliJ. So let's take a look. I'm going to open IntelliJ. I'm going to say IntelliJ, please open me a project. And we're going to use this one over here. I'm going to open this project. There we go. It's opening it up. It's loading a bit. This is, of course, in presentation mode. So you can follow up earlier. It's resolving the dependencies while it's doing this. Let's open this POM file it has over here. So this is the one generated from code.quarkus.io. It's a bit stuck. So it's probably just downloading the sources. Here we go. Yep. There it is. And so we're going to use Java 11, as you can see here. We're going to use this Kotlin version. We're going to use Quarkus 181. That's the latest version. So that's, of course, what code Quarkus.io gives us. And then here's our shopping list we had a moment earlier, which is the rest easy stuff for the rest stuff, which we put together with checks and stuff. The order is a bit strange here, though. We do have Optoplanar in there, as you can see. Optoplanar itself. And then the Quarkus integration, the H2 thing we asked for. So maybe it's basically it's all there. What do we get on top of that? We get some Kotlin sources, an example resource, not really what it was looking for. And we get some tests. I'm going to throw away the tests for today, as I don't want this video to run too late. But of course, you should be doing tests. And of course, here's how you can see how you can do it. And if you look at the source codes of this example, of the full example behind this, after you finish this video, you'll see that there's tests in there too. So please do that. Anyway, today no tests. Okay, so let's continue. We have our thing run. Let's first see if we can actually get this rolling. So I'm going to open up the console. And I'm going to do Maven Quarkus Dev. Maven Quarkus Dev. Right. And this will actually start up the Quarkus development mode for us. And during the rest of this video, I will no longer, I will not touch Maven again, right? I will not touch the command line again. I will just make changes, including changes in the POM follow any of the classes. And you will see that Quarkus will pick those up in less than a second, actually, in less than a second. So let's show that I'm here and I'm going to go to local host, right? Here we go. This is, of course, this is still set on the high resolution. Let's bring it normal. So this is our standard Quarkus thing. And if you actually look into that, we see that's in the resources, that's this resource over here. Let me just throw that away for a second, right? And refresh this. And then we get a 404, right? Nothing in there. We do say that these are the rest services available. This is the Hello World rest service that they gave us already. Let's take a look at that example resource. That's this one, a path of Hello World, right? So I'm going to rename that a bit. I want something that returns me a timetable. So let's rename this to a timetable. All right, here we go. And change the URL timetable. And we're going to say that this is not media type JSON, but not media type strings, but application JSON. We're going to do that for the entire rest resources. And similarly, I'm going to make sure that what it consumes is also JSON. So we're only going to communicate in JSON anymore. So I'm just going to specify all that here. And let's take a look now. Here we have our function Hello. And basically, it's going to, you know, we will want, and this is the getter of that, right? So we all want this to return a timetable. We're just going to do it like this. Timetable and open this up. Remove that. So we don't have a timetable class yet. So I'm just going to make a quick domain for that. Let me create a package, domain package. I'm just going to create a domain object called timetable for now. I'm another Java. This is a Kotlin thing, of course. Kotlin in the class called timetable. And we're just going to put in a name here for now. I know the name string, which is Hello, or maybe something else like High Kotlin, right? Of course, this is a bar. And we're going to use this in the timetable over here. And we're just going to have this return timetable. Here we go. Now we go back. We don't touch the terminal here. We just go back here to the browser, click refresh. And we get now, of course, look, there's this timetable thing. So let's actually go there. Let's actually go to slash timetable. And what you see is we get our JSON version of this High Kotlin thing, right? Okay. Now, okay, we have Quarkus set up. Let's do something domain specific, right? So we're going to create the timetable class diagram, the domain model, right? So in our domain model, what do we need? We need time slots and rooms. That's where we're going to assign our lessons to. And so our time slots will be for a particular day of the week, Monday, Tuesday, Friday. There's no date there. It's purely Monday, Tuesday, Friday, or so forth. And it will have a certain start time and an end time. So for example, from 830 to 930 is the first class, first time slots. And then the second one is 930 to 1030 and so forth, right? We'll also have a room object, which is like room A or B. And then of course, we're going to have our lessons, which will have a subject such as math or chemistry, a teacher, such as Marie Curie, and a student group, such as 9th grade or 10th grade. And the interesting thing is these lessons, we will need to assign them to a time slot and to a room. But that's the AI part. That's the object part who will actually assign us to those things. So we will start those out as NULL. So let's code these things in Kotlin. So here we go. We are, we will create a Kotlin class here for our time slot. That was the first class, time slot. And so our time slot has a late-init var of day of week. Now why late-init is because if it comes from the database, then Hibernate will fill it in for us. And if we create it for test data creation, we'll actually create a constructor for it. So late-init is actually a good approach here. And we're going to do the same for the start time, which is a local time. And here we go. And we're going to do this, and we're also going to create an end-time right-back as we saw a minute ago. So I'm going to create an explicit constructor for those three things. You might imagine that we could add these here on the top, but I actually want two constructors. So I'm just going to add an empty constructor too. So we now have two constructors, one to fill in these three things and one which is just empty. This is the one used by Hibernate as well as, yeah, Hibernate just for this case actually. And this is the one we'll use when we want to create, start creating test data. Okay. So let's create the room class. Here we go. We have a room class. And we're going to do very similar things here. So we're going to say a late-init var of the name of the room. And we're going to add a constructor for that, which just has that name as a constructor. The name could be room A, room B and stuff like that. And of course we're going to create a non-empty constructor again for Hibernate. Both of these things will later actually also end up in the database. But I'll worry about that. And so we'll need an ID too, but I'll worry about that in a minute. Let me just start. Let me just continue like this first. So I made a lesson class. What is our lesson? Our lesson has a late-init var of the actual subject, which is going to be string. We have the teacher. And we have the student group, which is also a string. Okay. Here we go. Now, interestingly enough, we need to assign these lessons to a time slot and to a room. So let's start by assigning them to a time slot. And so this is of the time slot type. Now, these actually start out as a URL. So while we, when we create a test data, they will not be assigned yet. And yet they will go into the database. So we're going to actually have to use a question mark here in, right? Because they can't be null. Same thing for room. This variable will be null in the beginning. It will be stored with any of those in the database. It will exist for a while until the plan comes around and actually assigns them. For test data generation, I will want to have a constructor later on, which just has these three fields here. And of course, because this is going to go in hibernate, we need an empty constructor. And in fact, we also need this one for optoptar, because optoptar will need to be able to create lessons too. We'll get back to that in a minute. Okay. Now let's hook these. So we now have a lesson room and a time slot class, but we will actually have multiple lesson instances that will need to be assigned. Matt, chemistry is a fourth, for example, multiple rooms and multiple time slots. And so we will want to keep all of that together somewhere. And that's where I'm going to make that timetable. Timetable is one data set, one school's problem, right? And your application might be handled in multiple schools, but each school has one timetable. And that's one thing that needs to be solved in a whole. It's unbreakable to be solved, actually. Well, you could partition it, but it's not a good idea. Anyway, so let's take a look what we want to do here. We want to hear in the timetable we want to have a list of all the possible time slots. So here we go. Time slot list. All right. We make a time slot list. We're going to make a room list too, which is a list of all the rooms in this school. And we're going to make a lesson as to which is a list of all the lessons in this school. Okay. Now, let's make a constructor for that. All right. For test data thing later on. Here we go. And let's also do an empty one. Actually, this is the one that opt-in really needs. This thing will not go into the database. So for them, it's not really needed. Let's go back to our timetable resource. As you can see, I made a spelling mistake. So let me fix that. Our timetable resource. In fact, if we are consistent, this T should be capital because the time table there has a capital. Okay. And here we're just going to add three empty lists for now. Not list of list, but list of, of course. I always get this wrong. We're just going to add three empty lists in there. And if we now jump back to our UI over here, to our UI, we ask for this resource. Let's take a look what we get. We get three empty lists. So far, so good. All right. Okay. So what's the next thing? The next thing is we need to add this stuff into the database. All of this needs to be database aware, right? So let's start with the time slot again. What I'm going to do is I'm going to add an entity annotation on this, you know, for hibernate, which will immediately complain because there is no ID. So we're going to add an ID. Let's let me first add the ID. The ID is var ID, the long question mark null. Why it will start out as null and then hibernate once it goes into the database will fill it up for us, but it will live a while until it actually hits the database. So this for hibernate is its ID. And we're going to have the value generated automatically. So we don't need to worry about that. I'm going to copy paste this ID approach for all for all three things that go into the database. So that's what goes into the database, the room goes into the database. So we need to add the annotation on this, right? And the lesson needs to go into the database. And the lesson into the database too. Okay, great. So now, oh, and of course, hibernate says our at least intelligent helps us here says, okay, the entity has an ID that that's the ID here, these fields I can figure out on my own because they're your strings. So that will go into var charge into database. But what about this these because you know, what's time slot, right? So you will need to tell them that this is a many to one relationship might we need to tell hibernate JPA that same for the room. It's a made to one relationship one lesson. And multiple lessons can be in the same time. So it's multiple lessons can be in the same room. As long as they're not in the same time slot in the same room at the same time, it's all fine. Okay. And if they are, we still need to be able to represent it in the database, just not a feasible schedule anymore. So so far so good. We will not put time table in the database, but we will want to fetch it from the database.  And in this, I am going to create a repository for these things. So let's start with Java force of habit, I guess. And I'm going to create a time slot repository here. All right. Here we go. We have a times of repository. And this is going to be a panache repository. So panache, as you as you probably noticed when I selected things for hibernate, that's actually the helper things on top of hibernate to make this much easier. And so if you just say that this is for a time slot, all right, then let me just show you what we get for free out of this. If you actually didn't just say, okay, what are the methods? So all kinds of methods we get out of this, we get a whole bunch of stuff like deleting, counting, finding, and so forth, and so forth, and so forth. Anyway, let's get back to our code. So this is basically for those of you familiar with a DAO pattern, an automatic DAO force, right? We will do the same for the room and the lesson. So let me just create those two. Let me just say, okay, here we go. We're going to create one for the room repository. All right, that's again a panache repository for room this time. Here we go. And we're going to create one for the lesson, the lesson repository. Here we go. Okay, forgot to click the right thing there. So here we go. And that's one for the lesson, right? So now we have those, we can actually ask if we have an instance of these, we can actually just ask, you know, give me your find methods, give me your delete methods, your add methods and stuff like that. We still need to expose them to be able to use in dependency, inject them into other bits of our like in the table time table resource. So we're going to have to add that these are application scopes, right? And so the lesson repository, the room repository, all of them are application scope, which basically means there's one instance of them. And we can just, and then we can reuse can inject them and things. So we will, for example, inject them in the timetable resource over here. So here we're going to say I'm going to inject the late any bar of the timetable repository time slots repository. Here we go. All right, which basically means that this time slots repository, which we created here, which is application scoped will be injected in here, and we will then be able to use that over here. So here we will be able to say, here we need to give a list of time slots, right? So we can just say that repository and just list all of them, right? We should probably also sort them, but I'm not going to do that right now. So now we actually create me, we actually give back the timetable with all the time slots from the database and not just an empty list. Similarly, we will do, of course, an inject of the room repository, which is a room repository. Here we go. All right. And over there we will again do a list, list all of. All right. So still no compilation error. So that's good. And we will inject the late any bar for the lesson repository, not sure why it's again proposing the other one, but anyway, please give me a lesson repository. And we're going to list all of that too, right? Okay, so let's see if that still works. We go over here, we crash the refresh button, the refresh button, internal server error. No pointer exception. That doesn't sound quite good, right? So why is that? Um, the null point reason. Interesting. Because we don't have our database setup yet, of course not. So we need to go into the application properties and actually make sure that our database is set up. So we need to tell Corkus, okay, Corkus, I would really like to have a data source of the DB kind of for H2. And I would really like that data source. So I need to give it a gdbc url and the gdbc url. All right, it's going to be gdbc h2 because we're using that type of database man because we're going to use it in memory. And I'll give it a school time tabling name that matters less. And the problem is that we need to also make sure that hibernate generates the timetable for us, right? And the schedule, the DLL schedule in the database for us. So what we're going to do is no, we're going to say, okay, database, database, um, generation is drop and create. So let's take a look now. Let me go back to over here with fresh refresh. And that looks much better, right? So now it actually goes to the H2 database, fetches all of the types of the rooms and lessons in there, which are none brings those back and gives us this resting. So we're actually now already touching the database. That's that's a good thing. Now, let's throw some stuff into the database to actually get some test data in there. So what I'm going to do is I'm going to add a package called bootstrap, right? And in here, I'm going to add a demo generator. I'm going to call them class. Demo data generator has a good name. Here we go. And now my demo data generator, it will, we're going to make it application scoped, just like repositories, which means we'll only need one of them, right? And what we're going to do is just like the timetable resource, I'm going to inject all of these repositories because we'll need them to actually add those testing, those test data in there. So I'm injecting the time slot of the room and lesson repository in here. So now I'm going to create a function here to generate the demo data. And a bit like this, but I should spell better generate. Okay. And we're going to have this of doing observes of the startup events.  And if it scores starting up, then please execute this code. And so, and when it starts up, we can actually now add some, some test data in there, right? Now, so what we can do is we can say, okay, time slot repository, persist. And here we can add a list of the time slots to persist and so forth, right? So instead, but as it will take a while to write all this, what I'm said, I'm going to do is I'm going to, I have some help profiles here. And one of them is for the demo data generation. I am this is, this is the one I'm going to just copy paste this stuff in there. And you can see also should make it also transactional. So let's let's do that in a second. So I'm going to just copy this in there. I'm going to cheat a little bit because writing all this is not interesting for you to follow up. So I'll just throw it in here. All right. And I'm going to make this transactional. Here we go. So let me add, we'll fix some of the import statements, right? And let me walk you through the code I've just added, which is going to look very familiar, I hope. So what, what did I just add? I said, okay, create me a time slot list, a mutable list, please. Shouldn't actually, doesn't actually have to be mutable. But anyway, yeah. And here's a list of all the time slots. So we're going to create for time slots for two days, Monday and Tuesday. And we're going to have five hours on a day, the first time open 83930 and so forth. I'm also going to create a room list. So in the end that persisted of course with the persist method I just shown you. We're going to add a room list with rooms A, B and C.  This is why I actually used the mutable list, but you can argue you can just throw it in one list, it would be more efficient. And at this part, let's not do that. That's already signed some of the lessons to give an idea what will happen if you do that. So let's just persist these. Okay, let's see how that works out. If you go back to our UI and we just click the refresh button. Again, I haven't touched. I think then it actually turns out. So yes, we have all our time slots lists. You have Monday, you know, all 10 of those. We have our rooms, rooms A, rooms B and room C, and we have our lessons. Now this is pretty ugly to actually look at, which is Jason of course. It's not really meant for humans to read. So let's see if we can make this a little bit more pretty. Let's see if we can make it solve them. So what we did, so now we need UI. So basically, we need to add to add this part to our REST application. The problem is our UI, well, we could write in Kotlin of course, but then we need to generate JavaScript out of that and so forth. I'm just going to use a static JavaScript file. That's the easiest approach because, but the thing is, I'm not really a fan of Java writing JavaScript. It's not type safe. So when I write JavaScript, this happens, right? I start, you know, saying a couple of things that are really not suited. And this video would become R rated if I actually would code this JavaScript part for your life. So instead, I'm not going to do that in public. So what I'm going to do instead is I'm going to take a little shortcut there. Here's my helper files. I have 40 UI, I have a couple of helper files here, which is really just an application. A client UI already, just a client side, right? So a JavaScript file, an HTML file, and an opt-up planner logo to show in there just to make it a bit more interesting. So where am I going to drop this? Well, I'm going to go to source main resources, meta in resources. And if I drop it in here, then they will automatically show up, right? Now let's take a look here. So we have our, this is the JavaScript file. You can see it's a typical JavaScript. I think I've shown enough. Otherwise, for, otherwise people might run away. And then here the HTML file. Now in the HTML file, I am using a bit of Twitter bootstrap in there. And so I want to use some font web jars in there. So we need to add these web jars to our .xml here. So I'm going to go into the .xml. I'm going to add some dependencies there. And once I do, let me scroll to the bottom here, you'll see that I will still not restart Quarkus Dev, because I will, I intended never to do that. So in, let me just add the dependency I want to add. So these are the ones I want to add. I'll copy them and explain them to you. So these are the ones I want to add. First of all, I'm going to add an extra Quarkus one that I didn't check on the beginning, but I could have, which is the web jars locator, which allows us to use these web jars and automatically expose them to be used from HTML. And then these are the actual web jars that I'm adding. That's Twitter bootstrap, jQuery, font awesome, and moment.js. Moment.js is something to do with time on the client side, which is important when you're doing scheduling like tasks, right? Fair enough. Let's see what happens if we now go back to our local hosting, and we go to the root of that and we do refresh. Here we go. Why is it? Okay. So a bit takes a second longer now. And here it is. Right. And I still have it on 100%. So here it is. Right. So what do we see here? We have our rooms, which are coming from the database A, B, and C. We have our time slots. We have our own assigned lessons. This is actually quite perfect, right? Let me just prove you that this is coming from the database. You might not believe this, right? So let me change this room A into room something else, right? Let's go to bootstrap here. Let's change this room into room K from Kotlin, right? And again, I just go here, I just click refresh. And now he doesn't have to do the POM stuff anymore. So it goes a bit faster. And this is now room K, as you can see, right? So it's that easy. I think it's time to add a little bit of artificial intelligence in this, because what we want to do now is we want to click the solve button. And when we do, we get a 404 because of course that stuff doesn't exist yet. All right. So we want to make sure that when we click the solve button, these undersigned lessons, math, physics, chemistry, and so forth, get assigned to these three rooms and to these time slots. So let's get back and let's see what we can do to make that happen. Well, we're going to go to the timetable resource here. And we're going to add a post for that for that solver to do for that solve. So we're going to add a solve function. And in here, we're going to do the magic, but actually do the solving rate. So what do we need for this? We need optoplanar for that. So let's go a bit further in our presentations. So we've just added the database. Let's do some AI planning optimization. So what we do that, we're going to add optoplanar. And optoplanar needs to know what it can optimize. So this is our domain mode. Optoplanar needs to know that it can actually change the lesson class instances. So those 20 lessons we have there in our test data set. And it can, in particular, it cannot change the subject or teaches or cannot decide who's going to teach which lesson, but not in this case at least. But it can decide for each of those lessons when and where those lessons will happen. So the time slot and the room. So what we're going to do is we're going to add a planning annotation on the lesson class because there's something in there that will change. And more particularly, is the planning variables that matter. That's the time slot and room fields. Those two fields will change. So those are the two we were going to add to the planning and a variable annotation. And any class that has a field that has a planning variable annotation must have a planning entity annotation. So these start out as NULL. And after solving, they will be non-NULL, right? Not NULL. So let's do that in the code. We go to our lesson here and we're going to say, okay, it's not just an entity, but also a planning entity. So this is for the database, for Hibernate. And this is for Optoplanar planning entity. And we're going to tell them, okay, so this one is a planning variable. You have to figure out in which room this goes into. And also for the room. Now the problem is that Optoplanar needs to know which time slots can I choose from. It cannot just create new time slots. It has to actually have a list to select time slots from. Same thing with the rooms. It needs to know that the rooms are room K, B and C there, right? So what we're going to do is we're going to give this a value ref.  And this will map somewhere else to list of time slots. And what we're also going to, what I'm also going to do is, and of course this is actually multiple fields. So I'll have to like this. And the same thing for the rooms. Somewhere we'll need to get the room range. Okay, fair enough. Where are those? Where will we get those things from? Well, we'll get those from the timetable class, because this actually had a list of all of the time slots, the list of all of the rooms, and so on. And so this is the ideal place to get these from. So here we're going to tell, we're going to say, okay, this is the data set. This is the problem we're going to give to Optoplanar. It's a timetable problem. So that basically means that once the lessons are assigned, it's also a solution. It's not just a problem, it's also a solution once these lessons are assigned. So we're going to give it the planning solution annotation. And so it needs to pick from these lists of time slots. So this is a value range provider, which actually provides all of the time slots that Optoplanar can choose from. And we need to give that a name. And the name is of course the time slot range. All right. And let me take a look here. This is the ID. So, and similarly, we are going to do the same for the room list. Here is a list of rooms to pick from. Optoplanar also needs to know where the lessons I need to assign, right? You can't just say any kind of lesson that's in memory. Actually, you need to get the reference to those. So we need to tell them that this is the planning entity collection. So that's actually a list or a collection or an area of all possible playing entities that it needs to assign, right, in the time table. One more thing we need to do here. Once Optoplanar goes through these lessons and by one and one by one starts assigning these lessons to a time slot and to a room, picked from these time slot ranges and room ranges, which are over here. All those lessons will be assigned. And that will actually, it will need to somehow score that solution. Tell how good that solution is. Tell if that solution is feasible or not. And if that solution, when the solution is better or worse. And we will represent that by a score, right? Let's call the score. And particularly by a hard soft score, which means hard constraints need to be fulfilled and soft constraints should be fulfilled as much as possible. So, and we're going to start that score out and URL because in the beginning nothing is assigned and we don't know the score. And Optoplanar will actually for us assign them and also tell us what the score is of how good he done his job. So it's like a student who actually grades himself. Okay, interesting. So that's the model side. Besides having the domain, we need some constraints too. So I'm going to add a package here for the constraints. And the constraints, well, I'm just going to add a single constraint provider. So that's something where we will define our constraints in constraints. There are like no to teacher, no teacher should have two lessons at the same time. No student groups, which have two lessons at the same time, things like that, right? So we're going to call the Scotland class the time table constraints provider. And that one will implement constraints provider. Here we go. Provider. And of course, I will complain because there are certain methods that are implemented. And we're just going to create an empty one for now, right? I think it's like this. Let me just check for a second. That's, that's, that's this. So we're going to create an area of just going to create an empty area for now. In a few minutes, I'm going to add constraints in here and we'll see how the solution actually behaves. The artificial intelligence actually changes its output based upon the constraints we will add. We'll do that in a few minutes. Because first of all, we need to make sure that all of this is actually hooked into our solving thing. So when we press the solve button, this is called still nothing happens. So we need to make sure at that moment in time, we're actually solving. So what I'm going to do is I'm going to do an injection of something called a solver manager. And that's what uses to, that's what you used to actually solve a problem. So that's for a timetable. And we're going to, and it also has a, you can give it multiple problems. So it has two generic types. One is the type of problem we're solving. That's our timetable problem. That's the one that has a planning solution annotation. And then the other thing is if you want to give it multiple problems, this is the, then we can differentiate them by some sort of idea. And this is the type of the idea. So I'm just going to put along here. Okay. So fair enough. Here we have our solve methods. So what are we going to do when we have our solve methods? We're going to say, please solve this problem. But we want to see as optimal finds better and better solutions, we immediately want to see those in the UI. We don't want to wait until it's finished. We want to see the intermediate results. So I'm going to actually use solve and listen, which means give me the intermediate solutions too. Now this has three parameters, at least the overload method I'm going to use. One is give me the idea of that. So I'm just going to hard code that to that problem ID one, because we're only going to solve one one school at a time right now. If you have a multi-tenancy approach, then we would, you know, each tenant would have their own idea. And we would give that to there. And then I need two functions. The first function is to actually find the timetable. So what I can just do is I can say, okay, this method, if it's transactional, let's do that right now. Then I can just say, okay, this get timetable. That's the first method. And then this will add. So the first method is to load the problem. The second method is to save the problem. So this is the one that I'm going to create a function for, function save of a timetable. Now it's important to understand that, well, this won't work to find the get timetable, because it needs to find by ID. So instead what I'm going to do is I'm going to find by ID here, I get an ID, a job ID, which is that long, this is that one lot one out there. And so I can just return, get timetable. That's actually good enough for me. And this will one will return a timetable. So now I can use this one. So this is just to wrap around that function, which transforms it from actually having to knowing the ID, just getting the one timetable that we have. Okay. And maybe solar manager should support such a function to just make it easier. So we don't need to write this boilerplate code if, if you don't do multi-tenant solving. That's interesting to think about. Anyway, once we have our timetable available here, then this will be called every time optomor finds a new best solution, in which case we will want to restore those lessons as particularly those assignments of time shop and so forth. So what I'm going to do here is I'm going to use a for loop in of the timetable lesson list. All right. So for each lesson in that lesson list, I'm going to look for the attached lesson. If you're familiar with JPA, that basically means that we're going to go into the lesson repository. So these lessons are not attached anymore in JPA terminology, which means that any change we do to them do not get stored into the database. So what I'm going to do is I'm going to find by ID the, the lesson that is, you know, the lesson that's assigned, right? And then it's a typist match, of course, I need to make sure that it is, it's not safe. The ID itself can also be known. So, but I know that one optomor gives us a lesson list that each of those lessons in that lesson list will come from the database, from the find by ID method, and therefore will have an ID, right? So it's safe to do this check. I also know that I know that these lessons are in the database right now. So I'm just going to for now just, just, you know, make, do the if, skip the if check, which is dangerous, of course, in real life environment, especially second one, you might want to do an extra check on that and, and be able to deal with that condition if that's the case. And luckily, Kotlin warms us for that. So then we're going to take our attached lesson, we're going to take the time slot. We're going to sign that to the time slot of our lesson. We just, you know, we're saving, right? We're going through all the lessons to save them. Similarly, we're doing the same for the room. All right. Okay, here we go. And now we're finished. So now what happens is when we click the solve button, it will call solve and listen, which will first load the problem by our find ID, find method, we'll just get the time table from the database. And then when we're finished, it will put it, it will save the database in, it will save each of the lessons of that time table in the database by basically just saving the time slot and room assignments. Let's take a look at how that works out. Okay, it didn't crash. That's a good thing. Well, it actually probably did crash because where is my test data? Let's take a look. Okay, we're getting an error here. So that happens. And the nice thing about this is that when this happens, you are getting a nice thing. So here is it's a good warning, good error message that which helps you. And here it says that the solution class must have one member with the planning score annotation, because I forgot something. Opto planner needs to know that this core is actually the score for this thing. And it needs to know it needs to have an annotation for that. And I forgot to tell him that. So let me just tell him that. All right, here we go, planning score. Let's go back here. And let's hope this time it's better. Yes. So it starts up at least, let's click the solve button. What will happen? Not found. Okay, that's not good. Of course, we need to make sure that this post method over here actually has a path. So that's a path there called solve. Because if you look at the solve button, it's actually going to go to that dash solving. So let's see. Now it's actually solving good. And again, another error. No worries. Let's take a look at what the problem is. Okay, the problem is that the context is not active. That's because it's not a transaction. So the save method should of course also be transactional. Right? So third time's a charm. I'm sure it is. Let's try again. Okay, let's take the solve button. Does it actually assign these things to a lesson? And it does.  So it actually did solve it. But there are no constraints yet. So opto plan is going to do whatever it wants.  So it's time to start adding a few constraints into this. So when we go back, we go back to the constraint provider here. And what we're going to do is we're going to say, okay, I want the room conflict constraint. And I'm just going to give back the constraint factory in that. And I'm going to create this method, right? So this will create a constraint for us. So you can do this in a simpler form, but this is actually a form that will give you incremental score calculation, which is going to be a huge performance gain, right? And opto plan will look at many, many combinations. So any combinations of the solution, it will look at any combinations of lessons being assigned to rooms and times. So it will look at, you will need to score those. And then it will try to find the best one out of those in a very, very smart way. It will not look at 1% of the solutions, not even 1% of the solutions, because the search piece is so high. But it will look in a very intelligent way into lots of solutions to come up with in as little time as possible, the best possible solution. And this API will actually help drive up the speed for that so it can look at more solutions, which is always better, of course, more solutions per second. So what are we going to do? It's very much like SQL. We're going to say, I'm going to look for a lesson. So I'm going to look for a lesson. And let's just say we have a simple version. Okay, this is a bit to correct syntax, of course. And then what we're going to say is, okay, let's just say if we have a lesson, we're going to penalize that. And then we can say what kind, what is it? It's a room conflict. And we just say, okay, it's a hard, soft score, one hard, for example, right? We don't want this to happen. This won't give much effect. And by the way, this constraint factory is empty. This won't give much effect because it will basically select every lesson. And for each lesson, we will use a point. But no matter how we design those lessons, that will actually not make any difference. So that's not what we want. What we want to check is when we have a lesson, and we join that with another lesson, just like in SQL, right? Now we have two lessons. And then for those two lessons, they actually have the same, the same time slot, right? And also the equal, the same room for there in the same room at the same time, right? Then we have a problem, right? So then we have a conflict. So every time optoplanar assigns two lessons in the same room at the same time, it's going to get hit on the head. It's going to this penalized method will will hit it on the head and it will get a hard constraint, right? So let's say look what happens if we now go back to the application. Again, just a second later we can test this out. We press the solve button and this looks a lot better, right? Because now every lesson is assigned to, I mean, there's no two lessons in the same room at the same time. Is this a feasible schedule? It's not. Why not? Well, okay, let's take a look at Alan Turing. So let's look at the teachers here. Alan Turing over here has to has to teach two lessons at the same time on Monday morning. This is not a feasible schedule. So let's go back to the code here. And let's actually also check for teacher conflicts. So I'm just going to duplicate this code now for so it's a bit faster. So we're going to call this teacher conflict, right? Same principle. When we have a lesson and another lesson which are in the same time slot, but now for the same teacher, then we're going to penalize this. Then we have a teacher conflict. Notice how these two constraints are isolated from each other. That's a good thing. So you can turn them off and on individually. And also you can, you know, work on one in isolation, which is a really, really good thing because otherwise it gets quite complex quite fast. Anyway, we've had this now. Let's take a look as if we press the refresh button and we press the solve button. All right. And we now see that room wise, this looks good. No two lessons in the same room at the same time. It's a bit strange. We have three lessons at the same time. We'll take a look at it in a minute. Teacher wise, this looks good. No teacher has two lessons at the same time. But the student group wise, that's why we had three lessons at the same time. The 10th grade has to do physics in Spanish at the same time. So again, same solution. We now also not just tech for teacher conflicts, but also for student group conflicts. So this is now a student group. And then we can simply add this constraint in there. And if we jump back to the UI here, we should now have our first feasible schedule. So feasible means no hard constraints are broken. Means that we can actually execute this plan. So room wise, this looks good. Teacher wise, this looks feasible. I'm not saying it looks good. It looks feasible. And the student wise, this looks also feasible and good. So teacher wise, it actually doesn't look good. Why not? Matt Alan Thuring, the poor guy, has to have a teacher lesson, then has an hour break and twiddle his thumbs, teacher lesson, twiddle his thumbs, teacher lesson, twiddle his thumbs. It's really, really, really a terrible schedule for him. So we can actually fix that. We can actually go back into the constraints, add soft constraints, and then Optopan will take this into account. And if you want to see that, please take a look at the source code of this. We add a bunch more soft constraints to actually improve the lives of the teachers and the student groups to improve the quality of education by basically scheduling them better. You can easily add your own. For example, no gym class after lunch, or at least try to avoid it. No three hours of math after each other on Monday morning. No student will survive that, or at least like that. So it's pretty easy to do all this. The code of this is available. Just go to the Optopan Quick Starts repository. The link is below in this video. And then you can run this yourself, or you can see how we've written it from scratch. So I would like to say thank you for listening. So this is the URL if you want to try out this code right now. You can also even build a native image of this with main quark is minus the native. That takes a bit longer. You need to have grow install and stuff like that. But that means you get a native executable. So instead of a bytecode that you need to run on a JVM. And here's the links to the projects, optopan.org, Quark is OTO, and of course Scotland, where we've written all of this thing into. If you have any questions or have data post a comment or to ask on the optopan.gov mailing list or stack overflow or something like that. So thank you for listening.


Good morning, John. I recently noticed that Days Since Hank Green Started a New Thing.com hasn't updated in 81 days. Have I been doing nothing in the last 81 days? No. So, honestly, as much as because I want to get my own head wrapped around all of this as, you know, I'd like to share what I've been up to, here's a video about what the heck I'm doing. So for a long time now, every Monday I record Journey to the Microcosmos and every Tuesday I go in and I shoot side shows. And some Tuesdays I also shoot Bizarre Beasts. I don't write any of those things anymore, I might have a little bit of editorial input here and there. But mostly I just read out loud. That's a lot of my job now. I've also been working a lot today on the Microcosmos Microscope. We did a Kickstarter for Microscope, mine is right over there. It's finally shipping out, but we are missing a piece. We think it got lost in transit, but we're shipping everybody's out and that final piece will go out when we get it, which hopefully will be soon. In the evenings I've been assembling Crash Course coins, I have a lot of coin boxes in my house right now. I'm doing that myself because it feels like a way to say thank you to the people who supported Crash Course through that thing. It's taking me more time than it would if someone else did it, but I don't know, I just feel like I should do it. I also make about 20 science tiktoks a month and about 60 not science tiktoks a month. Why I'm doing that is a bit of a mystery to me, but I'm trying not to ask too many questions. I'm always doing a little bit of prep for tangents. Sometimes that's writing science poems. Tangents is our science trivia game show podcast, it's 30 minutes long and it is so good. It's been climbing up the science charts, watching it get higher and higher is very exciting. You can start anywhere, but why not do the elephant episode that just came out because it was very good. I know I was always doing some prep for Dear Hank and John, though having Dubokie help with the science editorial part of that has made that easier. Currently prepping for an important upcoming meeting with a partner for Crash Course could be very good, but have to impress them and show how amazing we are, which should be easy because we are. Also working on Crash Course's partnership with ASU, which has given me a lot of insight into how education really functions in the US and like where it's letting people down. I'm renegotiating a contract right now, which is not my favorite thing. Also trying to figure out what to do about shipping costs generally, which have gone up a lot. I know how things are, but if our UPS male innovations rep is watching this, hey, could we just budge a little bit on that one thing? You know what it is. Also getting ready to market our second year of the Awesome Socks Club. One of the things I finished today was the list of tiktokers who I want to work with on promoting the socks this year. Thank you to everybody who's a member of the sock club. They have so far raised over $600,000 for partners in health and they're really good socks. And of course I'm also being helped by a ton of people in all of these things, who I'm all trying to be a good boss to, which involves like clearly communicating goals and values and like what ways we do things are good and what ways we do things are not so good. And also that stuff involves figuring out how to make money so that we can treat people well, which is like I'm grateful for all of it, but it's, you know, it's a lot of pressure. I don't always get it right. I don't always know what I'm doing. Everyone is still learning and like I'm a guy who isn't fantastic at focus as evidenced by this list. And yeah, John, there are also those other two things that we really wanted to do and that we wanted to have out by Christmas and that it isn't like we're going to have out by Christmas and that's a little bit frustrating, but it is what it is. They will happen eventually and they will be great when they happen and they will be greater when they happen because we waited. And am I trying to write a space mystery novel? Sure, maybe, but like that doesn't mean it's going to happen. Also this is Oran's first week of pre-K so we're like putting him at his school and it's cute and sad and scary. And I'm planning my 15th wedding anniversary. Look, it's a lot, but it wouldn't be this way if I didn't like it this way. I don't like to focus. But there is one thing that I do every single day and it is that I go and I check to see whether or not Apple is about to put those SD card slots back into the laptops. Please. All right, putting it all out there has made me feel a little bit better. Am I overwhelmed? Yes, but are there good reasons for that? Yes. And will all of these things get done? They will. Perfectly? No. But done. But done. John, I'll see you on Tuesday.


Good morning, Hank. It's Tuesday. So on Friday, Rosyana and I left the magic and awesome of NerdCon stories to head up to Princeton, Minnesota, where I raced cars on a dirt track against best-selling author and all-around awesome person, Maggie Steve Otter. So, Hank, an IndyCar driver I know once told me that in racing, the only thing more dangerous than being too aggressive is being too cautious, which is an observation that I think applies to more than just racing. And while I'm certainly an uncommonly anxious person, I don't think of myself as an overly cautious one. So I was feeling kind of excited as we arrived at the Princeton Speedway. I mean, at no point did I actually think I could win the race, but I did think I could, like, finish it without being pulled out of a burning vehicle, which, as it turned out, was overly optimistic. Took my first ever ride in a four-wheeler to my race car, which belonged to a 17-year-old, hence its number. My coach for the evening was his dad, Alan. And special shout-out to Alan's kids, my pit crew, 10-year-old Allison, and 8-year-old Aaron. My first lesson was getting in and out of the car, which, as you can see, is ridiculously difficult. Hank, I need to linger on this shot for a moment because I want you to understand how hard it is to get out of these cars, even when they are not on fire. Also, I want you to notice my excellent Eleanor and Park t-shirt, which I got at dftba.com. So Alan's an experienced race car driver and an excellent coach. He explained to me at least a dozen times that coming out of the corner, I would feel an urge to overcorrect the steering and or let off the throttle, and that giving into that urge would be a significant mistake. And I was able to remember that advice for like five and a half laps of actual racing.  And then after an impossibly beautiful sunset came to Princeton, I belted myself in for our first of three scheduled races. Maggie jumped out to a lead and she was faster than me and also a much better driver, but my car turned really well in the dirt and its power was exciting and intoxicating, and I was just trying to keep up with her, but then I thought, you know, maybe I could drive alongside of her and really make a race out of this. And then on the fifth lap, coming out of turn four, I felt an urge to correct the steering and yeah. The Speedway staff got to me very quickly, and although I could feel the heat of the fire in my back and legs, they kept me calm and pulled me out and I was fine, but I'm not going to lie, Hank. It was terrifying. But then they fixed the problem with the car and for some reason I decided to get back in it. In fact, I won the second heat. More precisely, Maggie let me win and I got a trophy and everything. And then we raced for a third time and Maggie dominated me so thoroughly that the regular pro drivers at the Speedway asked to take her on and she beat them as well.  And late that night as I tried to sleep, I kept playing the race back in my mind, me doing precisely the thing I'd been told not to, the heat of the flames against my back, my panic hands as I tried to unbuckle the belts, the smoky relief of being pulled from the car. There are of course smart risks. The proper line to run through life is somewhere between extreme caution and extreme aggression, but this wasn't one of them. That said, Hank, I have to confess that I am proud to have lost to Maggie, but not to myself. But in the end, Hank, I think I'm gonna use this occasion to announce my retirement from race car driving. I'm headed back to the grandstands where I belong. Hank, I'll see you on Friday.


So then we're already at the last talk of this first part of the post quantum session so Moving back from SIDH back to lattices So this talk is about differential fault attacks on deterministic lattice signatures so this is a work by Leon Groot Bröndering and Peter Pessel and Peter will give the talk Thank you for the introduction So it's probably not a well-kept secret anymore that many digital signature schemes are susceptible to nonce Reuse so if you sign two different messages Using the same nonce and you can then easily recover the secret key and this happened in the past A solution to this problem is to make the whole signature scheme completely deterministic So instead of using a random nonce you derive it by hashing The message M together with some secret K and that's what's actually already done in at DSA and deterministic easy DSA Now this is all nice But it also opens a problem that of differential fault attacks. Namely you can sign the same message M Here same message M twice. This means you will get the same nonce It's deterministic and then you induce some sort of computational fault after Computing this nonce. So you will have what looks like a different message So you will have a nonce reuse for different message and you can recover the key now This scenario was already explored for elliptic curve based schemes But then we have to ask you questions. Is it specific to elliptic curves? So can we do it on other schemes as well and that's of course where the lattices come in So what we do is we extend differential fault attacks to deterministic lattice signatures Namely to the lithium you should have heard of the lithium and to Q Tesla Both of which were submitted to the NIST competition or NIST call and are both deterministic Now that such differential fault attacks are possible here isn't all that surprising given that Delifium and Q Tesla shares some design similarities to their elliptic curve counterparts But there are some design peculiarities that set them apart from ECC like for instance rejection sampling key compression and it's also possible to to derive some more efficient And new attack paths like efficient exploitation of partial nonce reuse Okay, so in this work we focus on mainly the lithium Which is why I'm not going to explain it very little So you've already heard some stuff and just some things that have not been said yet But all our attacks carry over to Q Tesla as well, you know quite straightforward manner They both signature schemes are are somewhat similar Now Delifium is based on our module LWE assumption So it has polynomials with some base ring, which is at least for let's base signal Let this base group to graph cryptography somewhat small and then it works with vectors and matrices of these polynomials, so in key generation you have two vectors of polynomials with Somewhat small coefficient, so they're in a specific range and you have a random and public a so a matrix of polynomial And the public key is a s1 plus s2 So I wasn't had what hasn't been said yet in the previous presentation is that it uses determinism to protect against randomness Not only that but I'll come to that later Okay, so this is the main framework of the lithium So first what the first two is you sample this nonce y in a deterministic fashion So you can also call this the noise whatever you fancy Then you multiply it with this a Hash it together with the message to get the C and then you compute set equals y plus C Cs1 so in other words, it's a feature mere schnoi like signature scheme But what's new in Delifium or what's what's common in many lattice-based signatures is this rejection sampling so where you test if your outputs that follows some distribution and If it doesn't then you read restart this whole Signing process and in Delifium this rejection sampling is essentially just an coefficient wise range check Now Since this this this sampling of the nonce y is deterministic It's easy to see that well if you have the same message M You get the same y and this is then kind of a nonce reuse But of course you can't use a nonce reuse if you don't Have anything else you get the same output you can't extract any useful information from that So you have to change something else and you do this by injecting a computational fault So in the case of Delifium this would some look like something like this So you have one message M You sign this twice once just regularly and the second time you Compute the signature, but you inject a fault such that the nonce y is identical But that the C is something different Then you can set up these two equations set equals Y CS one once without fault once with the fault Subtract one another since Y is identical it cancels out and Then you what what you have left is a system in which the only unknown is the private key so you can easily Recover this private key. So that's quite similar to what happened in the ECC case Something about the lithium is that it uses key compression and due to this key compression. You can't easily Recover this second key part s2 But in the paper we show that An attacker can still forge signatures even if he only has access to this s1 Now, but there's one other thing we kind of forgot and skipped over and that it's And this one thing isn't that rejection doesn't only hurt in your real life, but also for our attack So what we have here is Unlike ECC or stuff like that you Sample this nonce y by using a hash from KM and some copper. It's copper. Copper is a rejection counter so this counts up and Is used so that you have a fresh Y in each of the iteration each time a signature gets rejected Now to have a nonce reuse you have to of course Use the same copper again This means that the key recovery is only successful if both the non-faulted execution and the faulted execution Accept the signature in the same iteration Now but as soon as we inject the fault We will also influence the intermediate used in the rejection Conditions so it might be that we inject the fault and due to the faulted values the signature is not accepted anymore And there unlike ECC based counterparts, so here the the fault position which Which target you effectively fault determines the success probability and we have a look at five Concrete fault scenarios so concrete position So the first one is the probably the most straightforward one you want to have a different C as challenge vector So what do you do your fault the computation of C? So this hashing operation here There what you can do is observe that In this equation set equals Y plus C as one if you have a look at the Distributions of these two variables you you'll see that well Y is is uniformly distributed in the range of plus minus five hundred thousand something and This C as one is kind of like in the range plus minus 50 or so so this means that Using just a different C won't affect set that much and since the first rejection condition is a range check on C This means that if it acts if if the signature was accepted originally then it will also likely be accepted With a different C. So this means we have a success probability of over 90 percent So but it's not only the direct computation of C that we can fault we can also fault any any result that goes into this Like for instance the computation of this W. So of the polynomial multiplication This multiplication uses the entity you've already heard of that and so the entity is a FFT over a prime field So it uses same Implementation techniques butterflies butterfly network and stuff and there if you have a look at this butterfly network It's quite easy to see if you inject a fault on the left side on the input of this Then a fault will spread to all of the output coefficients Whereas you fault on the right on the output only a couple of coefficients will be affected and the more coefficients you change the more Likely it will that that your new signature your faulted signature gets rejected So you have a success probability between 25 and 90 percent On depends on what you exactly fault, but overall of course this multiplication a larger target than the hashing Okay, then we can also fault the public key So this is loading of the a there we have two sub scenarios because this a is not to storage directly But generated from some seed and you can either attack this row directly this value or the extendable output function So and depending on what you fault you are between 25 or 54 percent But what's the what's interesting here is if you inject a fault into row you can think of yeah Maybe that could be also be a permanent fault and Finally Somewhat difference in the area is that you fault the nonce why what If we fault the nonce then the output will be different. So it's not a nonce we use anymore Yes, but what we do is we target a partial nonce we use so the nonce is somewhat similar to the original one But not the same There we exploit that the lithium uses the shake XOF quite extensively And if you have a look at this sponge structure Well, it's easy to see that if you inject a fault like for instance in the second application of catch F in the squeeze phase Then all the output coming before that H0 and H1 will be the same And everything behind that will be different So and as why is sampled from this output? We then have Two different where vectors y where the first couple of coefficients will be identical So that difference is zero and only the last couple of coefficients will be different But still this difference is way too large to to only apply proof force So what we do is we return this problem of key recovery to a lattice problem where we have some target T which is computed from Public Output from the public signature and then we can look for the key or then we have a Closest vector problem so we look for a vector close to the lattice generated by this term and The diff and we know that it's close because the difference between the target and the lattice point is exactly our key That has small coefficients Of course, we have to apply some restrictions on the fault So we can fold two out of the five catch F permutations that are needed in the squeeze phase And the computation of runtime of the lattice reduction below one minute and we have a success probability of 24% Okay, so we did simulations, but we also did experimental verifications so we Did clock glitches on an arm cortex m4 and for each of the fault scenarios a single random fault is sufficient And what we also did is that we we benchmarked the runtime of all the different scenarios So how much of our signing time is susceptible to a fault and there you can see that well Faulting the hash directly has a high success probability but it's a coin of a small target and the The expansion of the public key takes quite a lot of time Doesn't have that high of success probability, but appears to be a good target and for this FW We just did many real experiments and then get got the average success probability About points six or so Okay, so now that we have the attack we can think about counter measures in terms of the generic counter measures Of course the first thing that comes to mind is double computation at the run doubles the runtime, of course And to attack double computation you need to either inject the same fold twice Or you have some permanent fold like for instance if you are able to manipulate this seed now since Verification is quite a lot faster than Than our signing what you can alternatively do is you take the signature you get and then verify So this takes only about one quarter of the runtime But what's interesting here is that well if you fault the generation of the nonce All what you do is you sign with a different nonce and that's still a valid signature so using this scenario you can bypass this counter measure and a final counter measure that Can protect against all our scenarios and it's hardly any overhead is What we call additional randomness. So what you do is you don't only Output KM and copper to this deterministic sample, but also some random R Like a random bit string now this protects against Fault attacks against bad randomness because if you insert if you set R to be a constant all you do is Switch of the fault counter measure again And if you do it correctly it could also be used against some sort of counter measure against DPA recovery of this secret K And in fact Q Tesla Already added this counter measure so in an update That came after the initial publication of this work They made the added this counter measure in it's now mandatory. So the attacks don't apply anymore And that's why I had a star next to Q Tesla in the beginning With the lithium there is a little bit of a problem because the actual security proof that the lithium users Requires this determinism so the proof requires that the signature scheme is deterministic and it loses tightness with the There is a an alternative version that doesn't require this Determinism but it's not tight and it loses our security in the number of of of Signatures that you see per message. So that's a bit of a problem So if this didn't really contributes to attack is of course an open problem, but yeah, it's still violate some security guarantees Okay, that's then the end of my presentation. Thank you very much for attention Any questions for Peter? So maybe one for me so on slide 13. I think it was so you showed these Yeah, these different attacks and How much time they take them for the total signature time so if I just I'm not targeting anything I just let it run and I shoot this a fold. Yeah, that's that's there. That's the total Yeah, that's like about 30% of the runtime. So if you're really blindly just shoot at the thing part You can't be more Targeted like for instance this expansion of the of the Probably key will always be somewhere at the beginning So if you target this then you will probably have a higher higher success and then yeah with Chance one in two slightly above. Yeah, we'll succeed. All right, and then next slide. You said like if you add randomness I agree. That's a good countermeasure, but why doesn't that add anything to the runtime getting good quality randomness? Yeah, of course getting randomness isn't if you have it somewhere already. Yes, so of course that's Okay The 0% is if you have it ready and everything else is already set up if you have a hard drive RNG or I don't know what It will add something because if you want to also protect against DPA you will likely Fill the first block of shake with random stuff and so it will have a higher runtime, but Negligible compared to the other stuff Okay Any more questions if not let thanks Peter and all the other speakers in this session